diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index fad9d99fb96..f6bf1e478b1 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -2,7 +2,7 @@ If you're looking for help check [Stack Overflow](https://stackoverflow.com/questions/tagged/kubernetes) and the [troubleshooting guide](https://kubernetes.io/docs/tasks/debug-application-cluster/troubleshooting/). -If this may be security issue, please disclose it privately via https://kubernetes.io/security/. +If the matter is security related, please disclose it privately via https://kubernetes.io/security/. --> **Is this a BUG REPORT or FEATURE REQUEST?**: diff --git a/CHANGELOG-1.10.md b/CHANGELOG-1.10.md index 6b986951263..7671ef3c014 100644 --- a/CHANGELOG-1.10.md +++ b/CHANGELOG-1.10.md @@ -1,30 +1,37 @@ -- [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) - [Server Binaries](#server-binaries) - [Node Binaries](#node-binaries) - - [Changelog since v1.10.2](#changelog-since-v1102) + - [Changelog since v1.10.3](#changelog-since-v1103) - [Other notable changes](#other-notable-changes) -- [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-1) - [Server Binaries](#server-binaries-1) - [Node Binaries](#node-binaries-1) - - [Changelog since v1.10.1](#changelog-since-v1101) + - [Changelog since v1.10.2](#changelog-since-v1102) - [Other notable changes](#other-notable-changes-1) -- [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-2) - [Server Binaries](#server-binaries-2) - [Node Binaries](#node-binaries-2) - - [Changelog since v1.10.0](#changelog-since-v1100) + - [Changelog since v1.10.1](#changelog-since-v1101) - [Other notable changes](#other-notable-changes-2) -- [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-3) - [Server Binaries](#server-binaries-3) - [Node Binaries](#node-binaries-3) + - [Changelog since v1.10.0](#changelog-since-v1100) + - [Other notable changes](#other-notable-changes-3) +- [v1.10.0](#v1100) + - [Downloads for v1.10.0](#downloads-for-v1100) + - [Client Binaries](#client-binaries-4) + - [Server Binaries](#server-binaries-4) + - [Node Binaries](#node-binaries-4) - [Major Themes](#major-themes) - [Node](#node) - [Storage](#storage) @@ -38,7 +45,7 @@ - [Before Upgrading](#before-upgrading) - [Known Issues](#known-issues) - [Deprecations](#deprecations) - - [Other Notable Changes](#other-notable-changes-3) + - [Other Notable Changes](#other-notable-changes-4) - [Apps](#apps) - [AWS](#aws) - [Auth](#auth-1) @@ -61,69 +68,144 @@ - [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-4) - - [Server Binaries](#server-binaries-4) - - [Node Binaries](#node-binaries-4) - - [Changelog since v1.10.0-beta.4](#changelog-since-v1100-beta4) - - [Other notable changes](#other-notable-changes-4) -- [v1.10.0-beta.4](#v1100-beta4) - - [Downloads for v1.10.0-beta.4](#downloads-for-v1100-beta4) - [Client Binaries](#client-binaries-5) - [Server Binaries](#server-binaries-5) - [Node Binaries](#node-binaries-5) - - [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-5) -- [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-6) - [Server Binaries](#server-binaries-6) - [Node Binaries](#node-binaries-6) - - [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-6) -- [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-7) - [Server Binaries](#server-binaries-7) - [Node Binaries](#node-binaries-7) - - [Changelog since v1.10.0-beta.1](#changelog-since-v1100-beta1) - - [Action Required](#action-required) + - [Changelog since v1.10.0-beta.2](#changelog-since-v1100-beta2) - [Other notable changes](#other-notable-changes-7) -- [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-8) - [Server Binaries](#server-binaries-8) - [Node Binaries](#node-binaries-8) - - [Changelog since v1.10.0-alpha.3](#changelog-since-v1100-alpha3) - - [Action Required](#action-required-1) + - [Changelog since v1.10.0-beta.1](#changelog-since-v1100-beta1) + - [Action Required](#action-required) - [Other notable changes](#other-notable-changes-8) -- [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-9) - [Server Binaries](#server-binaries-9) - [Node Binaries](#node-binaries-9) - - [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-1) - [Other notable changes](#other-notable-changes-9) -- [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-10) - [Server Binaries](#server-binaries-10) - [Node Binaries](#node-binaries-10) - - [Changelog since v1.10.0-alpha.1](#changelog-since-v1100-alpha1) - - [Action Required](#action-required-2) + - [Changelog since v1.10.0-alpha.2](#changelog-since-v1100-alpha2) - [Other notable changes](#other-notable-changes-10) -- [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-11) - [Server Binaries](#server-binaries-11) - [Node Binaries](#node-binaries-11) + - [Changelog since v1.10.0-alpha.1](#changelog-since-v1100-alpha1) + - [Action Required](#action-required-2) + - [Other notable changes](#other-notable-changes-11) +- [v1.10.0-alpha.1](#v1100-alpha1) + - [Downloads for v1.10.0-alpha.1](#downloads-for-v1100-alpha1) + - [Client Binaries](#client-binaries-12) + - [Server Binaries](#server-binaries-12) + - [Node Binaries](#node-binaries-12) - [Changelog since v1.9.0](#changelog-since-v190) - [Action Required](#action-required-3) - - [Other notable changes](#other-notable-changes-11) + - [Other notable changes](#other-notable-changes-12) +# v1.10.4 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.10/examples) + +## Downloads for v1.10.4 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes.tar.gz) | `b6e04c7c95ec9cfe6463ccc0863cd7c5dc874409ce2c3dd130809ea3e22ec39d` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-src.tar.gz) | `fd93b9cf0f7735e85a90674f90a7b943539774406ac21ea351789bd5d5f32649` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-client-darwin-386.tar.gz) | `1beadf6a6031bb461b34b9286e652e5ff79f4373dfa8ee8489f02b42b741d69d` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-client-darwin-amd64.tar.gz) | `dbbb0f6d29002f8cfee39ffe61bcec74341916927ee7f2d2e41f18689364936f` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-client-linux-386.tar.gz) | `00363c5438dc049b26257dcf97f012bc0dc5844aa7804633d2dc077c9814d9b7` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-client-linux-amd64.tar.gz) | `2831fe621bf1542a1eac38b8f50aa40a96b26153e850b3ff7155e5ce4f4f400e` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-client-linux-arm.tar.gz) | `ca98be6e14e697e7dc3aa2f0f83422ed6bc466efaaf19139c84c6cb74f79477a` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-client-linux-arm64.tar.gz) | `444cddd2c0b2c7ab37f8c4786723c1c940fdcf52c24edefd992ad707e9628360` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-client-linux-ppc64le.tar.gz) | `f7ac9c508634c77a54e8a0b71684bbe454e3ddb325ff6c4450e8d013e90a7e7f` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-client-linux-s390x.tar.gz) | `ed5440b893e0e39eb2d09a4b32e072e6e51ec8aef6e674d6620e3e1c23b1715d` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-client-windows-386.tar.gz) | `80207e67c741a6fb30073fd5890edfd3e21ff9dc5560b802d8601e82d062b029` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-client-windows-amd64.tar.gz) | `7ada21ad4c0e10939f0bbb16ec3dc5c6d9329eff75e943eecca2461d0f874eb1` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-server-linux-amd64.tar.gz) | `e2381459ba91674b5e5cc10c8e8d6dc910e71874d01165ca07a94188edc8505e` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-server-linux-arm.tar.gz) | `c48cc7a90c57f3fa73de1362ef5f64542e11eb31290569b190e716c03f09ca39` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-server-linux-arm64.tar.gz) | `1ab1d282935be7e775ee07aab720c9bc8da6157386fc3d91565214cbc16debf1` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-server-linux-ppc64le.tar.gz) | `a64bb8c60e094cb03e29413bc83b6177caa07f786f43e52a8d748147138321c3` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-server-linux-s390x.tar.gz) | `5e96c974df9e41ca12a6ba0796227af48df6d6d6c5256abb7e39c0002504714e` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-node-linux-amd64.tar.gz) | `40b8bc76cb4a2676d02169e26f43d39198f6e41297f22ef07e1984feac3879b3` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-node-linux-arm.tar.gz) | `7d818b1fcf82a74de401936db1cd4704e52b594658c9be6c760b3c5ca2e49c01` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-node-linux-arm64.tar.gz) | `41e4fb14acaec64b7b79fd0c938a2c2c5b914de8b007afe3ffb0eb1c3e2d7f0e` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-node-linux-ppc64le.tar.gz) | `a22095e62acbcea4ea4d95e500eaa10d30db529b8b0465b67b44bd53a3df628f` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-node-linux-s390x.tar.gz) | `bfe8e8890d2ed5511cf4cbc9908b603a1b0610d7847c7c272011028b382f71de` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.4/kubernetes-node-windows-amd64.tar.gz) | `f9d9b614febf3c787c02e661bfc7a54cbff9a0ef0d260d43fe03190f13bdf065` + +## Changelog since v1.10.3 + +### Other notable changes + +* Fixes issue for readOnly subpath mounts for SELinux systems and when the volume mountPath already existed in the container image. ([#64351](https://github.com/kubernetes/kubernetes/pull/64351), [@msau42](https://github.com/msau42)) +* Fixed CSI gRPC connection leak during volume operations. ([#64519](https://github.com/kubernetes/kubernetes/pull/64519), [@vladimirvivien](https://github.com/vladimirvivien)) +* In case StorageObjectInUse feature is disabled and Persistent Volume (PV) or Persistent Volume Claim (PVC) contains a finalizer and the PV or PVC is deleted it is not automatically removed from the system. Now, it is automatically removed. ([#62938](https://github.com/kubernetes/kubernetes/pull/62938), [@pospispa](https://github.com/pospispa)) +* Fixed SELinux relabeling of CSI volumes. ([#64026](https://github.com/kubernetes/kubernetes/pull/64026), [@jsafrane](https://github.com/jsafrane)) +* Fixed error reporting of CSI volumes attachment. ([#63303](https://github.com/kubernetes/kubernetes/pull/63303), [@jsafrane](https://github.com/jsafrane)) +* fix azure file size grow issue ([#64383](https://github.com/kubernetes/kubernetes/pull/64383), [@andyzhangx](https://github.com/andyzhangx)) +* Fixed detach of already detached CSI volumes. ([#63295](https://github.com/kubernetes/kubernetes/pull/63295), [@jsafrane](https://github.com/jsafrane)) +* Update event-exporter to version v0.2.0 that supports old (gke_container/gce_instance) and new (k8s_container/k8s_node/k8s_pod) stackdriver resources. ([#63918](https://github.com/kubernetes/kubernetes/pull/63918), [@cezarygerard](https://github.com/cezarygerard)) +* Fix issue of colliding nodePorts when the cluster has services with externalTrafficPolicy=Local ([#64349](https://github.com/kubernetes/kubernetes/pull/64349), [@nicksardo](https://github.com/nicksardo)) +* Update nvidia-gpu-device-plugin DaemonSet config to use RollingUpdate updateStrategy instead of OnDelete. ([#64296](https://github.com/kubernetes/kubernetes/pull/64296), [@mindprince](https://github.com/mindprince)) +* kubeadm will no longer generate an unused etcd CA and certificates when configured to use an external etcd cluster. ([#63806](https://github.com/kubernetes/kubernetes/pull/63806), [@detiber](https://github.com/detiber)) +* Fix incorrectly propagated ResourceVersion in ListRequests returning 0 items. ([#64150](https://github.com/kubernetes/kubernetes/pull/64150), [@wojtek-t](https://github.com/wojtek-t)) +* Fix SessionAffinity not updated issue for Azure load balancer ([#64180](https://github.com/kubernetes/kubernetes/pull/64180), [@feiskyer](https://github.com/feiskyer)) +* Fixes a hang on kubelet startup when using systemd cgroup driver of libcontainer. ([#61926](https://github.com/kubernetes/kubernetes/pull/61926), [@filbranden](https://github.com/filbranden)) +* Prevent 1.10 e2es testing deprecated CAdvisorPort in v1.11 ([#64184](https://github.com/kubernetes/kubernetes/pull/64184), [@dixudx](https://github.com/dixudx)) +* GCE: Fix to make the built-in `kubernetes` service properly point to the master's load balancer address in clusters that use multiple master VMs. ([#63696](https://github.com/kubernetes/kubernetes/pull/63696), [@grosskur](https://github.com/grosskur)) +* etcd client add dial timeout. ([#61459](https://github.com/kubernetes/kubernetes/pull/61459), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* nil admission options are now consistent with other nil options. ([#63993](https://github.com/kubernetes/kubernetes/pull/63993), [@tamalsaha](https://github.com/tamalsaha)) +* Add a way to pass extra arguments to etcd. ([#63961](https://github.com/kubernetes/kubernetes/pull/63961), [@mborsz](https://github.com/mborsz)) +* kubeadm: surface external etcd preflight validation errors ([#60585](https://github.com/kubernetes/kubernetes/pull/60585), [@alexbrand](https://github.com/alexbrand)) + + + # v1.10.3 [Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.10/examples) diff --git a/CHANGELOG-1.11.md b/CHANGELOG-1.11.md index 264f31666ca..51cb6eab04f 100644 --- a/CHANGELOG-1.11.md +++ b/CHANGELOG-1.11.md @@ -1,24 +1,408 @@ -- [v1.11.0-alpha.2](#v1110-alpha2) - - [Downloads for v1.11.0-alpha.2](#downloads-for-v1110-alpha2) +- [v1.11.0-beta.2](#v1110-beta2) + - [Downloads for v1.11.0-beta.2](#downloads-for-v1110-beta2) - [Client Binaries](#client-binaries) - [Server Binaries](#server-binaries) - [Node Binaries](#node-binaries) - - [Changelog since v1.11.0-alpha.1](#changelog-since-v1110-alpha1) + - [Changelog since v1.11.0-beta.1](#changelog-since-v1110-beta1) + - [Action Required](#action-required) - [Other notable changes](#other-notable-changes) -- [v1.11.0-alpha.1](#v1110-alpha1) - - [Downloads for v1.11.0-alpha.1](#downloads-for-v1110-alpha1) +- [v1.11.0-beta.1](#v1110-beta1) + - [Downloads for v1.11.0-beta.1](#downloads-for-v1110-beta1) - [Client Binaries](#client-binaries-1) - [Server Binaries](#server-binaries-1) - [Node Binaries](#node-binaries-1) - - [Changelog since v1.10.0](#changelog-since-v1100) - - [Action Required](#action-required) + - [Changelog since v1.11.0-alpha.2](#changelog-since-v1110-alpha2) + - [Action Required](#action-required-1) - [Other notable changes](#other-notable-changes-1) +- [v1.11.0-alpha.2](#v1110-alpha2) + - [Downloads for v1.11.0-alpha.2](#downloads-for-v1110-alpha2) + - [Client Binaries](#client-binaries-2) + - [Server Binaries](#server-binaries-2) + - [Node Binaries](#node-binaries-2) + - [Changelog since v1.11.0-alpha.1](#changelog-since-v1110-alpha1) + - [Other notable changes](#other-notable-changes-2) +- [v1.11.0-alpha.1](#v1110-alpha1) + - [Downloads for v1.11.0-alpha.1](#downloads-for-v1110-alpha1) + - [Client Binaries](#client-binaries-3) + - [Server Binaries](#server-binaries-3) + - [Node Binaries](#node-binaries-3) + - [Changelog since v1.10.0](#changelog-since-v1100) + - [Action Required](#action-required-2) + - [Other notable changes](#other-notable-changes-3) +# v1.11.0-beta.2 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.11/examples) + +## Downloads for v1.11.0-beta.2 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes.tar.gz) | `0addbff3fc61047460da0fca7413f4cc679fac7482c3f09aa4f4a60d8ec8dd5c` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-src.tar.gz) | `943629abc5b046cc5db280417e5cf3a8342c5f67c8deb3d7283b02de67b3a3c3` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-darwin-386.tar.gz) | `9b714bb99e9d8c51c718d9ec719412b2006c921e6a5566acf387797b57014386` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-darwin-amd64.tar.gz) | `11fc9f94c82b2adc860964be8e84ed1e17ae711329cac3c7aff58067caeeffe2` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-386.tar.gz) | `016abd161dc394ab6e1e8f57066ff413b523c71ac2af458bfc8dfa2107530910` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-amd64.tar.gz) | `f98c223c24680aae583ff63fa8e1ef49421ddd660bd748fea493841c24ad6417` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-arm.tar.gz) | `78cf5dca303314023d6f82c7570e92b814304029fb7d3941d7c04855679e120d` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-arm64.tar.gz) | `c35e03687d491d9ca955121912c56d00741c86381370ed5890b0ee8b629a3e01` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-ppc64le.tar.gz) | `4e848a58f822f971dbda607d26128d1b718fc07665d2f65b87936eec40b037b2` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-s390x.tar.gz) | `ead83a70e4782efdaea3645ca2a59e51209041ce41f9d805d5c1d10f029b1cb0` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-windows-386.tar.gz) | `c357b28c83e769517d7b19e357260d62485e861005d98f84c752d109fa48bd20` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-windows-amd64.tar.gz) | `2ae78921a35a8a582b226521f904f0840c17e3e097364d6a3fcd10d196bec0dc` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-server-linux-amd64.tar.gz) | `26bd6e05a4bf942534f0578b1cdbd11b8c868aa3331e2681734ecc93d75f6b85` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-server-linux-arm.tar.gz) | `df706ccad0a235613e644eda363c49bfb858860a2ae5219b17b996f36669a7fc` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-server-linux-arm64.tar.gz) | `73f3e7a82d7c78a9f03ce0c84ae4904942f0bf88b3bf045fc9b1707b686cb04e` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-server-linux-ppc64le.tar.gz) | `ebeb67e45e630469d55b442d2c6092065f1c1403d1965c4340d0b6c1fa7f6676` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-server-linux-s390x.tar.gz) | `c82e6a41b8e451600fb5bfdad3addf3c35b5edb518a7bf9ebd03af0574d57975` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-linux-amd64.tar.gz) | `e6dbd56c10fee83f400e76ae02325eda0a583347f6b965eeb610c90d664d7990` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-linux-arm.tar.gz) | `df9d18c3af4d6ee237a238b3029823f6e90b2ae3f0d25b741d4b3fedb7ea14f8` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-linux-arm64.tar.gz) | `d84e98702651615336256d3453516df9ad39f39400f6091d9e2b4c95b4111ede` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-linux-ppc64le.tar.gz) | `a62037f00ab29302f72aa23116c304b676cc41a6f47f79a2faf4e4ea18059178` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-linux-s390x.tar.gz) | `bef66f2080f7ebf442234d841ec9c994089fa02b400d98e1b01021f1f66c4cd0` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-windows-amd64.tar.gz) | `2b029715b98c3355a172ed5a6e08e73ad4ef264c74a26ed5a3da67f90764b7dc` + +## Changelog since v1.11.0-beta.1 + +### Action Required + +* [action required] `kubeadm join` is now blocking on the kubelet performing the TLS Bootstrap properly. ([#64792](https://github.com/kubernetes/kubernetes/pull/64792), [@luxas](https://github.com/luxas)) + * Earlier, `kubeadm join` only did the discovery part and exited successfully without checking that the + * kubelet actually started properly and performed the TLS bootstrap correctly. Now, as kubeadm runs + * some post-join steps (e.g. annotating the Node API object with the CRISocket as in this PR, as a + * stop-gap until this is discoverable automatically), `kubeadm join` is now waiting for the kubelet to + * perform the TLS Bootstrap, and then uses that credential to perform further actions. This also + * improves the UX, as `kubeadm` will exit with a non-zero code if the kubelet isn't in a functional + * state, instead of pretending like everything's fine. +* [action required] The structure of the kubelet dropin in the kubeadm deb package has changed significantly. ([#64780](https://github.com/kubernetes/kubernetes/pull/64780), [@luxas](https://github.com/luxas)) + * Instead of hard-coding the parameters for the kubelet in the dropin, a structured configuration file + * for the kubelet is used, and is expected to be present in `/var/lib/kubelet/config.yaml`. + * For runtime-detected, instance-specific configuration values, a environment file with + * dynamically-generated flags at `kubeadm init` or `kubeadm join` run time is used. + * Finally, if the user wants to override something specific for the kubelet that can't be done via + * the kubeadm Configuration file (which is preferred), they might add flags to the + * `KUBELET_EXTRA_ARGS` environment variable in either `/etc/default/kubelet` + * or `/etc/sysconfig/kubelet`, depending on the system you're running on. +* [action required] The `--node-name` flag for kubeadm now dictates the Node API object name the ([#64706](https://github.com/kubernetes/kubernetes/pull/64706), [@liztio](https://github.com/liztio)) + * kubelet uses for registration, in all cases but where you might use an in-tree cloud provider. + * If you're not using an in-tree cloud provider, `--node-name` will set the Node API object name. + * If you're using an in-tree cloud provider, you MUST make `--node-name` match the name the + * in-tree cloud provider decides to use. +* [action required] kubeadm: The Token-related fields in the `MasterConfiguration` object have now been refactored. Instead of the top-level `.Token`, `.TokenTTL`, `.TokenUsages`, `.TokenGroups` fields, there is now a `BootstrapTokens` slice of `BootstrapToken` objects that support the same features under the `.Token`, `.TTL`, `.Usages`, `.Groups` fields. ([#64408](https://github.com/kubernetes/kubernetes/pull/64408), [@luxas](https://github.com/luxas)) + +### Other notable changes + +* Add Vertical Pod Autoscaler to autoscaling/v2beta1 ([#63797](https://github.com/kubernetes/kubernetes/pull/63797), [@kgrygiel](https://github.com/kgrygiel)) +* kubeadm: only run kube-proxy on architecture consistent nodes ([#64696](https://github.com/kubernetes/kubernetes/pull/64696), [@dixudx](https://github.com/dixudx)) +* kubeadm: Add a new `kubeadm upgrade node config` command ([#64624](https://github.com/kubernetes/kubernetes/pull/64624), [@luxas](https://github.com/luxas)) +* Orphan delete is now supported for custom resources ([#63386](https://github.com/kubernetes/kubernetes/pull/63386), [@roycaihw](https://github.com/roycaihw)) +* Update version of Istio addon from 0.6.0 to 0.8.0. ([#64537](https://github.com/kubernetes/kubernetes/pull/64537), [@ostromart](https://github.com/ostromart)) + * See https://istio.io/about/notes/0.8.html for full Isto release notes. +* Provides API support for external CSI storage drivers to support block volumes. ([#64723](https://github.com/kubernetes/kubernetes/pull/64723), [@vladimirvivien](https://github.com/vladimirvivien)) +* kubectl will list all allowed print formats when an invalid format is passed. ([#64371](https://github.com/kubernetes/kubernetes/pull/64371), [@CaoShuFeng](https://github.com/CaoShuFeng)) +* Use IONice to reduce IO priority of du and find ([#64800](https://github.com/kubernetes/kubernetes/pull/64800), [@dashpole](https://github.com/dashpole)) + * cAdvisor ContainerReference no longer contains Labels. Use ContainerSpec instead. + * Fix a bug where cadvisor failed to discover a sub-cgroup that was created soon after the parent cgroup. +* Kubelet will set extended resource capacity to zero after it restarts. If the extended resource is exported by a device plugin, its capacity will change to a valid value after the device plugin re-connects with the Kubelet. If the extended resource is exported by an external component through direct node status capacity patching, the component should repatch the field after kubelet becomes ready again. During the time gap, pods previously assigned with such resources may fail kubelet admission but their controller should create new pods in response to such failures. ([#64784](https://github.com/kubernetes/kubernetes/pull/64784), [@jiayingz](https://github.com/jiayingz)) +* Introduce ContainersReady condition in Pod Status ([#64646](https://github.com/kubernetes/kubernetes/pull/64646), [@freehan](https://github.com/freehan)) +* 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. ([#63717](https://github.com/kubernetes/kubernetes/pull/63717), [@ingvagabund](https://github.com/ingvagabund)) +* kubeadm now configures the etcd liveness probe correctly when etcd is listening on all interfaces ([#64670](https://github.com/kubernetes/kubernetes/pull/64670), [@stealthybox](https://github.com/stealthybox)) +* Fix regression in `v1.JobSpec.backoffLimit` that caused failed Jobs to be restarted indefinitely. ([#63650](https://github.com/kubernetes/kubernetes/pull/63650), [@soltysh](https://github.com/soltysh)) +* GCE: Update cloud provider to use TPU v1 API ([#64727](https://github.com/kubernetes/kubernetes/pull/64727), [@yguo0905](https://github.com/yguo0905)) +* Kubelet: Add security context for Windows containers ([#64009](https://github.com/kubernetes/kubernetes/pull/64009), [@feiskyer](https://github.com/feiskyer)) +* Volume topology aware dynamic provisioning ([#63193](https://github.com/kubernetes/kubernetes/pull/63193), [@lichuqiang](https://github.com/lichuqiang)) +* CoreDNS deployment configuration now uses k8s.gcr.io imageRepository ([#64775](https://github.com/kubernetes/kubernetes/pull/64775), [@rajansandeep](https://github.com/rajansandeep)) +* Updated Container Storage Interface specification version to v0.3.0 ([#64719](https://github.com/kubernetes/kubernetes/pull/64719), [@davidz627](https://github.com/davidz627)) +* Kubeadm: Make CoreDNS run in read-only mode and drop all unneeded privileges ([#64473](https://github.com/kubernetes/kubernetes/pull/64473), [@nberlee](https://github.com/nberlee)) +* Add a volume projection that is able to project service account tokens. ([#62005](https://github.com/kubernetes/kubernetes/pull/62005), [@mikedanese](https://github.com/mikedanese)) +* Fix kubectl auth can-i exit code. It will return 1 if the user is not allowed and 0 if it's allowed. ([#59579](https://github.com/kubernetes/kubernetes/pull/59579), [@fbac](https://github.com/fbac)) +* apply global flag "context" for kubectl config view --minify ([#64608](https://github.com/kubernetes/kubernetes/pull/64608), [@dixudx](https://github.com/dixudx)) +* Fix kube-controller-manager panic while provisioning Azure security group rules ([#64739](https://github.com/kubernetes/kubernetes/pull/64739), [@feiskyer](https://github.com/feiskyer)) +* API change for volume topology aware dynamic provisioning ([#63233](https://github.com/kubernetes/kubernetes/pull/63233), [@lichuqiang](https://github.com/lichuqiang)) +* Add azuredisk PV size grow feature ([#64386](https://github.com/kubernetes/kubernetes/pull/64386), [@andyzhangx](https://github.com/andyzhangx)) +* Modify e2e tests to use priorityClass beta version & switch priorityClass feature to beta ([#63724](https://github.com/kubernetes/kubernetes/pull/63724), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* Adding CSI driver registration code. ([#64560](https://github.com/kubernetes/kubernetes/pull/64560), [@sbezverk](https://github.com/sbezverk)) +* fixes a potential deadlock in the garbage collection controller ([#64235](https://github.com/kubernetes/kubernetes/pull/64235), [@liggitt](https://github.com/liggitt)) +* Fixes issue for readOnly subpath mounts for SELinux systems and when the volume mountPath already existed in the container image. ([#64351](https://github.com/kubernetes/kubernetes/pull/64351), [@msau42](https://github.com/msau42)) +* Add log and fs stats for Windows containers ([#62266](https://github.com/kubernetes/kubernetes/pull/62266), [@feiskyer](https://github.com/feiskyer)) +* client-go: credential exec plugins have been promoted to beta ([#64482](https://github.com/kubernetes/kubernetes/pull/64482), [@ericchiang](https://github.com/ericchiang)) +* Revert [#64364](https://github.com/kubernetes/kubernetes/pull/64364) to resurrect rescheduler. More info https://github.com/kubernetes/kubernetes/issues/64725 :) ([#64592](https://github.com/kubernetes/kubernetes/pull/64592), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* Add RequestedToCapacityRatioPriority priority function. Function is parametrized with set of points mapping node utilization (0-100) to score (0-10). ([#63929](https://github.com/kubernetes/kubernetes/pull/63929), [@losipiuk](https://github.com/losipiuk)) + * Function is linear between points. Resource utilization is defined as one minus ratio of total amount of resource requested by pods on node and node's capacity (scaled to 100). + * Final utilization used for computation is arithmetic mean of cpu utilization and memory utilization. + * Function is disabled by default and can be enabled via scheduler policy config file. + * If no parametrization is specified in config file it defaults to one which gives score 10 to utilization 0 and score 0 to utilization 100. +* `kubeadm init` detects if systemd-resolved is running and configures the kubelet to use a working resolv.conf. ([#64665](https://github.com/kubernetes/kubernetes/pull/64665), [@stealthybox](https://github.com/stealthybox)) +* fix data loss issue if using existing azure disk with partitions in disk mount ([#63270](https://github.com/kubernetes/kubernetes/pull/63270), [@andyzhangx](https://github.com/andyzhangx)) +* Meta data of CustomResources is now pruned and schema checked during deserialization of requests and when read from etcd. In the former case, invalid meta data is rejected, in the later it is dropped from the CustomResource objects. ([#64267](https://github.com/kubernetes/kubernetes/pull/64267), [@sttts](https://github.com/sttts)) +* Add Alpha support for dynamic volume limits based on node type ([#64154](https://github.com/kubernetes/kubernetes/pull/64154), [@gnufied](https://github.com/gnufied)) +* Fixed CSI gRPC connection leak during volume operations. ([#64519](https://github.com/kubernetes/kubernetes/pull/64519), [@vladimirvivien](https://github.com/vladimirvivien)) +* in-tree support for openstack credentials is now deprecated. please use the "client-keystone-auth" from the cloud-provider-openstack repository. details on how to use this new capability is documented here - https://github.com/kubernetes/cloud-provider-openstack/blob/master/docs/using-client-keystone-auth.md ([#64346](https://github.com/kubernetes/kubernetes/pull/64346), [@dims](https://github.com/dims)) +* `ScheduleDaemonSetPods` is an alpha feature (since v1.11) that causes DaemonSet Pods ([#63223](https://github.com/kubernetes/kubernetes/pull/63223), [@k82cn](https://github.com/k82cn)) + * to be scheduler by default scheduler, instead of Daemonset controller. When it is enabled, + * the `NodeAffinity` term (instead of `.spec.nodeName`) is added to the DaemonSet Pods; + * this enables the default scheduler to bind the Pod to the target host. If node affinity + * of DaemonSet Pod already exists, it will be replaced. + * DaemonSet controller will only perform these operations when creating DaemonSet Pods; + * and those operations will only modify the Pods of DaemonSet, no changes are made to the + * `.spec.template` of DaemonSet. +* fix formatAndMount func issue on Windows ([#63248](https://github.com/kubernetes/kubernetes/pull/63248), [@andyzhangx](https://github.com/andyzhangx)) +* AWS EBS, Azure Disk, GCE PD and Ceph RBD volume plugins support dynamic provisioning of raw block volumes. ([#64447](https://github.com/kubernetes/kubernetes/pull/64447), [@jsafrane](https://github.com/jsafrane)) +* kubeadm upgrade apply can now ignore version errors with --force ([#64570](https://github.com/kubernetes/kubernetes/pull/64570), [@liztio](https://github.com/liztio)) +* Adds feature gate for plugin watcher ([#64605](https://github.com/kubernetes/kubernetes/pull/64605), [@vikaschoudhary16](https://github.com/vikaschoudhary16)) +* Kubelet now proxies container streaming between apiserver and container runtime. The connection between kubelet and apiserver is authenticated. Container runtime should change streaming server to serve on localhost, to make the connection between kubelet and container runtime local. ([#64006](https://github.com/kubernetes/kubernetes/pull/64006), [@Random-Liu](https://github.com/Random-Liu)) + * In this way, the whole container streaming connection is secure. To switch back to the old behavior, set `--redirect-container-streaming=true` flag. +* TokenRequests now are required to have an expiration duration between 10 minutes and 2^32 seconds. ([#63999](https://github.com/kubernetes/kubernetes/pull/63999), [@mikedanese](https://github.com/mikedanese)) +* Expose `/debug/flags/v` to allow dynamically set glog logging level, if want to change glog level to 3, you only have to send a PUT request with like `curl -X PUT http://127.0.0.1:8080/debug/flags/v -d "3"`. ([#63777](https://github.com/kubernetes/kubernetes/pull/63777), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* New conformance test added for Watch. ([#61424](https://github.com/kubernetes/kubernetes/pull/61424), [@jennybuckley](https://github.com/jennybuckley)) +* The GitRepo volume type is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container. ([#63445](https://github.com/kubernetes/kubernetes/pull/63445), [@ericchiang](https://github.com/ericchiang)) +* kubeadm now preserves previous manifests after upgrades ([#64337](https://github.com/kubernetes/kubernetes/pull/64337), [@liztio](https://github.com/liztio)) +* Implement kubelet side online file system resizing ([#62460](https://github.com/kubernetes/kubernetes/pull/62460), [@mlmhl](https://github.com/mlmhl)) + + + +# v1.11.0-beta.1 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.11/examples) + +## Downloads for v1.11.0-beta.1 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes.tar.gz) | `3209303a10ca8dd311c500ee858b9151b43c1bb5c2b3a9fb9281722e021d6871` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-src.tar.gz) | `c2e4d3b1beb4cd0b2a775394a30da2c2949d380e57f729dc48c541069c103326` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-darwin-386.tar.gz) | `cbded4d58b3d2cbeb2e43c48c9dd359834c9c9aa376751a7f8960be45601fb40` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-darwin-amd64.tar.gz) | `ceccd21fda90b96865801053f1784d4062d69b11e2e911483223860dfe6c3a17` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-386.tar.gz) | `75c9794a7f43f891aa839b2571fa44ffced25197578adc31b4c3cb28d7fbf158` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-amd64.tar.gz) | `184905f6b8b856306483d811d015cf0b28c0703ceb372594622732da2a07989f` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-arm.tar.gz) | `2d985829499588d32483d7c6a36b3b0f2b6d4031eda31c65b066b77bc51bae66` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-arm64.tar.gz) | `268556ede751058162a42d0156f27e42e37b23d60b2485e350cffe6e1b376fa4` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-ppc64le.tar.gz) | `8859bd7a37bf5a659eb17e47d2c54d228950b2ef48243c93f11799c455789983` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-s390x.tar.gz) | `90bbe2fc45ae722a05270820336b9178baaab198401bb6888e817afe6a1a304e` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-windows-386.tar.gz) | `948b01f555abfc30990345004d5ce679d4b9d0a32d699a50b6d8309040b2b2f2` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-windows-amd64.tar.gz) | `091e9d4e7fa611cf06d2907d159e0cc36ae8602403ad0819d62df4ddbaba6095` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-server-linux-amd64.tar.gz) | `727a5e8241035d631d90f3d119a27384abe93cde14c242c4d2d1cf948f84a650` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-server-linux-arm.tar.gz) | `6eb7479348e9480d9d1ee31dc991297b93e076dd21b567c595f82d45b66ef949` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-server-linux-arm64.tar.gz) | `9eab5ccdfba2803a743ed12b4323ad0e8e0215779edf5752224103b6667a35c1` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-server-linux-ppc64le.tar.gz) | `d86b07ee28ed3d2c0668a2737fff4b3d025d4cd7b6f1aadc85f8f13b4c12e578` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-server-linux-s390x.tar.gz) | `c2d19acb88684a52a74f469ab26874ab224023f29290865e08c86338d30dd598` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-linux-amd64.tar.gz) | `2957bf3e9dc9cd9570597434909e5ef03e996f8443c02f9d95fa6de2cd17126f` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-linux-arm.tar.gz) | `5995b8b9628fca9eaa92c283cfb4199ab353efa8953b980eec994f49ac3a0ebd` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-linux-arm64.tar.gz) | `996691b3b894ec9769be1ee45c5053ff1560e3ef161de8f8b9ac067c0d3559d3` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-linux-ppc64le.tar.gz) | `8bb7fe72ec704afa5ad96356787972144b0f7923fc68678894424f1f62da7041` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-linux-s390x.tar.gz) | `4c1f0314ad60537c8a7866b0cabdece21284ee91ae692d1999b3d5273ee7cbaf` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-windows-amd64.tar.gz) | `158832f41cd452f93482cc8a8f1dd69cc243eb63ce3581e7f2eab2de323f6202` + +## Changelog since v1.11.0-alpha.2 + +### Action Required + +* [action required] `.NodeName` and `.CRISocket` in the `MasterConfiguration` and `NodeConfiguration` v1alpha1 API objects are now `.NodeRegistration.Name` and `.NodeRegistration.CRISocket` respectively in the v1alpha2 API. The `.NoTaintMaster` field has been removed in the v1alpha2 API. ([#64210](https://github.com/kubernetes/kubernetes/pull/64210), [@luxas](https://github.com/luxas)) +* (ACTION REQUIRED) PersisntVolumeLabel admission controller is now disabled by default. If you depend on this feature (AWS/GCE) then ensure it is added to the `--enable-admission-plugins` flag on the kube-apiserver. ([#64326](https://github.com/kubernetes/kubernetes/pull/64326), [@andrewsykim](https://github.com/andrewsykim)) +* [action required] kubeadm: The `:Etcd` struct has been refactored in the v1alpha2 API. All the options now reside under either `.Etcd.Local` or `.Etcd.External`. Automatic conversions from the v1alpha1 API are supported. ([#64066](https://github.com/kubernetes/kubernetes/pull/64066), [@luxas](https://github.com/luxas)) +* [action required] kubeadm: kubelets in kubeadm clusters now disable the readonly port (10255). If you're relying on unauthenticated access to the readonly port, please switch to using the secure port (10250). Instead, you can now use ServiceAccount tokens when talking to the secure port, which will make it easier to get access to e.g. the `/metrics` endpoint of the kubelet securely. ([#64187](https://github.com/kubernetes/kubernetes/pull/64187), [@luxas](https://github.com/luxas)) +* [action required] kubeadm: Support for `.AuthorizationModes` in the kubeadm v1alpha2 API has been removed. Instead, you can use the `.APIServerExtraArgs` and `.APIServerExtraVolumes` fields to achieve the same effect. Files using the v1alpha1 API and setting this field will be automatically upgraded to this v1alpha2 API and the information will be preserved. ([#64068](https://github.com/kubernetes/kubernetes/pull/64068), [@luxas](https://github.com/luxas)) +* [action required] The formerly publicly-available cAdvisor web UI that the kubelet ran on port 4194 by default is now turned off by default. The flag configuring what port to run this UI on `--cadvisor-port` was deprecated in v1.10. Now the default is `--cadvisor-port=0`, in other words, to not run the web server. The recommended way to run cAdvisor if you still need it, is via a DaemonSet. The `--cadvisor-port` will be removed in v1.12 ([#63881](https://github.com/kubernetes/kubernetes/pull/63881), [@luxas](https://github.com/luxas)) +* [action required] kubeadm: The `.ImagePullPolicy` field has been removed in the v1alpha2 API version. Instead it's set statically to `IfNotPresent` for all required images. If you want to always pull the latest images before cluster init (like what `Always` would do), run `kubeadm config images pull` before each `kubeadm init`. If you don't want the kubelet to pull any images at `kubeadm init` time, as you for instance don't have an internet connection, you can also run `kubeadm config images pull` before `kubeadm init` or side-load the images some other way (e.g. `docker load -i image.tar`). Having the images locally cached will result in no pull at runtime, which makes it possible to run without any internet connection. ([#64096](https://github.com/kubernetes/kubernetes/pull/64096), [@luxas](https://github.com/luxas)) +* [action required] In the new v1alpha2 kubeadm Configuration API, the `.CloudProvider` and `.PrivilegedPods` fields don't exist anymore. ([#63866](https://github.com/kubernetes/kubernetes/pull/63866), [@luxas](https://github.com/luxas)) + * Instead, you should use the out-of-tree cloud provider implementations which are beta in v1.11. + * If you have to use the legacy in-tree cloud providers, you can rearrange your config like the example below. In case you need the `cloud-config` file (located in `{cloud-config-path}`), you can mount it into the API Server and controller-manager containers using ExtraVolumes like the example below. + * If you need to use the `.PrivilegedPods` functionality, you can still edit the manifests in + * `/etc/kubernetes/manifests/`, and set `.SecurityContext.Privileged=true` for the apiserver + * and controller manager. + * --- + * kind: MasterConfiguration + * apiVersion: kubeadm.k8s.io/v1alpha2 + * apiServerExtraArgs: + * cloud-provider: "{cloud}" + * cloud-config: "{cloud-config-path}" + * apiServerExtraVolumes: + * - name: cloud + * hostPath: "{cloud-config-path}" + * mountPath: "{cloud-config-path}" + * controllerManagerExtraArgs: + * cloud-provider: "{cloud}" + * cloud-config: "{cloud-config-path}" + * controllerManagerExtraVolumes: + * - name: cloud + * hostPath: "{cloud-config-path}" + * mountPath: "{cloud-config-path}" + * --- +* [action required] kubeadm now uses an upgraded API version for the configuration file, `kubeadm.k8s.io/v1alpha2`. kubeadm in v1.11 will still be able to read `v1alpha1` configuration, and will automatically convert the configuration to `v1alpha2` internally and when storing the configuration in the ConfigMap in the cluster. ([#63788](https://github.com/kubernetes/kubernetes/pull/63788), [@luxas](https://github.com/luxas)) +* The annotation `service.alpha.kubernetes.io/tolerate-unready-endpoints` is deprecated. Users should use Service.spec.publishNotReadyAddresses instead. ([#63742](https://github.com/kubernetes/kubernetes/pull/63742), [@thockin](https://github.com/thockin)) +* avoid duplicate status in audit events ([#62695](https://github.com/kubernetes/kubernetes/pull/62695), [@CaoShuFeng](https://github.com/CaoShuFeng)) + +### Other notable changes + +* Remove rescheduler from master. ([#64364](https://github.com/kubernetes/kubernetes/pull/64364), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* Declare IPVS-based kube-proxy GA ([#58442](https://github.com/kubernetes/kubernetes/pull/58442), [@m1093782566](https://github.com/m1093782566)) +* kubeadm: conditionally set the kubelet cgroup driver for Docker ([#64347](https://github.com/kubernetes/kubernetes/pull/64347), [@neolit123](https://github.com/neolit123)) +* kubectl built for darwin from darwin now enables cgo to use the system-native C libraries for DNS resolution. Cross-compiled kubectl (e.g. from an official kubernetes release) still uses the go-native netgo DNS implementation. ([#64219](https://github.com/kubernetes/kubernetes/pull/64219), [@ixdy](https://github.com/ixdy)) +* AWS EBS volumes can be now used as ReadOnly in pods. ([#64403](https://github.com/kubernetes/kubernetes/pull/64403), [@jsafrane](https://github.com/jsafrane)) +* Exec authenticator plugin supports TLS client certificates. ([#61803](https://github.com/kubernetes/kubernetes/pull/61803), [@awly](https://github.com/awly)) +* Use Patch instead of Put to sync pod status ([#62306](https://github.com/kubernetes/kubernetes/pull/62306), [@freehan](https://github.com/freehan)) +* kubectl apply --prune supports CronJob resource. ([#62991](https://github.com/kubernetes/kubernetes/pull/62991), [@tomoe](https://github.com/tomoe)) +* Label ExternalEtcdClientCertificates can be used for ignoring all preflight check issues related to client certificate files for external etcd. ([#64269](https://github.com/kubernetes/kubernetes/pull/64269), [@kad](https://github.com/kad)) +* Provide a meaningful error message in openstack cloud provider when no valid IP address can be found for a node ([#64318](https://github.com/kubernetes/kubernetes/pull/64318), [@gonzolino](https://github.com/gonzolino)) +* kubeadm: Add a 'kubeadm config migrate' command to convert old API types to their newer counterparts in the new, supported API types. This is just a client-side tool, it just executes locally without requiring a cluster to be running. You can think about this as an Unix pipe that upgrades config files. ([#64232](https://github.com/kubernetes/kubernetes/pull/64232), [@luxas](https://github.com/luxas)) +* The --dry-run flag has been enabled for kubectl auth reconcile ([#64458](https://github.com/kubernetes/kubernetes/pull/64458), [@mrogers950](https://github.com/mrogers950)) +* Add probe based mechanism for kubelet plugin discovery ([#63328](https://github.com/kubernetes/kubernetes/pull/63328), [@vikaschoudhary16](https://github.com/vikaschoudhary16)) +* Add Establishing Controller on CRDs to avoid race between Established condition and CRs actually served. In HA setups, the Established condition is delayed by 5 seconds. ([#63068](https://github.com/kubernetes/kubernetes/pull/63068), [@xmudrii](https://github.com/xmudrii)) +* CoreDNS is now v1.1.3 ([#64258](https://github.com/kubernetes/kubernetes/pull/64258), [@rajansandeep](https://github.com/rajansandeep)) +* kubeadm will pull required images during preflight checks if it cannot find them on the system ([#64105](https://github.com/kubernetes/kubernetes/pull/64105), [@chuckha](https://github.com/chuckha)) +* kubeadm: rename the addon parameter `kube-dns` to `coredns` for `kubeadm alpha phases addons` as CoreDNS is now the default DNS server in 1.11. ([#64274](https://github.com/kubernetes/kubernetes/pull/64274), [@neolit123](https://github.com/neolit123)) +* kubeadm: when starting the API server use the arguments --enable-admission-plugins and --disable-admission-plugins instead of the deprecated --admission-control. ([#64165](https://github.com/kubernetes/kubernetes/pull/64165), [@neolit123](https://github.com/neolit123)) +* Add spec.additionalPrinterColumns to CRDs to define server side printing columns. ([#60991](https://github.com/kubernetes/kubernetes/pull/60991), [@sttts](https://github.com/sttts)) +* fix azure file size grow issue ([#64383](https://github.com/kubernetes/kubernetes/pull/64383), [@andyzhangx](https://github.com/andyzhangx)) +* Fix issue of colliding nodePorts when the cluster has services with externalTrafficPolicy=Local ([#64349](https://github.com/kubernetes/kubernetes/pull/64349), [@nicksardo](https://github.com/nicksardo)) +* fixes a panic applying json patches containing out of bounds operations ([#64355](https://github.com/kubernetes/kubernetes/pull/64355), [@liggitt](https://github.com/liggitt)) +* Fail fast if cgroups-per-qos is set on Windows ([#62984](https://github.com/kubernetes/kubernetes/pull/62984), [@feiskyer](https://github.com/feiskyer)) +* Move Volume expansion to Beta ([#64288](https://github.com/kubernetes/kubernetes/pull/64288), [@gnufied](https://github.com/gnufied)) +* kubectl delete does not use reapers for removing objects anymore, but relies on server-side GC entirely ([#63979](https://github.com/kubernetes/kubernetes/pull/63979), [@soltysh](https://github.com/soltysh)) +* Basic plumbing for volume topology aware dynamic provisioning ([#63232](https://github.com/kubernetes/kubernetes/pull/63232), [@lichuqiang](https://github.com/lichuqiang)) +* API server properly parses propagationPolicy as a query parameter sent with a delete request ([#63414](https://github.com/kubernetes/kubernetes/pull/63414), [@roycaihw](https://github.com/roycaihw)) +* Property `serverAddressByClientCIDRs` in `metav1.APIGroup` (discovery API) now become optional instead of required ([#61963](https://github.com/kubernetes/kubernetes/pull/61963), [@roycaihw](https://github.com/roycaihw)) +* 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)) +* Add reason message logs for non-exist Azure resources ([#64248](https://github.com/kubernetes/kubernetes/pull/64248), [@feiskyer](https://github.com/feiskyer)) +* Fix SessionAffinity not updated issue for Azure load balancer ([#64180](https://github.com/kubernetes/kubernetes/pull/64180), [@feiskyer](https://github.com/feiskyer)) +* The kube-apiserver openapi doc now includes extensions identifying APIService and CustomResourceDefinition kinds ([#64174](https://github.com/kubernetes/kubernetes/pull/64174), [@liggitt](https://github.com/liggitt)) +* apiservices/status and certificatesigningrequests/status now support GET and PATCH ([#64063](https://github.com/kubernetes/kubernetes/pull/64063), [@roycaihw](https://github.com/roycaihw)) +* kubectl: This client version requires the `apps/v1` APIs, so it will not work against a cluster version older than v1.9.0. Note that kubectl only guarantees compatibility with clusters that are +/-1 minor version away. ([#61419](https://github.com/kubernetes/kubernetes/pull/61419), [@enisoc](https://github.com/enisoc)) +* Correct the way we reset containers and pods in kubeadm via crictl ([#63862](https://github.com/kubernetes/kubernetes/pull/63862), [@runcom](https://github.com/runcom)) +* Allow env from resource with keys & updated tests ([#60636](https://github.com/kubernetes/kubernetes/pull/60636), [@PhilipGough](https://github.com/PhilipGough)) +* The kubelet certificate rotation feature can now be enabled via the `.RotateCertificates` field in the kubelet's config file. The `--rotate-certificates` flag is now deprecated, and will be removed in a future release. ([#63912](https://github.com/kubernetes/kubernetes/pull/63912), [@luxas](https://github.com/luxas)) +* Use DeleteOptions.PropagationPolicy instead of OrphanDependents in kubectl ([#59851](https://github.com/kubernetes/kubernetes/pull/59851), [@nilebox](https://github.com/nilebox)) +* add block device support for azure disk ([#63841](https://github.com/kubernetes/kubernetes/pull/63841), [@andyzhangx](https://github.com/andyzhangx)) +* Fix incorrectly propagated ResourceVersion in ListRequests returning 0 items. ([#64150](https://github.com/kubernetes/kubernetes/pull/64150), [@wojtek-t](https://github.com/wojtek-t)) +* Changes ext3/ext4 volume creation to not reserve any portion of the volume for the root user. ([#64102](https://github.com/kubernetes/kubernetes/pull/64102), [@atombender](https://github.com/atombender)) +* Add CRD Versioning with NOP converter ([#63830](https://github.com/kubernetes/kubernetes/pull/63830), [@mbohlool](https://github.com/mbohlool)) +* adds a kubectl wait command ([#64034](https://github.com/kubernetes/kubernetes/pull/64034), [@deads2k](https://github.com/deads2k)) +* "kubeadm init" now writes a structured and versioned kubelet ComponentConfiguration file to `/var/lib/kubelet/config.yaml` and an environment file with runtime flags (you can source this file in the systemd kubelet dropin) to `/var/lib/kubelet/kubeadm-flags.env`. ([#63887](https://github.com/kubernetes/kubernetes/pull/63887), [@luxas](https://github.com/luxas)) +* `kubectl auth reconcile` only works with rbac.v1 ([#63967](https://github.com/kubernetes/kubernetes/pull/63967), [@deads2k](https://github.com/deads2k)) +* The dynamic Kubelet config feature will now update config in the event of a ConfigMap mutation, which reduces the chance for silent config skew. Only name, namespace, and kubeletConfigKey may now be set in Node.Spec.ConfigSource.ConfigMap. The least disruptive pattern for config management is still to create a new ConfigMap and incrementally roll out a new Node.Spec.ConfigSource. ([#63221](https://github.com/kubernetes/kubernetes/pull/63221), [@mtaufen](https://github.com/mtaufen)) +* Graduate CRI container log rotation to beta, and enable it by default. ([#64046](https://github.com/kubernetes/kubernetes/pull/64046), [@yujuhong](https://github.com/yujuhong)) +* APIServices with kube-like versions (e.g. v1, v2beta1, etc.) will be sorted appropriately within each group. ([#64004](https://github.com/kubernetes/kubernetes/pull/64004), [@mbohlool](https://github.com/mbohlool)) +* kubectl and client-go now detects duplicated name for user, cluster and context when loading kubeconfig and reports error ([#60464](https://github.com/kubernetes/kubernetes/pull/60464), [@roycaihw](https://github.com/roycaihw)) +* event object references with apiversion will now report an apiversion. ([#63913](https://github.com/kubernetes/kubernetes/pull/63913), [@deads2k](https://github.com/deads2k)) +* Subresources for custom resources is now beta and enabled by default. With this, updates to the `/status` subresource will disallow updates to all fields other than `.status` (not just `.spec` and `.metadata` as before). Also, `required` can be used at the root of the CRD OpenAPI validation schema when the `/status` subresource is enabled. ([#63598](https://github.com/kubernetes/kubernetes/pull/63598), [@nikhita](https://github.com/nikhita)) +* increase grpc client default response size ([#63977](https://github.com/kubernetes/kubernetes/pull/63977), [@runcom](https://github.com/runcom)) +* HTTP transport now uses `context.Context` to cancel dial operations. k8s.io/client-go/transport/Config struct has been updated to accept a function with a `context.Context` parameter. This is a breaking change if you use this field in your code. ([#60012](https://github.com/kubernetes/kubernetes/pull/60012), [@ash2k](https://github.com/ash2k)) +* Adds a mechanism in vSphere Cloud Provider to get credentials from Kubernetes secrets ([#63902](https://github.com/kubernetes/kubernetes/pull/63902), [@abrarshivani](https://github.com/abrarshivani)) +* kubeadm: A `kubeadm config print-default` command has now been added that you can use as a starting point when writing your own kubeadm configuration files ([#63969](https://github.com/kubernetes/kubernetes/pull/63969), [@luxas](https://github.com/luxas)) +* Update event-exporter to version v0.2.0 that supports old (gke_container/gce_instance) and new (k8s_container/k8s_node/k8s_pod) stackdriver resources. ([#63918](https://github.com/kubernetes/kubernetes/pull/63918), [@cezarygerard](https://github.com/cezarygerard)) +* Cluster Autoscaler 1.2.2 (release notes: https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.2.2) ([#63974](https://github.com/kubernetes/kubernetes/pull/63974), [@aleksandra-malinowska](https://github.com/aleksandra-malinowska)) +* Update kubeadm's minimum supported kubernetes in v1.11.x to 1.10 ([#63920](https://github.com/kubernetes/kubernetes/pull/63920), [@dixudx](https://github.com/dixudx)) +* Add 'UpdateStrategyType' and 'RollingUpdateStrategy' to 'kubectl describe sts' command output. ([#63844](https://github.com/kubernetes/kubernetes/pull/63844), [@tossmilestone](https://github.com/tossmilestone)) +* Remove UID mutation from request.context. ([#63957](https://github.com/kubernetes/kubernetes/pull/63957), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* kubeadm has removed `.Etcd.SelfHosting` from its configuration API. It was never used in practice. ([#63871](https://github.com/kubernetes/kubernetes/pull/63871), [@luxas](https://github.com/luxas)) +* list/watch API requests with a fieldSelector that specifies `metadata.name` can now be authorized as requests for an individual named resource ([#63469](https://github.com/kubernetes/kubernetes/pull/63469), [@wojtek-t](https://github.com/wojtek-t)) +* Add a way to pass extra arguments to etcd. ([#63961](https://github.com/kubernetes/kubernetes/pull/63961), [@mborsz](https://github.com/mborsz)) +* minor fix for VolumeZoneChecker predicate, storageclass can be in annotation and spec. ([#63749](https://github.com/kubernetes/kubernetes/pull/63749), [@wenlxie](https://github.com/wenlxie)) +* vSphere Cloud Provider: add SAML token authentication support ([#63824](https://github.com/kubernetes/kubernetes/pull/63824), [@dougm](https://github.com/dougm)) +* adds the `kubeadm upgrade diff` command to show how static pod manifests will be changed by an upgrade. ([#63930](https://github.com/kubernetes/kubernetes/pull/63930), [@liztio](https://github.com/liztio)) +* Fix memory cgroup notifications, and reduce associated log spam. ([#63220](https://github.com/kubernetes/kubernetes/pull/63220), [@dashpole](https://github.com/dashpole)) +* Adds a `kubeadm config images pull` command to pull container images used by kubeadm. ([#63833](https://github.com/kubernetes/kubernetes/pull/63833), [@chuckha](https://github.com/chuckha)) +* Restores the pre-1.10 behavior of the openstack cloud provider which uses the instance name as the Kubernetes Node name. This requires instances be named with RFC-1123 compatible names. ([#63903](https://github.com/kubernetes/kubernetes/pull/63903), [@liggitt](https://github.com/liggitt)) +* Added support for NFS relations on kubernetes-worker charm. ([#63817](https://github.com/kubernetes/kubernetes/pull/63817), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* Stop using InfluxDB as default cluster monitoring ([#62328](https://github.com/kubernetes/kubernetes/pull/62328), [@serathius](https://github.com/serathius)) + * InfluxDB cluster monitoring is deprecated and will be removed in v1.12 +* GCE: Fix to make the built-in `kubernetes` service properly point to the master's load balancer address in clusters that use multiple master VMs. ([#63696](https://github.com/kubernetes/kubernetes/pull/63696), [@grosskur](https://github.com/grosskur)) +* Kubernetes cluster on GCE have crictl installed now. Users can use it to help debug their node. The documentation of crictl can be found https://github.com/kubernetes-incubator/cri-tools/blob/master/docs/crictl.md. ([#63357](https://github.com/kubernetes/kubernetes/pull/63357), [@Random-Liu](https://github.com/Random-Liu)) +* The NodeRestriction admission plugin now prevents kubelets from modifying/removing taints applied to their Node API object. ([#63167](https://github.com/kubernetes/kubernetes/pull/63167), [@liggitt](https://github.com/liggitt)) +* The status of dynamic Kubelet config is now reported via Node.Status.Config, rather than the KubeletConfigOk node condition. ([#63314](https://github.com/kubernetes/kubernetes/pull/63314), [@mtaufen](https://github.com/mtaufen)) +* kubeadm now checks that IPv4/IPv6 forwarding is enabled ([#63872](https://github.com/kubernetes/kubernetes/pull/63872), [@kad](https://github.com/kad)) +* kubeadm will now deploy CoreDNS by default instead of KubeDNS ([#63509](https://github.com/kubernetes/kubernetes/pull/63509), [@detiber](https://github.com/detiber)) +* This PR will leverage subtests on the existing table tests for the scheduler units. ([#63658](https://github.com/kubernetes/kubernetes/pull/63658), [@xchapter7x](https://github.com/xchapter7x)) + * Some refactoring of error/status messages and functions to align with new approach. +* kubeadm upgrade now supports external etcd setups again ([#63495](https://github.com/kubernetes/kubernetes/pull/63495), [@detiber](https://github.com/detiber)) +* fix mount unmount failure for a Windows pod ([#63272](https://github.com/kubernetes/kubernetes/pull/63272), [@andyzhangx](https://github.com/andyzhangx)) +* CRI: update documents for container logpath. The container log path has been changed from containername_attempt#.log to containername/attempt#.log ([#62015](https://github.com/kubernetes/kubernetes/pull/62015), [@feiskyer](https://github.com/feiskyer)) +* Create a new `dryRun` query parameter for mutating endpoints. If the parameter is set, then the query will be rejected, as the feature is not implemented yet. This will allow forward compatibility with future clients; otherwise, future clients talking with older apiservers might end up modifying a resource even if they include the `dryRun` query parameter. ([#63557](https://github.com/kubernetes/kubernetes/pull/63557), [@apelisse](https://github.com/apelisse)) +* kubelet: fix hangs in updating Node status after network interruptions/changes between the kubelet and API server ([#63492](https://github.com/kubernetes/kubernetes/pull/63492), [@liggitt](https://github.com/liggitt)) +* The `PriorityClass` API is promoted to `scheduling.k8s.io/v1beta1` ([#63100](https://github.com/kubernetes/kubernetes/pull/63100), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* Services can listen on same host ports on different interfaces with --nodeport-addresses specified ([#62003](https://github.com/kubernetes/kubernetes/pull/62003), [@m1093782566](https://github.com/m1093782566)) +* kubeadm will no longer generate an unused etcd CA and certificates when configured to use an external etcd cluster. ([#63806](https://github.com/kubernetes/kubernetes/pull/63806), [@detiber](https://github.com/detiber)) +* corrects a race condition in bootstrapping aggregated cluster roles in new HA clusters ([#63761](https://github.com/kubernetes/kubernetes/pull/63761), [@liggitt](https://github.com/liggitt)) +* Adding initial Korean translation for kubectl ([#62040](https://github.com/kubernetes/kubernetes/pull/62040), [@ianychoi](https://github.com/ianychoi)) +* Report node DNS info with --node-ip flag ([#63170](https://github.com/kubernetes/kubernetes/pull/63170), [@micahhausler](https://github.com/micahhausler)) +* The old dynamic client has been replaced by a new one. The previous dynamic client will exist for one release in `client-go/deprecated-dynamic`. Switch as soon as possible. ([#63446](https://github.com/kubernetes/kubernetes/pull/63446), [@deads2k](https://github.com/deads2k)) +* CustomResourceDefinitions Status subresource now supports GET and PATCH ([#63619](https://github.com/kubernetes/kubernetes/pull/63619), [@roycaihw](https://github.com/roycaihw)) +* Re-enable nodeipam controller for external clouds. ([#63049](https://github.com/kubernetes/kubernetes/pull/63049), [@andrewsykim](https://github.com/andrewsykim)) +* Removes a preflight check for kubeadm that validated custom kube-apiserver, kube-controller-manager and kube-scheduler arguments. ([#63673](https://github.com/kubernetes/kubernetes/pull/63673), [@chuckha](https://github.com/chuckha)) +* Adds a list-images subcommand to kubeadm that lists required images for a kubeadm install. ([#63450](https://github.com/kubernetes/kubernetes/pull/63450), [@chuckha](https://github.com/chuckha)) +* Apply pod name and namespace labels to pod cgroup in cAdvisor metrics ([#63406](https://github.com/kubernetes/kubernetes/pull/63406), [@derekwaynecarr](https://github.com/derekwaynecarr)) +* try to read openstack auth config from client config and fall back to read from the environment variables if not available ([#60200](https://github.com/kubernetes/kubernetes/pull/60200), [@dixudx](https://github.com/dixudx)) +* GC is now bound by QPS (it wasn't before) and so if you need more QPS to avoid ratelimiting GC, you'll have to set it. ([#63657](https://github.com/kubernetes/kubernetes/pull/63657), [@shyamjvs](https://github.com/shyamjvs)) +* The Kubelet's deprecated --allow-privileged flag now defaults to true. This enables users to stop setting --allow-privileged in order to transition to PodSecurityPolicy. Previously, users had to continue setting --allow-privileged, because the default was false. ([#63442](https://github.com/kubernetes/kubernetes/pull/63442), [@mtaufen](https://github.com/mtaufen)) +* You must now specify Node.Spec.ConfigSource.ConfigMap.KubeletConfigKey when using dynamic Kubelet config to tell the Kubelet which key of the ConfigMap identifies its config file. ([#59847](https://github.com/kubernetes/kubernetes/pull/59847), [@mtaufen](https://github.com/mtaufen)) +* Kubernetes version command line parameter in kubeadm has been updated to drop an unnecessary redirection from ci/latest.txt to ci-cross/latest.txt. Users should know exactly where the builds are stored on Google Cloud storage buckets from now on. For example for 1.9 and 1.10, users can specify ci/latest-1.9 and ci/latest-1.10 as the CI build jobs what build images correctly updates those. The CI jobs for master update the ci-cross/latest location, so if you are looking for latest master builds, then the correct parameter to use would be ci-cross/latest. ([#63504](https://github.com/kubernetes/kubernetes/pull/63504), [@dims](https://github.com/dims)) +* Search standard KubeConfig file locations when using `kubeadm token` without `--kubeconfig`. ([#62850](https://github.com/kubernetes/kubernetes/pull/62850), [@neolit123](https://github.com/neolit123)) +* Include the list of security groups when failing with the errors that more then one is tagged ([#58874](https://github.com/kubernetes/kubernetes/pull/58874), [@sorenmat](https://github.com/sorenmat)) +* Allow "required" to be used at the CRD OpenAPI validation schema when the /status subresource is enabled. ([#63533](https://github.com/kubernetes/kubernetes/pull/63533), [@sttts](https://github.com/sttts)) +* When updating /status subresource of a custom resource, only the value at the `.status` subpath for the update is considered. ([#63385](https://github.com/kubernetes/kubernetes/pull/63385), [@CaoShuFeng](https://github.com/CaoShuFeng)) +* Supported nodeSelector.matchFields (node's `metadata.node`) in scheduler. ([#62453](https://github.com/kubernetes/kubernetes/pull/62453), [@k82cn](https://github.com/k82cn)) +* Do not check vmSetName when getting Azure node's IP ([#63541](https://github.com/kubernetes/kubernetes/pull/63541), [@feiskyer](https://github.com/feiskyer)) +* Fix stackdriver metrics for node memory using wrong metric type ([#63535](https://github.com/kubernetes/kubernetes/pull/63535), [@serathius](https://github.com/serathius)) +* [fluentd-gcp addon] Use the logging agent's node name as the metadata agent URL. ([#63353](https://github.com/kubernetes/kubernetes/pull/63353), [@bmoyles0117](https://github.com/bmoyles0117)) +* `kubectl cp` supports completion. ([#60371](https://github.com/kubernetes/kubernetes/pull/60371), [@superbrothers](https://github.com/superbrothers)) +* Azure VMSS: support VM names to contain the `_` character ([#63526](https://github.com/kubernetes/kubernetes/pull/63526), [@djsly](https://github.com/djsly)) +* OpenStack built-in cloud provider is now deprecated. Please use the external cloud provider for OpenStack. ([#63524](https://github.com/kubernetes/kubernetes/pull/63524), [@dims](https://github.com/dims)) +* the shortcuts which were moved server-side in at least 1.9 have been removed from being hardcoded in kubectl ([#63507](https://github.com/kubernetes/kubernetes/pull/63507), [@deads2k](https://github.com/deads2k)) +* Fixes fake client generation for non-namespaced subresources ([#60445](https://github.com/kubernetes/kubernetes/pull/60445), [@jhorwit2](https://github.com/jhorwit2)) +* `kubectl delete` with selection criteria defaults to ignoring not found errors ([#63490](https://github.com/kubernetes/kubernetes/pull/63490), [@deads2k](https://github.com/deads2k)) +* Increase scheduler cache generation number monotonically in order to avoid collision and use of stale information in scheduler. ([#63264](https://github.com/kubernetes/kubernetes/pull/63264), [@bsalamat](https://github.com/bsalamat)) +* Fixes issue where subpath readOnly mounts failed ([#63045](https://github.com/kubernetes/kubernetes/pull/63045), [@msau42](https://github.com/msau42)) +* Update to use go1.10.2 ([#63412](https://github.com/kubernetes/kubernetes/pull/63412), [@praseodym](https://github.com/praseodym)) +* `kubectl create [secret | configmap] --from-file` now works on Windows with fully-qualified paths ([#63439](https://github.com/kubernetes/kubernetes/pull/63439), [@liggitt](https://github.com/liggitt)) +* kube-apiserver: the default `--endpoint-reconciler-type` is now `lease`. The `master-count` endpoint reconciler type is deprecated and will be removed in 1.13. ([#63383](https://github.com/kubernetes/kubernetes/pull/63383), [@liggitt](https://github.com/liggitt)) +* owner references can be set during creation without deletion power ([#63403](https://github.com/kubernetes/kubernetes/pull/63403), [@deads2k](https://github.com/deads2k)) +* Lays groundwork for OIDC distributed claims handling in the apiserver authentication token checker. ([#63213](https://github.com/kubernetes/kubernetes/pull/63213), [@filmil](https://github.com/filmil)) + * A distributed claim allows the OIDC provider to delegate a claim to a + * separate URL. Distributed claims are of the form as seen below, and are + * defined in the OIDC Connect Core 1.0, section 5.6.2. + * For details, see: + * http://openid.net/specs/openid-connect-core-1_0.html#AggregatedDistributedClaims +* Use /usr/bin/env in all script shebangs to increase portability. ([#62657](https://github.com/kubernetes/kubernetes/pull/62657), [@matthyx](https://github.com/matthyx)) + + + # v1.11.0-alpha.2 [Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/master/examples) diff --git a/CHANGELOG-1.8.md b/CHANGELOG-1.8.md index bf1ae69e404..c8e2e512165 100644 --- a/CHANGELOG-1.8.md +++ b/CHANGELOG-1.8.md @@ -1,102 +1,109 @@ -- [v1.8.13](#v1813) - - [Downloads for v1.8.13](#downloads-for-v1813) +- [v1.8.14](#v1814) + - [Downloads for v1.8.14](#downloads-for-v1814) - [Client Binaries](#client-binaries) - [Server Binaries](#server-binaries) - [Node Binaries](#node-binaries) - - [Changelog since v1.8.12](#changelog-since-v1812) + - [Changelog since v1.8.13](#changelog-since-v1813) - [Other notable changes](#other-notable-changes) -- [v1.8.12](#v1812) - - [Downloads for v1.8.12](#downloads-for-v1812) +- [v1.8.13](#v1813) + - [Downloads for v1.8.13](#downloads-for-v1813) - [Client Binaries](#client-binaries-1) - [Server Binaries](#server-binaries-1) - [Node Binaries](#node-binaries-1) - - [Changelog since v1.8.11](#changelog-since-v1811) + - [Changelog since v1.8.12](#changelog-since-v1812) - [Other notable changes](#other-notable-changes-1) -- [v1.8.11](#v1811) - - [Downloads for v1.8.11](#downloads-for-v1811) +- [v1.8.12](#v1812) + - [Downloads for v1.8.12](#downloads-for-v1812) - [Client Binaries](#client-binaries-2) - [Server Binaries](#server-binaries-2) - [Node Binaries](#node-binaries-2) - - [Changelog since v1.8.10](#changelog-since-v1810) - - [Action Required](#action-required) + - [Changelog since v1.8.11](#changelog-since-v1811) - [Other notable changes](#other-notable-changes-2) -- [v1.8.10](#v1810) - - [Downloads for v1.8.10](#downloads-for-v1810) +- [v1.8.11](#v1811) + - [Downloads for v1.8.11](#downloads-for-v1811) - [Client Binaries](#client-binaries-3) - [Server Binaries](#server-binaries-3) - [Node Binaries](#node-binaries-3) - - [Changelog since v1.8.9](#changelog-since-v189) + - [Changelog since v1.8.10](#changelog-since-v1810) + - [Action Required](#action-required) - [Other notable changes](#other-notable-changes-3) -- [v1.8.9](#v189) - - [Downloads for v1.8.9](#downloads-for-v189) +- [v1.8.10](#v1810) + - [Downloads for v1.8.10](#downloads-for-v1810) - [Client Binaries](#client-binaries-4) - [Server Binaries](#server-binaries-4) - [Node Binaries](#node-binaries-4) - - [Changelog since v1.8.8](#changelog-since-v188) + - [Changelog since v1.8.9](#changelog-since-v189) - [Other notable changes](#other-notable-changes-4) -- [v1.8.8](#v188) - - [Downloads for v1.8.8](#downloads-for-v188) +- [v1.8.9](#v189) + - [Downloads for v1.8.9](#downloads-for-v189) - [Client Binaries](#client-binaries-5) - [Server Binaries](#server-binaries-5) - [Node Binaries](#node-binaries-5) - - [Changelog since v1.8.7](#changelog-since-v187) + - [Changelog since v1.8.8](#changelog-since-v188) - [Other notable changes](#other-notable-changes-5) -- [v1.8.7](#v187) - - [Downloads for v1.8.7](#downloads-for-v187) +- [v1.8.8](#v188) + - [Downloads for v1.8.8](#downloads-for-v188) - [Client Binaries](#client-binaries-6) - [Server Binaries](#server-binaries-6) - [Node Binaries](#node-binaries-6) - - [Changelog since v1.8.6](#changelog-since-v186) + - [Changelog since v1.8.7](#changelog-since-v187) - [Other notable changes](#other-notable-changes-6) -- [v1.8.6](#v186) - - [Downloads for v1.8.6](#downloads-for-v186) +- [v1.8.7](#v187) + - [Downloads for v1.8.7](#downloads-for-v187) - [Client Binaries](#client-binaries-7) - [Server Binaries](#server-binaries-7) - [Node Binaries](#node-binaries-7) - - [Changelog since v1.8.5](#changelog-since-v185) + - [Changelog since v1.8.6](#changelog-since-v186) - [Other notable changes](#other-notable-changes-7) -- [v1.8.5](#v185) - - [Downloads for v1.8.5](#downloads-for-v185) +- [v1.8.6](#v186) + - [Downloads for v1.8.6](#downloads-for-v186) - [Client Binaries](#client-binaries-8) - [Server Binaries](#server-binaries-8) - [Node Binaries](#node-binaries-8) - - [Changelog since v1.8.4](#changelog-since-v184) + - [Changelog since v1.8.5](#changelog-since-v185) - [Other notable changes](#other-notable-changes-8) -- [v1.8.4](#v184) - - [Downloads for v1.8.4](#downloads-for-v184) +- [v1.8.5](#v185) + - [Downloads for v1.8.5](#downloads-for-v185) - [Client Binaries](#client-binaries-9) - [Server Binaries](#server-binaries-9) - [Node Binaries](#node-binaries-9) - - [Changelog since v1.8.3](#changelog-since-v183) + - [Changelog since v1.8.4](#changelog-since-v184) - [Other notable changes](#other-notable-changes-9) -- [v1.8.3](#v183) - - [Downloads for v1.8.3](#downloads-for-v183) +- [v1.8.4](#v184) + - [Downloads for v1.8.4](#downloads-for-v184) - [Client Binaries](#client-binaries-10) - [Server Binaries](#server-binaries-10) - [Node Binaries](#node-binaries-10) - - [Changelog since v1.8.2](#changelog-since-v182) + - [Changelog since v1.8.3](#changelog-since-v183) - [Other notable changes](#other-notable-changes-10) -- [v1.8.2](#v182) - - [Downloads for v1.8.2](#downloads-for-v182) +- [v1.8.3](#v183) + - [Downloads for v1.8.3](#downloads-for-v183) - [Client Binaries](#client-binaries-11) - [Server Binaries](#server-binaries-11) - [Node Binaries](#node-binaries-11) - - [Changelog since v1.8.1](#changelog-since-v181) + - [Changelog since v1.8.2](#changelog-since-v182) - [Other notable changes](#other-notable-changes-11) -- [v1.8.1](#v181) - - [Downloads for v1.8.1](#downloads-for-v181) +- [v1.8.2](#v182) + - [Downloads for v1.8.2](#downloads-for-v182) - [Client Binaries](#client-binaries-12) - [Server Binaries](#server-binaries-12) - [Node Binaries](#node-binaries-12) - - [Changelog since v1.8.0](#changelog-since-v180) - - [Action Required](#action-required-1) + - [Changelog since v1.8.1](#changelog-since-v181) - [Other notable changes](#other-notable-changes-12) -- [v1.8.0](#v180) - - [Downloads for v1.8.0](#downloads-for-v180) +- [v1.8.1](#v181) + - [Downloads for v1.8.1](#downloads-for-v181) - [Client Binaries](#client-binaries-13) - [Server Binaries](#server-binaries-13) - [Node Binaries](#node-binaries-13) + - [Changelog since v1.8.0](#changelog-since-v180) + - [Action Required](#action-required-1) + - [Other notable changes](#other-notable-changes-13) +- [v1.8.0](#v180) + - [Downloads for v1.8.0](#downloads-for-v180) + - [Client Binaries](#client-binaries-14) + - [Server Binaries](#server-binaries-14) + - [Node Binaries](#node-binaries-14) - [Introduction to v1.8.0](#introduction-to-v180) - [Major Themes](#major-themes) - [SIG API Machinery](#sig-api-machinery) @@ -157,49 +164,110 @@ - [External Dependencies](#external-dependencies) - [v1.8.0-rc.1](#v180-rc1) - [Downloads for v1.8.0-rc.1](#downloads-for-v180-rc1) - - [Client Binaries](#client-binaries-14) - - [Server Binaries](#server-binaries-14) - - [Node Binaries](#node-binaries-14) - - [Changelog since v1.8.0-beta.1](#changelog-since-v180-beta1) - - [Action Required](#action-required-2) - - [Other notable changes](#other-notable-changes-13) -- [v1.8.0-beta.1](#v180-beta1) - - [Downloads for v1.8.0-beta.1](#downloads-for-v180-beta1) - [Client Binaries](#client-binaries-15) - [Server Binaries](#server-binaries-15) - [Node Binaries](#node-binaries-15) - - [Changelog since v1.8.0-alpha.3](#changelog-since-v180-alpha3) - - [Action Required](#action-required-3) + - [Changelog since v1.8.0-beta.1](#changelog-since-v180-beta1) + - [Action Required](#action-required-2) - [Other notable changes](#other-notable-changes-14) -- [v1.8.0-alpha.3](#v180-alpha3) - - [Downloads for v1.8.0-alpha.3](#downloads-for-v180-alpha3) +- [v1.8.0-beta.1](#v180-beta1) + - [Downloads for v1.8.0-beta.1](#downloads-for-v180-beta1) - [Client Binaries](#client-binaries-16) - [Server Binaries](#server-binaries-16) - [Node Binaries](#node-binaries-16) - - [Changelog since v1.8.0-alpha.2](#changelog-since-v180-alpha2) - - [Action Required](#action-required-4) + - [Changelog since v1.8.0-alpha.3](#changelog-since-v180-alpha3) + - [Action Required](#action-required-3) - [Other notable changes](#other-notable-changes-15) -- [v1.8.0-alpha.2](#v180-alpha2) - - [Downloads for v1.8.0-alpha.2](#downloads-for-v180-alpha2) +- [v1.8.0-alpha.3](#v180-alpha3) + - [Downloads for v1.8.0-alpha.3](#downloads-for-v180-alpha3) - [Client Binaries](#client-binaries-17) - [Server Binaries](#server-binaries-17) - [Node Binaries](#node-binaries-17) - - [Changelog since v1.7.0](#changelog-since-v170) - - [Action Required](#action-required-5) + - [Changelog since v1.8.0-alpha.2](#changelog-since-v180-alpha2) + - [Action Required](#action-required-4) - [Other notable changes](#other-notable-changes-16) -- [v1.8.0-alpha.1](#v180-alpha1) - - [Downloads for v1.8.0-alpha.1](#downloads-for-v180-alpha1) +- [v1.8.0-alpha.2](#v180-alpha2) + - [Downloads for v1.8.0-alpha.2](#downloads-for-v180-alpha2) - [Client Binaries](#client-binaries-18) - [Server Binaries](#server-binaries-18) - [Node Binaries](#node-binaries-18) + - [Changelog since v1.7.0](#changelog-since-v170) + - [Action Required](#action-required-5) + - [Other notable changes](#other-notable-changes-17) +- [v1.8.0-alpha.1](#v180-alpha1) + - [Downloads for v1.8.0-alpha.1](#downloads-for-v180-alpha1) + - [Client Binaries](#client-binaries-19) + - [Server Binaries](#server-binaries-19) + - [Node Binaries](#node-binaries-19) - [Changelog since v1.7.0-alpha.4](#changelog-since-v170-alpha4) - [Action Required](#action-required-6) - - [Other notable changes](#other-notable-changes-17) + - [Other notable changes](#other-notable-changes-18) +# v1.8.14 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.8/examples) + +## Downloads for v1.8.14 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes.tar.gz) | `d2013bbc635031c1f388b53a32164447f196bf34f91f3f72f52e400eea548fd8` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-src.tar.gz) | `ed46ded775aea6f9a588cb2ff9ae589d36cca16900a6296a9d99f208fe4a34dc` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-client-darwin-386.tar.gz) | `5137f01bb56b7a46ec6aacfdd90bbb65784c97feb32efb69334c0d7d5a7ffe85` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-client-darwin-amd64.tar.gz) | `1752603560668b060b8ed277a8edb2879e844414e19708ee35ab03e87ffff50e` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-client-linux-386.tar.gz) | `0ed204cbb6735407ec0eb8cd3fe99f1443550bc4c00bb6313a00851cc387a616` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-client-linux-amd64.tar.gz) | `66da3e182d7289e3147dbc25bc61a2ec92bb5fa5c13fa0972446639523a9a02f` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-client-linux-arm.tar.gz) | `93541062a6e04b06f177793d1e875eb8f4ccd9f1c0e69025abf75efe3d6da0a2` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-client-linux-arm64.tar.gz) | `ea38a7ad0152858aa9326cf2248fe33cb1f38c42e1c28428b7d91eb8cdff1a03` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-client-linux-ppc64le.tar.gz) | `da651a6d058c3b4a65d145eb4ed57afb227774784ff262bb220132c5e1a9caf2` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-client-linux-s390x.tar.gz) | `98b3bb4297c81fe268144d461cc97e6c18c5ad8cc7b93197050be92e7b92e906` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-client-windows-386.tar.gz) | `5f96970061ad3b8086d27c52ec32d48e0086f780a341d9ed66ec8712ded80df5` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-client-windows-amd64.tar.gz) | `49cab034eb39c827c6fa4e299d1687edb3f3956b035850887be6e040fde21c50` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-server-linux-amd64.tar.gz) | `0ef5b508f57d575eee0fb47c6c0aca68a7da43dd50086c23082da778e2893c41` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-server-linux-arm.tar.gz) | `8d6c1831181ba1f53e62eeb61ba136b28e240ddc3d51c4f15539a624247053f2` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-server-linux-arm64.tar.gz) | `00ae57855ffafcd069514d284f9c9076fb79ed63fe9be7104fa134b51ed15c36` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-server-linux-ppc64le.tar.gz) | `774a9eb65abd8f483a8417ca79d1339783c1cb1d0e8fe2b2821ddd24ab670ec9` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-server-linux-s390x.tar.gz) | `3e0805494c234544a086465dac6d868551876e2a3175c17e46e85e6d141165d5` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-node-linux-amd64.tar.gz) | `495bc4ec731ca959951b7e9a9cff92eabc2cc83055f4efe8d25f2159aefdf867` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-node-linux-arm.tar.gz) | `b08d12bc9d66c3d4fab0cbe24fb7478910293c09b731f0a6d48631065633347e` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-node-linux-arm64.tar.gz) | `50a2c150c8a0622aadffb40f4330f844d633d440187814181858b937fb0a18c7` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-node-linux-ppc64le.tar.gz) | `2936000403e4eb07d6188aa1a1b65f60b99771c8b463174e5e3db907a923f625` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-node-linux-s390x.tar.gz) | `3bd2d3b518304b0f68150ef05ecae6da8c1819f58ab15f42ce6eab1d3f6b781b` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.8.14/kubernetes-node-windows-amd64.tar.gz) | `046341bc2f68f5d47dde21d7eb195bcdca9a973593a157677e8d46cd4c3ca530` + +## Changelog since v1.8.13 + +### Other notable changes + +* Bump version of prometheus-to-sd to 0.2.6 to decrease log noise and include latest security patches. ([#64963](https://github.com/kubernetes/kubernetes/pull/64963), [@loburm](https://github.com/loburm)) +* Fixes issue for readOnly subpath mounts for SELinux systems and when the volume mountPath already existed in the container image. ([#64351](https://github.com/kubernetes/kubernetes/pull/64351), [@msau42](https://github.com/msau42)) +* Fix issue of colliding nodePorts when the cluster has services with externalTrafficPolicy=Local ([#64468](https://github.com/kubernetes/kubernetes/pull/64468), [@nicksardo](https://github.com/nicksardo)) +* GCE: Fix to make the built-in `kubernetes` service properly point to the master's load balancer address in clusters that use multiple master VMs. ([#63696](https://github.com/kubernetes/kubernetes/pull/63696), [@grosskur](https://github.com/grosskur)) +* Add a way to pass extra arguments to etcd. ([#63961](https://github.com/kubernetes/kubernetes/pull/63961), [@mborsz](https://github.com/mborsz)) +* kubelet: fix hangs in updating Node status after network interruptions/changes between the kubelet and API server ([#63492](https://github.com/kubernetes/kubernetes/pull/63492), [@liggitt](https://github.com/liggitt)) + + + # v1.8.13 [Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.8/examples) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index ca14a53b477..693bb939a1a 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -114,8 +114,8 @@ }, { "ImportPath": "github.com/Microsoft/hcsshim", - "Comment": "V0.6.3", - "Rev": "6ea7fe54f719d95721e7d9b26ac0add224c9b923" + "Comment": "v0.6.11", + "Rev": "800683ae704ac360b2f3f47fa88f3a6c8c9091b5" }, { "ImportPath": "github.com/NYTimes/gziphandler", @@ -490,8 +490,8 @@ }, { "ImportPath": "github.com/container-storage-interface/spec/lib/go/csi/v0", - "Comment": "v0.2.0", - "Rev": "35d9f9d77954980e449e52c3f3e43c21bd8171f5" + "Comment": "v0.3.0", + "Rev": "2178fdeea87f1150a17a63252eee28d4d8141f72" }, { "ImportPath": "github.com/containerd/console", @@ -499,48 +499,48 @@ }, { "ImportPath": "github.com/containerd/containerd/api/services/containers/v1", - "Comment": "v1.0.0-beta.2-159-g27d450a", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/api/services/tasks/v1", - "Comment": "v1.0.0-beta.2-159-g27d450a", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/api/services/version/v1", - "Comment": "v1.0.0-beta.2-159-g27d450a", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/api/types", - "Comment": "v1.0.0-beta.2-159-g27d450a", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/api/types/task", - "Comment": "v1.0.0-beta.2-159-g27d450a", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/containers", - "Comment": "v1.0.0-beta.2-159-g27d450a", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/dialer", - "Comment": "v1.0.0-beta.2-159-g27d450a", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/errdefs", - "Comment": "v1.0.0-beta.2-159-g27d450a", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/namespaces", - "Comment": "v1.0.0-beta.2-159-g27d450a", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containernetworking/cni/libcni", @@ -1019,157 +1019,162 @@ }, { "ImportPath": "github.com/docker/distribution/digestset", - "Comment": "v2.6.0-rc.1-209-gedc3ab2", + "Comment": "v2.6.0-rc.1-209-gedc3ab29", "Rev": "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c" }, { "ImportPath": "github.com/docker/distribution/reference", - "Comment": "v2.6.0-rc.1-209-gedc3ab2", + "Comment": "v2.6.0-rc.1-209-gedc3ab29", "Rev": "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c" }, { "ImportPath": "github.com/docker/docker/api", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/blkiodev", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/container", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/events", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/filters", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/image", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/mount", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/network", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/registry", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/strslice", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/swarm", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/swarm/runtime", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/time", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/versions", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/volume", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/client", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/ioutils", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/jsonlog", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/jsonmessage", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/longpath", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/mount", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/parsers", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" + }, + { + "ImportPath": "github.com/docker/docker/pkg/parsers/operatingsystem", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/stdcopy", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/sysinfo", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/system", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/term", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/term/windows", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/tlsconfig", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { @@ -1194,7 +1199,7 @@ }, { "ImportPath": "github.com/docker/libnetwork/ipvs", - "Comment": "v0.8.0-dev.2-910-gba46b92", + "Comment": "v0.8.0-dev.2-910-gba46b928", "Rev": "ba46b928444931e6865d8618dc03622cac79aa6f" }, { @@ -1240,6 +1245,7 @@ }, { "ImportPath": "github.com/evanphx/json-patch", + "Comment": "v3.0.0-23-g94e38aa", "Rev": "94e38aa1586e8a6c8a75770bddf5ff84c48a106b" }, { @@ -1311,132 +1317,132 @@ }, { "ImportPath": "github.com/gogo/protobuf/gogoproto", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/compare", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/defaultcheck", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/description", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/embedcheck", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/enumstringer", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/equal", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/face", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/gostring", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/marshalto", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/oneofcheck", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/populate", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/size", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/stringer", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/testgen", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/union", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/unmarshal", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/proto", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/descriptor", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/generator", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/grpc", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/plugin", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/sortkeys", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/types", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/vanity", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/vanity/command", - "Comment": "v0.4-3-gc0656ed", + "Comment": "v0.4-3-gc0656edd", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { @@ -1453,39 +1459,48 @@ }, { "ImportPath": "github.com/golang/protobuf/jsonpb", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/protoc-gen-go/descriptor", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" - }, - { - "ImportPath": "github.com/golang/protobuf/ptypes/empty", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/struct", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/golang/protobuf/ptypes/wrappers", + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -1493,249 +1508,257 @@ }, { "ImportPath": "github.com/google/cadvisor/accelerators", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/api", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/cache/memory", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/client/v2", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/collector", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/container", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/container/common", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/container/containerd", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/container/crio", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/container/docker", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/container/libcontainer", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/container/raw", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/container/rkt", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/container/systemd", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/devicemapper", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/events", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/fs", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/healthz", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/http", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/http/mux", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/info/v1", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/info/v2", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/machine", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/manager", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/manager/watcher", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/manager/watcher/raw", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/manager/watcher/rkt", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/metrics", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/pages", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/pages/static", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/storage", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/summary", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/utils", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/utils/cloudinfo", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/utils/cpuload", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/utils/cpuload/netlink", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/utils/docker", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/utils/oomparser", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/utils/sysfs", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/utils/sysinfo", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/validate", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/version", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/cadvisor/zfs", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.1", + "Rev": "49c4fae21f151168b09758b7da1968fed8cd56a0" }, { "ImportPath": "github.com/google/certificate-transparency-go", + "Comment": "v1.0.10", "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { "ImportPath": "github.com/google/certificate-transparency-go/asn1", + "Comment": "v1.0.10", "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { "ImportPath": "github.com/google/certificate-transparency-go/client", + "Comment": "v1.0.10", "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { "ImportPath": "github.com/google/certificate-transparency-go/client/configpb", + "Comment": "v1.0.10", "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { "ImportPath": "github.com/google/certificate-transparency-go/jsonclient", + "Comment": "v1.0.10", "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { "ImportPath": "github.com/google/certificate-transparency-go/tls", + "Comment": "v1.0.10", "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { "ImportPath": "github.com/google/certificate-transparency-go/x509", + "Comment": "v1.0.10", "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { "ImportPath": "github.com/google/certificate-transparency-go/x509/pkix", + "Comment": "v1.0.10", "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { @@ -2006,8 +2029,8 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Comment": "1.1.3-16-g2ddf6d7", - "Rev": "2ddf6d758266fcb080a4f9e054b9f292c85e6798" + "Comment": "1.1.3-22-gf2b4162", + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/jteeuwen/go-bindata", @@ -2095,6 +2118,11 @@ "Comment": "v1.1.0-2-g8bdf7d1", "Rev": "8bdf7d1a087ccc975cf37dd6507da50698fd19ca" }, + { + "ImportPath": "github.com/mattn/go-shellwords", + "Comment": "v1.0.3-20-gf8471b0", + "Rev": "f8471b0a71ded0ab910825ee2cf230f25de000f1" + }, { "ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil", "Rev": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a" @@ -3083,47 +3111,47 @@ }, { "ImportPath": "google.golang.org/api/compute/v0.alpha", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/compute/v0.beta", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/compute/v1", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/container/v1", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/gensupport", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/googleapi", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/googleapi/internal/uritemplates", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/logging/v2beta1", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/monitoring/v3", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/pubsub/v1", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { - "ImportPath": "google.golang.org/api/tpu/v1alpha1", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "ImportPath": "google.golang.org/api/tpu/v1", + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/genproto/googleapis/api/annotations", @@ -3158,11 +3186,6 @@ "Comment": "v1.7.5", "Rev": "5b3c4e850e90a4cf6a20ebd46c8b32a0a3afcb9e" }, - { - "ImportPath": "google.golang.org/grpc/grpclb/grpc_lb_v1", - "Comment": "v1.7.5", - "Rev": "5b3c4e850e90a4cf6a20ebd46c8b32a0a3afcb9e" - }, { "ImportPath": "google.golang.org/grpc/grpclb/grpc_lb_v1/messages", "Comment": "v1.7.5", @@ -3334,35 +3357,39 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/aggregator", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/generators", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" + }, + { + "ImportPath": "k8s.io/kube-openapi/pkg/util/proto/testing", + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto/validation", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/utils/clock", diff --git a/Godeps/LICENSES b/Godeps/LICENSES index c2cb197bc23..99dccec64ac 100644 --- a/Godeps/LICENSES +++ b/Godeps/LICENSES @@ -40289,6 +40289,205 @@ Apache License ================================================================================ +================================================================================ += vendor/github.com/docker/docker/pkg/parsers/operatingsystem licensed under: = + + + Apache License + Version 2.0, January 2004 + https://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 + + Copyright 2013-2017 Docker, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + 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, + WITHOUT 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/docker/docker/LICENSE 9740d093a080530b5c5c6573df9af45a +================================================================================ + + ================================================================================ = vendor/github.com/docker/docker/pkg/stdcopy licensed under: = @@ -47950,45 +48149,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -================================================================================ -= vendor/github.com/golang/protobuf/ptypes/empty licensed under: = - -Go support for Protocol Buffers - Google's data interchange format - -Copyright 2010 The Go Authors. All rights reserved. -https://github.com/golang/protobuf - -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/golang/protobuf/LICENSE 14db3a56c3796a940ba32948a15f97d0 -================================================================================ - - ================================================================================ = vendor/github.com/golang/protobuf/ptypes/struct licensed under: = @@ -48067,6 +48227,45 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ +================================================================================ += vendor/github.com/golang/protobuf/ptypes/wrappers licensed under: = + +Go support for Protocol Buffers - Google's data interchange format + +Copyright 2010 The Go Authors. All rights reserved. +https://github.com/golang/protobuf + +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/golang/protobuf/LICENSE 14db3a56c3796a940ba32948a15f97d0 +================================================================================ + + ================================================================================ = vendor/github.com/google/btree licensed under: = @@ -72257,6 +72456,35 @@ SOFTWARE. ================================================================================ +================================================================================ += vendor/github.com/mattn/go-shellwords licensed under: = + +The MIT License (MIT) + +Copyright (c) 2017 Yasuhiro Matsumoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + += vendor/github.com/mattn/go-shellwords/LICENSE e5116fc268f5118168ff06a271b50ef9 +================================================================================ + + ================================================================================ = vendor/github.com/matttproud/golang_protobuf_extensions/pbutil licensed under: = @@ -93345,7 +93573,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/google.golang.org/api/tpu/v1alpha1 licensed under: = += vendor/google.golang.org/api/tpu/v1 licensed under: = Copyright (c) 2011 Google Inc. All rights reserved. @@ -94849,216 +95077,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -================================================================================ -= vendor/google.golang.org/grpc/grpclb/grpc_lb_v1 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/google.golang.org/grpc/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 -================================================================================ - - ================================================================================ = vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/messages licensed under: = @@ -102669,6 +102687,216 @@ Apache License ================================================================================ +================================================================================ += vendor/k8s.io/kube-openapi/pkg/util/proto/testing 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/proto/validation licensed under: = diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index 08514f8b210..c6d05481a5e 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -45,7 +45,6 @@ aliases: - shiywang - smarterclayton - soltysh - - sttts sig-testing-reviewers: - fejta - ixdy @@ -187,6 +186,8 @@ aliases: - cmluciano - bsalamat - m1093782566 + - tallclair + - feiskyer api-approvers: - erictune - lavalamp diff --git a/SECURITY_CONTACTS b/SECURITY_CONTACTS new file mode 100644 index 00000000000..0648a8ebff7 --- /dev/null +++ b/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# 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/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 390902a04e3..c3b6ea3f3ed 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -76510,6 +76510,30 @@ } } }, + "io.k8s.api.core.v1.CinderPersistentVolumeSource": { + "description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "required": [ + "volumeID" + ], + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "string" + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "boolean" + }, + "secretRef": { + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack.", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretReference" + }, + "volumeID": { + "description": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "string" + } + } + }, "io.k8s.api.core.v1.CinderVolumeSource": { "description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", "required": [ @@ -76524,6 +76548,10 @@ "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", "type": "boolean" }, + "secretRef": { + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack.", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, "volumeID": { "description": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", "type": "string" @@ -77675,7 +77703,7 @@ } }, "io.k8s.api.core.v1.GitRepoVolumeSource": { - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -78449,7 +78477,7 @@ } }, "io.k8s.api.core.v1.NodeSelectorTerm": { - "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed.", + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "description": "A list of node selector requirements by node's labels.", @@ -78957,7 +78985,7 @@ }, "cinder": { "description": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - "$ref": "#/definitions/io.k8s.api.core.v1.CinderVolumeSource" + "$ref": "#/definitions/io.k8s.api.core.v1.CinderPersistentVolumeSource" }, "claimRef": { "description": "ClaimRef is part of a bi-directional binding between PersistentVolume and PersistentVolumeClaim. Expected to be non-nil when bound. claim.VolumeName is the authoritative bind between PV and PVC. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#binding", @@ -79210,7 +79238,7 @@ "type": "string" }, "type": { - "description": "Type is the type of the condition. Currently only Ready. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", + "description": "Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", "type": "string" } } @@ -79287,6 +79315,18 @@ } ] }, + "io.k8s.api.core.v1.PodReadinessGate": { + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "description": "ConditionType refers to a condition in the pod's condition list with matching type.", + "type": "string" + } + } + }, "io.k8s.api.core.v1.PodSecurityContext": { "description": "PodSecurityContext holds pod-level security attributes and common container settings. Some fields are also present in container.securityContext. Field values of container.securityContext take precedence over field values of PodSecurityContext.", "properties": { @@ -79320,6 +79360,13 @@ "type": "integer", "format": "int64" } + }, + "sysctls": { + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Sysctl" + } } } }, @@ -79422,6 +79469,13 @@ "description": "If specified, indicates the pod's priority. \"system-node-critical\" and \"system-cluster-critical\" are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default.", "type": "string" }, + "readinessGates": { + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PodReadinessGate" + } + }, "restartPolicy": { "description": "Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy", "type": "string" @@ -79474,7 +79528,7 @@ } }, "io.k8s.api.core.v1.PodStatus": { - "description": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system.", + "description": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system, especially if the node that hosts the pod cannot contact the control plane.", "properties": { "conditions": { "description": "Current service state of pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", @@ -79512,7 +79566,7 @@ "type": "string" }, "phase": { - "description": "Current condition of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", + "description": "The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. The conditions array, the reason and message fields, and the individual container status arrays contain more detail about the pod's status. There are five possible phase values:\n\nPending: The pod has been accepted by the Kubernetes system, but one or more of the container images has not been created. This includes time before being scheduled as well as time spent downloading images over the network, which could take a while. Running: The pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting. Succeeded: All containers in the pod have terminated in success, and will not be restarted. Failed: All containers in the pod have terminated, and at least one container has terminated in failure. The container either exited with non-zero status or was terminated by the system. Unknown: For some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod.\n\nMore info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", "type": "string" }, "podIP": { @@ -80078,12 +80132,16 @@ "description": "ResourceQuotaSpec defines the desired hard limits to enforce for Quota.", "properties": { "hard": { - "description": "Hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/", + "description": "hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/", "type": "object", "additionalProperties": { "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" } }, + "scopeSelector": { + "description": "scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota but expressed using ScopeSelectorOperator in combination with possible values. For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched.", + "$ref": "#/definitions/io.k8s.api.core.v1.ScopeSelector" + }, "scopes": { "description": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects.", "type": "array", @@ -80252,6 +80310,42 @@ } } }, + "io.k8s.api.core.v1.ScopeSelector": { + "description": "A scope selector represents the AND of the selectors represented by the scoped-resource selector requirements.", + "properties": { + "matchExpressions": { + "description": "A list of scope selector requirements by scope of the resources.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ScopedResourceSelectorRequirement" + } + } + } + }, + "io.k8s.api.core.v1.ScopedResourceSelectorRequirement": { + "description": "A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator that relates the scope name and values.", + "required": [ + "scopeName", + "operator" + ], + "properties": { + "operator": { + "description": "Represents a scope's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist.", + "type": "string" + }, + "scopeName": { + "description": "The name of the scope that the selector applies to.", + "type": "string" + }, + "values": { + "description": "An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, "io.k8s.api.core.v1.Secret": { "description": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.", "properties": { @@ -80569,6 +80663,27 @@ } ] }, + "io.k8s.api.core.v1.ServiceAccountTokenProjection": { + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.", + "type": "string" + }, + "expirationSeconds": { + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.", + "type": "integer", + "format": "int64" + }, + "path": { + "description": "Path is the path relative to the mount point of the file to project the token into.", + "type": "string" + } + } + }, "io.k8s.api.core.v1.ServiceList": { "description": "ServiceList holds a list of services.", "required": [ @@ -80773,6 +80888,23 @@ } } }, + "io.k8s.api.core.v1.Sysctl": { + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "description": "Name of a property to set", + "type": "string" + }, + "value": { + "description": "Value of a property to set", + "type": "string" + } + } + }, "io.k8s.api.core.v1.TCPSocketAction": { "description": "TCPSocketAction describes an action based on opening a socket", "required": [ @@ -80840,6 +80972,38 @@ } } }, + "io.k8s.api.core.v1.TopologySelectorLabelRequirement": { + "description": "A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.", + "required": [ + "key", + "values" + ], + "properties": { + "key": { + "description": "The label key that the selector applies to.", + "type": "string" + }, + "values": { + "description": "An array of string values. One value must match the label to be selected. Each entry in Values is ORed.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.TopologySelectorTerm": { + "description": "A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.", + "properties": { + "matchLabelExpressions": { + "description": "A list of topology selector requirements by labels.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.TopologySelectorLabelRequirement" + } + } + } + }, "io.k8s.api.core.v1.Volume": { "description": "Volume represents a named volume in a pod that may be accessed by any container in the pod.", "required": [ @@ -80895,7 +81059,7 @@ "$ref": "#/definitions/io.k8s.api.core.v1.GCEPersistentDiskVolumeSource" }, "gitRepo": { - "description": "GitRepo represents a git repository at a particular revision.", + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "$ref": "#/definitions/io.k8s.api.core.v1.GitRepoVolumeSource" }, "glusterfs": { @@ -81029,6 +81193,10 @@ "secret": { "description": "information about the secret data to project", "$ref": "#/definitions/io.k8s.api.core.v1.SecretProjection" + }, + "serviceAccountToken": { + "description": "information about the serviceAccountToken data to project", + "$ref": "#/definitions/io.k8s.api.core.v1.ServiceAccountTokenProjection" } } }, @@ -81232,6 +81400,10 @@ "pathPrefix": { "description": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", "type": "string" + }, + "readOnly": { + "description": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.", + "type": "boolean" } } }, @@ -82197,6 +82369,13 @@ "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.AllowedHostPath" } }, + "allowedUnsafeSysctls": { + "description": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc.", + "type": "array", + "items": { + "type": "string" + } + }, "defaultAddCapabilities": { "description": "defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list.", "type": "array", @@ -82208,6 +82387,13 @@ "description": "defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", "type": "boolean" }, + "forbiddenSysctls": { + "description": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc.", + "type": "array", + "items": { + "type": "string" + } + }, "fsGroup": { "description": "fsGroup is the strategy that will dictate what fs group is used by the SecurityContext.", "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.FSGroupStrategyOptions" @@ -82776,6 +82962,10 @@ "pathPrefix": { "description": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", "type": "string" + }, + "readOnly": { + "description": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.", + "type": "boolean" } } }, @@ -83081,6 +83271,13 @@ "$ref": "#/definitions/io.k8s.api.policy.v1beta1.AllowedHostPath" } }, + "allowedUnsafeSysctls": { + "description": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc.", + "type": "array", + "items": { + "type": "string" + } + }, "defaultAddCapabilities": { "description": "defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list.", "type": "array", @@ -83092,6 +83289,13 @@ "description": "defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", "type": "boolean" }, + "forbiddenSysctls": { + "description": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc.", + "type": "array", + "items": { + "type": "string" + } + }, "fsGroup": { "description": "fsGroup is the strategy that will dictate what fs group is used by the SecurityContext.", "$ref": "#/definitions/io.k8s.api.policy.v1beta1.FSGroupStrategyOptions" @@ -84615,6 +84819,13 @@ "description": "AllowVolumeExpansion shows whether the storage class allow volume expand", "type": "boolean" }, + "allowedTopologies": { + "description": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.TopologySelectorTerm" + } + }, "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" @@ -84846,6 +85057,13 @@ "description": "AllowVolumeExpansion shows whether the storage class allow volume expand", "type": "boolean" }, + "allowedTopologies": { + "description": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.TopologySelectorTerm" + } + }, "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" @@ -85067,6 +85285,41 @@ } } }, + "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition": { + "description": "CustomResourceColumnDefinition specifies a column for server side printing.", + "required": [ + "name", + "type", + "JSONPath" + ], + "properties": { + "JSONPath": { + "description": "JSONPath is a simple JSON path, i.e. with array notation.", + "type": "string" + }, + "description": { + "description": "description is a human readable description of this column.", + "type": "string" + }, + "format": { + "description": "format is an optional OpenAPI type definition for this column. The 'name' format is applied to the primary identifier column to assist in clients identifying column is the resource name. See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.", + "type": "string" + }, + "name": { + "description": "name is a human readable name for the column.", + "type": "string" + }, + "priority": { + "description": "priority is an integer defining the relative importance of this column compared to others. Lower numbers are considered higher priority. Columns that may be omitted in limited space scenarios should be given a higher priority.", + "type": "integer", + "format": "int32" + }, + "type": { + "description": "type is an OpenAPI type definition for this column. See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.", + "type": "string" + } + } + }, "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition": { "description": "CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format \u003c.spec.name\u003e.\u003c.spec.group\u003e.", "properties": { @@ -85207,6 +85460,13 @@ "scope" ], "properties": { + "additionalPrinterColumns": { + "description": "AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition" + } + }, "group": { "description": "Group is the group this resource belongs in", "type": "string" diff --git a/api/swagger-spec/apps_v1.json b/api/swagger-spec/apps_v1.json index f951a05981d..decde3cbd24 100644 --- a/api/swagger-spec/apps_v1.json +++ b/api/swagger-spec/apps_v1.json @@ -6743,6 +6743,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -6775,7 +6782,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -6956,7 +6963,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -7246,6 +7253,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -7612,6 +7623,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -7670,6 +7685,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -8384,6 +8421,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -8440,7 +8502,7 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed.", + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", @@ -8669,6 +8731,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1.DaemonSetUpdateStrategy": { "id": "v1.DaemonSetUpdateStrategy", "description": "DaemonSetUpdateStrategy is a struct used to control the update strategy for a DaemonSet.", diff --git a/api/swagger-spec/apps_v1beta1.json b/api/swagger-spec/apps_v1beta1.json index 3811b8905da..65d43b33b7a 100644 --- a/api/swagger-spec/apps_v1beta1.json +++ b/api/swagger-spec/apps_v1beta1.json @@ -4377,6 +4377,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -4409,7 +4416,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -4590,7 +4597,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -4880,6 +4887,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -5246,6 +5257,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -5304,6 +5319,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -6018,6 +6055,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -6074,7 +6136,7 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed.", + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", @@ -6303,6 +6365,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1beta1.DeploymentStrategy": { "id": "v1beta1.DeploymentStrategy", "description": "DeploymentStrategy describes how to replace existing pods with new ones.", diff --git a/api/swagger-spec/apps_v1beta2.json b/api/swagger-spec/apps_v1beta2.json index 91c674f3c1a..9d85269bba5 100644 --- a/api/swagger-spec/apps_v1beta2.json +++ b/api/swagger-spec/apps_v1beta2.json @@ -6743,6 +6743,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -6775,7 +6782,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -6956,7 +6963,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -7246,6 +7253,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -7612,6 +7623,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -7670,6 +7685,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -8384,6 +8421,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -8440,7 +8502,7 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed.", + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", @@ -8669,6 +8731,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1beta2.DaemonSetUpdateStrategy": { "id": "v1beta2.DaemonSetUpdateStrategy", "description": "DaemonSetUpdateStrategy is a struct used to control the update strategy for a DaemonSet.", diff --git a/api/swagger-spec/batch_v1.json b/api/swagger-spec/batch_v1.json index bb316ff8fe9..9b42270259e 100644 --- a/api/swagger-spec/batch_v1.json +++ b/api/swagger-spec/batch_v1.json @@ -1717,6 +1717,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -1749,7 +1756,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -1930,7 +1937,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -2220,6 +2227,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -2586,6 +2597,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -2644,6 +2659,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -3358,6 +3395,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -3414,7 +3476,7 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed.", + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", @@ -3643,6 +3705,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1.JobStatus": { "id": "v1.JobStatus", "description": "JobStatus represents the current state of a Job.", diff --git a/api/swagger-spec/batch_v1beta1.json b/api/swagger-spec/batch_v1beta1.json index ccd0c6c5d8a..ea1a94055b6 100644 --- a/api/swagger-spec/batch_v1beta1.json +++ b/api/swagger-spec/batch_v1beta1.json @@ -1772,6 +1772,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -1804,7 +1811,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -1985,7 +1992,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -2275,6 +2282,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -2641,6 +2652,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -2699,6 +2714,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -3413,6 +3450,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -3469,7 +3531,7 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed.", + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", @@ -3698,6 +3760,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1beta1.CronJobStatus": { "id": "v1beta1.CronJobStatus", "description": "CronJobStatus represents the current state of a cron job.", diff --git a/api/swagger-spec/batch_v2alpha1.json b/api/swagger-spec/batch_v2alpha1.json index 3c9f4227fcf..117a82c7f2c 100644 --- a/api/swagger-spec/batch_v2alpha1.json +++ b/api/swagger-spec/batch_v2alpha1.json @@ -1772,6 +1772,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -1804,7 +1811,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -1985,7 +1992,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -2275,6 +2282,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -2641,6 +2652,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -2699,6 +2714,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -3413,6 +3450,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -3469,7 +3531,7 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed.", + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", @@ -3698,6 +3760,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v2alpha1.CronJobStatus": { "id": "v2alpha1.CronJobStatus", "description": "CronJobStatus represents the current state of a cron job.", diff --git a/api/swagger-spec/extensions_v1beta1.json b/api/swagger-spec/extensions_v1beta1.json index 4ab3384c071..70e44ef33cd 100644 --- a/api/swagger-spec/extensions_v1beta1.json +++ b/api/swagger-spec/extensions_v1beta1.json @@ -7385,6 +7385,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -7417,7 +7424,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -7598,7 +7605,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -7888,6 +7895,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -8254,6 +8265,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -8312,6 +8327,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -9026,6 +9063,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -9082,7 +9144,7 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed.", + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", @@ -9311,6 +9373,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1beta1.DaemonSetUpdateStrategy": { "id": "v1beta1.DaemonSetUpdateStrategy", "properties": { @@ -10342,6 +10417,20 @@ "$ref": "v1beta1.AllowedFlexVolume" }, "description": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field." + }, + "allowedUnsafeSysctls": { + "type": "array", + "items": { + "type": "string" + }, + "description": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc." + }, + "forbiddenSysctls": { + "type": "array", + "items": { + "type": "string" + }, + "description": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc." } } }, @@ -10467,6 +10556,10 @@ "pathPrefix": { "type": "string", "description": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`" + }, + "readOnly": { + "type": "boolean", + "description": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly." } } }, diff --git a/api/swagger-spec/policy_v1beta1.json b/api/swagger-spec/policy_v1beta1.json index 1b755ad6214..e62fd2425fb 100644 --- a/api/swagger-spec/policy_v1beta1.json +++ b/api/swagger-spec/policy_v1beta1.json @@ -2499,6 +2499,20 @@ "$ref": "v1beta1.AllowedFlexVolume" }, "description": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field." + }, + "allowedUnsafeSysctls": { + "type": "array", + "items": { + "type": "string" + }, + "description": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc." + }, + "forbiddenSysctls": { + "type": "array", + "items": { + "type": "string" + }, + "description": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc." } } }, @@ -2650,6 +2664,10 @@ "pathPrefix": { "type": "string", "description": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`" + }, + "readOnly": { + "type": "boolean", + "description": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly." } } }, diff --git a/api/swagger-spec/settings.k8s.io_v1alpha1.json b/api/swagger-spec/settings.k8s.io_v1alpha1.json index d4427baab0f..cc69f22d36a 100644 --- a/api/swagger-spec/settings.k8s.io_v1alpha1.json +++ b/api/swagger-spec/settings.k8s.io_v1alpha1.json @@ -1587,7 +1587,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -1768,7 +1768,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -2058,6 +2058,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -2386,6 +2390,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -2444,6 +2452,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", diff --git a/api/swagger-spec/storage.k8s.io_v1.json b/api/swagger-spec/storage.k8s.io_v1.json index 19adf296d06..2ffcfd9c7ea 100644 --- a/api/swagger-spec/storage.k8s.io_v1.json +++ b/api/swagger-spec/storage.k8s.io_v1.json @@ -818,6 +818,13 @@ "volumeBindingMode": { "$ref": "v1.VolumeBindingMode", "description": "VolumeBindingMode indicates how PersistentVolumeClaims should be provisioned and bound. When unset, VolumeBindingImmediate is used. This field is alpha-level and is only honored by servers that enable the VolumeScheduling feature." + }, + "allowedTopologies": { + "type": "array", + "items": { + "$ref": "v1.TopologySelectorTerm" + }, + "description": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature." } } }, @@ -1067,6 +1074,40 @@ "id": "v1.VolumeBindingMode", "properties": {} }, + "v1.TopologySelectorTerm": { + "id": "v1.TopologySelectorTerm", + "description": "A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.", + "properties": { + "matchLabelExpressions": { + "type": "array", + "items": { + "$ref": "v1.TopologySelectorLabelRequirement" + }, + "description": "A list of topology selector requirements by labels." + } + } + }, + "v1.TopologySelectorLabelRequirement": { + "id": "v1.TopologySelectorLabelRequirement", + "description": "A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.", + "required": [ + "key", + "values" + ], + "properties": { + "key": { + "type": "string", + "description": "The label key that the selector applies to." + }, + "values": { + "type": "array", + "items": { + "type": "string" + }, + "description": "An array of string values. One value must match the label to be selected. Each entry in Values is ORed." + } + } + }, "v1.WatchEvent": { "id": "v1.WatchEvent", "required": [ diff --git a/api/swagger-spec/storage.k8s.io_v1beta1.json b/api/swagger-spec/storage.k8s.io_v1beta1.json index 3f987d8a84f..3859a22033d 100644 --- a/api/swagger-spec/storage.k8s.io_v1beta1.json +++ b/api/swagger-spec/storage.k8s.io_v1beta1.json @@ -1512,6 +1512,13 @@ "volumeBindingMode": { "$ref": "v1beta1.VolumeBindingMode", "description": "VolumeBindingMode indicates how PersistentVolumeClaims should be provisioned and bound. When unset, VolumeBindingImmediate is used. This field is alpha-level and is only honored by servers that enable the VolumeScheduling feature." + }, + "allowedTopologies": { + "type": "array", + "items": { + "$ref": "v1.TopologySelectorTerm" + }, + "description": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature." } } }, @@ -1761,6 +1768,40 @@ "id": "v1beta1.VolumeBindingMode", "properties": {} }, + "v1.TopologySelectorTerm": { + "id": "v1.TopologySelectorTerm", + "description": "A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.", + "properties": { + "matchLabelExpressions": { + "type": "array", + "items": { + "$ref": "v1.TopologySelectorLabelRequirement" + }, + "description": "A list of topology selector requirements by labels." + } + } + }, + "v1.TopologySelectorLabelRequirement": { + "id": "v1.TopologySelectorLabelRequirement", + "description": "A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.", + "required": [ + "key", + "values" + ], + "properties": { + "key": { + "type": "string", + "description": "The label key that the selector applies to." + }, + "values": { + "type": "array", + "items": { + "type": "string" + }, + "description": "An array of string values. One value must match the label to be selected. Each entry in Values is ORed." + } + } + }, "v1.WatchEvent": { "id": "v1.WatchEvent", "required": [ diff --git a/api/swagger-spec/v1.json b/api/swagger-spec/v1.json index 7ac54ed33b1..94cdaea1866 100644 --- a/api/swagger-spec/v1.json +++ b/api/swagger-spec/v1.json @@ -19321,7 +19321,7 @@ "description": "ISCSI represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Provisioned by an admin." }, "cinder": { - "$ref": "v1.CinderVolumeSource", + "$ref": "v1.CinderPersistentVolumeSource", "description": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" }, "cephfs": { @@ -19651,8 +19651,8 @@ } } }, - "v1.CinderVolumeSource": { - "id": "v1.CinderVolumeSource", + "v1.CinderPersistentVolumeSource": { + "id": "v1.CinderPersistentVolumeSource", "description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", "required": [ "volumeID" @@ -19669,6 +19669,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.SecretReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -20106,7 +20110,7 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed.", + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", @@ -20356,6 +20360,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -20388,7 +20399,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -20496,7 +20507,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -20724,6 +20735,31 @@ } } }, + "v1.CinderVolumeSource": { + "id": "v1.CinderVolumeSource", + "description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "required": [ + "volumeID" + ], + "properties": { + "volumeID": { + "type": "string", + "description": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "fsType": { + "type": "string", + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "readOnly": { + "type": "boolean", + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." + } + } + }, "v1.CephFSVolumeSource": { "id": "v1.CephFSVolumeSource", "description": "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.", @@ -20926,6 +20962,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -20984,6 +21024,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.ScaleIOVolumeSource": { "id": "v1.ScaleIOVolumeSource", "description": "ScaleIOVolumeSource represents a persistent ScaleIO volume", @@ -21663,6 +21725,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -21887,13 +21974,26 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1.PodStatus": { "id": "v1.PodStatus", - "description": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system.", + "description": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system, especially if the node that hosts the pod cannot contact the control plane.", "properties": { "phase": { "type": "string", - "description": "Current condition of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase" + "description": "The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. The conditions array, the reason and message fields, and the individual container status arrays contain more detail about the pod's status. There are five possible phase values:\n\nPending: The pod has been accepted by the Kubernetes system, but one or more of the container images has not been created. This includes time before being scheduled as well as time spent downloading images over the network, which could take a while. Running: The pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting. Succeeded: All containers in the pod have terminated in success, and will not be restarted. Failed: All containers in the pod have terminated, and at least one container has terminated in failure. The container either exited with non-zero status or was terminated by the system. Unknown: For some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod.\n\nMore info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase" }, "conditions": { "type": "array", @@ -21956,7 +22056,7 @@ "properties": { "type": { "type": "string", - "description": "Type is the type of the condition. Currently only Ready. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions" + "description": "Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions" }, "status": { "type": "string", @@ -22457,7 +22557,7 @@ "properties": { "hard": { "type": "object", - "description": "Hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/" + "description": "hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/" }, "scopes": { "type": "array", @@ -22465,6 +22565,10 @@ "$ref": "v1.ResourceQuotaScope" }, "description": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects." + }, + "scopeSelector": { + "$ref": "v1.ScopeSelector", + "description": "scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota but expressed using ScopeSelectorOperator in combination with possible values. For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched." } } }, @@ -22472,6 +22576,44 @@ "id": "v1.ResourceQuotaScope", "properties": {} }, + "v1.ScopeSelector": { + "id": "v1.ScopeSelector", + "description": "A scope selector represents the AND of the selectors represented by the scoped-resource selector requirements.", + "properties": { + "matchExpressions": { + "type": "array", + "items": { + "$ref": "v1.ScopedResourceSelectorRequirement" + }, + "description": "A list of scope selector requirements by scope of the resources." + } + } + }, + "v1.ScopedResourceSelectorRequirement": { + "id": "v1.ScopedResourceSelectorRequirement", + "description": "A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator that relates the scope name and values.", + "required": [ + "scopeName", + "operator" + ], + "properties": { + "scopeName": { + "type": "string", + "description": "The name of the scope that the selector applies to." + }, + "operator": { + "type": "string", + "description": "Represents a scope's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist." + }, + "values": { + "type": "array", + "items": { + "type": "string" + }, + "description": "An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch." + } + } + }, "v1.ResourceQuotaStatus": { "id": "v1.ResourceQuotaStatus", "description": "ResourceQuotaStatus defines the enforced hard limits and observed use.", diff --git a/build/debs/10-kubeadm.conf b/build/debs/10-kubeadm.conf index f2974f90486..bd1b077f399 100644 --- a/build/debs/10-kubeadm.conf +++ b/build/debs/10-kubeadm.conf @@ -1,13 +1,11 @@ +# Note: This dropin only works with kubeadm and kubelet v1.11+ [Service] Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf" -Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true" -Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin" -Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local" -Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt" -# Value should match Docker daemon settings. -# Defaults are "cgroupfs" for Debian/Ubuntu/OpenSUSE and "systemd" for Fedora/CentOS/RHEL -Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=cgroupfs" -Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0" -Environment="KUBELET_CERTIFICATE_ARGS=--rotate-certificates=true" +Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml" +# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically +EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env +# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use +# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file. +EnvironmentFile=-/etc/default/kubelet ExecStart= -ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CGROUP_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS +ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS diff --git a/build/debs/BUILD b/build/debs/BUILD index 31700d04524..17ee17563cd 100644 --- a/build/debs/BUILD +++ b/build/debs/BUILD @@ -3,6 +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") # We do not include kube-scheduler, kube-controller-manager, # kube-apiserver, and kube-proxy in this list even though we @@ -13,6 +14,7 @@ release_filegroup( name = "debs", srcs = [ ":cloud-controller-manager.deb", + ":cri-tools.deb", ":kubeadm.deb", ":kubectl.deb", ":kubelet.deb", @@ -86,6 +88,12 @@ pkg_tar( deps = ["@kubernetes_cni//file"], ) +pkg_tar( + name = "cri-tools-data", + package_dir = "/usr/bin", + deps = ["@cri_tools//file"], +) + k8s_deb( name = "cloud-controller-manager", description = "Kubernetes Cloud Controller Manager", @@ -167,6 +175,12 @@ The Container Networking Interface tools for provisioning container networks. version_file = "//build:cni_package_version", ) +k8s_deb( + name = "cri-tools", + description = """Container Runtime Interface tools (crictl)""", + version = CRI_TOOLS_VERSION, +) + filegroup( name = "package-srcs", srcs = glob(["**"]), diff --git a/build/lib/release.sh b/build/lib/release.sh index aaec30f52e0..27008de5f23 100644 --- a/build/lib/release.sh +++ b/build/lib/release.sh @@ -382,6 +382,7 @@ function kube::release::package_kube_manifests_tarball() { cp "${src_dir}/cluster-autoscaler.manifest" "${dst_dir}/" cp "${src_dir}/etcd.manifest" "${dst_dir}" cp "${src_dir}/kube-scheduler.manifest" "${dst_dir}" + cp "${src_dir}/kms-plugin-container.manifest" "${dst_dir}" cp "${src_dir}/kube-apiserver.manifest" "${dst_dir}" cp "${src_dir}/abac-authz-policy.jsonl" "${dst_dir}" cp "${src_dir}/kube-controller-manager.manifest" "${dst_dir}" diff --git a/build/root/Makefile b/build/root/Makefile index c7e16e90e6b..32ddf4fda04 100644 --- a/build/root/Makefile +++ b/build/root/Makefile @@ -124,7 +124,7 @@ ifeq ($(PRINT_HELP),y) verify: @echo "$$VERIFY_HELP_INFO" else -verify: verify_generated_files +verify: KUBE_VERIFY_GIT_BRANCH=$(BRANCH) hack/make-rules/verify.sh endif @@ -139,7 +139,7 @@ ifeq ($(PRINT_HELP),y) quick-verify: @echo "$$QUICK_VERIFY_HELP_INFO" else -quick-verify: verify_generated_files +quick-verify: QUICK=true SILENT=false hack/make-rules/verify.sh endif @@ -483,21 +483,6 @@ generated_files: $(MAKE) -f Makefile.generated_files $@ CALLED_FROM_MAIN_MAKEFILE=1 endif -define VERIFY_GENERATED_FILES_HELP_INFO -# Verify auto-generated files needed for the build. -# -# Example: -# make verify_generated_files -endef -.PHONY: verify_generated_files -ifeq ($(PRINT_HELP),y) -verify_generated_files: - @echo "$$VERIFY_GENERATED_FILES_HELP_INFO" -else -verify_generated_files: - $(MAKE) -f Makefile.generated_files $@ CALLED_FROM_MAIN_MAKEFILE=1 -endif - define HELP_INFO # Print make targets and help info # diff --git a/build/root/Makefile.generated_files b/build/root/Makefile.generated_files index 59372a0c305..b4d94fba725 100644 --- a/build/root/Makefile.generated_files +++ b/build/root/Makefile.generated_files @@ -37,81 +37,54 @@ SHELL := /bin/bash .PHONY: generated_files generated_files: gen_deepcopy gen_defaulter gen_conversion gen_openapi gen_bindata -.PHONY: verify_generated_files -verify_generated_files: verify_gen_deepcopy \ - verify_gen_defaulter \ - verify_gen_conversion +# +# Helper logic to calculate Go's dependency DAG ourselves. +# + +# This is a file that will be emitted by the go2make tool, containing a +# variable for each Go package in the project (including deps) which lists all +# of the transitive deps of that package. Each variable is named the same as +# the package - for example the variable for `k8s.io/kubernetes/pkg/api` is +# $(k8s.io/kubernetes/pkg/api). This is roughly the same DAG that the Go +# compiler uses. These variables can be used to figure out if, for example, +# generated code needs to be regenerated. +GO_PKGDEPS_FILE = go-pkgdeps.mk + +# Include the Go package dependencies file. This will cause the rule of +# the same name to be considered and if it is updated, make will restart and +# reload the updated deps. +sinclude $(META_DIR)/$(GO_PKGDEPS_FILE) + +# Update the set of Go deps for our project. This will let us determine if +# we really need to do expensive codegen. We use FORCE because it is not a +# PHONY file, but we do want it to be re-evaluated every time make is run. The +# file will only be touched if it actually changes. +$(META_DIR)/$(GO_PKGDEPS_FILE): FORCE + if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ + echo "DBG: calculating Go dependencies"; \ + fi + hack/run-in-gopath.sh go install ./hack/make-rules/helpers/go2make + hack/run-in-gopath.sh go2make \ + k8s.io/kubernetes/... \ + --prune k8s.io/kubernetes/staging \ + --prune k8s.io/kubernetes/vendor \ + k8s.io/kubernetes/vendor/k8s.io/... \ + github.com/jteeuwen/go-bindata/go-bindata/... \ + > $@.tmp + if ! cmp -s $@.tmp $@; then \ + if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ + echo "DBG: $(GO_PKGDEPS_FILE) changed"; \ + fi; \ + cat $@.tmp > $@; \ + fi + rm -f $@.tmp + +.PHONY: FORCE +FORCE: -# Code-generation logic. # -# This stuff can be pretty tricky, and there's probably some corner cases that -# we don't handle well. That said, here's a straightforward test to prove that -# the most common cases work. Sadly, it is manual. +# Helper logic to find which directories need codegen as quickly as possible. # -# make clean -# find . -name .make\* | xargs rm -f -# find . -name zz_generated\* | xargs rm -f -# # verify `find . -name zz_generated.deepcopy.go | wc -l` is 0 -# # verify `find . -name .make | wc -l` is 0 -# -# make nonexistent -# # expect "No rule to make target" -# # verify `find .make/ -type f | wc -l` has many files -# -# make gen_deepcopy -# # expect deepcopy-gen is built exactly once -# # expect many files to be regenerated -# # verify `find . -name zz_generated.deepcopy.go | wc -l` has files -# make gen_deepcopy -# # expect nothing to be rebuilt, finish in O(seconds) -# touch pkg/api/types.go -# make gen_deepcopy -# # expect one file to be regenerated -# make gen_deepcopy -# # expect nothing to be rebuilt, finish in O(seconds) -# touch vendor/k8s.io/code-generator/cmd/deepcopy-gen/main.go -# make gen_deepcopy -# # expect deepcopy-gen is built exactly once -# # expect many files to be regenerated -# # verify `find . -name zz_generated.deepcopy.go | wc -l` has files -# make gen_deepcopy -# # expect nothing to be rebuilt, finish in O(seconds) -# -# make gen_conversion -# # expect conversion-gen is built exactly once -# # expect many files to be regenerated -# # verify `find . -name zz_generated.conversion.go | wc -l` has files -# make gen_conversion -# # expect nothing to be rebuilt, finish in O(seconds) -# touch pkg/api/types.go -# make gen_conversion -# # expect one file to be regenerated -# make gen_conversion -# # expect nothing to be rebuilt, finish in O(seconds) -# touch vendor/k8s.io/code-generator/cmd/conversion-gen/main.go -# make gen_conversion -# # expect conversion-gen is built exactly once -# # expect many files to be regenerated -# # verify `find . -name zz_generated.conversion.go | wc -l` has files -# make gen_conversion -# # expect nothing to be rebuilt, finish in O(seconds) -# -# make all -# # expect it to build -# -# make test -# # expect it to pass -# -# make clean -# # verify `find . -name zz_generated.deepcopy.go | wc -l` is 0 -# # verify `find . -name .make | wc -l` is 0 -# -# make all WHAT=cmd/kube-proxy -# # expect it to build -# -# make clean -# make test WHAT=cmd/kube-proxy -# # expect it to pass # This variable holds a list of every directory that contains Go files in this # project. Other rules and variables can use this as a starting point to @@ -123,63 +96,6 @@ ALL_GO_DIRS := $(shell \ hack/make-rules/helpers/cache_go_dirs.sh $(META_DIR)/all_go_dirs.mk \ ) -# The name of the metadata file which lists *.go files in each pkg. -GOFILES_META := gofiles.mk - -# Establish a dependency between the deps file and the dir. Whenever a dir -# changes (files added or removed) the deps file will be considered stale. -# -# The variable value was set in $(GOFILES_META) and included as part of the -# dependency management logic. -# -# This is looser than we really need (e.g. we don't really care about non *.go -# files or even *_test.go files), but this is much easier to represent. -# -# Because we 'sinclude' the deps file, it is considered for rebuilding, as part -# of make's normal evaluation. If it gets rebuilt, make will restart. -# -# The '$(eval)' is needed because this has a different RHS for each LHS, and -# would otherwise produce results that make can't parse. -$(foreach dir, $(ALL_GO_DIRS), $(eval \ - $(META_DIR)/$(dir)/$(GOFILES_META): $(dir) \ -)) - -# How to rebuild a deps file. When make determines that the deps file is stale -# (see above), it executes this rule, and then re-loads the deps file. -# -# This is looser than we really need (e.g. we don't really care about test -# files), but this is MUCH faster than calling `go list`. -# -# We regenerate the output file in order to satisfy make's "newer than" rules, -# but we only need to rebuild targets if the contents actually changed. That -# is what the .stamp file represents. -$(foreach dir, $(ALL_GO_DIRS), \ - $(META_DIR)/$(dir)/$(GOFILES_META)): - FILES=$$(ls $$@.tmp; \ - if ! cmp -s $@.tmp $@; then \ - if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ - echo "DBG: gofiles changed for $@"; \ - fi; \ - touch $@.stamp; \ - fi; \ - mv $@.tmp $@ - -# This is required to fill in the DAG, since some cases (e.g. 'make clean all') -# will reference the .stamp file when it doesn't exist. We don't need to -# rebuild it in that case, just keep make happy. -$(foreach dir, $(ALL_GO_DIRS), \ - $(META_DIR)/$(dir)/$(GOFILES_META).stamp): - -# Include any deps files as additional Makefile rules. This triggers make to -# consider the deps files for rebuild, which makes the whole -# dependency-management logic work. 'sinclude' is "silent include" which does -# not fail if the file does not exist. -$(foreach dir, $(ALL_GO_DIRS), $(eval \ - sinclude $(META_DIR)/$(dir)/$(GOFILES_META) \ -)) - # Generate a list of all files that have a `+k8s:` comment-tag. This will be # used to derive lists of files/dirs for generation tools. ifeq ($(DBG_MAKEFILE),1) @@ -190,7 +106,12 @@ ALL_K8S_TAG_FILES := $(shell \ | xargs grep --color=never -l '^// *+k8s:' \ ) + # +# Code generation logic. +# + + # Deep-copy generation # # Any package that wants deep-copy functions generated must include a @@ -220,34 +141,27 @@ DEEPCOPY_DIRS := $(shell \ ) DEEPCOPY_FILES := $(addsuffix /$(DEEPCOPY_FILENAME), $(DEEPCOPY_DIRS)) -# Shell function for reuse in rules. -RUN_GEN_DEEPCOPY = \ - function run_gen_deepcopy() { \ - if [[ -f $(META_DIR)/$(DEEPCOPY_GEN).todo ]]; then \ - pkgs=$$(cat $(META_DIR)/$(DEEPCOPY_GEN).todo | paste -sd, -); \ - if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ - echo "DBG: running $(DEEPCOPY_GEN) for $$pkgs"; \ - fi; \ - ./hack/run-in-gopath.sh $(DEEPCOPY_GEN) \ - --v $(KUBE_VERBOSE) \ - --logtostderr \ - -i "$$pkgs" \ - --bounding-dirs $(PRJ_SRC_PATH),"k8s.io/api" \ - -O $(DEEPCOPY_BASENAME) \ - "$$@"; \ - fi \ - }; \ - run_gen_deepcopy +# Reset the list of packages that need generation. +$(shell mkdir -p $$(dirname $(META_DIR)/$(DEEPCOPY_GEN))) +$(shell rm -f $(META_DIR)/$(DEEPCOPY_GEN).todo) # This rule aggregates the set of files to generate and then generates them all # in a single run of the tool. .PHONY: gen_deepcopy -gen_deepcopy: $(DEEPCOPY_FILES) $(DEEPCOPY_GEN) - $(RUN_GEN_DEEPCOPY) - -.PHONY: verify_gen_deepcopy -verify_gen_deepcopy: $(DEEPCOPY_GEN) - $(RUN_GEN_DEEPCOPY) --verify-only +gen_deepcopy: $(DEEPCOPY_GEN) $(META_DIR)/$(DEEPCOPY_GEN).todo + if [[ -s $(META_DIR)/$(DEEPCOPY_GEN).todo ]]; then \ + pkgs=$$(cat $(META_DIR)/$(DEEPCOPY_GEN).todo | paste -sd, -); \ + if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ + echo "DBG: running $(DEEPCOPY_GEN) for $$pkgs"; \ + fi; \ + ./hack/run-in-gopath.sh $(DEEPCOPY_GEN) \ + --v $(KUBE_VERBOSE) \ + --logtostderr \ + -i "$$pkgs" \ + --bounding-dirs $(PRJ_SRC_PATH),"k8s.io/api" \ + -O $(DEEPCOPY_BASENAME) \ + "$$@"; \ + fi \ # For each dir in DEEPCOPY_DIRS, this establishes a dependency between the # output file and the input files that should trigger a rebuild. @@ -258,71 +172,35 @@ verify_gen_deepcopy: $(DEEPCOPY_GEN) # # The '$(eval)' is needed because this has a different RHS for each LHS, and # would otherwise produce results that make can't parse. -# -# We depend on the $(GOFILES_META).stamp to detect when the set of input files -# has changed. This allows us to detect deleted input files. -$(foreach dir, $(DEEPCOPY_DIRS), $(eval \ - $(dir)/$(DEEPCOPY_FILENAME): $(META_DIR)/$(dir)/$(GOFILES_META).stamp \ - $(gofiles__$(dir)) \ +$(foreach dir, $(DEEPCOPY_DIRS), $(eval \ + $(dir)/$(DEEPCOPY_FILENAME): $($(PRJ_SRC_PATH)/$(dir)) \ )) -# Unilaterally remove any leftovers from previous runs. -$(shell rm -f $(META_DIR)/$(DEEPCOPY_GEN)*.todo) - # How to regenerate deep-copy code. This is a little slow to run, so we batch # it up and trigger the batch from the 'generated_files' target. +$(META_DIR)/$(DEEPCOPY_GEN).todo: $(DEEPCOPY_FILES) + $(DEEPCOPY_FILES): $(DEEPCOPY_GEN) - mkdir -p $$(dirname $(META_DIR)/$(DEEPCOPY_GEN)) if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ echo "DBG: deepcopy needed $(@D): $?"; \ ls -lf --full-time $@ $? || true; \ fi echo $(PRJ_SRC_PATH)/$(@D) >> $(META_DIR)/$(DEEPCOPY_GEN).todo -# This calculates the dependencies for the generator tool, so we only rebuild -# it when needed. It is PHONY so that it always runs, but it only updates the -# file if the contents have actually changed. We 'sinclude' this later. -.PHONY: $(META_DIR)/$(DEEPCOPY_GEN).mk -$(META_DIR)/$(DEEPCOPY_GEN).mk: - mkdir -p $(@D); \ - (echo -n "$(DEEPCOPY_GEN): "; \ - ./hack/run-in-gopath.sh go list \ - -f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \ - ./vendor/k8s.io/code-generator/cmd/deepcopy-gen \ - | grep --color=never "^$(PRJ_SRC_PATH)/" \ - | xargs ./hack/run-in-gopath.sh go list \ - -f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \ - | paste -sd' ' - \ - | sed 's/ / \\=,/g' \ - | tr '=,' '\n\t' \ - | sed "s|$$(pwd -P)/||"; \ - ) > $@.tmp; \ - if ! cmp -s $@.tmp $@; then \ - if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ - echo "DBG: $(DEEPCOPY_GEN).mk changed"; \ - fi; \ - cat $@.tmp > $@; \ - rm -f $@.tmp; \ - fi - -# Include dependency info for the generator tool. This will cause the rule of -# the same name to be considered and if it is updated, make will restart. -sinclude $(META_DIR)/$(DEEPCOPY_GEN).mk - # How to build the generator tool. The deps for this are defined in -# the $(DEEPCOPY_GEN).mk, above. +# the $(GO_PKGDEPS_FILE), above. # # A word on the need to touch: This rule might trigger if, for example, a # non-Go file was added or deleted from a directory on which this depends. # This target needs to be reconsidered, but Go realizes it doesn't actually # have to be rebuilt. In that case, make will forever see the dependency as -# newer than the binary, and try to rebuild it over and over. So we touch it, -# and make is happy. -$(DEEPCOPY_GEN): +# newer than the binary, and try to "rebuild" it over and over. So we touch +# it, and make is happy. +$(DEEPCOPY_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/deepcopy-gen) hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/deepcopy-gen touch $@ -# + # Defaulter generation # # Any package that wants defaulter functions generated must include a @@ -359,134 +237,64 @@ DEFAULTER_DIRS := $(shell \ DEFAULTER_FILES := $(addsuffix /$(DEFAULTER_FILENAME), $(DEFAULTER_DIRS)) -RUN_GEN_DEFAULTER := \ - function run_gen_defaulter() { \ - if [[ -f $(META_DIR)/$(DEFAULTER_GEN).todo ]]; then \ - pkgs=$$(cat $(META_DIR)/$(DEFAULTER_GEN).todo | paste -sd, -); \ - if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ - echo "DBG: running $(DEFAULTER_GEN) for $$pkgs"; \ - fi; \ - ./hack/run-in-gopath.sh $(DEFAULTER_GEN) \ - --v $(KUBE_VERBOSE) \ - --logtostderr \ - -i "$$pkgs" \ - --extra-peer-dirs $$(echo $(addprefix $(PRJ_SRC_PATH)/, $(DEFAULTER_DIRS)) | sed 's/ /,/g') \ - -O $(DEFAULTER_BASENAME) \ - "$$@"; \ - fi \ - }; \ - run_gen_defaulter +# Reset the list of packages that need generation. +$(shell mkdir -p $$(dirname $(META_DIR)/$(DEFAULTER_GEN))) +$(shell rm -f $(META_DIR)/$(DEFAULTER_GEN).todo) # This rule aggregates the set of files to generate and then generates them all # in a single run of the tool. .PHONY: gen_defaulter -gen_defaulter: $(DEFAULTER_FILES) $(DEFAULTER_GEN) - $(RUN_GEN_DEFAULTER) - -.PHONY: verify_gen_deepcopy -verify_gen_defaulter: $(DEFAULTER_GEN) - $(RUN_GEN_DEFAULTER) --verify-only +gen_defaulter: $(DEFAULTER_GEN) $(META_DIR)/$(DEFAULTER_GEN).todo + if [[ -s $(META_DIR)/$(DEFAULTER_GEN).todo ]]; then \ + pkgs=$$(cat $(META_DIR)/$(DEFAULTER_GEN).todo | paste -sd, -); \ + if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ + echo "DBG: running $(DEFAULTER_GEN) for $$pkgs"; \ + fi; \ + ./hack/run-in-gopath.sh $(DEFAULTER_GEN) \ + --v $(KUBE_VERBOSE) \ + --logtostderr \ + -i "$$pkgs" \ + --extra-peer-dirs $$(echo $(addprefix $(PRJ_SRC_PATH)/, $(DEFAULTER_DIRS)) | sed 's/ /,/g') \ + -O $(DEFAULTER_BASENAME) \ + "$$@"; \ + fi # For each dir in DEFAULTER_DIRS, this establishes a dependency between the # output file and the input files that should trigger a rebuild. # -# The variable value was set in $(GOFILES_META) and included as part of the -# dependency management logic. -# -# Note that this is a deps-only statement, not a full rule (see below). This -# has to be done in a distinct step because wildcards don't work in static -# pattern rules. +# Note that this is a deps-only statement, not a full rule (see below for that). # # The '$(eval)' is needed because this has a different RHS for each LHS, and # would otherwise produce results that make can't parse. -# -# We depend on the $(GOFILES_META).stamp to detect when the set of input files -# has changed. This allows us to detect deleted input files. -$(foreach dir, $(DEFAULTER_DIRS), $(eval \ - $(dir)/$(DEFAULTER_FILENAME): $(META_DIR)/$(dir)/$(GOFILES_META).stamp \ - $(gofiles__$(dir)) \ +$(foreach dir, $(DEFAULTER_DIRS), $(eval \ + $(dir)/$(DEFAULTER_FILENAME): $($(PRJ_SRC_PATH)/$(dir)) \ )) -# For each dir in DEFAULTER_DIRS, for each target in $(defaulters__$(dir)), -# this establishes a dependency between the output file and the input files -# that should trigger a rebuild. -# -# The variable value was set in $(GOFILES_META) and included as part of the -# dependency management logic. -# -# Note that this is a deps-only statement, not a full rule (see below). This -# has to be done in a distinct step because wildcards don't work in static -# pattern rules. -# -# The '$(eval)' is needed because this has a different RHS for each LHS, and -# would otherwise produce results that make can't parse. -# -# We depend on the $(GOFILES_META).stamp to detect when the set of input files -# has changed. This allows us to detect deleted input files. -$(foreach dir, $(DEFAULTER_DIRS), \ - $(foreach tgt, $(defaulters__$(dir)), $(eval \ - $(dir)/$(DEFAULTER_FILENAME): $(META_DIR)/$(tgt)/$(GOFILES_META).stamp \ - $(gofiles__$(tgt)) \ - )) \ -) - -# Unilaterally remove any leftovers from previous runs. -$(shell rm -f $(META_DIR)/$(DEFAULTER_GEN)*.todo) - # How to regenerate defaulter code. This is a little slow to run, so we batch # it up and trigger the batch from the 'generated_files' target. +$(META_DIR)/$(DEFAULTER_GEN).todo: $(DEFAULTER_FILES) + $(DEFAULTER_FILES): $(DEFAULTER_GEN) - mkdir -p $$(dirname $(META_DIR)/$(DEFAULTER_GEN)) if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ echo "DBG: defaulter needed $(@D): $?"; \ ls -lf --full-time $@ $? || true; \ fi echo $(PRJ_SRC_PATH)/$(@D) >> $(META_DIR)/$(DEFAULTER_GEN).todo -# This calculates the dependencies for the generator tool, so we only rebuild -# it when needed. It is PHONY so that it always runs, but it only updates the -# file if the contents have actually changed. We 'sinclude' this later. -.PHONY: $(META_DIR)/$(DEFAULTER_GEN).mk -$(META_DIR)/$(DEFAULTER_GEN).mk: - mkdir -p $(@D); \ - (echo -n "$(DEFAULTER_GEN): "; \ - ./hack/run-in-gopath.sh go list \ - -f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \ - ./vendor/k8s.io/code-generator/cmd/defaulter-gen \ - | grep --color=never "^$(PRJ_SRC_PATH)/" \ - | xargs ./hack/run-in-gopath.sh go list \ - -f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \ - | paste -sd' ' - \ - | sed 's/ / \\=,/g' \ - | tr '=,' '\n\t' \ - | sed "s|$$(pwd -P)/||"; \ - ) > $@.tmp; \ - if ! cmp -s $@.tmp $@; then \ - if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ - echo "DBG: $(DEFAULTER_GEN).mk changed"; \ - fi; \ - cat $@.tmp > $@; \ - rm -f $@.tmp; \ - fi - -# Include dependency info for the generator tool. This will cause the rule of -# the same name to be considered and if it is updated, make will restart. -sinclude $(META_DIR)/$(DEFAULTER_GEN).mk - # How to build the generator tool. The deps for this are defined in -# the $(DEFAULTER_GEN).mk, above. +# the $(GO_PKGDEPS_FILE), above. # # A word on the need to touch: This rule might trigger if, for example, a # non-Go file was added or deleted from a directory on which this depends. # This target needs to be reconsidered, but Go realizes it doesn't actually # have to be rebuilt. In that case, make will forever see the dependency as -# newer than the binary, and try to rebuild it over and over. So we touch it, -# and make is happy. -$(DEFAULTER_GEN): +# newer than the binary, and try to "rebuild" it over and over. So we touch +# it, and make is happy. +$(DEFAULTER_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/defaulter-gen) hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/defaulter-gen touch $@ -# + # Conversion generation # # Any package that wants conversion functions generated must include one or @@ -526,171 +334,52 @@ CONVERSION_DIRS := $(shell \ CONVERSION_FILES := $(addsuffix /$(CONVERSION_FILENAME), $(CONVERSION_DIRS)) CONVERSION_EXTRA_PEER_DIRS := k8s.io/kubernetes/pkg/apis/core,k8s.io/kubernetes/pkg/apis/core/v1,k8s.io/api/core/v1 -# Shell function for reuse in rules. -RUN_GEN_CONVERSION = \ - function run_gen_conversion() { \ - if [[ -f $(META_DIR)/$(CONVERSION_GEN).todo ]]; then \ - pkgs=$$(cat $(META_DIR)/$(CONVERSION_GEN).todo | paste -sd, -); \ - if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ - echo "DBG: running $(CONVERSION_GEN) for $$pkgs"; \ - fi; \ - ./hack/run-in-gopath.sh $(CONVERSION_GEN) \ - --extra-peer-dirs $(CONVERSION_EXTRA_PEER_DIRS) \ - --v $(KUBE_VERBOSE) \ - --logtostderr \ - -i "$$pkgs" \ - -O $(CONVERSION_BASENAME) \ - "$$@"; \ - fi \ - }; \ - run_gen_conversion +# Reset the list of packages that need generation. +$(shell mkdir -p $$(dirname $(META_DIR)/$(CONVERSION_GEN))) +$(shell rm -f $(META_DIR)/$(CONVERSION_GEN).todo) # This rule aggregates the set of files to generate and then generates them all # in a single run of the tool. .PHONY: gen_conversion -gen_conversion: $(CONVERSION_FILES) $(CONVERSION_GEN) - $(RUN_GEN_CONVERSION) - -.PHONY: verify_gen_conversion -verify_gen_conversion: $(CONVERSION_GEN) - $(RUN_GEN_CONVERSION) --verify-only - -# Establish a dependency between the deps file and the dir. Whenever a dir -# changes (files added or removed) the deps file will be considered stale. -# -# This is looser than we really need (e.g. we don't really care about non *.go -# files or even *_test.go files), but this is much easier to represent. -# -# Because we 'sinclude' the deps file, it is considered for rebuilding, as part -# of make's normal evaluation. If it gets rebuilt, make will restart. -# -# The '$(eval)' is needed because this has a different RHS for each LHS, and -# would otherwise produce results that make can't parse. -$(foreach dir, $(CONVERSION_DIRS), $(eval \ - $(META_DIR)/$(dir)/$(CONVERSIONS_META): $(dir) \ -)) - -# How to rebuild a deps file. When make determines that the deps file is stale -# (see above), it executes this rule, and then re-loads the deps file. -# -# This is looser than we really need (e.g. we don't really care about test -# files), but this is MUCH faster than calling `go list`. -# -# We regenerate the output file in order to satisfy make's "newer than" rules, -# but we only need to rebuild targets if the contents actually changed. That -# is what the .stamp file represents. -$(foreach dir, $(CONVERSION_DIRS), \ - $(META_DIR)/$(dir)/$(CONVERSIONS_META)): - TAGS=$$(grep --color=never -h '^// *+k8s:conversion-gen=' $$@.tmp; \ - if ! cmp -s $@.tmp $@; then \ - if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ - echo "DBG: conversions changed for $@"; \ - fi; \ - touch $@.stamp; \ - fi; \ - mv $@.tmp $@ - -# Include any deps files as additional Makefile rules. This triggers make to -# consider the deps files for rebuild, which makes the whole -# dependency-management logic work. 'sinclude' is "silent include" which does -# not fail if the file does not exist. -$(foreach dir, $(CONVERSION_DIRS), $(eval \ - sinclude $(META_DIR)/$(dir)/$(CONVERSIONS_META) \ -)) +gen_conversion: $(CONVERSION_GEN) $(META_DIR)/$(CONVERSION_GEN).todo + if [[ -s $(META_DIR)/$(CONVERSION_GEN).todo ]]; then \ + pkgs=$$(cat $(META_DIR)/$(CONVERSION_GEN).todo | paste -sd, -); \ + if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ + echo "DBG: running $(CONVERSION_GEN) for $$pkgs"; \ + fi; \ + ./hack/run-in-gopath.sh $(CONVERSION_GEN) \ + --extra-peer-dirs $(CONVERSION_EXTRA_PEER_DIRS) \ + --v $(KUBE_VERBOSE) \ + --logtostderr \ + -i "$$pkgs" \ + -O $(CONVERSION_BASENAME) \ + "$$@"; \ + fi # For each dir in CONVERSION_DIRS, this establishes a dependency between the # output file and the input files that should trigger a rebuild. # -# The variable value was set in $(GOFILES_META) and included as part of the -# dependency management logic. -# -# Note that this is a deps-only statement, not a full rule (see below). This -# has to be done in a distinct step because wildcards don't work in static -# pattern rules. +# Note that this is a deps-only statement, not a full rule (see below for that). # # The '$(eval)' is needed because this has a different RHS for each LHS, and # would otherwise produce results that make can't parse. -# -# We depend on the $(GOFILES_META).stamp to detect when the set of input files -# has changed. This allows us to detect deleted input files. -$(foreach dir, $(CONVERSION_DIRS), $(eval \ - $(dir)/$(CONVERSION_FILENAME): $(META_DIR)/$(dir)/$(GOFILES_META).stamp \ - $(gofiles__$(dir)) \ +$(foreach dir, $(CONVERSION_DIRS), $(eval \ + $(dir)/$(CONVERSION_FILENAME): $($(PRJ_SRC_PATH)/$(dir)) \ )) -# For each dir in CONVERSION_DIRS, for each target in $(conversions__$(dir)), -# this establishes a dependency between the output file and the input files -# that should trigger a rebuild. -# -# The variable value was set in $(GOFILES_META) and included as part of the -# dependency management logic. -# -# Note that this is a deps-only statement, not a full rule (see below). This -# has to be done in a distinct step because wildcards don't work in static -# pattern rules. -# -# The '$(eval)' is needed because this has a different RHS for each LHS, and -# would otherwise produce results that make can't parse. -# -# We depend on the $(GOFILES_META).stamp to detect when the set of input files -# has changed. This allows us to detect deleted input files. -$(foreach dir, $(CONVERSION_DIRS), \ - $(foreach tgt, $(conversions__$(dir)), $(eval \ - $(dir)/$(CONVERSION_FILENAME): $(META_DIR)/$(tgt)/$(GOFILES_META).stamp \ - $(gofiles__$(tgt)) \ - )) \ -) - -# Unilaterally remove any leftovers from previous runs. -$(shell rm -f $(META_DIR)/$(CONVERSION_GEN)*.todo) - # How to regenerate conversion code. This is a little slow to run, so we batch # it up and trigger the batch from the 'generated_files' target. +$(META_DIR)/$(CONVERSION_GEN).todo: $(CONVERSION_FILES) + $(CONVERSION_FILES): $(CONVERSION_GEN) - mkdir -p $$(dirname $(META_DIR)/$(CONVERSION_GEN)) if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ echo "DBG: conversion needed $(@D): $?"; \ ls -lf --full-time $@ $? || true; \ fi echo $(PRJ_SRC_PATH)/$(@D) >> $(META_DIR)/$(CONVERSION_GEN).todo -# This calculates the dependencies for the generator tool, so we only rebuild -# it when needed. It is PHONY so that it always runs, but it only updates the -# file if the contents have actually changed. We 'sinclude' this later. -.PHONY: $(META_DIR)/$(CONVERSION_GEN).mk -$(META_DIR)/$(CONVERSION_GEN).mk: - mkdir -p $(@D); \ - (echo -n "$(CONVERSION_GEN): "; \ - ./hack/run-in-gopath.sh go list \ - -f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \ - ./vendor/k8s.io/code-generator/cmd/conversion-gen \ - | grep --color=never "^$(PRJ_SRC_PATH)/" \ - | xargs ./hack/run-in-gopath.sh go list \ - -f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \ - | paste -sd' ' - \ - | sed 's/ / \\=,/g' \ - | tr '=,' '\n\t' \ - | sed "s|$$(pwd -P)/||"; \ - ) > $@.tmp; \ - if ! cmp -s $@.tmp $@; then \ - if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ - echo "DBG: $(CONVERSION_GEN).mk changed"; \ - fi; \ - cat $@.tmp > $@; \ - rm -f $@.tmp; \ - fi - -# Include dependency info for the generator tool. This will cause the rule of -# the same name to be considered and if it is updated, make will restart. -sinclude $(META_DIR)/$(CONVERSION_GEN).mk - # How to build the generator tool. The deps for this are defined in -# the $(CONVERSION_GEN).mk, above. +# the $(GO_PKGDEPS_FILE), above. # # A word on the need to touch: This rule might trigger if, for example, a # non-Go file was added or deleted from a directory on which this depends. @@ -698,12 +387,12 @@ sinclude $(META_DIR)/$(CONVERSION_GEN).mk # have to be rebuilt. In that case, make will forever see the dependency as # newer than the binary, and try to rebuild it over and over. So we touch it, # and make is happy. -$(CONVERSION_GEN): +$(CONVERSION_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/conversion-gen) hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/conversion-gen touch $@ -# -# Open-api generation + +# OpenAPI generation # # Any package that wants open-api functions generated must include a # comment-tag in column 0 of one file of the form: @@ -736,77 +425,38 @@ gen_openapi: $(OPENAPI_OUTFILE) $(OPENAPI_GEN) # For each dir in OPENAPI_DIRS, this establishes a dependency between the # output file and the input files that should trigger a rebuild. # -# Note that this is a deps-only statement, not a full rule (see below). This -# has to be done in a distinct step because wildcards don't work in static -# pattern rules. +# Note that this is a deps-only statement, not a full rule (see below for that). # # The '$(eval)' is needed because this has a different RHS for each LHS, and # would otherwise produce results that make can't parse. -# -# We depend on the $(GOFILES_META).stamp to detect when the set of input files -# has changed. This allows us to detect deleted input files. -$(foreach dir, $(OPENAPI_DIRS), $(eval \ - $(OPENAPI_OUTFILE): $(META_DIR)/$(dir)/$(GOFILES_META).stamp \ - $(gofiles__$(dir)) \ +$(foreach dir, $(OPENAPI_DIRS), $(eval \ + $(OPENAPI_OUTFILE): $($(PRJ_SRC_PATH)/$(dir)) \ )) # How to regenerate open-api code. This emits a single file for all results. -$(OPENAPI_OUTFILE): $(OPENAPI_GEN) $(OPENAPI_GEN) - function run_gen_openapi() { \ - ./hack/run-in-gopath.sh $(OPENAPI_GEN) \ - --v $(KUBE_VERBOSE) \ - --logtostderr \ - -i $$(echo $(addprefix $(PRJ_SRC_PATH)/, $(OPENAPI_DIRS)) | sed 's/ /,/g') \ - -p $(PRJ_SRC_PATH)/$(OPENAPI_OUTPUT_PKG) \ - -O $(OPENAPI_BASENAME) \ - "$$@"; \ - }; \ - run_gen_openapi - -# This calculates the dependencies for the generator tool, so we only rebuild -# it when needed. It is PHONY so that it always runs, but it only updates the -# file if the contents have actually changed. We 'sinclude' this later. -.PHONY: $(META_DIR)/$(OPENAPI_GEN).mk -$(META_DIR)/$(OPENAPI_GEN).mk: - mkdir -p $(@D); \ - (echo -n "$(OPENAPI_GEN): "; \ - ./hack/run-in-gopath.sh go list \ - -f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \ - ./vendor/k8s.io/code-generator/cmd/openapi-gen \ - | grep --color=never "^$(PRJ_SRC_PATH)/" \ - | xargs ./hack/run-in-gopath.sh go list \ - -f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \ - | paste -sd' ' - \ - | sed 's/ / \\=,/g' \ - | tr '=,' '\n\t' \ - | sed "s|$$(pwd -P)/||"; \ - ) > $@.tmp; \ - if ! cmp -s $@.tmp $@; then \ - if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ - echo "DBG: $(OPENAPI_GEN).mk changed"; \ - fi; \ - cat $@.tmp > $@; \ - rm -f $@.tmp; \ - fi - -# Include dependency info for the generator tool. This will cause the rule of -# the same name to be considered and if it is updated, make will restart. -sinclude $(META_DIR)/$(OPENAPI_GEN).mk +$(OPENAPI_OUTFILE): $(OPENAPI_GEN) + ./hack/run-in-gopath.sh $(OPENAPI_GEN) \ + --v $(KUBE_VERBOSE) \ + --logtostderr \ + -i $$(echo $(addprefix $(PRJ_SRC_PATH)/, $(OPENAPI_DIRS)) | sed 's/ /,/g') \ + -p $(PRJ_SRC_PATH)/$(OPENAPI_OUTPUT_PKG) \ + -O $(OPENAPI_BASENAME) \ + "$$@" # How to build the generator tool. The deps for this are defined in -# the $(OPENAPI_GEN).mk, above. +# the $(GO_PKGDEPS_FILE), above. # # A word on the need to touch: This rule might trigger if, for example, a # non-Go file was added or deleted from a directory on which this depends. # This target needs to be reconsidered, but Go realizes it doesn't actually # have to be rebuilt. In that case, make will forever see the dependency as -# newer than the binary, and try to rebuild it over and over. So we touch it, -# and make is happy. -$(OPENAPI_GEN): +# newer than the binary, and try to "rebuild" it over and over. So we touch +# it, and make is happy. +$(OPENAPI_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/openapi-gen) hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/openapi-gen touch $@ -# + # bindata generation # @@ -822,38 +472,6 @@ BINDATA_SCRIPT := hack/generate-bindata.sh gen_bindata: $(BINDATA_GEN) FORCE ./hack/run-in-gopath.sh $(BINDATA_SCRIPT) -FORCE: - -# This calculates the dependencies for the generator tool, so we only rebuild -# it when needed. It is PHONY so that it always runs, but it only updates the -# file if the contents have actually changed. We 'sinclude' this later. -.PHONY: $(META_DIR)/$(BINDATA_GEN).mk -$(META_DIR)/$(BINDATA_GEN).mk: - mkdir -p $(@D); \ - (echo -n "$(BINDATA_GEN): "; \ - ./hack/run-in-gopath.sh go list \ - -f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \ - ./vendor/github.com/jteeuwen/go-bindata/go-bindata \ - | grep --color=never "^$(PRJ_SRC_PATH)/" \ - | xargs ./hack/run-in-gopath.sh go list \ - -f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \ - | paste -sd' ' - \ - | sed 's/ / \\=,/g' \ - | tr '=,' '\n\t' \ - | sed "s|$$(pwd -P)/||"; \ - ) > $@.tmp; \ - if ! cmp -s $@.tmp $@; then \ - if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ - echo "DBG: $(BINDATA_GEN).mk changed"; \ - fi; \ - cat $@.tmp > $@; \ - rm -f $@.tmp; \ - fi - -# Include dependency info for the generator tool. This will cause the rule of -# the same name to be considered and if it is updated, make will restart. -sinclude $(META_DIR)/$(BINDATA_GEN).mk - # How to build the generator tool. The deps for this are defined in # the $(BINDATA_GEN).mk, above. # @@ -863,6 +481,6 @@ sinclude $(META_DIR)/$(BINDATA_GEN).mk # have to be rebuilt. In that case, make will forever see the dependency as # newer than the binary, and try to rebuild it over and over. So we touch it, # and make is happy. -$(BINDATA_GEN): +$(BINDATA_GEN): $(k8s.io/kubernetes/vendor/github.com/jteeuwen/go-bindata/go-bindata) hack/make-rules/build.sh ./vendor/github.com/jteeuwen/go-bindata/go-bindata touch $@ diff --git a/build/root/WORKSPACE b/build/root/WORKSPACE index bef78c3677b..f2908b1b2db 100644 --- a/build/root/WORKSPACE +++ b/build/root/WORKSPACE @@ -1,4 +1,5 @@ load("//build:workspace_mirror.bzl", "mirror") +load("//build:workspace.bzl", "CRI_TOOLS_VERSION") http_archive( name = "io_bazel_rules_go", @@ -58,6 +59,12 @@ http_file( urls = mirror("https://storage.googleapis.com/kubernetes-release/network-plugins/cni-plugins-amd64-v0.6.0.tgz"), ) +http_file( + name = "cri_tools", + sha256 = "672cdc7670003949bb247fb2e3e0dccab74de0075fc283d6579e88a6c1ab3256", + urls = mirror("https://github.com/kubernetes-incubator/cri-tools/releases/download/v%s/crictl-v%s-linux-amd64.tar.gz" % (CRI_TOOLS_VERSION, CRI_TOOLS_VERSION)), +) + docker_pull( name = "debian-iptables-amd64", digest = "sha256:fb18678f8203ca1bd2fad2671e3ebd80cb408a1baae423d4ad39c05f4caac4e1", diff --git a/build/rpms/10-kubeadm.conf b/build/rpms/10-kubeadm.conf index 8472af6aa24..19475e59ac9 100644 --- a/build/rpms/10-kubeadm.conf +++ b/build/rpms/10-kubeadm.conf @@ -1,14 +1,11 @@ +# Note: This dropin only works with kubeadm and kubelet v1.11+ [Service] -EnvironmentFile=-/etc/sysconfig/kubelet Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf" -Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true" -Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin" -Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local" -Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt" -# Value should match Docker daemon settings. -# Defaults are "cgroupfs" for Debian/Ubuntu/OpenSUSE and "systemd" for Fedora/CentOS/RHEL -Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=systemd" -Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0" -Environment="KUBELET_CERTIFICATE_ARGS=--rotate-certificates=true" +Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml" +# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically +EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env +# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use +# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file. +EnvironmentFile=-/etc/sysconfig/kubelet ExecStart= -ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CGROUP_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS +ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS diff --git a/build/rpms/BUILD b/build/rpms/BUILD index 041607c94bd..8a5017212b0 100644 --- a/build/rpms/BUILD +++ b/build/rpms/BUILD @@ -1,10 +1,12 @@ package(default_visibility = ["//visibility:public"]) load("@bazel_tools//tools/build_defs/pkg:rpm.bzl", "pkg_rpm") +load("//build:workspace.bzl", "CRI_TOOLS_VERSION") filegroup( name = "rpms", srcs = [ + ":cri-tools", ":kubeadm", ":kubectl", ":kubelet", @@ -65,6 +67,17 @@ pkg_rpm( version_file = "//build:cni_package_version", ) +pkg_rpm( + name = "cri-tools", + architecture = "x86_64", + data = [ + "@cri_tools//file", + ], + spec_file = "cri-tools.spec", + tags = ["manual"], + version = CRI_TOOLS_VERSION, +) + filegroup( name = "package-srcs", srcs = glob(["**"]), diff --git a/build/rpms/cri-tools.spec b/build/rpms/cri-tools.spec new file mode 100644 index 00000000000..6a6f3f8f1a8 --- /dev/null +++ b/build/rpms/cri-tools.spec @@ -0,0 +1,21 @@ +Name: cri-tools +Version: OVERRIDE_THIS +Release: 00 +License: ASL 2.0 +Summary: Container Runtime Interface tools + +URL: https://kubernetes.io + +%description +Binaries to interface with the container runtime. + +%prep +# This has to be hard coded because bazel does a path substitution before rpm's %{version} is substituted. +tar -xzf {crictl-v1.11.0-linux-amd64.tar.gz} + +%install +install -m 755 -d %{buildroot}%{_bindir} +install -p -m 755 -t %{buildroot}%{_bindir} crictl + +%files +%{_bindir}/crictl diff --git a/build/visible_to/BUILD b/build/visible_to/BUILD index 8e883787192..9ba4b3ce50c 100644 --- a/build/visible_to/BUILD +++ b/build/visible_to/BUILD @@ -202,22 +202,12 @@ package_group( ], ) -package_group( - name = "pkg_kubectl_cmd_util_CONSUMERS_BAD", - includes = [ - ":KUBEADM_BAD", - ], - packages = [ - "//cmd/kube-proxy/app", - ], -) - package_group( name = "pkg_kubectl_cmd_util_CONSUMERS", includes = [ ":COMMON_generators", ":COMMON_testing", - ":pkg_kubectl_cmd_util_CONSUMERS_BAD", + ":KUBEADM_BAD", ], packages = [ "//cmd/kubectl", diff --git a/build/workspace.bzl b/build/workspace.bzl new file mode 100644 index 00000000000..d55d8c11cac --- /dev/null +++ b/build/workspace.bzl @@ -0,0 +1,15 @@ +# 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. + +CRI_TOOLS_VERSION = "1.11.0" diff --git a/cluster/addons/calico-policy-controller/globalbgpconfig-crd.yaml b/cluster/addons/calico-policy-controller/globalbgpconfig-crd.yaml index 2d3e6bd2849..a0a98b8cc71 100644 --- a/cluster/addons/calico-policy-controller/globalbgpconfig-crd.yaml +++ b/cluster/addons/calico-policy-controller/globalbgpconfig-crd.yaml @@ -1,5 +1,4 @@ apiVersion: apiextensions.k8s.io/v1beta1 -description: Calico Global BGP Configuration kind: CustomResourceDefinition metadata: name: globalbgpconfigs.crd.projectcalico.org diff --git a/cluster/addons/calico-policy-controller/globalfelixconfig-crd.yaml b/cluster/addons/calico-policy-controller/globalfelixconfig-crd.yaml index 7e5c7b19699..619bdb91ece 100644 --- a/cluster/addons/calico-policy-controller/globalfelixconfig-crd.yaml +++ b/cluster/addons/calico-policy-controller/globalfelixconfig-crd.yaml @@ -1,5 +1,4 @@ apiVersion: apiextensions.k8s.io/v1beta1 -description: Calico Global Felix Configuration kind: CustomResourceDefinition metadata: name: globalfelixconfigs.crd.projectcalico.org diff --git a/cluster/addons/calico-policy-controller/globalnetworkpolicy-crd.yaml b/cluster/addons/calico-policy-controller/globalnetworkpolicy-crd.yaml index 398c05949b5..1a9ede8e60b 100644 --- a/cluster/addons/calico-policy-controller/globalnetworkpolicy-crd.yaml +++ b/cluster/addons/calico-policy-controller/globalnetworkpolicy-crd.yaml @@ -1,5 +1,4 @@ apiVersion: apiextensions.k8s.io/v1beta1 -description: Calico Global Network Policies kind: CustomResourceDefinition metadata: name: globalnetworkpolicies.crd.projectcalico.org diff --git a/cluster/addons/calico-policy-controller/ippool-crd.yaml b/cluster/addons/calico-policy-controller/ippool-crd.yaml index c09f73c188a..c0ffcea34f5 100644 --- a/cluster/addons/calico-policy-controller/ippool-crd.yaml +++ b/cluster/addons/calico-policy-controller/ippool-crd.yaml @@ -1,5 +1,4 @@ apiVersion: apiextensions.k8s.io/v1beta1 -description: Calico IP Pools kind: CustomResourceDefinition metadata: name: ippools.crd.projectcalico.org diff --git a/cluster/addons/dashboard/OWNERS b/cluster/addons/dashboard/OWNERS index 222788b954c..04353ada135 100644 --- a/cluster/addons/dashboard/OWNERS +++ b/cluster/addons/dashboard/OWNERS @@ -1,6 +1,12 @@ approvers: -- floreks -- maciaszczykm +- bryk reviewers: +- cheld +- cupofcat +- danielromlein - floreks +- ianlewis +- konryd - maciaszczykm +- mhenc +- rf232 diff --git a/cluster/addons/dns/Makefile b/cluster/addons/dns/coredns/Makefile similarity index 92% rename from cluster/addons/dns/Makefile rename to cluster/addons/dns/coredns/Makefile index 01f45e4ba51..d3455dd853f 100644 --- a/cluster/addons/dns/Makefile +++ b/cluster/addons/dns/coredns/Makefile @@ -29,6 +29,6 @@ all: transform %.sed: %.base sed -f transforms2sed.sed $< | sed s/__SOURCE_FILENAME__/$ $@ -transform: kube-dns.yaml.in kube-dns.yaml.sed coredns.yaml.in coredns.yaml.sed +transform: coredns.yaml.in coredns.yaml.sed .PHONY: transform diff --git a/cluster/addons/dns/coredns.yaml.base b/cluster/addons/dns/coredns/coredns.yaml.base similarity index 89% rename from cluster/addons/dns/coredns.yaml.base rename to cluster/addons/dns/coredns/coredns.yaml.base index a392c38a7d0..5e2ad3dc180 100644 --- a/cluster/addons/dns/coredns.yaml.base +++ b/cluster/addons/dns/coredns/coredns.yaml.base @@ -66,6 +66,7 @@ data: prometheus :9153 proxy . /etc/resolv.conf cache 30 + reload } --- apiVersion: extensions/v1beta1 @@ -105,7 +106,7 @@ spec: operator: "Exists" containers: - name: coredns - image: coredns/coredns:1.0.6 + image: k8s.gcr.io/coredns:1.1.3 imagePullPolicy: IfNotPresent resources: limits: @@ -117,6 +118,7 @@ spec: volumeMounts: - name: config-volume mountPath: /etc/coredns + readOnly: true ports: - containerPort: 53 name: dns @@ -124,6 +126,9 @@ spec: - containerPort: 53 name: dns-tcp protocol: TCP + - containerPort: 9153 + name: metrics + protocol: TCP livenessProbe: httpGet: path: /health @@ -133,6 +138,14 @@ spec: timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - all + readOnlyRootFilesystem: true dnsPolicy: Default volumes: - name: config-volume @@ -147,6 +160,8 @@ kind: Service metadata: name: kube-dns namespace: kube-system + annotations: + prometheus.io/scrape: "true" labels: k8s-app: kube-dns kubernetes.io/cluster-service: "true" diff --git a/cluster/addons/dns/coredns.yaml.in b/cluster/addons/dns/coredns/coredns.yaml.in similarity index 90% rename from cluster/addons/dns/coredns.yaml.in rename to cluster/addons/dns/coredns/coredns.yaml.in index 322650444f7..c74860fd340 100644 --- a/cluster/addons/dns/coredns.yaml.in +++ b/cluster/addons/dns/coredns/coredns.yaml.in @@ -66,6 +66,7 @@ data: prometheus :9153 proxy . /etc/resolv.conf cache 30 + reload } --- apiVersion: extensions/v1beta1 @@ -105,7 +106,7 @@ spec: operator: "Exists" containers: - name: coredns - image: coredns/coredns:1.0.6 + image: k8s.gcr.io/coredns:1.1.3 imagePullPolicy: IfNotPresent resources: limits: @@ -117,6 +118,7 @@ spec: volumeMounts: - name: config-volume mountPath: /etc/coredns + readOnly: true ports: - containerPort: 53 name: dns @@ -124,6 +126,9 @@ spec: - containerPort: 53 name: dns-tcp protocol: TCP + - containerPort: 9153 + name: metrics + protocol: TCP livenessProbe: httpGet: path: /health @@ -133,6 +138,14 @@ spec: timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - all + readOnlyRootFilesystem: true dnsPolicy: Default volumes: - name: config-volume @@ -147,6 +160,8 @@ kind: Service metadata: name: kube-dns namespace: kube-system + annotations: + prometheus.io/scrape: "true" labels: k8s-app: kube-dns kubernetes.io/cluster-service: "true" diff --git a/cluster/addons/dns/coredns.yaml.sed b/cluster/addons/dns/coredns/coredns.yaml.sed similarity index 90% rename from cluster/addons/dns/coredns.yaml.sed rename to cluster/addons/dns/coredns/coredns.yaml.sed index 9c4f037997b..3b6d8091963 100644 --- a/cluster/addons/dns/coredns.yaml.sed +++ b/cluster/addons/dns/coredns/coredns.yaml.sed @@ -66,6 +66,7 @@ data: prometheus :9153 proxy . /etc/resolv.conf cache 30 + reload } --- apiVersion: extensions/v1beta1 @@ -105,7 +106,7 @@ spec: operator: "Exists" containers: - name: coredns - image: coredns/coredns:1.0.6 + image: k8s.gcr.io/coredns:1.1.3 imagePullPolicy: IfNotPresent resources: limits: @@ -117,6 +118,7 @@ spec: volumeMounts: - name: config-volume mountPath: /etc/coredns + readOnly: true ports: - containerPort: 53 name: dns @@ -124,6 +126,9 @@ spec: - containerPort: 53 name: dns-tcp protocol: TCP + - containerPort: 9153 + name: metrics + protocol: TCP livenessProbe: httpGet: path: /health @@ -133,6 +138,14 @@ spec: timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - all + readOnlyRootFilesystem: true dnsPolicy: Default volumes: - name: config-volume @@ -147,6 +160,8 @@ kind: Service metadata: name: kube-dns namespace: kube-system + annotations: + prometheus.io/scrape: "true" labels: k8s-app: kube-dns kubernetes.io/cluster-service: "true" diff --git a/cluster/addons/dns/transforms2salt.sed b/cluster/addons/dns/coredns/transforms2salt.sed similarity index 100% rename from cluster/addons/dns/transforms2salt.sed rename to cluster/addons/dns/coredns/transforms2salt.sed diff --git a/cluster/addons/dns/transforms2sed.sed b/cluster/addons/dns/coredns/transforms2sed.sed similarity index 100% rename from cluster/addons/dns/transforms2sed.sed rename to cluster/addons/dns/coredns/transforms2sed.sed diff --git a/cluster/addons/dns/kube-dns/Makefile b/cluster/addons/dns/kube-dns/Makefile new file mode 100644 index 00000000000..50419ff3247 --- /dev/null +++ b/cluster/addons/dns/kube-dns/Makefile @@ -0,0 +1,34 @@ +# 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. + +# Makefile for the kubedns underscore templates to Salt/Pillar and other formats. + +# If you update the *.base templates, please run this Makefile before pushing. +# +# Usage: +# make + +all: transform + +# .base -> .in pattern rule +%.in: %.base + sed -f transforms2salt.sed $< | sed s/__SOURCE_FILENAME__/$ $@ + +# .base -> .sed pattern rule +%.sed: %.base + sed -f transforms2sed.sed $< | sed s/__SOURCE_FILENAME__/$ $@ + +transform: kube-dns.yaml.in kube-dns.yaml.sed + +.PHONY: transform diff --git a/cluster/addons/dns/README.md b/cluster/addons/dns/kube-dns/README.md similarity index 89% rename from cluster/addons/dns/README.md rename to cluster/addons/dns/kube-dns/README.md index 64cecaa72a9..f3e2c1fef7b 100644 --- a/cluster/addons/dns/README.md +++ b/cluster/addons/dns/kube-dns/README.md @@ -9,7 +9,7 @@ can use the DNS Service’s IP to resolve DNS names. ## Manually scale kube-dns Deployment kube-dns creates only one DNS Pod by default. If -[dns-horizontal-autoscaler](../dns-horizontal-autoscaler/) +[dns-horizontal-autoscaler](../../dns-horizontal-autoscaler/) is not enabled, you may need to manually scale kube-dns Deployment. Please use below `kubectl scale` command to scale: @@ -18,9 +18,9 @@ kubectl --namespace=kube-system scale deployment kube-dns --replicas=> ./config/elasticsearch.yml -exec su elasticsearch -c ./bin/es-docker +exec su elasticsearch -c /usr/local/bin/docker-entrypoint.sh diff --git a/cluster/addons/fluentd-elasticsearch/es-statefulset.yaml b/cluster/addons/fluentd-elasticsearch/es-statefulset.yaml index 36adf388313..a6178c8a5e8 100644 --- a/cluster/addons/fluentd-elasticsearch/es-statefulset.yaml +++ b/cluster/addons/fluentd-elasticsearch/es-statefulset.yaml @@ -54,7 +54,7 @@ metadata: namespace: kube-system labels: k8s-app: elasticsearch-logging - version: v5.6.4 + version: v6.2.4 kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: @@ -63,17 +63,17 @@ spec: selector: matchLabels: k8s-app: elasticsearch-logging - version: v5.6.4 + version: v6.2.4 template: metadata: labels: k8s-app: elasticsearch-logging - version: v5.6.4 + version: v6.2.4 kubernetes.io/cluster-service: "true" spec: serviceAccountName: elasticsearch-logging containers: - - image: k8s.gcr.io/elasticsearch:v5.6.4 + - image: k8s.gcr.io/elasticsearch:v6.2.4 name: elasticsearch-logging resources: # need more cpu upon initialization, therefore burstable class diff --git a/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml b/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml index c39cb5958d7..c01b90b82ba 100644 --- a/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml +++ b/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml @@ -48,35 +48,36 @@ roleRef: apiVersion: apps/v1 kind: DaemonSet metadata: - name: fluentd-es-v2.1.0 + name: fluentd-es-v2.2.0 namespace: kube-system labels: k8s-app: fluentd-es - version: v2.1.0 + version: v2.2.0 kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: selector: matchLabels: k8s-app: fluentd-es - version: v2.1.0 + version: v2.2.0 template: metadata: labels: k8s-app: fluentd-es kubernetes.io/cluster-service: "true" - version: v2.1.0 + version: v2.2.0 # This annotation ensures that fluentd does not get evicted if the node # supports critical pod annotation based priority scheme. # Note that this does not guarantee admission on the nodes (#40573). annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-node-critical serviceAccountName: fluentd-es containers: - name: fluentd-es - image: k8s.gcr.io/fluentd-elasticsearch:v2.1.0 + image: k8s.gcr.io/fluentd-elasticsearch:v2.2.0 env: - name: FLUENTD_ARGS value: --no-supervisor -q diff --git a/cluster/addons/fluentd-elasticsearch/fluentd-es-image/Gemfile b/cluster/addons/fluentd-elasticsearch/fluentd-es-image/Gemfile index 6ca3818a18b..dae30ddbbd7 100644 --- a/cluster/addons/fluentd-elasticsearch/fluentd-es-image/Gemfile +++ b/cluster/addons/fluentd-elasticsearch/fluentd-es-image/Gemfile @@ -1,11 +1,11 @@ source 'https://rubygems.org' -gem 'fluentd', '<=1.2.1' +gem 'fluentd', '<=1.2.2' gem 'activesupport', '~>5.2.0' gem 'fluent-plugin-kubernetes_metadata_filter', '~>2.1.2' -gem 'fluent-plugin-elasticsearch', '~>2.10.1' -gem 'fluent-plugin-systemd', '~>1.0.0' +gem 'fluent-plugin-elasticsearch', '~>2.10.5' +gem 'fluent-plugin-systemd', '~>1.0.1' gem 'fluent-plugin-detect-exceptions', '~>0.0.11' gem 'fluent-plugin-prometheus', '~>1.0.1' gem 'fluent-plugin-multi-format-parser', '~>1.0.0' -gem 'oj', '~>3.6.0' +gem 'oj', '~>3.6.2' diff --git a/cluster/addons/fluentd-elasticsearch/fluentd-es-image/Makefile b/cluster/addons/fluentd-elasticsearch/fluentd-es-image/Makefile index bb0680cc4f1..55e54881faa 100644 --- a/cluster/addons/fluentd-elasticsearch/fluentd-es-image/Makefile +++ b/cluster/addons/fluentd-elasticsearch/fluentd-es-image/Makefile @@ -16,7 +16,7 @@ PREFIX = staging-k8s.gcr.io IMAGE = fluentd-elasticsearch -TAG = v2.1.0 +TAG = v2.2.0 build: docker build --pull -t $(PREFIX)/$(IMAGE):$(TAG) . diff --git a/cluster/addons/fluentd-elasticsearch/kibana-deployment.yaml b/cluster/addons/fluentd-elasticsearch/kibana-deployment.yaml index 8cd00fe52e5..b80525d2027 100644 --- a/cluster/addons/fluentd-elasticsearch/kibana-deployment.yaml +++ b/cluster/addons/fluentd-elasticsearch/kibana-deployment.yaml @@ -16,10 +16,12 @@ spec: metadata: labels: k8s-app: kibana-logging + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: containers: - name: kibana-logging - image: docker.elastic.co/kibana/kibana:5.6.4 + image: docker.elastic.co/kibana/kibana-oss:6.2.4 resources: # need more cpu upon initialization, therefore burstable class limits: @@ -31,10 +33,6 @@ spec: value: http://elasticsearch-logging:9200 - name: SERVER_BASEPATH value: /api/v1/namespaces/kube-system/services/kibana-logging/proxy - - name: XPACK_MONITORING_ENABLED - value: "false" - - name: XPACK_SECURITY_ENABLED - value: "false" ports: - containerPort: 5601 name: ui diff --git a/cluster/addons/istio/auth/istio-auth.yaml b/cluster/addons/istio/auth/istio-auth.yaml index f87d4f2b201..5b30bb3b9d5 100644 --- a/cluster/addons/istio/auth/istio-auth.yaml +++ b/cluster/addons/istio/auth/istio-auth.yaml @@ -1,15 +1,17 @@ -# GENERATED FILE. Use with Kubernetes 1.7+ -# TO UPDATE, modify files in install/kubernetes/templates and run install/updateVersion.sh -# -# Required for Istio as k8s addon. apiVersion: v1 kind: Namespace metadata: - name: default + name: kube-public labels: - istio-injection: enabled - addonmanager.kubernetes.io/mode: Reconcile --- + istio-injection: disabled +--- +apiVersion: v1 +kind: Namespace +metadata: + name: kube-system + labels: + istio-injection: disabled +--- ################################ # Istio system namespace ################################ @@ -20,1874 +22,540 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + istio-injection: disabled --- -################################ -# Istio RBAC -################################ -# Permissions and roles for istio -# To debug: start the cluster with -vmodule=rbac,3 to enable verbose logging on RBAC DENY -# Also helps to enable logging on apiserver 'wrap' to see the URLs. -# Each RBAC deny needs to be mapped into a rule for the role. -# If using minikube, start with '--extra-config=apiserver.Authorization.Mode=RBAC' -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-pilot-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["config.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["*"] -- apiGroups: ["extensions"] - resources: ["thirdpartyresources", "thirdpartyresources.extensions", "ingresses", "ingresses/status"] - verbs: ["*"] -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["create", "get", "list", "watch", "update"] -- apiGroups: [""] - resources: ["endpoints", "pods", "services"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["namespaces", "nodes", "secrets"] - verbs: ["get", "list", "watch"] -- apiGroups: ["admissionregistration.k8s.io"] - resources: ["externaladmissionhookconfigurations"] - verbs: ["create", "update", "delete"] ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-injector-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["*"] - resources: ["configmaps"] - verbs: ["get", "list", "watch"] ---- -# Mixer CRD needs to watch and list CRDs -# It also uses discovery API to discover Kinds of config.istio.io -# K8s adapter needs to list pods, services etc. -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-mixer-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["config.istio.io"] # Istio CRD watcher - resources: ["*"] - verbs: ["get", "list", "watch"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] - verbs: ["get", "list", "watch"] ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-ca-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["create", "get", "watch", "list", "update"] -- apiGroups: [""] - resources: ["serviceaccounts"] - verbs: ["get", "watch", "list"] -- apiGroups: [""] - resources: ["services"] - verbs: ["get", "watch", "list"] ---- -# Permissions for the sidecar proxy. -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["extensions"] - resources: ["thirdpartyresources", "ingresses"] - verbs: ["get", "watch", "list", "update"] -- apiGroups: [""] - resources: ["configmaps", "pods", "endpoints", "services"] - verbs: ["get", "watch", "list"] ---- -# Grant permissions to the Pilot/discovery. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-pilot-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-pilot-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-pilot-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the Sidecar sidecar-injector -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-injector-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-sidecar-injector-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-sidecar-injector-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the CA. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-ca-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-ca-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-ca-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the Ingress controller. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-ingress-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-ingress-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-pilot-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the sidecar. -# TEMPORARY: the istioctl should generate a separate service account for the proxy, and permission -# granted only to that account ! -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: default - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-sidecar-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to Mixer. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-mixer-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-mixer-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-mixer-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Mixer +# Source: istio/charts/mixer/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: - name: istio-mixer + name: istio-statsd-prom-bridge namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-statsd-prom-bridge + chart: mixer-0.8.0 + release: istio + heritage: Tiller + istio: mixer data: mapping.conf: |- --- apiVersion: v1 -kind: Service -metadata: - name: istio-mixer - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - istio: mixer -spec: - ports: - - name: tcp-plain - port: 9091 - - name: tcp-mtls - port: 15004 - - name: http-monitoring - port: 9093 - - name: configapi - port: 9094 - - name: statsd-prom - port: 9102 - - name: statsd-udp - port: 9125 - protocol: UDP - - name: prometheus - port: 42422 - selector: - istio: mixer ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-mixer-service-account - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: istio-mixer - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - template: - metadata: - labels: - istio: mixer - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-mixer-service-account - containers: - - name: statsd-to-prometheus - image: gcr.io/istio-release/statsd-exporter:v0.5.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9102 - - containerPort: 9125 - protocol: UDP - args: - - '-statsd.mapping-config=/etc/statsd/mapping.conf' - volumeMounts: - - name: config-volume - mountPath: /etc/statsd - - name: mixer - image: gcr.io/istio-release/mixer:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9091 - - containerPort: 9093 - - containerPort: 9094 - - containerPort: 42422 - args: - - --configStoreURL=k8s:// - - --configDefaultNamespace=istio-system - - --zipkinURL=http://zipkin:9411/api/v1/spans - - --logtostderr - - -v - - "2" - - name: istio-proxy - image: gcr.io/istio-release/proxy:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15004 - args: - - proxy - - mixer - - -v - - "2" - - --controlPlaneAuthPolicy - - MUTUAL_TLS - - --customConfigFile - - /etc/istio/proxy/envoy_mixer_auth.json - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - volumes: - - name: istio-certs - secret: - secretName: istio.istio-mixer-service-account - optional: true - - name: config-volume - configMap: - name: istio-mixer ---- -# Mixer CRD definitions are generated using -# mixs crd all - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: rules.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: istio.io.mixer - istio: core -spec: - group: config.istio.io - names: - kind: rule - plural: rules - singular: rule - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: attributemanifests.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: istio.io.mixer - istio: core -spec: - group: config.istio.io - names: - kind: attributemanifest - plural: attributemanifests - singular: attributemanifest - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: circonuses.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: circonus - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: circonus - plural: circonuses - singular: circonus - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: deniers.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: denier - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: denier - plural: deniers - singular: denier - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: fluentds.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: fluentd - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: fluentd - plural: fluentds - singular: fluentd - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: kubernetesenvs.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: kubernetesenv - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: kubernetesenv - plural: kubernetesenvs - singular: kubernetesenv - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: listcheckers.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: listchecker - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: listchecker - plural: listcheckers - singular: listchecker - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: memquotas.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: memquota - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: memquota - plural: memquotas - singular: memquota - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: noops.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: noop - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: noop - plural: noops - singular: noop - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: opas.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: opa - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: opa - plural: opas - singular: opa - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: prometheuses.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: prometheus - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: prometheus - plural: prometheuses - singular: prometheus - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: rbacs.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: rbac - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: rbac - plural: rbacs - singular: rbac - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: servicecontrols.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: servicecontrol - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: servicecontrol - plural: servicecontrols - singular: servicecontrol - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: solarwindses.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: solarwinds - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: solarwinds - plural: solarwindses - singular: solarwinds - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: stackdrivers.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: stackdriver - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: stackdriver - plural: stackdrivers - singular: stackdriver - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: statsds.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: statsd - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: statsd - plural: statsds - singular: statsd - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: stdios.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: stdio - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: stdio - plural: stdios - singular: stdio - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: apikeys.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: apikey - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: apikey - plural: apikeys - singular: apikey - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: authorizations.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: authorization - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: authorization - plural: authorizations - singular: authorization - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: checknothings.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: checknothing - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: checknothing - plural: checknothings - singular: checknothing - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: kuberneteses.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: adapter.template.kubernetes - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: kubernetes - plural: kuberneteses - singular: kubernetes - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: listentries.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: listentry - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: listentry - plural: listentries - singular: listentry - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: logentries.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: logentry - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: logentry - plural: logentries - singular: logentry - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: metrics.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: metric - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: metric - plural: metrics - singular: metric - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: quotas.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: quota - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: quota - plural: quotas - singular: quota - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: reportnothings.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: reportnothing - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: reportnothing - plural: reportnothings - singular: reportnothing - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: servicecontrolreports.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: servicecontrolreport - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: servicecontrolreport - plural: servicecontrolreports - singular: servicecontrolreport - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: tracespans.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: tracespan - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: tracespan - plural: tracespans - singular: tracespan - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: serviceroles.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio: rbac -spec: - group: config.istio.io - names: - kind: ServiceRole - plural: serviceroles - singular: servicerole - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: servicerolebindings.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio: rbac -spec: - group: config.istio.io - names: - kind: ServiceRoleBinding - plural: servicerolebindings - singular: servicerolebinding - scope: Namespaced - version: v1alpha2 ---- - -apiVersion: "config.istio.io/v1alpha2" -kind: attributemanifest -metadata: - name: istioproxy - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - attributes: - origin.ip: - valueType: IP_ADDRESS - origin.uid: - valueType: STRING - origin.user: - valueType: STRING - request.headers: - valueType: STRING_MAP - request.id: - valueType: STRING - request.host: - valueType: STRING - request.method: - valueType: STRING - request.path: - valueType: STRING - request.reason: - valueType: STRING - request.referer: - valueType: STRING - request.scheme: - valueType: STRING - request.size: - valueType: INT64 - request.time: - valueType: TIMESTAMP - request.useragent: - valueType: STRING - response.code: - valueType: INT64 - response.duration: - valueType: DURATION - response.headers: - valueType: STRING_MAP - response.size: - valueType: INT64 - response.time: - valueType: TIMESTAMP - source.uid: - valueType: STRING - source.user: - valueType: STRING - destination.uid: - valueType: STRING - connection.id: - valueType: STRING - connection.received.bytes: - valueType: INT64 - connection.received.bytes_total: - valueType: INT64 - connection.sent.bytes: - valueType: INT64 - connection.sent.bytes_total: - valueType: INT64 - connection.duration: - valueType: DURATION - context.protocol: - valueType: STRING - context.timestamp: - valueType: TIMESTAMP - context.time: - valueType: TIMESTAMP - api.service: - valueType: STRING - api.version: - valueType: STRING - api.operation: - valueType: STRING - api.protocol: - valueType: STRING - request.auth.principal: - valueType: STRING - request.auth.audiences: - valueType: STRING - request.auth.presenter: - valueType: STRING - request.api_key: - valueType: STRING - ---- -apiVersion: "config.istio.io/v1alpha2" -kind: attributemanifest -metadata: - name: kubernetes - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - attributes: - source.ip: - valueType: IP_ADDRESS - source.labels: - valueType: STRING_MAP - source.name: - valueType: STRING - source.namespace: - valueType: STRING - source.service: - valueType: STRING - source.serviceAccount: - valueType: STRING - destination.ip: - valueType: IP_ADDRESS - destination.labels: - valueType: STRING_MAP - destination.name: - valueType: STRING - destination.namespace: - valueType: STRING - destination.service: - valueType: STRING - destination.serviceAccount: - valueType: STRING ---- -apiVersion: "config.istio.io/v1alpha2" -kind: stdio -metadata: - name: handler - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - outputAsJson: true ---- -apiVersion: "config.istio.io/v1alpha2" -kind: logentry -metadata: - name: accesslog - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - severity: '"Default"' - timestamp: request.time - variables: - sourceIp: source.ip | ip("0.0.0.0") - destinationIp: destination.ip | ip("0.0.0.0") - sourceUser: source.user | "" - method: request.method | "" - url: request.path | "" - protocol: request.scheme | "http" - responseCode: response.code | 0 - responseSize: response.size | 0 - requestSize: request.size | 0 - latency: response.duration | "0ms" - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: stdio - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - match: "true" # If omitted match is true. - actions: - - handler: handler.stdio - instances: - - accesslog.logentry ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: requestcount - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - value: "1" - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: requestduration - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - value: response.duration | "0ms" - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: requestsize - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - value: request.size | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: responsesize - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - value: response.size | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: tcpbytesent - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp -spec: - value: connection.sent.bytes | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: tcpbytereceived - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp -spec: - value: connection.received.bytes | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: prometheus -metadata: - name: handler - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - metrics: - - name: request_count - instance_name: requestcount.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - - name: request_duration - instance_name: requestduration.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - explicit_buckets: - bounds: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10] - - name: request_size - instance_name: requestsize.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - exponentialBuckets: - numFiniteBuckets: 8 - scale: 1 - growthFactor: 10 - - name: response_size - instance_name: responsesize.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - exponentialBuckets: - numFiniteBuckets: 8 - scale: 1 - growthFactor: 10 - - name: tcp_bytes_sent - instance_name: tcpbytesent.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version - - name: tcp_bytes_received - instance_name: tcpbytereceived.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version ---- -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: promhttp - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: http -spec: - actions: - - handler: handler.prometheus - instances: - - requestcount.metric - - requestduration.metric - - requestsize.metric - - responsesize.metric ---- -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: promtcp - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only execute when context.protocol == TCP -spec: - actions: - - handler: handler.prometheus - instances: - - tcpbytesent.metric - - tcpbytereceived.metric ---- - -apiVersion: "config.istio.io/v1alpha2" -kind: kubernetesenv -metadata: - name: handler - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - # when running from mixer root, use the following config after adding a - # symbolic link to a kubernetes config file via: - # - # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig - # - # kubeconfig_path: "mixer/adapter/kubernetes/kubeconfig" - ---- -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: kubeattrgenrulerule - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - actions: - - handler: handler.kubernetesenv - instances: - - attributes.kubernetes ---- -apiVersion: "config.istio.io/v1alpha2" -kind: kubernetes -metadata: - name: attributes - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - # Pass the required attribute data to the adapter - source_uid: source.uid | "" - source_ip: source.ip | ip("0.0.0.0") # default to unspecified ip addr - destination_uid: destination.uid | "" - destination_ip: destination.ip | ip("0.0.0.0") # default to unspecified ip addr - origin_uid: '""' - origin_ip: ip("0.0.0.0") # default to unspecified ip addr - attribute_bindings: - # Fill the new attributes from the adapter produced output. - # $out refers to an instance of OutputTemplate message - source.ip: $out.source_pod_ip | ip("0.0.0.0") - source.labels: $out.source_labels | emptyStringMap() - source.namespace: $out.source_namespace | "default" - source.service: $out.source_service | "unknown" - source.serviceAccount: $out.source_service_account_name | "unknown" - destination.ip: $out.destination_pod_ip | ip("0.0.0.0") - destination.labels: $out.destination_labels | emptyStringMap() - destination.namespace: $out.destination_namespace | "default" - destination.service: $out.destination_service | "unknown" - destination.serviceAccount: $out.destination_service_account_name | "unknown" ---- -################################ -# Istio configMap cluster-wide -################################ -apiVersion: v1 kind: ConfigMap metadata: - name: istio + name: istio-mixer-custom-resources namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-mixer + chart: mixer-0.8.0 + release: istio + heritage: Tiller + istio: mixer data: - mesh: |- - # Uncomment the following line to enable mutual TLS between proxies - authPolicy: MUTUAL_TLS - # - # Edit this list to avoid using mTLS to connect to these services. - # Typically, these are control services (e.g kubernetes API server) that don't have Istio sidecar - # to transparently terminate mTLS authentication. - mtlsExcludedServices: ["kubernetes.default.svc.cluster.local"] - - # Set the following variable to true to disable policy checks by the Mixer. - # Note that metrics will still be reported to the Mixer. - disablePolicyChecks: false - # Set enableTracing to false to disable request tracing. - enableTracing: true - # - # To disable the mixer completely (including metrics), comment out - # the following lines - mixerCheckServer: istio-mixer.istio-system:15004 - mixerReportServer: istio-mixer.istio-system:15004 - # This is the ingress service name, update if you used a different name - ingressService: istio-ingress - # - # Along with discoveryRefreshDelay, this setting determines how - # frequently should Envoy fetch and update its internal configuration - # from Istio Pilot. Lower refresh delay results in higher CPU - # utilization and potential performance loss in exchange for faster - # convergence. Tweak this value according to your setup. - rdsRefreshDelay: 1s - # - defaultConfig: - # NOTE: If you change any values in this section, make sure to make - # the same changes in start up args in istio-ingress pods. - # See rdsRefreshDelay for explanation about this setting. - discoveryRefreshDelay: 1s + custom-resources.yaml: |- + apiVersion: "config.istio.io/v1alpha2" + kind: attributemanifest + metadata: + name: istioproxy + namespace: istio-system + spec: + attributes: + origin.ip: + valueType: IP_ADDRESS + origin.uid: + valueType: STRING + origin.user: + valueType: STRING + request.headers: + valueType: STRING_MAP + request.id: + valueType: STRING + request.host: + valueType: STRING + request.method: + valueType: STRING + request.path: + valueType: STRING + request.reason: + valueType: STRING + request.referer: + valueType: STRING + request.scheme: + valueType: STRING + request.total_size: + valueType: INT64 + request.size: + valueType: INT64 + request.time: + valueType: TIMESTAMP + request.useragent: + valueType: STRING + response.code: + valueType: INT64 + response.duration: + valueType: DURATION + response.headers: + valueType: STRING_MAP + response.total_size: + valueType: INT64 + response.size: + valueType: INT64 + response.time: + valueType: TIMESTAMP + source.uid: + valueType: STRING + source.user: + valueType: STRING + destination.uid: + valueType: STRING + connection.id: + valueType: STRING + connection.received.bytes: + valueType: INT64 + connection.received.bytes_total: + valueType: INT64 + connection.sent.bytes: + valueType: INT64 + connection.sent.bytes_total: + valueType: INT64 + connection.duration: + valueType: DURATION + connection.mtls: + valueType: BOOL + context.protocol: + valueType: STRING + context.timestamp: + valueType: TIMESTAMP + context.time: + valueType: TIMESTAMP + api.service: + valueType: STRING + api.version: + valueType: STRING + api.operation: + valueType: STRING + api.protocol: + valueType: STRING + request.auth.principal: + valueType: STRING + request.auth.audiences: + valueType: STRING + request.auth.presenter: + valueType: STRING + request.auth.claims: + valueType: STRING_MAP + request.auth.raw_claims: + valueType: STRING + request.api_key: + valueType: STRING + + --- + apiVersion: "config.istio.io/v1alpha2" + kind: attributemanifest + metadata: + name: kubernetes + namespace: istio-system + spec: + attributes: + source.ip: + valueType: IP_ADDRESS + source.labels: + valueType: STRING_MAP + source.name: + valueType: STRING + source.namespace: + valueType: STRING + source.service: + valueType: STRING + source.serviceAccount: + valueType: STRING + destination.ip: + valueType: IP_ADDRESS + destination.labels: + valueType: STRING_MAP + destination.name: + valueType: STRING + destination.namespace: + valueType: STRING + destination.service: + valueType: STRING + destination.serviceAccount: + valueType: STRING + --- + apiVersion: "config.istio.io/v1alpha2" + kind: stdio + metadata: + name: handler + namespace: istio-system + spec: + outputAsJson: true + --- + apiVersion: "config.istio.io/v1alpha2" + kind: logentry + metadata: + name: accesslog + namespace: istio-system + spec: + severity: '"Info"' + timestamp: request.time + variables: + originIp: origin.ip | ip("0.0.0.0") + sourceIp: source.ip | ip("0.0.0.0") + sourceService: source.service | "" + sourceUser: source.user | source.uid | "" + sourceNamespace: source.namespace | "" + destinationIp: destination.ip | ip("0.0.0.0") + destinationService: destination.service | "" + destinationNamespace: destination.namespace | "" + apiName: api.service | "" + apiVersion: api.version | "" + apiClaims: request.headers["sec-istio-auth-userinfo"]| "" + apiKey: request.api_key | request.headers["x-api-key"] | "" + requestOperation: api.operation | "" + protocol: request.scheme | "http" + method: request.method | "" + url: request.path | "" + responseCode: response.code | 0 + responseSize: response.size | 0 + requestSize: request.size | 0 + latency: response.duration | "0ms" + connectionMtls: connection.mtls | false + userAgent: request.useragent | "" + responseTimestamp: response.time + receivedBytes: request.total_size | connection.received.bytes | 0 + sentBytes: response.total_size | connection.sent.bytes | 0 + referer: request.referer | "" + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: stdio + namespace: istio-system + spec: + match: "true" # If omitted match is true. + actions: + - handler: handler.stdio + instances: + - accesslog.logentry + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestcount + namespace: istio-system + spec: + value: "1" + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestduration + namespace: istio-system + spec: + value: response.duration | "0ms" + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestsize + namespace: istio-system + spec: + value: request.size | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: responsesize + namespace: istio-system + spec: + value: response.size | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: tcpbytesent + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp + spec: + value: connection.sent.bytes | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: tcpbytereceived + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp + spec: + value: connection.received.bytes | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: prometheus + metadata: + name: handler + namespace: istio-system + spec: + metrics: + - name: request_count + instance_name: requestcount.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + - name: request_duration + instance_name: requestduration.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + explicit_buckets: + bounds: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10] + - name: request_size + instance_name: requestsize.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + exponentialBuckets: + numFiniteBuckets: 8 + scale: 1 + growthFactor: 10 + - name: response_size + instance_name: responsesize.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + exponentialBuckets: + numFiniteBuckets: 8 + scale: 1 + growthFactor: 10 + - name: tcp_bytes_sent + instance_name: tcpbytesent.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - connection_mtls + - name: tcp_bytes_received + instance_name: tcpbytereceived.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - connection_mtls + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: promhttp + namespace: istio-system + labels: + istio-protocol: http + spec: + actions: + - handler: handler.prometheus + instances: + - requestcount.metric + - requestduration.metric + - requestsize.metric + - responsesize.metric + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: promtcp + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only execute when context.protocol == TCP + spec: + actions: + - handler: handler.prometheus + instances: + - tcpbytesent.metric + - tcpbytereceived.metric + --- + + apiVersion: "config.istio.io/v1alpha2" + kind: kubernetesenv + metadata: + name: handler + namespace: istio-system + spec: + # when running from mixer root, use the following config after adding a + # symbolic link to a kubernetes config file via: # - # TCP connection timeout between Envoy & the application, and between Envoys. - connectTimeout: 10s + # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig # - ### ADVANCED SETTINGS ############# - # Where should envoy's configuration be stored in the istio-proxy container - configPath: "/etc/istio/proxy" - binaryPath: "/usr/local/bin/envoy" - # The pseudo service name used for Envoy. - serviceCluster: istio-proxy - # These settings that determine how long an old Envoy - # process should be kept alive after an occasional reload. - drainDuration: 45s - parentShutdownDuration: 1m0s - # - # Port where Envoy listens (on local host) for admin commands - # You can exec into the istio-proxy container in a pod and - # curl the admin port (curl http://localhost:15000/) to obtain - # diagnostic information from Envoy. See - # https://lyft.github.io/envoy/docs/operations/admin.html - # for more details - proxyAdminPort: 15000 - # - # Address where Istio Pilot service is running - discoveryAddress: istio-pilot.istio-system:15003 - # - # Zipkin trace collector - zipkinAddress: zipkin.istio-system:9411 - # - # Statsd metrics collector. Istio mixer exposes a UDP endpoint - # to collect and convert statsd metrics into Prometheus metrics. - statsdUdpAddress: istio-mixer.istio-system:9125 - # Uncomment the following line to enable mutual TLS authentication between - # sidecars and istio control plane. - controlPlaneAuthPolicy: MUTUAL_TLS ---- -################################ -# Pilot -################################ -# Pilot CRDs -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: destinationpolicies.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: DestinationPolicy - listKind: DestinationPolicyList - plural: destinationpolicies - singular: destinationpolicy - scope: Namespaced - version: v1alpha2 ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: egressrules.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: EgressRule - listKind: EgressRuleList - plural: egressrules - singular: egressrule - scope: Namespaced - version: v1alpha2 ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: routerules.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: RouteRule - listKind: RouteRuleList - plural: routerules - singular: routerule - scope: Namespaced - version: v1alpha2 ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: v1alpha2routerules.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: V1alpha2RouteRule - listKind: V1alpha2RouteRuleList - plural: v1alpha2routerules - singular: v1alpha2routerule - scope: Namespaced - version: v1alpha2 ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: destinationrules.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: + # kubeconfig_path: "mixer/adapter/kubernetes/kubeconfig" + + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: kubeattrgenrulerule + namespace: istio-system + spec: + actions: + - handler: handler.kubernetesenv + instances: + - attributes.kubernetes + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: tcpkubeattrgenrulerule + namespace: istio-system + spec: + match: context.protocol == "tcp" + actions: + - handler: handler.kubernetesenv + instances: + - attributes.kubernetes + --- + apiVersion: "config.istio.io/v1alpha2" + kind: kubernetes + metadata: + name: attributes + namespace: istio-system + spec: + # Pass the required attribute data to the adapter + source_uid: source.uid | "" + source_ip: source.ip | ip("0.0.0.0") # default to unspecified ip addr + destination_uid: destination.uid | "" + origin_uid: '""' + origin_ip: ip("0.0.0.0") # default to unspecified ip addr + attribute_bindings: + # Fill the new attributes from the adapter produced output. + # $out refers to an instance of OutputTemplate message + source.ip: $out.source_pod_ip | ip("0.0.0.0") + source.labels: $out.source_labels | emptyStringMap() + source.namespace: $out.source_namespace | "default" + source.service: $out.source_service | "unknown" + source.serviceAccount: $out.source_service_account_name | "unknown" + destination.ip: $out.destination_pod_ip | ip("0.0.0.0") + destination.labels: $out.destination_labels | emptyStringMap() + destination.namespace: $out.destination_namespace | "default" + destination.service: $out.destination_service | "unknown" + destination.serviceAccount: $out.destination_service_account_name | "unknown" + --- + # Configuration needed by Mixer. + # Mixer cluster is delivered via CDS + # Specify mixer cluster settings + apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule - listKind: DestinationRuleList - plural: destinationrules - singular: destinationrule - scope: Namespaced - version: v1alpha2 ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: externalservices.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: ExternalService - listKind: ExternalServiceList - plural: externalservices - singular: externalservice - scope: Namespaced - version: v1alpha2 ---- -# Pilot service for discovery -apiVersion: v1 -kind: Service -metadata: - name: istio-pilot - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - istio: pilot -spec: - ports: - - port: 15003 - name: http-discovery - - port: 8080 - name: http-legacy-discovery - - port: 9093 - name: http-monitoring - - port: 443 - name: admission-webhook - selector: - istio: pilot ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-pilot-service-account - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: istio-pilot - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - template: metadata: - labels: - istio: pilot - annotations: - sidecar.istio.io/inject: "false" + name: istio-policy + namespace: istio-system spec: - serviceAccountName: istio-pilot-service-account - containers: - - name: discovery - image: gcr.io/istio-release/pilot:0.6.0 - imagePullPolicy: IfNotPresent - args: ["discovery", "-v", "2", "--admission-service", "istio-pilot"] - ports: - - containerPort: 8080 - - containerPort: 443 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: PILOT_THROTTLE - value: "200" - volumeMounts: - - name: config-volume - mountPath: /etc/istio/config - - name: istio-proxy - image: gcr.io/istio-release/proxy:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15003 - args: - - proxy - - pilot - - -v - - "2" - - --discoveryAddress - - istio-pilot:15003 - - --controlPlaneAuthPolicy - - MUTUAL_TLS - - --customConfigFile - - /etc/istio/proxy/envoy_pilot_auth.json - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - volumes: - - name: config-volume - configMap: - name: istio - - name: istio-certs - secret: - secretName: istio.istio-pilot-service-account - optional: true ---- -################################ -# Istio ingress -################################ -apiVersion: v1 -kind: Service -metadata: - name: istio-ingress - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - istio: ingress -spec: - type: LoadBalancer - ports: - - port: 80 -# nodePort: 32000 - name: http - - port: 443 - name: https - selector: - istio: ingress ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-ingress-service-account - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: istio-ingress - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - template: + host: istio-policy.istio-system.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + name: grpc-mixer-mtls + tls: + mode: ISTIO_MUTUAL + connectionPool: + http: + http2MaxRequests: 10000 + maxRequestsPerConnection: 10000 + --- + apiVersion: networking.istio.io/v1alpha3 + kind: DestinationRule metadata: - labels: - istio: ingress - annotations: - sidecar.istio.io/inject: "false" + name: istio-telemetry + namespace: istio-system spec: - serviceAccountName: istio-ingress-service-account - containers: - - name: istio-ingress - image: gcr.io/istio-release/proxy:0.6.0 - args: - - proxy - - ingress - - -v - - "2" - - --discoveryAddress - - istio-pilot:15003 - - --discoveryRefreshDelay - - '1s' #discoveryRefreshDelay - - --drainDuration - - '45s' #drainDuration - - --parentShutdownDuration - - '1m0s' #parentShutdownDuration - - --connectTimeout - - '10s' #connectTimeout - - --serviceCluster - - istio-ingress - - --zipkinAddress - - zipkin:9411 - - --statsdUdpAddress - - istio-mixer:9125 - - --proxyAdminPort - - "15000" - - --controlPlaneAuthPolicy - - MUTUAL_TLS - imagePullPolicy: IfNotPresent - ports: - - containerPort: 80 - - containerPort: 443 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: ingress-certs - mountPath: /etc/istio/ingress-certs - readOnly: true - volumes: - - name: istio-certs - secret: - secretName: istio.default - optional: true - - name: ingress-certs - secret: - secretName: istio-ingress-certs - optional: true ---- -################################ -# Istio-CA cluster-wide -################################ -# Service account CA -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-ca-service-account - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- -# Istio CA watching all namespaces -apiVersion: v1 -kind: Deployment -apiVersion: extensions/v1beta1 -metadata: - name: istio-ca - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - template: - metadata: - labels: - istio: istio-ca - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-ca-service-account - containers: - - name: istio-ca - image: gcr.io/istio-release/istio-ca:0.6.0 - imagePullPolicy: IfNotPresent - command: ["/usr/local/bin/istio_ca"] - args: - - --istio-ca-storage-namespace=istio-system - - --grpc-port=8060 - - --grpc-hostname=istio-ca - - --self-signed-ca=true - - --logtostderr - - --stderrthreshold - - INFO ---- -apiVersion: v1 -kind: Service -metadata: - name: grafana - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" -spec: - ports: - - port: 3000 - protocol: TCP - name: http - selector: - app: grafana ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: grafana - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - template: - metadata: - labels: - app: grafana - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: grafana - containers: - - name: grafana - image: gcr.io/istio-release/grafana:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 3000 - env: - # Only put environment related config here. Generic Istio config - # should go in addons/grafana/grafana.ini. - - name: GF_PATHS_DATA - value: /data/grafana - volumeMounts: - - mountPath: /data/grafana - name: grafana-data - volumes: - - name: grafana-data - emptyDir: {} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: grafana - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- + host: istio-telemetry.istio-system.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + name: grpc-mixer-mtls + tls: + mode: ISTIO_MUTUAL + connectionPool: + http: + http2MaxRequests: 10000 + maxRequestsPerConnection: 10000 + --- + + --- +# Source: istio/charts/prometheus/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: @@ -1896,6 +564,10 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: prometheus + chart: prometheus-0.1.0 + release: istio + heritage: Tiller data: prometheus.yml: |- global: @@ -1912,7 +584,7 @@ data: relabel_configs: - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] action: keep - regex: istio-system;istio-mixer;prometheus + regex: istio-system;istio-telemetry;prometheus - job_name: 'envoy' # Override the global default and scrape targets from this job every 5 seconds. @@ -1926,9 +598,9 @@ data: relabel_configs: - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] action: keep - regex: istio-system;istio-mixer;statsd-prom + regex: istio-system;istio-statsd-prom-bridge;statsd-prom - - job_name: 'mixer' + - job_name: 'istio-policy' # Override the global default and scrape targets from this job every 5 seconds. scrape_interval: 5s # metrics_path defaults to '/metrics' @@ -1940,7 +612,21 @@ data: relabel_configs: - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] action: keep - regex: istio-system;istio-mixer;http-monitoring + regex: istio-system;istio-policy;http-monitoring + + - job_name: 'istio-telemetry' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-telemetry;http-monitoring - job_name: 'pilot' # Override the global default and scrape targets from this job every 5 seconds. @@ -2076,65 +762,444 @@ data: target_label: pod_name --- +# Source: istio/templates/configmap.yaml apiVersion: v1 -kind: Service +kind: ConfigMap metadata: - annotations: - prometheus.io/scrape: 'true' + name: istio + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - name: prometheus - name: prometheus - namespace: istio-system -spec: - selector: - app: prometheus - ports: - - name: prometheus - protocol: TCP - port: 9090 + app: istio + chart: istio-0.8.0 + release: istio + heritage: Tiller +data: + mesh: |- + # Mutual TLS between proxies + authPolicy: MUTUAL_TLS + mtlsExcludedServices: ["kubernetes.default.svc.cluster.local"] + # + # Edit this list to avoid using mTLS to connect to these services. + # Typically, these are control services (e.g kubernetes API server) that don't have istio sidecar + # to transparently terminate mTLS authentication. + # mtlsExcludedServices: ["kubernetes.default.svc.cluster.local"] + + # Set the following variable to true to disable policy checks by the Mixer. + # Note that metrics will still be reported to the Mixer. + disablePolicyChecks: false + # Set enableTracing to false to disable request tracing. + enableTracing: true + # + # To disable the mixer completely (including metrics), comment out + # the following lines + mixerCheckServer: istio-policy.istio-system.svc.cluster.local:15004 + mixerReportServer: istio-telemetry.istio-system.svc.cluster.local:15004 + # This is the ingress service name, update if you used a different name + ingressService: istio-ingress + # + # Along with discoveryRefreshDelay, this setting determines how + # frequently should Envoy fetch and update its internal configuration + # from istio Pilot. Lower refresh delay results in higher CPU + # utilization and potential performance loss in exchange for faster + # convergence. Tweak this value according to your setup. + rdsRefreshDelay: 10s + # + defaultConfig: + # NOTE: If you change any values in this section, make sure to make + # the same changes in start up args in istio-ingress pods. + # See rdsRefreshDelay for explanation about this setting. + discoveryRefreshDelay: 10s + # + # TCP connection timeout between Envoy & the application, and between Envoys. + connectTimeout: 10s + # + ### ADVANCED SETTINGS ############# + # Where should envoy's configuration be stored in the istio-proxy container + configPath: "/etc/istio/proxy" + binaryPath: "/usr/local/bin/envoy" + # The pseudo service name used for Envoy. + serviceCluster: istio-proxy + # These settings that determine how long an old Envoy + # process should be kept alive after an occasional reload. + drainDuration: 45s + parentShutdownDuration: 1m0s + # + # The mode used to redirect inbound connections to Envoy. This setting + # has no effect on outbound traffic: iptables REDIRECT is always used for + # outbound connections. + # If "REDIRECT", use iptables REDIRECT to NAT and redirect to Envoy. + # The "REDIRECT" mode loses source addresses during redirection. + # If "TPROXY", use iptables TPROXY to redirect to Envoy. + # The "TPROXY" mode preserves both the source and destination IP + # addresses and ports, so that they can be used for advanced filtering + # and manipulation. + # The "TPROXY" mode also configures the sidecar to run with the + # CAP_NET_ADMIN capability, which is required to use TPROXY. + #interceptionMode: REDIRECT + # + # Port where Envoy listens (on local host) for admin commands + # You can exec into the istio-proxy container in a pod and + # curl the admin port (curl http://localhost:15000/) to obtain + # diagnostic information from Envoy. See + # https://lyft.github.io/envoy/docs/operations/admin.html + # for more details + proxyAdminPort: 15000 + # + # Zipkin trace collector + zipkinAddress: zipkin.istio-system:9411 + # + # Statsd metrics collector converts statsd metrics into Prometheus metrics. + statsdUdpAddress: istio-statsd-prom-bridge.istio-system:9125 + # + # Mutual TLS authentication between sidecars and istio control plane. + controlPlaneAuthPolicy: MUTUAL_TLS + # + # Address where istio Pilot service is running + discoveryAddress: istio-pilot.istio-system:15005 + --- -apiVersion: extensions/v1beta1 -kind: Deployment +# Source: istio/templates/sidecar-injector-configmap.yaml +apiVersion: v1 +kind: ConfigMap metadata: - name: prometheus + name: istio-sidecar-injector namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio + chart: istio-0.8.0 + release: istio + heritage: Tiller + istio: sidecar-injector +data: + config: |- + policy: enabled + template: |- + metadata: + annotations: + container.seccomp.security.alpha.kubernetes.io/istio-proxy: 'docker/default' + initContainers: + - name: istio-init + image: gcr.io/istio-release/proxy_init:0.8.0 + args: + - "-p" + - [[ .MeshConfig.ProxyListenPort ]] + - "-u" + - 1337 + - "-m" + - [[ or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String ]] + - "-i" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeOutboundIPRanges") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeOutboundIPRanges" ]]" + [[ else -]] + - "*" + [[ end -]] + - "-x" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeOutboundIPRanges") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeOutboundIPRanges" ]]" + [[ else -]] + - "" + [[ end -]] + - "-b" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeInboundPorts") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeInboundPorts" ]]" + [[ else -]] + - [[ range .Spec.Containers -]][[ range .Ports -]][[ .ContainerPort -]], [[ end -]][[ end -]][[ end]] + - "-d" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeInboundPorts") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeInboundPorts" ]]" + [[ else -]] + - "" + [[ end -]] + imagePullPolicy: IfNotPresent + securityContext: + capabilities: + add: + - NET_ADMIN + privileged: true + restartPolicy: Always + + containers: + - name: istio-proxy + image: [[ if (isset .ObjectMeta.Annotations "sidecar.istio.io/proxyImage") -]] + "[[ index .ObjectMeta.Annotations "sidecar.istio.io/proxyImage" ]]" + [[ else -]] + gcr.io/istio-release/proxyv2:0.8.0 + [[ end -]] + args: + - proxy + - sidecar + - --configPath + - [[ .ProxyConfig.ConfigPath ]] + - --binaryPath + - [[ .ProxyConfig.BinaryPath ]] + - --serviceCluster + [[ if ne "" (index .ObjectMeta.Labels "app") -]] + - [[ index .ObjectMeta.Labels "app" ]] + [[ else -]] + - "istio-proxy" + [[ end -]] + - --drainDuration + - [[ formatDuration .ProxyConfig.DrainDuration ]] + - --parentShutdownDuration + - [[ formatDuration .ProxyConfig.ParentShutdownDuration ]] + - --discoveryAddress + - [[ .ProxyConfig.DiscoveryAddress ]] + - --discoveryRefreshDelay + - [[ formatDuration .ProxyConfig.DiscoveryRefreshDelay ]] + - --zipkinAddress + - [[ .ProxyConfig.ZipkinAddress ]] + - --connectTimeout + - [[ formatDuration .ProxyConfig.ConnectTimeout ]] + - --statsdUdpAddress + - [[ .ProxyConfig.StatsdUdpAddress ]] + - --proxyAdminPort + - [[ .ProxyConfig.ProxyAdminPort ]] + - --controlPlaneAuthPolicy + - [[ .ProxyConfig.ControlPlaneAuthPolicy ]] + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: ISTIO_META_INTERCEPTION_MODE + value: [[ or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String ]] + imagePullPolicy: IfNotPresent + securityContext: + privileged: false + readOnlyRootFilesystem: true + [[ if eq (or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String) "TPROXY" -]] + capabilities: + add: + - NET_ADMIN + [[ else -]] + runAsUser: 1337 + [[ end -]] + restartPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - mountPath: /etc/istio/proxy + name: istio-envoy + - mountPath: /etc/certs/ + name: istio-certs + readOnly: true + volumes: + - emptyDir: + medium: Memory + name: istio-envoy + - name: istio-certs + secret: + optional: true + [[ if eq .Spec.ServiceAccountName "" -]] + secretName: istio.default + [[ else -]] + secretName: [[ printf "istio.%s" .Spec.ServiceAccountName ]] + [[ end -]] + + +--- +# Source: istio/charts/egressgateway/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-egressgateway-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: egressgateway + chart: egressgateway-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/ingress/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-ingress-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/ingressgateway/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-ingressgateway-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingressgateway + chart: ingressgateway-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/mixer/templates/create-custom-resources-job.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-mixer-post-install-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-mixer-post-install-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] # istio CRD watcher + resources: ["*"] + verbs: ["create", "get", "list", "watch", "patch"] +- apiGroups: ["networking.istio.io"] # needed to create mixer destination rules + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-mixer-post-install-role-binding-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-mixer-post-install-istio-system +subjects: + - kind: ServiceAccount + name: istio-mixer-post-install-account + namespace: istio-system +--- + +apiVersion: batch/v1 +kind: Job +metadata: + name: istio-mixer-post-install + namespace: istio-system + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-delete-policy": before-hook-creation + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + release: istio + heritage: Tiller spec: - selector: - matchLabels: - app: prometheus template: metadata: - name: prometheus + name: istio-mixer-post-install labels: - app: prometheus - annotations: - sidecar.istio.io/inject: "false" + app: mixer + release: istio spec: - serviceAccountName: prometheus + serviceAccountName: istio-mixer-post-install-account containers: - - name: prometheus - image: gcr.io/istio-release/prom/prometheus:v2.0.0 - imagePullPolicy: IfNotPresent - args: - - '--storage.tsdb.retention=6h' - - '--config.file=/etc/prometheus/prometheus.yml' - ports: - - name: web - containerPort: 9090 - volumeMounts: - - name: config-volume - mountPath: /etc/prometheus + - name: hyperkube + image: "gcr.io/istio-release/coreos/hyperkube:v1.7.6_coreos.0" + command: + - ./kubectl + - apply + - -f + - /tmp/mixer/custom-resources.yaml + volumeMounts: + - mountPath: "/tmp/mixer" + name: tmp-configmap-mixer volumes: - - name: config-volume - configMap: - name: prometheus + - name: tmp-configmap-mixer + configMap: + name: istio-mixer-custom-resources + restartPolicy: Never # CRD might take some time till they are available to consume + --- +# Source: istio/charts/mixer/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-mixer-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/pilot/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-pilot-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/prometheus/templates/serviceaccount.yaml + apiVersion: v1 kind: ServiceAccount metadata: @@ -2144,10 +1209,957 @@ metadata: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile --- +# Source: istio/charts/security/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-citadel-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-cleanup-old-ca-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-sidecar-injector-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/mixer/templates/crds.yaml +# Mixer CRDs +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: rules.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer + istio: core +spec: + group: config.istio.io + names: + kind: rule + plural: rules + singular: rule + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: attributemanifests.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer + istio: core +spec: + group: config.istio.io + names: + kind: attributemanifest + plural: attributemanifests + singular: attributemanifest + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: circonuses.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: circonus + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: circonus + plural: circonuses + singular: circonus + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: deniers.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: denier + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: denier + plural: deniers + singular: denier + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: fluentds.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: fluentd + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: fluentd + plural: fluentds + singular: fluentd + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: kubernetesenvs.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: kubernetesenv + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: kubernetesenv + plural: kubernetesenvs + singular: kubernetesenv + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: listcheckers.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: listchecker + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: listchecker + plural: listcheckers + singular: listchecker + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: memquotas.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: memquota + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: memquota + plural: memquotas + singular: memquota + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: noops.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: noop + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: noop + plural: noops + singular: noop + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: opas.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: opa + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: opa + plural: opas + singular: opa + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: prometheuses.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: prometheus + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: prometheus + plural: prometheuses + singular: prometheus + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: rbacs.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: rbac + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: rbac + plural: rbacs + singular: rbac + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: servicecontrols.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: servicecontrol + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: servicecontrol + plural: servicecontrols + singular: servicecontrol + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: solarwindses.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: solarwinds + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: solarwinds + plural: solarwindses + singular: solarwinds + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: stackdrivers.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: stackdriver + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: stackdriver + plural: stackdrivers + singular: stackdriver + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: statsds.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: statsd + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: statsd + plural: statsds + singular: statsd + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: stdios.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: stdio + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: stdio + plural: stdios + singular: stdio + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: apikeys.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: apikey + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: apikey + plural: apikeys + singular: apikey + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: authorizations.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: authorization + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: authorization + plural: authorizations + singular: authorization + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: checknothings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: checknothing + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: checknothing + plural: checknothings + singular: checknothing + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: kuberneteses.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: adapter.template.kubernetes + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: kubernetes + plural: kuberneteses + singular: kubernetes + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: listentries.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: listentry + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: listentry + plural: listentries + singular: listentry + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: logentries.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: logentry + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: logentry + plural: logentries + singular: logentry + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: metrics.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: metric + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: metric + plural: metrics + singular: metric + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: quotas.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: quota + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: quota + plural: quotas + singular: quota + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: reportnothings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: reportnothing + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: reportnothing + plural: reportnothings + singular: reportnothing + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: servicecontrolreports.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: servicecontrolreport + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: servicecontrolreport + plural: servicecontrolreports + singular: servicecontrolreport + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: tracespans.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: tracespan + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: tracespan + plural: tracespans + singular: tracespan + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: serviceroles.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer + istio: rbac +spec: + group: config.istio.io + names: + kind: ServiceRole + plural: serviceroles + singular: servicerole + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: servicerolebindings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer + istio: rbac +spec: + group: config.istio.io + names: + kind: ServiceRoleBinding + plural: servicerolebindings + singular: servicerolebinding + scope: Namespaced + version: v1alpha2 + +--- +# Source: istio/charts/pilot/templates/crds.yaml +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: destinationpolicies.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: config.istio.io + names: + kind: DestinationPolicy + listKind: DestinationPolicyList + plural: destinationpolicies + singular: destinationpolicy + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: egressrules.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: config.istio.io + names: + kind: EgressRule + listKind: EgressRuleList + plural: egressrules + singular: egressrule + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: routerules.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: config.istio.io + names: + kind: RouteRule + listKind: RouteRuleList + plural: routerules + singular: routerule + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: virtualservices.networking.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: networking.istio.io + names: + kind: VirtualService + listKind: VirtualServiceList + plural: virtualservices + singular: virtualservice + scope: Namespaced + version: v1alpha3 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: destinationrules.networking.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: networking.istio.io + names: + kind: DestinationRule + listKind: DestinationRuleList + plural: destinationrules + singular: destinationrule + scope: Namespaced + version: v1alpha3 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: serviceentries.networking.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: networking.istio.io + names: + kind: ServiceEntry + listKind: ServiceEntryList + plural: serviceentries + singular: serviceentry + scope: Namespaced + version: v1alpha3 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: gateways.networking.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: networking.istio.io + names: + kind: Gateway + plural: gateways + singular: gateway + scope: Namespaced + version: v1alpha3 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: policies.authentication.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: authentication.istio.io + names: + kind: Policy + plural: policies + singular: policy + scope: Namespaced + version: v1alpha1 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: httpapispecbindings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: HTTPAPISpecBinding + plural: httpapispecbindings + singular: httpapispecbinding + scope: Namespaced + version: v1alpha2 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: httpapispecs.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: HTTPAPISpec + plural: httpapispecs + singular: httpapispec + scope: Namespaced + version: v1alpha2 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: quotaspecbindings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: QuotaSpecBinding + plural: quotaspecbindings + singular: quotaspecbinding + scope: Namespaced + version: v1alpha2 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: quotaspecs.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: QuotaSpec + plural: quotaspecs + singular: quotaspec + scope: Namespaced + version: v1alpha2 + + +--- +# Source: istio/charts/ingress/templates/clusterrole.yaml + apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: - name: prometheus + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + heritage: Tiller + release: istio + name: istio-ingress-istio-system +rules: +- apiGroups: ["extensions"] + resources: ["thirdpartyresources", "ingresses"] + verbs: ["get", "watch", "list", "update"] +- apiGroups: [""] + resources: ["configmaps", "pods", "endpoints", "services"] + verbs: ["get", "watch", "list"] + +--- +# Source: istio/charts/mixer/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-mixer-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] # istio CRD watcher + resources: ["*"] + verbs: ["create", "get", "list", "watch", "patch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] + verbs: ["get", "list", "watch"] + +--- +# Source: istio/charts/pilot/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-pilot-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["networking.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["authentication.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["*"] +- apiGroups: ["extensions"] + resources: ["thirdpartyresources", "thirdpartyresources.extensions", "ingresses", "ingresses/status"] + verbs: ["*"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["endpoints", "pods", "services"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["namespaces", "nodes", "secrets"] + verbs: ["get", "list", "watch"] + +--- +# Source: istio/charts/prometheus/templates/clusterrole.yaml + +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: prometheus-istio-system + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile @@ -2170,104 +2182,1764 @@ rules: apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: - name: prometheus + name: prometheus-istio-system + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: prometheus + name: prometheus-istio-system subjects: - kind: ServiceAccount name: prometheus namespace: istio-system --- + + --- -apiVersion: extensions/v1beta1 -kind: Deployment +# Source: istio/charts/security/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole metadata: - name: servicegraph + name: istio-citadel-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - template: - metadata: - labels: - app: servicegraph - annotations: - sidecar.istio.io/inject: "false" - spec: - containers: - - name: servicegraph - image: gcr.io/istio-release/servicegraph:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8088 - args: - - --prometheusAddr=http://prometheus:9090 + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "watch", "list", "update", "delete"] +- apiGroups: [""] + resources: ["serviceaccounts"] + verbs: ["get", "watch", "list"] +- apiGroups: [""] + resources: ["services"] + verbs: ["get", "watch", "list"] --- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: Role +metadata: + name: istio-cleanup-old-ca-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: [""] + resources: ["deployments", "serviceaccounts", "services"] + verbs: ["get", "delete"] +- apiGroups: ["extensions"] + resources: ["deployments", "replicasets"] + verbs: ["get", "list", "update", "delete"] + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-sidecar-injector-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["*"] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch", "patch"] + +--- +# Source: istio/charts/ingress/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-ingress-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-pilot-istio-system +subjects: + - kind: ServiceAccount + name: istio-ingress-service-account + namespace: istio-system + +--- +# Source: istio/charts/mixer/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-mixer-admin-role-binding-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-mixer-istio-system +subjects: + - kind: ServiceAccount + name: istio-mixer-service-account + namespace: istio-system + +--- +# Source: istio/charts/pilot/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-pilot-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-pilot-istio-system +subjects: + - kind: ServiceAccount + name: istio-pilot-service-account + namespace: istio-system + +--- +# Source: istio/charts/security/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-citadel-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-citadel-istio-system +subjects: + - kind: ServiceAccount + name: istio-citadel-service-account + namespace: istio-system +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding +metadata: + name: istio-cleanup-old-ca-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: istio-cleanup-old-ca-istio-system +subjects: + - kind: ServiceAccount + name: istio-cleanup-old-ca-service-account + namespace: istio-system + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-sidecar-injector-admin-role-binding-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-sidecar-injector-istio-system +subjects: + - kind: ServiceAccount + name: istio-sidecar-injector-service-account + namespace: istio-system +--- +# Source: istio/charts/egressgateway/templates/service.yaml apiVersion: v1 kind: Service metadata: - name: servicegraph + name: istio-egressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: egressgateway-0.8.0 + release: istio + heritage: Tiller + istio: egressgateway +spec: + type: ClusterIP + selector: + istio: egressgateway + ports: + - + name: http + port: 80 + - + name: https + port: 443 + +--- +# Source: istio/charts/ingress/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-ingress namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/cluster-service: "true" + chart: ingress-0.8.0 + release: istio + heritage: Tiller + istio: ingress spec: - ports: - - name: http - port: 8088 + type: LoadBalancer selector: - app: servicegraph + istio: ingress + ports: + - + name: http + nodePort: 32000 + port: 80 + - + name: https + port: 443 --- + --- -apiVersion: extensions/v1beta1 -kind: Deployment +# Source: istio/charts/ingressgateway/templates/service.yaml +apiVersion: v1 +kind: Service metadata: - name: zipkin + name: istio-ingressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: ingressgateway-0.8.0 + release: istio + heritage: Tiller + istio: ingressgateway +spec: + type: LoadBalancer + selector: + istio: ingressgateway + ports: + - + name: http + nodePort: 31380 + port: 80 + - + name: https + nodePort: 31390 + port: 443 + - + name: tcp + nodePort: 31400 + port: 31400 + +--- +# Source: istio/charts/mixer/templates/service.yaml + +apiVersion: v1 +kind: Service +metadata: + name: istio-policy namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: mixer-0.8.0 + release: istio + istio: mixer +spec: + ports: + - name: grpc-mixer + port: 9091 + - name: grpc-mixer-mtls + port: 15004 + - name: http-monitoring + port: 9093 + selector: + istio: mixer + istio-mixer-type: policy +--- +apiVersion: v1 +kind: Service +metadata: + name: istio-telemetry + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: mixer-0.8.0 + release: istio + istio: mixer +spec: + ports: + - name: grpc-mixer + port: 9091 + - name: grpc-mixer-mtls + port: 15004 + - name: http-monitoring + port: 9093 + - name: prometheus + port: 42422 + selector: + istio: mixer + istio-mixer-type: telemetry +--- + +--- +# Source: istio/charts/mixer/templates/statsdtoprom.yaml + +--- +apiVersion: v1 +kind: Service +metadata: + name: istio-statsd-prom-bridge + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: mixer-0.8.0 + release: istio + istio: statsd-prom-bridge +spec: + ports: + - name: statsd-prom + port: 9102 + - name: statsd-udp + port: 9125 + protocol: UDP + selector: + istio: statsd-prom-bridge + +--- + +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-statsd-prom-bridge + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + chart: mixer-0.8.0 + release: istio + istio: mixer spec: template: metadata: labels: - app: zipkin + istio: statsd-prom-bridge annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: + serviceAccountName: istio-mixer-service-account + volumes: + - name: config-volume + configMap: + name: istio-statsd-prom-bridge containers: - - name: zipkin - image: gcr.io/istio-release/zipkin:2.5.3 + - name: statsd-prom-bridge + image: "gcr.io/istio-release/prom/statsd-exporter:latest" imagePullPolicy: IfNotPresent ports: - - containerPort: 9411 + - containerPort: 9102 + - containerPort: 9125 + protocol: UDP + args: + - '-statsd.mapping-config=/etc/statsd/mapping.conf' + resources: + {} + + volumeMounts: + - name: config-volume + mountPath: /etc/statsd + +--- +# Source: istio/charts/pilot/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-pilot + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + app: istio-pilot + chart: pilot-0.8.0 + release: istio + heritage: Tiller +spec: + ports: + - port: 15003 + name: http-old-discovery # mTLS or non-mTLS depending on auth setting + - port: 15005 + name: https-discovery # always mTLS + - port: 15007 + name: http-discovery # always plain-text + - port: 15010 + name: grpc-xds # direct + - port: 15011 + name: https-xds # mTLS + - port: 8080 + name: http-legacy-discovery # direct + - port: 9093 + name: http-monitoring + selector: + istio: pilot + +--- +# Source: istio/charts/prometheus/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: prometheus + namespace: istio-system + annotations: + prometheus.io/scrape: 'true' + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + name: prometheus +spec: + selector: + app: prometheus + ports: + - name: http-prometheus + protocol: TCP + port: 9090 + +--- +# Source: istio/charts/security/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + # we use the normal name here (e.g. 'prometheus') + # as grafana is configured to use this as a data source + name: istio-citadel + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + app: istio-citadel +spec: + ports: + - name: grpc-citadel + port: 8060 + targetPort: 8060 + protocol: TCP + - name: http-monitoring + port: 9093 + selector: + istio: citadel + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + istio: sidecar-injector +spec: + ports: + - port: 443 + selector: + istio: sidecar-injector + +--- +# Source: istio/charts/egressgateway/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-egressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: egressgateway + chart: egressgateway-0.8.0 + release: istio + heritage: Tiller + istio: egressgateway +spec: + template: + metadata: + labels: + istio: egressgateway + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-egressgateway-service-account + containers: + - name: egressgateway + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + args: + - proxy + - router + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-egressgateway + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - MUTUAL_TLS + - --discoveryAddress + - istio-pilot:15005 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: "istio.default" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/ingress/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-ingress + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + release: istio + heritage: Tiller + istio: ingress +spec: + template: + metadata: + labels: + istio: ingress + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-ingress-service-account + containers: + - name: ingress + image: "gcr.io/istio-release/proxy:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + args: + - proxy + - ingress + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-ingress + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - MUTUAL_TLS + - --discoveryAddress + - istio-pilot:15005 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: ingress-certs + mountPath: /etc/istio/ingress-certs + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: "istio.default" + optional: true + - name: ingress-certs + secret: + secretName: istio-ingress-certs + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/ingressgateway/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingressgateway + chart: ingressgateway-0.8.0 + release: istio + heritage: Tiller + istio: ingressgateway +spec: + template: + metadata: + labels: + istio: ingressgateway + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-ingressgateway-service-account + containers: + - name: ingressgateway + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + - containerPort: 31400 + args: + - proxy + - router + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-ingressgateway + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - MUTUAL_TLS + - --discoveryAddress + - istio-pilot:15005 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: ingressgateway-certs + mountPath: "/etc/istio/ingressgateway-certs" + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: "istio.default" + optional: true + - name: ingressgateway-certs + secret: + secretName: "istio-ingressgateway-certs" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/mixer/templates/deployment.yaml + +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-policy + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + chart: mixer-0.8.0 + release: istio + istio: mixer +spec: + template: + metadata: + labels: + istio: mixer + istio-mixer-type: policy + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-mixer-service-account + volumes: + - name: istio-certs + secret: + secretName: istio.istio-mixer-service-account + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + containers: + - name: mixer + image: "gcr.io/istio-release/mixer:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9092 + - containerPort: 9093 + - containerPort: 42422 + args: + - --address + - tcp://127.0.0.1:9092 + - --configStoreURL=k8s:// + - --configDefaultNamespace=istio-system + - --trace_zipkin_url=http://zipkin:9411/api/v1/spans + resources: + {} + + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9091 + - containerPort: 15004 + args: + - proxy + - --serviceCluster + - istio-policy + - --templateFile + - /etc/istio/proxy/envoy_policy.yaml.tmpl + - --controlPlaneAuthPolicy + - MUTUAL_TLS env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-telemetry + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + chart: mixer-0.8.0 + release: istio + istio: mixer +spec: + template: + metadata: + labels: + istio: mixer + istio-mixer-type: telemetry + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-mixer-service-account + volumes: + - name: istio-certs + secret: + secretName: istio.istio-mixer-service-account + optional: true + containers: + - name: mixer + image: "gcr.io/istio-release/mixer:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9092 + - containerPort: 9093 + - containerPort: 42422 + args: + - --address + - tcp://127.0.0.1:9092 + - --configStoreURL=k8s:// + - --configDefaultNamespace=istio-system + - --trace_zipkin_url=http://zipkin:9411/api/v1/spans + resources: + {} + + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9091 + - containerPort: 15004 + args: + - proxy + - --serviceCluster + - istio-telemetry + - --templateFile + - /etc/istio/proxy/envoy_telemetry.yaml.tmpl + - --controlPlaneAuthPolicy + - MUTUAL_TLS + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + +--- + +--- +# Source: istio/charts/pilot/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-pilot + namespace: istio-system + # TODO: default tempate doesn't have this, which one is right ? + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + release: istio + heritage: Tiller + istio: pilot + annotations: + checksum/config-volume: f8da08b6b8c170dde721efd680270b2901e750d4aa186ebb6c22bef5b78a43f9 +spec: + template: + metadata: + labels: + istio: pilot + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-pilot-service-account + containers: + - name: discovery + image: "gcr.io/istio-release/pilot:0.8.0" + imagePullPolicy: IfNotPresent + args: + - "discovery" +# TODO(sdake) remove when secrets are automagically registered + ports: + - containerPort: 8080 + - containerPort: 15010 + readinessProbe: + httpGet: + path: /v1/registration + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 5 + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: PILOT_THROTTLE + value: "500" + - name: PILOT_CACHE_SQUASH + value: "5" + resources: + {} + + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15003 + - containerPort: 15005 + - containerPort: 15007 + - containerPort: 15011 + args: + - proxy + - --serviceCluster + - istio-pilot + - --templateFile + - /etc/istio/proxy/envoy_pilot.yaml.tmpl + - --controlPlaneAuthPolicy + - MUTUAL_TLS + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + volumes: + - name: config-volume + configMap: + name: istio + - name: istio-certs + secret: + secretName: "istio.istio-pilot-service-account" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/prometheus/templates/deployment.yaml +# TODO: the original template has service account, roles, etc +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: prometheus + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: prometheus + chart: prometheus-0.1.0 + release: istio + heritage: Tiller +spec: + selector: + matchLabels: + app: prometheus + template: + metadata: + labels: + app: prometheus + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: prometheus + + containers: + - name: prometheus + image: "gcr.io/istio-release/prom/prometheus:latest" + imagePullPolicy: IfNotPresent + args: + - '--storage.tsdb.retention=6h' + - '--config.file=/etc/prometheus/prometheus.yml' + ports: + - containerPort: 9090 + name: http + livenessProbe: + httpGet: + path: /-/healthy + port: 9090 + readinessProbe: + httpGet: + path: /-/ready + port: 9090 + resources: + {} + + volumeMounts: + - name: config-volume + mountPath: /etc/prometheus + volumes: + - name: config-volume + configMap: + name: prometheus + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/security/templates/deployment.yaml +# istio CA watching all namespaces +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-citadel + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + release: istio + heritage: Tiller + istio: citadel +spec: + template: + metadata: + labels: + istio: citadel + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-citadel-service-account + containers: + - name: citadel + image: "gcr.io/istio-release/citadel:0.8.0" + imagePullPolicy: IfNotPresent + args: + - --append-dns-names=true + - --grpc-port=8060 + - --grpc-hostname=citadel + - --self-signed-ca=true + - --citadel-storage-namespace=istio-system + resources: + {} + + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: sidecarInjectorWebhook + chart: sidecarInjectorWebhook-0.8.0 + release: istio + heritage: Tiller + istio: sidecar-injector +spec: + template: + metadata: + labels: + istio: sidecar-injector + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-sidecar-injector-service-account + containers: + - name: sidecar-injector-webhook + image: "gcr.io/istio-release/sidecar_injector:0.8.0" + imagePullPolicy: IfNotPresent + args: + - --caCertFile=/etc/istio/certs/root-cert.pem + - --tlsCertFile=/etc/istio/certs/cert-chain.pem + - --tlsKeyFile=/etc/istio/certs/key.pem + - --injectConfig=/etc/istio/inject/config + - --meshConfig=/etc/istio/config/mesh + - --healthCheckInterval=2s + - --healthCheckFile=/health + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + readOnly: true + - name: certs + mountPath: /etc/istio/certs + readOnly: true + - name: inject-config + mountPath: /etc/istio/inject + readOnly: true + livenessProbe: + exec: + command: + - /usr/local/bin/sidecar-injector + - probe + - --probe-path=/health + - --interval=2s + initialDelaySeconds: 4 + periodSeconds: 4 + readinessProbe: + exec: + command: + - /usr/local/bin/sidecar-injector + - probe + - --probe-path=/health + - --interval=2s + initialDelaySeconds: 4 + periodSeconds: 4 + volumes: + - name: config-volume + configMap: + name: istio + - name: certs + secret: + secretName: istio.istio-sidecar-injector-service-account + - name: inject-config + configMap: + name: istio-sidecar-injector + items: + - key: config + path: config + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/security/templates/cleanup-old-ca.yaml + +apiVersion: batch/v1 +kind: Job +metadata: + name: istio-cleanup-old-ca + namespace: istio-system + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-delete-policy": hook-succeeded + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + release: istio + heritage: Tiller +spec: + template: + metadata: + name: istio-cleanup-old-ca + labels: + app: security + release: istio + spec: + serviceAccountName: istio-cleanup-old-ca-service-account + containers: + - name: hyperkube + image: "gcr.io/istio-release/coreos/hyperkube:v1.7.6_coreos.0" + command: + - /bin/bash + - -c + - > + NS="-n istio-system"; + ./kubectl get deploy istio-ca $NS; + if [[ $? = 0 ]]; then ./kubectl delete deploy istio-ca $NS; fi; + ./kubectl get serviceaccount istio-ca-service-account $NS; + if [[ $? = 0 ]]; then ./kubectl delete serviceaccount istio-ca-service-account $NS; fi; + ./kubectl get service istio-ca-ilb $NS; + if [[ $? = 0 ]]; then ./kubectl delete service istio-ca-ilb $NS; fi + restartPolicy: Never +--- +# Source: istio/charts/egressgateway/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-egressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-egressgateway + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/ingress/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-ingress + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-ingress + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/ingressgateway/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-ingressgateway + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/mutatingwebhook.yaml +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: MutatingWebhookConfiguration +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + release: istio + heritage: Tiller +webhooks: + - name: sidecar-injector.istio.io + clientConfig: + service: + name: istio-sidecar-injector + namespace: istio-system + path: "/inject" + caBundle: "" + rules: + - operations: [ "CREATE" ] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + failurePolicy: Fail + namespaceSelector: + matchExpressions: + - key: istio-injection + operator: NotIn + values: + - disabled +--- +# Source: istio/charts/mixer/templates/config.yaml + + +--- +# Source: istio/charts/prometheus/templates/ingress.yaml --- apiVersion: v1 kind: Service metadata: - name: zipkin + name: grafana namespace: istio-system + annotations: + auth.istio.io/3000: NONE labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/cluster-service: "true" spec: ports: - - name: http - port: 9411 + - port: 3000 + protocol: TCP + name: http selector: - app: zipkin + app: grafana +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: grafana + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + template: + metadata: + labels: + app: grafana + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: grafana + containers: + - name: grafana + image: gcr.io/istio-release/grafana:0.8.0 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + env: + # Only put environment related config here. Generic Istio config + # should go in addons/grafana/grafana.ini. + - name: GF_PATHS_DATA + value: /data/grafana + volumeMounts: + - mountPath: /data/grafana + name: grafana-data + volumes: + - name: grafana-data + emptyDir: {} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: grafana + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile --- diff --git a/cluster/addons/istio/noauth/istio.yaml b/cluster/addons/istio/noauth/istio.yaml index ba798b9dfe5..363ecb9d800 100644 --- a/cluster/addons/istio/noauth/istio.yaml +++ b/cluster/addons/istio/noauth/istio.yaml @@ -1,14 +1,16 @@ -# GENERATED FILE. Use with Kubernetes 1.7+ -# TO UPDATE, modify files in install/kubernetes/templates and run install/updateVersion.sh -# -# Required for Istio as k8s addon. apiVersion: v1 kind: Namespace metadata: - name: default + name: kube-public labels: - istio-injection: enabled - addonmanager.kubernetes.io/mode: Reconcile + istio-injection: disabled +--- +apiVersion: v1 +kind: Namespace +metadata: + name: kube-system + labels: + istio-injection: disabled --- ################################ # Istio system namespace @@ -20,1874 +22,530 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + istio-injection: disabled --- -################################ -# Istio RBAC -################################ -# Permissions and roles for istio -# To debug: start the cluster with -vmodule=rbac,3 to enable verbose logging on RBAC DENY -# Also helps to enable logging on apiserver 'wrap' to see the URLs. -# Each RBAC deny needs to be mapped into a rule for the role. -# If using minikube, start with '--extra-config=apiserver.Authorization.Mode=RBAC' -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-pilot-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["config.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["*"] -- apiGroups: ["extensions"] - resources: ["thirdpartyresources", "thirdpartyresources.extensions", "ingresses", "ingresses/status"] - verbs: ["*"] -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["create", "get", "list", "watch", "update"] -- apiGroups: [""] - resources: ["endpoints", "pods", "services"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["namespaces", "nodes", "secrets"] - verbs: ["get", "list", "watch"] -- apiGroups: ["admissionregistration.k8s.io"] - resources: ["externaladmissionhookconfigurations"] - verbs: ["create", "update", "delete"] ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-injector-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["*"] - resources: ["configmaps"] - verbs: ["get", "list", "watch"] ---- -# Mixer CRD needs to watch and list CRDs -# It also uses discovery API to discover Kinds of config.istio.io -# K8s adapter needs to list pods, services etc. -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-mixer-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["config.istio.io"] # Istio CRD watcher - resources: ["*"] - verbs: ["get", "list", "watch"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] - verbs: ["get", "list", "watch"] ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-ca-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["create", "get", "watch", "list", "update"] -- apiGroups: [""] - resources: ["serviceaccounts"] - verbs: ["get", "watch", "list"] -- apiGroups: [""] - resources: ["services"] - verbs: ["get", "watch", "list"] ---- -# Permissions for the sidecar proxy. -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["extensions"] - resources: ["thirdpartyresources", "ingresses"] - verbs: ["get", "watch", "list", "update"] -- apiGroups: [""] - resources: ["configmaps", "pods", "endpoints", "services"] - verbs: ["get", "watch", "list"] ---- -# Grant permissions to the Pilot/discovery. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-pilot-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-pilot-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-pilot-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the Sidecar sidecar-injector -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-injector-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-sidecar-injector-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-sidecar-injector-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the CA. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-ca-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-ca-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-ca-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the Ingress controller. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-ingress-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-ingress-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-pilot-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the sidecar. -# TEMPORARY: the istioctl should generate a separate service account for the proxy, and permission -# granted only to that account ! -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: default - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-sidecar-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to Mixer. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-mixer-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-mixer-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-mixer-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Mixer +# Source: istio/charts/mixer/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: - name: istio-mixer + name: istio-statsd-prom-bridge namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-statsd-prom-bridge + chart: mixer-0.8.0 + release: istio + heritage: Tiller + istio: mixer data: mapping.conf: |- --- apiVersion: v1 -kind: Service -metadata: - name: istio-mixer - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - istio: mixer -spec: - ports: - - name: tcp-plain - port: 9091 - - name: tcp-mtls - port: 15004 - - name: http-monitoring - port: 9093 - - name: configapi - port: 9094 - - name: statsd-prom - port: 9102 - - name: statsd-udp - port: 9125 - protocol: UDP - - name: prometheus - port: 42422 - selector: - istio: mixer ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-mixer-service-account - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: istio-mixer - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - template: - metadata: - labels: - istio: mixer - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-mixer-service-account - containers: - - name: statsd-to-prometheus - image: gcr.io/istio-release/statsd-exporter:v0.5.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9102 - - containerPort: 9125 - protocol: UDP - args: - - '-statsd.mapping-config=/etc/statsd/mapping.conf' - volumeMounts: - - name: config-volume - mountPath: /etc/statsd - - name: mixer - image: gcr.io/istio-release/mixer:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9091 - - containerPort: 9093 - - containerPort: 9094 - - containerPort: 42422 - args: - - --configStoreURL=k8s:// - - --configDefaultNamespace=istio-system - - --zipkinURL=http://zipkin:9411/api/v1/spans - - --logtostderr - - -v - - "2" - - name: istio-proxy - image: gcr.io/istio-release/proxy:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15004 - args: - - proxy - - mixer - - -v - - "2" - - --controlPlaneAuthPolicy - - NONE #--controlPlaneAuthPolicy - - --customConfigFile - - /etc/istio/proxy/envoy_mixer.json - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - volumes: - - name: istio-certs - secret: - secretName: istio.istio-mixer-service-account - optional: true - - name: config-volume - configMap: - name: istio-mixer ---- -# Mixer CRD definitions are generated using -# mixs crd all - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: rules.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: istio.io.mixer - istio: core -spec: - group: config.istio.io - names: - kind: rule - plural: rules - singular: rule - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: attributemanifests.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: istio.io.mixer - istio: core -spec: - group: config.istio.io - names: - kind: attributemanifest - plural: attributemanifests - singular: attributemanifest - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: circonuses.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: circonus - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: circonus - plural: circonuses - singular: circonus - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: deniers.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: denier - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: denier - plural: deniers - singular: denier - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: fluentds.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: fluentd - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: fluentd - plural: fluentds - singular: fluentd - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: kubernetesenvs.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: kubernetesenv - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: kubernetesenv - plural: kubernetesenvs - singular: kubernetesenv - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: listcheckers.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: listchecker - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: listchecker - plural: listcheckers - singular: listchecker - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: memquotas.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: memquota - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: memquota - plural: memquotas - singular: memquota - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: noops.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: noop - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: noop - plural: noops - singular: noop - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: opas.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: opa - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: opa - plural: opas - singular: opa - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: prometheuses.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: prometheus - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: prometheus - plural: prometheuses - singular: prometheus - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: rbacs.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: rbac - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: rbac - plural: rbacs - singular: rbac - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: servicecontrols.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: servicecontrol - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: servicecontrol - plural: servicecontrols - singular: servicecontrol - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: solarwindses.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: solarwinds - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: solarwinds - plural: solarwindses - singular: solarwinds - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: stackdrivers.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: stackdriver - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: stackdriver - plural: stackdrivers - singular: stackdriver - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: statsds.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: statsd - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: statsd - plural: statsds - singular: statsd - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: stdios.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: stdio - istio: mixer-adapter -spec: - group: config.istio.io - names: - kind: stdio - plural: stdios - singular: stdio - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: apikeys.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: apikey - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: apikey - plural: apikeys - singular: apikey - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: authorizations.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: authorization - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: authorization - plural: authorizations - singular: authorization - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: checknothings.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: checknothing - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: checknothing - plural: checknothings - singular: checknothing - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: kuberneteses.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: adapter.template.kubernetes - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: kubernetes - plural: kuberneteses - singular: kubernetes - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: listentries.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: listentry - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: listentry - plural: listentries - singular: listentry - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: logentries.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: logentry - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: logentry - plural: logentries - singular: logentry - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: metrics.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: metric - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: metric - plural: metrics - singular: metric - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: quotas.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: quota - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: quota - plural: quotas - singular: quota - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: reportnothings.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: reportnothing - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: reportnothing - plural: reportnothings - singular: reportnothing - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: servicecontrolreports.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: servicecontrolreport - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: servicecontrolreport - plural: servicecontrolreports - singular: servicecontrolreport - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: tracespans.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - package: tracespan - istio: mixer-instance -spec: - group: config.istio.io - names: - kind: tracespan - plural: tracespans - singular: tracespan - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: serviceroles.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio: rbac -spec: - group: config.istio.io - names: - kind: ServiceRole - plural: serviceroles - singular: servicerole - scope: Namespaced - version: v1alpha2 ---- - -kind: CustomResourceDefinition -apiVersion: apiextensions.k8s.io/v1beta1 -metadata: - name: servicerolebindings.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio: rbac -spec: - group: config.istio.io - names: - kind: ServiceRoleBinding - plural: servicerolebindings - singular: servicerolebinding - scope: Namespaced - version: v1alpha2 ---- - -apiVersion: "config.istio.io/v1alpha2" -kind: attributemanifest -metadata: - name: istioproxy - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - attributes: - origin.ip: - valueType: IP_ADDRESS - origin.uid: - valueType: STRING - origin.user: - valueType: STRING - request.headers: - valueType: STRING_MAP - request.id: - valueType: STRING - request.host: - valueType: STRING - request.method: - valueType: STRING - request.path: - valueType: STRING - request.reason: - valueType: STRING - request.referer: - valueType: STRING - request.scheme: - valueType: STRING - request.size: - valueType: INT64 - request.time: - valueType: TIMESTAMP - request.useragent: - valueType: STRING - response.code: - valueType: INT64 - response.duration: - valueType: DURATION - response.headers: - valueType: STRING_MAP - response.size: - valueType: INT64 - response.time: - valueType: TIMESTAMP - source.uid: - valueType: STRING - source.user: - valueType: STRING - destination.uid: - valueType: STRING - connection.id: - valueType: STRING - connection.received.bytes: - valueType: INT64 - connection.received.bytes_total: - valueType: INT64 - connection.sent.bytes: - valueType: INT64 - connection.sent.bytes_total: - valueType: INT64 - connection.duration: - valueType: DURATION - context.protocol: - valueType: STRING - context.timestamp: - valueType: TIMESTAMP - context.time: - valueType: TIMESTAMP - api.service: - valueType: STRING - api.version: - valueType: STRING - api.operation: - valueType: STRING - api.protocol: - valueType: STRING - request.auth.principal: - valueType: STRING - request.auth.audiences: - valueType: STRING - request.auth.presenter: - valueType: STRING - request.api_key: - valueType: STRING - ---- -apiVersion: "config.istio.io/v1alpha2" -kind: attributemanifest -metadata: - name: kubernetes - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - attributes: - source.ip: - valueType: IP_ADDRESS - source.labels: - valueType: STRING_MAP - source.name: - valueType: STRING - source.namespace: - valueType: STRING - source.service: - valueType: STRING - source.serviceAccount: - valueType: STRING - destination.ip: - valueType: IP_ADDRESS - destination.labels: - valueType: STRING_MAP - destination.name: - valueType: STRING - destination.namespace: - valueType: STRING - destination.service: - valueType: STRING - destination.serviceAccount: - valueType: STRING ---- -apiVersion: "config.istio.io/v1alpha2" -kind: stdio -metadata: - name: handler - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - outputAsJson: true ---- -apiVersion: "config.istio.io/v1alpha2" -kind: logentry -metadata: - name: accesslog - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - severity: '"Default"' - timestamp: request.time - variables: - sourceIp: source.ip | ip("0.0.0.0") - destinationIp: destination.ip | ip("0.0.0.0") - sourceUser: source.user | "" - method: request.method | "" - url: request.path | "" - protocol: request.scheme | "http" - responseCode: response.code | 0 - responseSize: response.size | 0 - requestSize: request.size | 0 - latency: response.duration | "0ms" - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: stdio - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - match: "true" # If omitted match is true. - actions: - - handler: handler.stdio - instances: - - accesslog.logentry ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: requestcount - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - value: "1" - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: requestduration - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - value: response.duration | "0ms" - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: requestsize - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - value: request.size | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: responsesize - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - value: response.size | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: tcpbytesent - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp -spec: - value: connection.sent.bytes | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: tcpbytereceived - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp -spec: - value: connection.received.bytes | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: prometheus -metadata: - name: handler - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - metrics: - - name: request_count - instance_name: requestcount.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - - name: request_duration - instance_name: requestduration.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - explicit_buckets: - bounds: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10] - - name: request_size - instance_name: requestsize.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - exponentialBuckets: - numFiniteBuckets: 8 - scale: 1 - growthFactor: 10 - - name: response_size - instance_name: responsesize.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - exponentialBuckets: - numFiniteBuckets: 8 - scale: 1 - growthFactor: 10 - - name: tcp_bytes_sent - instance_name: tcpbytesent.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version - - name: tcp_bytes_received - instance_name: tcpbytereceived.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version ---- -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: promhttp - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: http -spec: - actions: - - handler: handler.prometheus - instances: - - requestcount.metric - - requestduration.metric - - requestsize.metric - - responsesize.metric ---- -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: promtcp - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only execute when context.protocol == TCP -spec: - actions: - - handler: handler.prometheus - instances: - - tcpbytesent.metric - - tcpbytereceived.metric ---- - -apiVersion: "config.istio.io/v1alpha2" -kind: kubernetesenv -metadata: - name: handler - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - # when running from mixer root, use the following config after adding a - # symbolic link to a kubernetes config file via: - # - # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig - # - # kubeconfig_path: "mixer/adapter/kubernetes/kubeconfig" - ---- -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: kubeattrgenrulerule - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - actions: - - handler: handler.kubernetesenv - instances: - - attributes.kubernetes ---- -apiVersion: "config.istio.io/v1alpha2" -kind: kubernetes -metadata: - name: attributes - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - # Pass the required attribute data to the adapter - source_uid: source.uid | "" - source_ip: source.ip | ip("0.0.0.0") # default to unspecified ip addr - destination_uid: destination.uid | "" - destination_ip: destination.ip | ip("0.0.0.0") # default to unspecified ip addr - origin_uid: '""' - origin_ip: ip("0.0.0.0") # default to unspecified ip addr - attribute_bindings: - # Fill the new attributes from the adapter produced output. - # $out refers to an instance of OutputTemplate message - source.ip: $out.source_pod_ip | ip("0.0.0.0") - source.labels: $out.source_labels | emptyStringMap() - source.namespace: $out.source_namespace | "default" - source.service: $out.source_service | "unknown" - source.serviceAccount: $out.source_service_account_name | "unknown" - destination.ip: $out.destination_pod_ip | ip("0.0.0.0") - destination.labels: $out.destination_labels | emptyStringMap() - destination.namespace: $out.destination_namespace | "default" - destination.service: $out.destination_service | "unknown" - destination.serviceAccount: $out.destination_service_account_name | "unknown" ---- -################################ -# Istio configMap cluster-wide -################################ -apiVersion: v1 kind: ConfigMap metadata: - name: istio + name: istio-mixer-custom-resources namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-mixer + chart: mixer-0.8.0 + release: istio + heritage: Tiller + istio: mixer data: - mesh: |- - # Uncomment the following line to enable mutual TLS between proxies - # authPolicy: MUTUAL_TLS - # - # Edit this list to avoid using mTLS to connect to these services. - # Typically, these are control services (e.g kubernetes API server) that don't have Istio sidecar - # to transparently terminate mTLS authentication. - mtlsExcludedServices: ["kubernetes.default.svc.cluster.local"] - - # Set the following variable to true to disable policy checks by the Mixer. - # Note that metrics will still be reported to the Mixer. - disablePolicyChecks: false - # Set enableTracing to false to disable request tracing. - enableTracing: true - # - # To disable the mixer completely (including metrics), comment out - # the following lines - mixerCheckServer: istio-mixer.istio-system:15004 - mixerReportServer: istio-mixer.istio-system:15004 - # This is the ingress service name, update if you used a different name - ingressService: istio-ingress - # - # Along with discoveryRefreshDelay, this setting determines how - # frequently should Envoy fetch and update its internal configuration - # from Istio Pilot. Lower refresh delay results in higher CPU - # utilization and potential performance loss in exchange for faster - # convergence. Tweak this value according to your setup. - rdsRefreshDelay: 1s - # - defaultConfig: - # NOTE: If you change any values in this section, make sure to make - # the same changes in start up args in istio-ingress pods. - # See rdsRefreshDelay for explanation about this setting. - discoveryRefreshDelay: 1s + custom-resources.yaml: |- + apiVersion: "config.istio.io/v1alpha2" + kind: attributemanifest + metadata: + name: istioproxy + namespace: istio-system + spec: + attributes: + origin.ip: + valueType: IP_ADDRESS + origin.uid: + valueType: STRING + origin.user: + valueType: STRING + request.headers: + valueType: STRING_MAP + request.id: + valueType: STRING + request.host: + valueType: STRING + request.method: + valueType: STRING + request.path: + valueType: STRING + request.reason: + valueType: STRING + request.referer: + valueType: STRING + request.scheme: + valueType: STRING + request.total_size: + valueType: INT64 + request.size: + valueType: INT64 + request.time: + valueType: TIMESTAMP + request.useragent: + valueType: STRING + response.code: + valueType: INT64 + response.duration: + valueType: DURATION + response.headers: + valueType: STRING_MAP + response.total_size: + valueType: INT64 + response.size: + valueType: INT64 + response.time: + valueType: TIMESTAMP + source.uid: + valueType: STRING + source.user: + valueType: STRING + destination.uid: + valueType: STRING + connection.id: + valueType: STRING + connection.received.bytes: + valueType: INT64 + connection.received.bytes_total: + valueType: INT64 + connection.sent.bytes: + valueType: INT64 + connection.sent.bytes_total: + valueType: INT64 + connection.duration: + valueType: DURATION + connection.mtls: + valueType: BOOL + context.protocol: + valueType: STRING + context.timestamp: + valueType: TIMESTAMP + context.time: + valueType: TIMESTAMP + api.service: + valueType: STRING + api.version: + valueType: STRING + api.operation: + valueType: STRING + api.protocol: + valueType: STRING + request.auth.principal: + valueType: STRING + request.auth.audiences: + valueType: STRING + request.auth.presenter: + valueType: STRING + request.auth.claims: + valueType: STRING_MAP + request.auth.raw_claims: + valueType: STRING + request.api_key: + valueType: STRING + + --- + apiVersion: "config.istio.io/v1alpha2" + kind: attributemanifest + metadata: + name: kubernetes + namespace: istio-system + spec: + attributes: + source.ip: + valueType: IP_ADDRESS + source.labels: + valueType: STRING_MAP + source.name: + valueType: STRING + source.namespace: + valueType: STRING + source.service: + valueType: STRING + source.serviceAccount: + valueType: STRING + destination.ip: + valueType: IP_ADDRESS + destination.labels: + valueType: STRING_MAP + destination.name: + valueType: STRING + destination.namespace: + valueType: STRING + destination.service: + valueType: STRING + destination.serviceAccount: + valueType: STRING + --- + apiVersion: "config.istio.io/v1alpha2" + kind: stdio + metadata: + name: handler + namespace: istio-system + spec: + outputAsJson: true + --- + apiVersion: "config.istio.io/v1alpha2" + kind: logentry + metadata: + name: accesslog + namespace: istio-system + spec: + severity: '"Info"' + timestamp: request.time + variables: + originIp: origin.ip | ip("0.0.0.0") + sourceIp: source.ip | ip("0.0.0.0") + sourceService: source.service | "" + sourceUser: source.user | source.uid | "" + sourceNamespace: source.namespace | "" + destinationIp: destination.ip | ip("0.0.0.0") + destinationService: destination.service | "" + destinationNamespace: destination.namespace | "" + apiName: api.service | "" + apiVersion: api.version | "" + apiClaims: request.headers["sec-istio-auth-userinfo"]| "" + apiKey: request.api_key | request.headers["x-api-key"] | "" + requestOperation: api.operation | "" + protocol: request.scheme | "http" + method: request.method | "" + url: request.path | "" + responseCode: response.code | 0 + responseSize: response.size | 0 + requestSize: request.size | 0 + latency: response.duration | "0ms" + connectionMtls: connection.mtls | false + userAgent: request.useragent | "" + responseTimestamp: response.time + receivedBytes: request.total_size | connection.received.bytes | 0 + sentBytes: response.total_size | connection.sent.bytes | 0 + referer: request.referer | "" + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: stdio + namespace: istio-system + spec: + match: "true" # If omitted match is true. + actions: + - handler: handler.stdio + instances: + - accesslog.logentry + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestcount + namespace: istio-system + spec: + value: "1" + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestduration + namespace: istio-system + spec: + value: response.duration | "0ms" + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestsize + namespace: istio-system + spec: + value: request.size | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: responsesize + namespace: istio-system + spec: + value: response.size | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: tcpbytesent + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp + spec: + value: connection.sent.bytes | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: tcpbytereceived + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp + spec: + value: connection.received.bytes | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: prometheus + metadata: + name: handler + namespace: istio-system + spec: + metrics: + - name: request_count + instance_name: requestcount.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + - name: request_duration + instance_name: requestduration.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + explicit_buckets: + bounds: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10] + - name: request_size + instance_name: requestsize.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + exponentialBuckets: + numFiniteBuckets: 8 + scale: 1 + growthFactor: 10 + - name: response_size + instance_name: responsesize.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + exponentialBuckets: + numFiniteBuckets: 8 + scale: 1 + growthFactor: 10 + - name: tcp_bytes_sent + instance_name: tcpbytesent.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - connection_mtls + - name: tcp_bytes_received + instance_name: tcpbytereceived.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - connection_mtls + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: promhttp + namespace: istio-system + labels: + istio-protocol: http + spec: + actions: + - handler: handler.prometheus + instances: + - requestcount.metric + - requestduration.metric + - requestsize.metric + - responsesize.metric + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: promtcp + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only execute when context.protocol == TCP + spec: + actions: + - handler: handler.prometheus + instances: + - tcpbytesent.metric + - tcpbytereceived.metric + --- + + apiVersion: "config.istio.io/v1alpha2" + kind: kubernetesenv + metadata: + name: handler + namespace: istio-system + spec: + # when running from mixer root, use the following config after adding a + # symbolic link to a kubernetes config file via: # - # TCP connection timeout between Envoy & the application, and between Envoys. - connectTimeout: 10s + # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig # - ### ADVANCED SETTINGS ############# - # Where should envoy's configuration be stored in the istio-proxy container - configPath: "/etc/istio/proxy" - binaryPath: "/usr/local/bin/envoy" - # The pseudo service name used for Envoy. - serviceCluster: istio-proxy - # These settings that determine how long an old Envoy - # process should be kept alive after an occasional reload. - drainDuration: 45s - parentShutdownDuration: 1m0s - # - # Port where Envoy listens (on local host) for admin commands - # You can exec into the istio-proxy container in a pod and - # curl the admin port (curl http://localhost:15000/) to obtain - # diagnostic information from Envoy. See - # https://lyft.github.io/envoy/docs/operations/admin.html - # for more details - proxyAdminPort: 15000 - # - # Address where Istio Pilot service is running - discoveryAddress: istio-pilot.istio-system:15003 - # - # Zipkin trace collector - zipkinAddress: zipkin.istio-system:9411 - # - # Statsd metrics collector. Istio mixer exposes a UDP endpoint - # to collect and convert statsd metrics into Prometheus metrics. - statsdUdpAddress: istio-mixer.istio-system:9125 - # Uncomment the following line to enable mutual TLS authentication between - # sidecars and istio control plane. - # controlPlaneAuthPolicy: MUTUAL_TLS ---- -################################ -# Pilot -################################ -# Pilot CRDs -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: destinationpolicies.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: DestinationPolicy - listKind: DestinationPolicyList - plural: destinationpolicies - singular: destinationpolicy - scope: Namespaced - version: v1alpha2 ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: egressrules.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: EgressRule - listKind: EgressRuleList - plural: egressrules - singular: egressrule - scope: Namespaced - version: v1alpha2 ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: routerules.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: RouteRule - listKind: RouteRuleList - plural: routerules - singular: routerule - scope: Namespaced - version: v1alpha2 ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: v1alpha2routerules.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: V1alpha2RouteRule - listKind: V1alpha2RouteRuleList - plural: v1alpha2routerules - singular: v1alpha2routerule - scope: Namespaced - version: v1alpha2 ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: destinationrules.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: + # kubeconfig_path: "mixer/adapter/kubernetes/kubeconfig" + + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: kubeattrgenrulerule + namespace: istio-system + spec: + actions: + - handler: handler.kubernetesenv + instances: + - attributes.kubernetes + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: tcpkubeattrgenrulerule + namespace: istio-system + spec: + match: context.protocol == "tcp" + actions: + - handler: handler.kubernetesenv + instances: + - attributes.kubernetes + --- + apiVersion: "config.istio.io/v1alpha2" + kind: kubernetes + metadata: + name: attributes + namespace: istio-system + spec: + # Pass the required attribute data to the adapter + source_uid: source.uid | "" + source_ip: source.ip | ip("0.0.0.0") # default to unspecified ip addr + destination_uid: destination.uid | "" + origin_uid: '""' + origin_ip: ip("0.0.0.0") # default to unspecified ip addr + attribute_bindings: + # Fill the new attributes from the adapter produced output. + # $out refers to an instance of OutputTemplate message + source.ip: $out.source_pod_ip | ip("0.0.0.0") + source.labels: $out.source_labels | emptyStringMap() + source.namespace: $out.source_namespace | "default" + source.service: $out.source_service | "unknown" + source.serviceAccount: $out.source_service_account_name | "unknown" + destination.ip: $out.destination_pod_ip | ip("0.0.0.0") + destination.labels: $out.destination_labels | emptyStringMap() + destination.namespace: $out.destination_namespace | "default" + destination.service: $out.destination_service | "unknown" + destination.serviceAccount: $out.destination_service_account_name | "unknown" + --- + # Configuration needed by Mixer. + # Mixer cluster is delivered via CDS + # Specify mixer cluster settings + apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule - listKind: DestinationRuleList - plural: destinationrules - singular: destinationrule - scope: Namespaced - version: v1alpha2 ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: externalservices.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: ExternalService - listKind: ExternalServiceList - plural: externalservices - singular: externalservice - scope: Namespaced - version: v1alpha2 ---- -# Pilot service for discovery -apiVersion: v1 -kind: Service -metadata: - name: istio-pilot - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - istio: pilot -spec: - ports: - - port: 15003 - name: http-discovery - - port: 8080 - name: http-legacy-discovery - - port: 9093 - name: http-monitoring - - port: 443 - name: admission-webhook - selector: - istio: pilot ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-pilot-service-account - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: istio-pilot - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - template: metadata: - labels: - istio: pilot - annotations: - sidecar.istio.io/inject: "false" + name: istio-policy + namespace: istio-system spec: - serviceAccountName: istio-pilot-service-account - containers: - - name: discovery - image: gcr.io/istio-release/pilot:0.6.0 - imagePullPolicy: IfNotPresent - args: ["discovery", "-v", "2", "--admission-service", "istio-pilot"] - ports: - - containerPort: 8080 - - containerPort: 443 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: PILOT_THROTTLE - value: "200" - volumeMounts: - - name: config-volume - mountPath: /etc/istio/config - - name: istio-proxy - image: gcr.io/istio-release/proxy:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15003 - args: - - proxy - - pilot - - -v - - "2" - - --discoveryAddress - - istio-pilot:15003 - - --controlPlaneAuthPolicy - - NONE #--controlPlaneAuthPolicy - - --customConfigFile - - /etc/istio/proxy/envoy_pilot.json - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - volumes: - - name: config-volume - configMap: - name: istio - - name: istio-certs - secret: - secretName: istio.istio-pilot-service-account - optional: true ---- -################################ -# Istio ingress -################################ -apiVersion: v1 -kind: Service -metadata: - name: istio-ingress - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - istio: ingress -spec: - type: LoadBalancer - ports: - - port: 80 -# nodePort: 32000 - name: http - - port: 443 - name: https - selector: - istio: ingress ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-ingress-service-account - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: istio-ingress - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - template: + host: istio-policy.istio-system.svc.cluster.local + trafficPolicy: + connectionPool: + http: + http2MaxRequests: 10000 + maxRequestsPerConnection: 10000 + --- + apiVersion: networking.istio.io/v1alpha3 + kind: DestinationRule metadata: - labels: - istio: ingress - annotations: - sidecar.istio.io/inject: "false" + name: istio-telemetry + namespace: istio-system spec: - serviceAccountName: istio-ingress-service-account - containers: - - name: istio-ingress - image: gcr.io/istio-release/proxy:0.6.0 - args: - - proxy - - ingress - - -v - - "2" - - --discoveryAddress - - istio-pilot:15003 - - --discoveryRefreshDelay - - '1s' #discoveryRefreshDelay - - --drainDuration - - '45s' #drainDuration - - --parentShutdownDuration - - '1m0s' #parentShutdownDuration - - --connectTimeout - - '10s' #connectTimeout - - --serviceCluster - - istio-ingress - - --zipkinAddress - - zipkin:9411 - - --statsdUdpAddress - - istio-mixer:9125 - - --proxyAdminPort - - "15000" - - --controlPlaneAuthPolicy - - NONE #--controlPlaneAuthPolicy - imagePullPolicy: IfNotPresent - ports: - - containerPort: 80 - - containerPort: 443 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: ingress-certs - mountPath: /etc/istio/ingress-certs - readOnly: true - volumes: - - name: istio-certs - secret: - secretName: istio.default - optional: true - - name: ingress-certs - secret: - secretName: istio-ingress-certs - optional: true ---- -################################ -# Istio-CA cluster-wide -################################ -# Service account CA -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-ca-service-account - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- -# Istio CA watching all namespaces -apiVersion: v1 -kind: Deployment -apiVersion: extensions/v1beta1 -metadata: - name: istio-ca - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - template: - metadata: - labels: - istio: istio-ca - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-ca-service-account - containers: - - name: istio-ca - image: gcr.io/istio-release/istio-ca:0.6.0 - imagePullPolicy: IfNotPresent - command: ["/usr/local/bin/istio_ca"] - args: - - --istio-ca-storage-namespace=istio-system - - --grpc-port=8060 - - --grpc-hostname=istio-ca - - --self-signed-ca=true - - --logtostderr - - --stderrthreshold - - INFO ---- -apiVersion: v1 -kind: Service -metadata: - name: grafana - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" -spec: - ports: - - port: 3000 - protocol: TCP - name: http - selector: - app: grafana ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: grafana - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - template: - metadata: - labels: - app: grafana - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: grafana - containers: - - name: grafana - image: gcr.io/istio-release/grafana:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 3000 - env: - # Only put environment related config here. Generic Istio config - # should go in addons/grafana/grafana.ini. - - name: GF_PATHS_DATA - value: /data/grafana - volumeMounts: - - mountPath: /data/grafana - name: grafana-data - volumes: - - name: grafana-data - emptyDir: {} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: grafana - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- + host: istio-telemetry.istio-system.svc.cluster.local + trafficPolicy: + connectionPool: + http: + http2MaxRequests: 10000 + maxRequestsPerConnection: 10000 + --- + + --- +# Source: istio/charts/prometheus/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: @@ -1896,6 +554,10 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: prometheus + chart: prometheus-0.1.0 + release: istio + heritage: Tiller data: prometheus.yml: |- global: @@ -1912,7 +574,7 @@ data: relabel_configs: - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] action: keep - regex: istio-system;istio-mixer;prometheus + regex: istio-system;istio-telemetry;prometheus - job_name: 'envoy' # Override the global default and scrape targets from this job every 5 seconds. @@ -1926,9 +588,9 @@ data: relabel_configs: - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] action: keep - regex: istio-system;istio-mixer;statsd-prom + regex: istio-system;istio-statsd-prom-bridge;statsd-prom - - job_name: 'mixer' + - job_name: 'istio-policy' # Override the global default and scrape targets from this job every 5 seconds. scrape_interval: 5s # metrics_path defaults to '/metrics' @@ -1940,7 +602,21 @@ data: relabel_configs: - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] action: keep - regex: istio-system;istio-mixer;http-monitoring + regex: istio-system;istio-policy;http-monitoring + + - job_name: 'istio-telemetry' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-telemetry;http-monitoring - job_name: 'pilot' # Override the global default and scrape targets from this job every 5 seconds. @@ -2076,65 +752,441 @@ data: target_label: pod_name --- +# Source: istio/templates/configmap.yaml apiVersion: v1 -kind: Service +kind: ConfigMap metadata: - annotations: - prometheus.io/scrape: 'true' + name: istio + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - name: prometheus - name: prometheus - namespace: istio-system -spec: - selector: - app: prometheus - ports: - - name: prometheus - protocol: TCP - port: 9090 + app: istio + chart: istio-0.8.0 + release: istio + heritage: Tiller +data: + mesh: |- + # + # Edit this list to avoid using mTLS to connect to these services. + # Typically, these are control services (e.g kubernetes API server) that don't have istio sidecar + # to transparently terminate mTLS authentication. + # mtlsExcludedServices: ["kubernetes.default.svc.cluster.local"] + + # Set the following variable to true to disable policy checks by the Mixer. + # Note that metrics will still be reported to the Mixer. + disablePolicyChecks: false + # Set enableTracing to false to disable request tracing. + enableTracing: true + # + # To disable the mixer completely (including metrics), comment out + # the following lines + mixerCheckServer: istio-policy.istio-system.svc.cluster.local:15004 + mixerReportServer: istio-telemetry.istio-system.svc.cluster.local:15004 + # This is the ingress service name, update if you used a different name + ingressService: istio-ingress + # + # Along with discoveryRefreshDelay, this setting determines how + # frequently should Envoy fetch and update its internal configuration + # from istio Pilot. Lower refresh delay results in higher CPU + # utilization and potential performance loss in exchange for faster + # convergence. Tweak this value according to your setup. + rdsRefreshDelay: 10s + # + defaultConfig: + # NOTE: If you change any values in this section, make sure to make + # the same changes in start up args in istio-ingress pods. + # See rdsRefreshDelay for explanation about this setting. + discoveryRefreshDelay: 10s + # + # TCP connection timeout between Envoy & the application, and between Envoys. + connectTimeout: 10s + # + ### ADVANCED SETTINGS ############# + # Where should envoy's configuration be stored in the istio-proxy container + configPath: "/etc/istio/proxy" + binaryPath: "/usr/local/bin/envoy" + # The pseudo service name used for Envoy. + serviceCluster: istio-proxy + # These settings that determine how long an old Envoy + # process should be kept alive after an occasional reload. + drainDuration: 45s + parentShutdownDuration: 1m0s + # + # The mode used to redirect inbound connections to Envoy. This setting + # has no effect on outbound traffic: iptables REDIRECT is always used for + # outbound connections. + # If "REDIRECT", use iptables REDIRECT to NAT and redirect to Envoy. + # The "REDIRECT" mode loses source addresses during redirection. + # If "TPROXY", use iptables TPROXY to redirect to Envoy. + # The "TPROXY" mode preserves both the source and destination IP + # addresses and ports, so that they can be used for advanced filtering + # and manipulation. + # The "TPROXY" mode also configures the sidecar to run with the + # CAP_NET_ADMIN capability, which is required to use TPROXY. + #interceptionMode: REDIRECT + # + # Port where Envoy listens (on local host) for admin commands + # You can exec into the istio-proxy container in a pod and + # curl the admin port (curl http://localhost:15000/) to obtain + # diagnostic information from Envoy. See + # https://lyft.github.io/envoy/docs/operations/admin.html + # for more details + proxyAdminPort: 15000 + # + # Zipkin trace collector + zipkinAddress: zipkin.istio-system:9411 + # + # Statsd metrics collector converts statsd metrics into Prometheus metrics. + statsdUdpAddress: istio-statsd-prom-bridge.istio-system:9125 + # + # Mutual TLS authentication between sidecars and istio control plane. + controlPlaneAuthPolicy: NONE + # + # Address where istio Pilot service is running + discoveryAddress: istio-pilot.istio-system:15007 + --- -apiVersion: extensions/v1beta1 -kind: Deployment +# Source: istio/templates/sidecar-injector-configmap.yaml +apiVersion: v1 +kind: ConfigMap metadata: - name: prometheus + name: istio-sidecar-injector namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio + chart: istio-0.8.0 + release: istio + heritage: Tiller + istio: sidecar-injector +data: + config: |- + policy: enabled + template: |- + metadata: + annotations: + container.seccomp.security.alpha.kubernetes.io/istio-proxy: 'docker/default' + initContainers: + - name: istio-init + image: gcr.io/istio-release/proxy_init:0.8.0 + args: + - "-p" + - [[ .MeshConfig.ProxyListenPort ]] + - "-u" + - 1337 + - "-m" + - [[ or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String ]] + - "-i" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeOutboundIPRanges") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeOutboundIPRanges" ]]" + [[ else -]] + - "*" + [[ end -]] + - "-x" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeOutboundIPRanges") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeOutboundIPRanges" ]]" + [[ else -]] + - "" + [[ end -]] + - "-b" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeInboundPorts") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeInboundPorts" ]]" + [[ else -]] + - [[ range .Spec.Containers -]][[ range .Ports -]][[ .ContainerPort -]], [[ end -]][[ end -]][[ end]] + - "-d" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeInboundPorts") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeInboundPorts" ]]" + [[ else -]] + - "" + [[ end -]] + imagePullPolicy: IfNotPresent + securityContext: + capabilities: + add: + - NET_ADMIN + privileged: true + restartPolicy: Always + + containers: + - name: istio-proxy + image: [[ if (isset .ObjectMeta.Annotations "sidecar.istio.io/proxyImage") -]] + "[[ index .ObjectMeta.Annotations "sidecar.istio.io/proxyImage" ]]" + [[ else -]] + gcr.io/istio-release/proxyv2:0.8.0 + [[ end -]] + args: + - proxy + - sidecar + - --configPath + - [[ .ProxyConfig.ConfigPath ]] + - --binaryPath + - [[ .ProxyConfig.BinaryPath ]] + - --serviceCluster + [[ if ne "" (index .ObjectMeta.Labels "app") -]] + - [[ index .ObjectMeta.Labels "app" ]] + [[ else -]] + - "istio-proxy" + [[ end -]] + - --drainDuration + - [[ formatDuration .ProxyConfig.DrainDuration ]] + - --parentShutdownDuration + - [[ formatDuration .ProxyConfig.ParentShutdownDuration ]] + - --discoveryAddress + - [[ .ProxyConfig.DiscoveryAddress ]] + - --discoveryRefreshDelay + - [[ formatDuration .ProxyConfig.DiscoveryRefreshDelay ]] + - --zipkinAddress + - [[ .ProxyConfig.ZipkinAddress ]] + - --connectTimeout + - [[ formatDuration .ProxyConfig.ConnectTimeout ]] + - --statsdUdpAddress + - [[ .ProxyConfig.StatsdUdpAddress ]] + - --proxyAdminPort + - [[ .ProxyConfig.ProxyAdminPort ]] + - --controlPlaneAuthPolicy + - [[ .ProxyConfig.ControlPlaneAuthPolicy ]] + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: ISTIO_META_INTERCEPTION_MODE + value: [[ or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String ]] + imagePullPolicy: IfNotPresent + securityContext: + privileged: false + readOnlyRootFilesystem: true + [[ if eq (or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String) "TPROXY" -]] + capabilities: + add: + - NET_ADMIN + [[ else -]] + runAsUser: 1337 + [[ end -]] + restartPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - mountPath: /etc/istio/proxy + name: istio-envoy + - mountPath: /etc/certs/ + name: istio-certs + readOnly: true + volumes: + - emptyDir: + medium: Memory + name: istio-envoy + - name: istio-certs + secret: + optional: true + [[ if eq .Spec.ServiceAccountName "" -]] + secretName: istio.default + [[ else -]] + secretName: [[ printf "istio.%s" .Spec.ServiceAccountName ]] + [[ end -]] + + +--- +# Source: istio/charts/egressgateway/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-egressgateway-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: egressgateway + chart: egressgateway-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/ingress/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-ingress-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/ingressgateway/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-ingressgateway-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingressgateway + chart: ingressgateway-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/mixer/templates/create-custom-resources-job.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-mixer-post-install-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-mixer-post-install-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] # istio CRD watcher + resources: ["*"] + verbs: ["create", "get", "list", "watch", "patch"] +- apiGroups: ["networking.istio.io"] # needed to create mixer destination rules + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-mixer-post-install-role-binding-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-mixer-post-install-istio-system +subjects: + - kind: ServiceAccount + name: istio-mixer-post-install-account + namespace: istio-system +--- + +apiVersion: batch/v1 +kind: Job +metadata: + name: istio-mixer-post-install + namespace: istio-system + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-delete-policy": before-hook-creation + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + release: istio + heritage: Tiller spec: - selector: - matchLabels: - app: prometheus template: metadata: - name: prometheus + name: istio-mixer-post-install labels: - app: prometheus - annotations: - sidecar.istio.io/inject: "false" + app: mixer + release: istio spec: - serviceAccountName: prometheus + serviceAccountName: istio-mixer-post-install-account containers: - - name: prometheus - image: gcr.io/istio-release/prom/prometheus:v2.0.0 - imagePullPolicy: IfNotPresent - args: - - '--storage.tsdb.retention=6h' - - '--config.file=/etc/prometheus/prometheus.yml' - ports: - - name: web - containerPort: 9090 - volumeMounts: - - name: config-volume - mountPath: /etc/prometheus + - name: hyperkube + image: "gcr.io/istio-release/coreos/hyperkube:v1.7.6_coreos.0" + command: + - ./kubectl + - apply + - -f + - /tmp/mixer/custom-resources.yaml + volumeMounts: + - mountPath: "/tmp/mixer" + name: tmp-configmap-mixer volumes: - - name: config-volume - configMap: - name: prometheus + - name: tmp-configmap-mixer + configMap: + name: istio-mixer-custom-resources + restartPolicy: Never # CRD might take some time till they are available to consume + --- +# Source: istio/charts/mixer/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-mixer-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/pilot/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-pilot-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/prometheus/templates/serviceaccount.yaml + apiVersion: v1 kind: ServiceAccount metadata: @@ -2144,10 +1196,957 @@ metadata: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile --- +# Source: istio/charts/security/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-citadel-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-cleanup-old-ca-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-sidecar-injector-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/mixer/templates/crds.yaml +# Mixer CRDs +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: rules.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer + istio: core +spec: + group: config.istio.io + names: + kind: rule + plural: rules + singular: rule + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: attributemanifests.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer + istio: core +spec: + group: config.istio.io + names: + kind: attributemanifest + plural: attributemanifests + singular: attributemanifest + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: circonuses.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: circonus + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: circonus + plural: circonuses + singular: circonus + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: deniers.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: denier + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: denier + plural: deniers + singular: denier + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: fluentds.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: fluentd + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: fluentd + plural: fluentds + singular: fluentd + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: kubernetesenvs.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: kubernetesenv + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: kubernetesenv + plural: kubernetesenvs + singular: kubernetesenv + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: listcheckers.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: listchecker + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: listchecker + plural: listcheckers + singular: listchecker + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: memquotas.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: memquota + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: memquota + plural: memquotas + singular: memquota + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: noops.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: noop + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: noop + plural: noops + singular: noop + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: opas.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: opa + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: opa + plural: opas + singular: opa + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: prometheuses.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: prometheus + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: prometheus + plural: prometheuses + singular: prometheus + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: rbacs.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: rbac + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: rbac + plural: rbacs + singular: rbac + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: servicecontrols.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: servicecontrol + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: servicecontrol + plural: servicecontrols + singular: servicecontrol + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: solarwindses.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: solarwinds + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: solarwinds + plural: solarwindses + singular: solarwinds + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: stackdrivers.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: stackdriver + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: stackdriver + plural: stackdrivers + singular: stackdriver + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: statsds.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: statsd + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: statsd + plural: statsds + singular: statsd + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: stdios.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: stdio + istio: mixer-adapter +spec: + group: config.istio.io + names: + kind: stdio + plural: stdios + singular: stdio + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: apikeys.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: apikey + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: apikey + plural: apikeys + singular: apikey + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: authorizations.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: authorization + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: authorization + plural: authorizations + singular: authorization + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: checknothings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: checknothing + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: checknothing + plural: checknothings + singular: checknothing + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: kuberneteses.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: adapter.template.kubernetes + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: kubernetes + plural: kuberneteses + singular: kubernetes + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: listentries.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: listentry + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: listentry + plural: listentries + singular: listentry + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: logentries.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: logentry + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: logentry + plural: logentries + singular: logentry + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: metrics.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: metric + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: metric + plural: metrics + singular: metric + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: quotas.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: quota + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: quota + plural: quotas + singular: quota + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: reportnothings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: reportnothing + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: reportnothing + plural: reportnothings + singular: reportnothing + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: servicecontrolreports.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: servicecontrolreport + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: servicecontrolreport + plural: servicecontrolreports + singular: servicecontrolreport + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: tracespans.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: tracespan + istio: mixer-instance +spec: + group: config.istio.io + names: + kind: tracespan + plural: tracespans + singular: tracespan + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: serviceroles.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer + istio: rbac +spec: + group: config.istio.io + names: + kind: ServiceRole + plural: serviceroles + singular: servicerole + scope: Namespaced + version: v1alpha2 +--- + +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: servicerolebindings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer + istio: rbac +spec: + group: config.istio.io + names: + kind: ServiceRoleBinding + plural: servicerolebindings + singular: servicerolebinding + scope: Namespaced + version: v1alpha2 + +--- +# Source: istio/charts/pilot/templates/crds.yaml +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: destinationpolicies.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: config.istio.io + names: + kind: DestinationPolicy + listKind: DestinationPolicyList + plural: destinationpolicies + singular: destinationpolicy + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: egressrules.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: config.istio.io + names: + kind: EgressRule + listKind: EgressRuleList + plural: egressrules + singular: egressrule + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: routerules.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: config.istio.io + names: + kind: RouteRule + listKind: RouteRuleList + plural: routerules + singular: routerule + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: virtualservices.networking.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: networking.istio.io + names: + kind: VirtualService + listKind: VirtualServiceList + plural: virtualservices + singular: virtualservice + scope: Namespaced + version: v1alpha3 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: destinationrules.networking.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: networking.istio.io + names: + kind: DestinationRule + listKind: DestinationRuleList + plural: destinationrules + singular: destinationrule + scope: Namespaced + version: v1alpha3 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: serviceentries.networking.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: networking.istio.io + names: + kind: ServiceEntry + listKind: ServiceEntryList + plural: serviceentries + singular: serviceentry + scope: Namespaced + version: v1alpha3 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: gateways.networking.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: networking.istio.io + names: + kind: Gateway + plural: gateways + singular: gateway + scope: Namespaced + version: v1alpha3 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: policies.authentication.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: authentication.istio.io + names: + kind: Policy + plural: policies + singular: policy + scope: Namespaced + version: v1alpha1 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: httpapispecbindings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: HTTPAPISpecBinding + plural: httpapispecbindings + singular: httpapispecbinding + scope: Namespaced + version: v1alpha2 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: httpapispecs.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: HTTPAPISpec + plural: httpapispecs + singular: httpapispec + scope: Namespaced + version: v1alpha2 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: quotaspecbindings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: QuotaSpecBinding + plural: quotaspecbindings + singular: quotaspecbinding + scope: Namespaced + version: v1alpha2 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: quotaspecs.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: QuotaSpec + plural: quotaspecs + singular: quotaspec + scope: Namespaced + version: v1alpha2 + + +--- +# Source: istio/charts/ingress/templates/clusterrole.yaml + apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: - name: prometheus + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + heritage: Tiller + release: istio + name: istio-ingress-istio-system +rules: +- apiGroups: ["extensions"] + resources: ["thirdpartyresources", "ingresses"] + verbs: ["get", "watch", "list", "update"] +- apiGroups: [""] + resources: ["configmaps", "pods", "endpoints", "services"] + verbs: ["get", "watch", "list"] + +--- +# Source: istio/charts/mixer/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-mixer-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] # istio CRD watcher + resources: ["*"] + verbs: ["create", "get", "list", "watch", "patch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] + verbs: ["get", "list", "watch"] + +--- +# Source: istio/charts/pilot/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-pilot-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["networking.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["authentication.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["*"] +- apiGroups: ["extensions"] + resources: ["thirdpartyresources", "thirdpartyresources.extensions", "ingresses", "ingresses/status"] + verbs: ["*"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["endpoints", "pods", "services"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["namespaces", "nodes", "secrets"] + verbs: ["get", "list", "watch"] + +--- +# Source: istio/charts/prometheus/templates/clusterrole.yaml + +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: prometheus-istio-system + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile @@ -2170,104 +2169,1764 @@ rules: apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: - name: prometheus + name: prometheus-istio-system + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: prometheus + name: prometheus-istio-system subjects: - kind: ServiceAccount name: prometheus namespace: istio-system --- + + --- -apiVersion: extensions/v1beta1 -kind: Deployment +# Source: istio/charts/security/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole metadata: - name: servicegraph + name: istio-citadel-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - template: - metadata: - labels: - app: servicegraph - annotations: - sidecar.istio.io/inject: "false" - spec: - containers: - - name: servicegraph - image: gcr.io/istio-release/servicegraph:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8088 - args: - - --prometheusAddr=http://prometheus:9090 + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "watch", "list", "update", "delete"] +- apiGroups: [""] + resources: ["serviceaccounts"] + verbs: ["get", "watch", "list"] +- apiGroups: [""] + resources: ["services"] + verbs: ["get", "watch", "list"] --- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: Role +metadata: + name: istio-cleanup-old-ca-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: [""] + resources: ["deployments", "serviceaccounts", "services"] + verbs: ["get", "delete"] +- apiGroups: ["extensions"] + resources: ["deployments", "replicasets"] + verbs: ["get", "list", "update", "delete"] + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-sidecar-injector-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["*"] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch", "patch"] + +--- +# Source: istio/charts/ingress/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-ingress-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-pilot-istio-system +subjects: + - kind: ServiceAccount + name: istio-ingress-service-account + namespace: istio-system + +--- +# Source: istio/charts/mixer/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-mixer-admin-role-binding-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-mixer-istio-system +subjects: + - kind: ServiceAccount + name: istio-mixer-service-account + namespace: istio-system + +--- +# Source: istio/charts/pilot/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-pilot-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-pilot-istio-system +subjects: + - kind: ServiceAccount + name: istio-pilot-service-account + namespace: istio-system + +--- +# Source: istio/charts/security/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-citadel-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-citadel-istio-system +subjects: + - kind: ServiceAccount + name: istio-citadel-service-account + namespace: istio-system +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding +metadata: + name: istio-cleanup-old-ca-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: istio-cleanup-old-ca-istio-system +subjects: + - kind: ServiceAccount + name: istio-cleanup-old-ca-service-account + namespace: istio-system + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-sidecar-injector-admin-role-binding-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-sidecar-injector-istio-system +subjects: + - kind: ServiceAccount + name: istio-sidecar-injector-service-account + namespace: istio-system +--- +# Source: istio/charts/egressgateway/templates/service.yaml apiVersion: v1 kind: Service metadata: - name: servicegraph + name: istio-egressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: egressgateway-0.8.0 + release: istio + heritage: Tiller + istio: egressgateway +spec: + type: ClusterIP + selector: + istio: egressgateway + ports: + - + name: http + port: 80 + - + name: https + port: 443 + +--- +# Source: istio/charts/ingress/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-ingress namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/cluster-service: "true" + chart: ingress-0.8.0 + release: istio + heritage: Tiller + istio: ingress spec: - ports: - - name: http - port: 8088 + type: LoadBalancer selector: - app: servicegraph + istio: ingress + ports: + - + name: http + nodePort: 32000 + port: 80 + - + name: https + port: 443 --- + --- -apiVersion: extensions/v1beta1 -kind: Deployment +# Source: istio/charts/ingressgateway/templates/service.yaml +apiVersion: v1 +kind: Service metadata: - name: zipkin + name: istio-ingressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: ingressgateway-0.8.0 + release: istio + heritage: Tiller + istio: ingressgateway +spec: + type: LoadBalancer + selector: + istio: ingressgateway + ports: + - + name: http + nodePort: 31380 + port: 80 + - + name: https + nodePort: 31390 + port: 443 + - + name: tcp + nodePort: 31400 + port: 31400 + +--- +# Source: istio/charts/mixer/templates/service.yaml + +apiVersion: v1 +kind: Service +metadata: + name: istio-policy namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: mixer-0.8.0 + release: istio + istio: mixer +spec: + ports: + - name: grpc-mixer + port: 9091 + - name: grpc-mixer-mtls + port: 15004 + - name: http-monitoring + port: 9093 + selector: + istio: mixer + istio-mixer-type: policy +--- +apiVersion: v1 +kind: Service +metadata: + name: istio-telemetry + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: mixer-0.8.0 + release: istio + istio: mixer +spec: + ports: + - name: grpc-mixer + port: 9091 + - name: grpc-mixer-mtls + port: 15004 + - name: http-monitoring + port: 9093 + - name: prometheus + port: 42422 + selector: + istio: mixer + istio-mixer-type: telemetry +--- + +--- +# Source: istio/charts/mixer/templates/statsdtoprom.yaml + +--- +apiVersion: v1 +kind: Service +metadata: + name: istio-statsd-prom-bridge + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: mixer-0.8.0 + release: istio + istio: statsd-prom-bridge +spec: + ports: + - name: statsd-prom + port: 9102 + - name: statsd-udp + port: 9125 + protocol: UDP + selector: + istio: statsd-prom-bridge + +--- + +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-statsd-prom-bridge + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + chart: mixer-0.8.0 + release: istio + istio: mixer spec: template: metadata: labels: - app: zipkin + istio: statsd-prom-bridge annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: + serviceAccountName: istio-mixer-service-account + volumes: + - name: config-volume + configMap: + name: istio-statsd-prom-bridge containers: - - name: zipkin - image: gcr.io/istio-release/zipkin:2.5.3 + - name: statsd-prom-bridge + image: "gcr.io/istio-release/prom/statsd-exporter:latest" imagePullPolicy: IfNotPresent ports: - - containerPort: 9411 + - containerPort: 9102 + - containerPort: 9125 + protocol: UDP + args: + - '-statsd.mapping-config=/etc/statsd/mapping.conf' + resources: + {} + + volumeMounts: + - name: config-volume + mountPath: /etc/statsd + +--- +# Source: istio/charts/pilot/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-pilot + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + app: istio-pilot + chart: pilot-0.8.0 + release: istio + heritage: Tiller +spec: + ports: + - port: 15003 + name: http-old-discovery # mTLS or non-mTLS depending on auth setting + - port: 15005 + name: https-discovery # always mTLS + - port: 15007 + name: http-discovery # always plain-text + - port: 15010 + name: grpc-xds # direct + - port: 15011 + name: https-xds # mTLS + - port: 8080 + name: http-legacy-discovery # direct + - port: 9093 + name: http-monitoring + selector: + istio: pilot + +--- +# Source: istio/charts/prometheus/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: prometheus + namespace: istio-system + annotations: + prometheus.io/scrape: 'true' + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + name: prometheus +spec: + selector: + app: prometheus + ports: + - name: http-prometheus + protocol: TCP + port: 9090 + +--- +# Source: istio/charts/security/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + # we use the normal name here (e.g. 'prometheus') + # as grafana is configured to use this as a data source + name: istio-citadel + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + app: istio-citadel +spec: + ports: + - name: grpc-citadel + port: 8060 + targetPort: 8060 + protocol: TCP + - name: http-monitoring + port: 9093 + selector: + istio: citadel + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + istio: sidecar-injector +spec: + ports: + - port: 443 + selector: + istio: sidecar-injector + +--- +# Source: istio/charts/egressgateway/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-egressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: egressgateway + chart: egressgateway-0.8.0 + release: istio + heritage: Tiller + istio: egressgateway +spec: + template: + metadata: + labels: + istio: egressgateway + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-egressgateway-service-account + containers: + - name: egressgateway + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + args: + - proxy + - router + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-egressgateway + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:8080 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: "istio.default" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/ingress/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-ingress + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + release: istio + heritage: Tiller + istio: ingress +spec: + template: + metadata: + labels: + istio: ingress + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-ingress-service-account + containers: + - name: ingress + image: "gcr.io/istio-release/proxy:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + args: + - proxy + - ingress + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-ingress + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:8080 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: ingress-certs + mountPath: /etc/istio/ingress-certs + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: "istio.default" + optional: true + - name: ingress-certs + secret: + secretName: istio-ingress-certs + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/ingressgateway/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingressgateway + chart: ingressgateway-0.8.0 + release: istio + heritage: Tiller + istio: ingressgateway +spec: + template: + metadata: + labels: + istio: ingressgateway + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-ingressgateway-service-account + containers: + - name: ingressgateway + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + - containerPort: 31400 + args: + - proxy + - router + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-ingressgateway + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:8080 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: ingressgateway-certs + mountPath: "/etc/istio/ingressgateway-certs" + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: "istio.default" + optional: true + - name: ingressgateway-certs + secret: + secretName: "istio-ingressgateway-certs" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/mixer/templates/deployment.yaml + +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-policy + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + chart: mixer-0.8.0 + release: istio + istio: mixer +spec: + template: + metadata: + labels: + istio: mixer + istio-mixer-type: policy + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-mixer-service-account + volumes: + - name: istio-certs + secret: + secretName: istio.istio-mixer-service-account + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + containers: + - name: mixer + image: "gcr.io/istio-release/mixer:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9092 + - containerPort: 9093 + - containerPort: 42422 + args: + - --address + - tcp://127.0.0.1:9092 + - --configStoreURL=k8s:// + - --configDefaultNamespace=istio-system + - --trace_zipkin_url=http://zipkin:9411/api/v1/spans + resources: + {} + + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9091 + - containerPort: 15004 + args: + - proxy + - --serviceCluster + - istio-policy + - --templateFile + - /etc/istio/proxy/envoy_policy.yaml.tmpl + - --controlPlaneAuthPolicy + - NONE env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-telemetry + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + chart: mixer-0.8.0 + release: istio + istio: mixer +spec: + template: + metadata: + labels: + istio: mixer + istio-mixer-type: telemetry + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-mixer-service-account + volumes: + - name: istio-certs + secret: + secretName: istio.istio-mixer-service-account + optional: true + containers: + - name: mixer + image: "gcr.io/istio-release/mixer:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9092 + - containerPort: 9093 + - containerPort: 42422 + args: + - --address + - tcp://127.0.0.1:9092 + - --configStoreURL=k8s:// + - --configDefaultNamespace=istio-system + - --trace_zipkin_url=http://zipkin:9411/api/v1/spans + resources: + {} + + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9091 + - containerPort: 15004 + args: + - proxy + - --serviceCluster + - istio-telemetry + - --templateFile + - /etc/istio/proxy/envoy_telemetry.yaml.tmpl + - --controlPlaneAuthPolicy + - NONE + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + +--- + +--- +# Source: istio/charts/pilot/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-pilot + namespace: istio-system + # TODO: default tempate doesn't have this, which one is right ? + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + release: istio + heritage: Tiller + istio: pilot + annotations: + checksum/config-volume: f8da08b6b8c170dde721efd680270b2901e750d4aa186ebb6c22bef5b78a43f9 +spec: + template: + metadata: + labels: + istio: pilot + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-pilot-service-account + containers: + - name: discovery + image: "gcr.io/istio-release/pilot:0.8.0" + imagePullPolicy: IfNotPresent + args: + - "discovery" +# TODO(sdake) remove when secrets are automagically registered + ports: + - containerPort: 8080 + - containerPort: 15010 + readinessProbe: + httpGet: + path: /v1/registration + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 5 + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: PILOT_THROTTLE + value: "500" + - name: PILOT_CACHE_SQUASH + value: "5" + resources: + {} + + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15003 + - containerPort: 15005 + - containerPort: 15007 + - containerPort: 15011 + args: + - proxy + - --serviceCluster + - istio-pilot + - --templateFile + - /etc/istio/proxy/envoy_pilot.yaml.tmpl + - --controlPlaneAuthPolicy + - NONE + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + volumes: + - name: config-volume + configMap: + name: istio + - name: istio-certs + secret: + secretName: "istio.istio-pilot-service-account" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/prometheus/templates/deployment.yaml +# TODO: the original template has service account, roles, etc +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: prometheus + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: prometheus + chart: prometheus-0.1.0 + release: istio + heritage: Tiller +spec: + selector: + matchLabels: + app: prometheus + template: + metadata: + labels: + app: prometheus + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: prometheus + + containers: + - name: prometheus + image: "gcr.io/istio-release/prom/prometheus:latest" + imagePullPolicy: IfNotPresent + args: + - '--storage.tsdb.retention=6h' + - '--config.file=/etc/prometheus/prometheus.yml' + ports: + - containerPort: 9090 + name: http + livenessProbe: + httpGet: + path: /-/healthy + port: 9090 + readinessProbe: + httpGet: + path: /-/ready + port: 9090 + resources: + {} + + volumeMounts: + - name: config-volume + mountPath: /etc/prometheus + volumes: + - name: config-volume + configMap: + name: prometheus + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/security/templates/deployment.yaml +# istio CA watching all namespaces +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-citadel + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + release: istio + heritage: Tiller + istio: citadel +spec: + template: + metadata: + labels: + istio: citadel + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-citadel-service-account + containers: + - name: citadel + image: "gcr.io/istio-release/citadel:0.8.0" + imagePullPolicy: IfNotPresent + args: + - --append-dns-names=true + - --grpc-port=8060 + - --grpc-hostname=citadel + - --self-signed-ca=true + - --citadel-storage-namespace=istio-system + resources: + {} + + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: sidecarInjectorWebhook + chart: sidecarInjectorWebhook-0.8.0 + release: istio + heritage: Tiller + istio: sidecar-injector +spec: + template: + metadata: + labels: + istio: sidecar-injector + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-sidecar-injector-service-account + containers: + - name: sidecar-injector-webhook + image: "gcr.io/istio-release/sidecar_injector:0.8.0" + imagePullPolicy: IfNotPresent + args: + - --caCertFile=/etc/istio/certs/root-cert.pem + - --tlsCertFile=/etc/istio/certs/cert-chain.pem + - --tlsKeyFile=/etc/istio/certs/key.pem + - --injectConfig=/etc/istio/inject/config + - --meshConfig=/etc/istio/config/mesh + - --healthCheckInterval=2s + - --healthCheckFile=/health + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + readOnly: true + - name: certs + mountPath: /etc/istio/certs + readOnly: true + - name: inject-config + mountPath: /etc/istio/inject + readOnly: true + livenessProbe: + exec: + command: + - /usr/local/bin/sidecar-injector + - probe + - --probe-path=/health + - --interval=2s + initialDelaySeconds: 4 + periodSeconds: 4 + readinessProbe: + exec: + command: + - /usr/local/bin/sidecar-injector + - probe + - --probe-path=/health + - --interval=2s + initialDelaySeconds: 4 + periodSeconds: 4 + volumes: + - name: config-volume + configMap: + name: istio + - name: certs + secret: + secretName: istio.istio-sidecar-injector-service-account + - name: inject-config + configMap: + name: istio-sidecar-injector + items: + - key: config + path: config + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/security/templates/cleanup-old-ca.yaml + +apiVersion: batch/v1 +kind: Job +metadata: + name: istio-cleanup-old-ca + namespace: istio-system + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-delete-policy": hook-succeeded + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + release: istio + heritage: Tiller +spec: + template: + metadata: + name: istio-cleanup-old-ca + labels: + app: security + release: istio + spec: + serviceAccountName: istio-cleanup-old-ca-service-account + containers: + - name: hyperkube + image: "gcr.io/istio-release/coreos/hyperkube:v1.7.6_coreos.0" + command: + - /bin/bash + - -c + - > + NS="-n istio-system"; + ./kubectl get deploy istio-ca $NS; + if [[ $? = 0 ]]; then ./kubectl delete deploy istio-ca $NS; fi; + ./kubectl get serviceaccount istio-ca-service-account $NS; + if [[ $? = 0 ]]; then ./kubectl delete serviceaccount istio-ca-service-account $NS; fi; + ./kubectl get service istio-ca-ilb $NS; + if [[ $? = 0 ]]; then ./kubectl delete service istio-ca-ilb $NS; fi + restartPolicy: Never +--- +# Source: istio/charts/egressgateway/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-egressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-egressgateway + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/ingress/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-ingress + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-ingress + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/ingressgateway/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-ingressgateway + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/mutatingwebhook.yaml +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: MutatingWebhookConfiguration +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + release: istio + heritage: Tiller +webhooks: + - name: sidecar-injector.istio.io + clientConfig: + service: + name: istio-sidecar-injector + namespace: istio-system + path: "/inject" + caBundle: "" + rules: + - operations: [ "CREATE" ] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + failurePolicy: Fail + namespaceSelector: + matchExpressions: + - key: istio-injection + operator: NotIn + values: + - disabled +--- +# Source: istio/charts/mixer/templates/config.yaml + + +--- +# Source: istio/charts/prometheus/templates/ingress.yaml --- apiVersion: v1 kind: Service metadata: - name: zipkin + name: grafana namespace: istio-system + annotations: + auth.istio.io/3000: NONE labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/cluster-service: "true" spec: ports: - - name: http - port: 9411 + - port: 3000 + protocol: TCP + name: http selector: - app: zipkin + app: grafana +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: grafana + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + template: + metadata: + labels: + app: grafana + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: grafana + containers: + - name: grafana + image: gcr.io/istio-release/grafana:0.8.0 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + env: + # Only put environment related config here. Generic Istio config + # should go in addons/grafana/grafana.ini. + - name: GF_PATHS_DATA + value: /data/grafana + volumeMounts: + - mountPath: /data/grafana + name: grafana-data + volumes: + - name: grafana-data + emptyDir: {} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: grafana + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile --- diff --git a/cluster/addons/rbac/cluster-autoscaler/cluster-autoscaler-rbac.yaml b/cluster/addons/rbac/cluster-autoscaler/cluster-autoscaler-rbac.yaml new file mode 100644 index 00000000000..822f3c7b4c1 --- /dev/null +++ b/cluster/addons/rbac/cluster-autoscaler/cluster-autoscaler-rbac.yaml @@ -0,0 +1,68 @@ +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: cluster-autoscaler + labels: + addonmanager.kubernetes.io/mode: Reconcile +rules: + # leader election + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["create"] + - apiGroups: [""] + resources: ["endpoints"] + resourceNames: ["cluster-autoscaler"] + verbs: ["get", "update", "patch", "delete"] + # accessing & modifying cluster state (nodes & pods) + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch", "update", "patch"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["pods/eviction"] + verbs: ["create"] + # read-only access to cluster state + - apiGroups: [""] + resources: ["services", "replicationcontrollers", "persistentvolumes", "persistentvolumeclaims"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps", "extensions"] + resources: ["daemonsets", "replicasets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps"] + resources: ["statefulsets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["policy"] + resources: ["poddisruptionbudgets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["get", "list", "watch"] + # misc access + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "update", "patch"] + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["create"] + - apiGroups: [""] + resources: ["configmaps"] + resourceNames: ["cluster-autoscaler-status"] + verbs: ["get", "update", "patch", "delete"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: cluster-autoscaler + labels: + addonmanager.kubernetes.io/mode: Reconcile +subjects: + - kind: User + name: cluster-autoscaler + namespace: kube-system +roleRef: + kind: ClusterRole + name: cluster-autoscaler + apiGroup: rbac.authorization.k8s.io + diff --git a/cluster/centos/deployAddons.sh b/cluster/centos/deployAddons.sh index 349b308ddbd..b19d1cd1ef7 100755 --- a/cluster/centos/deployAddons.sh +++ b/cluster/centos/deployAddons.sh @@ -26,7 +26,7 @@ export KUBE_CONFIG_FILE=${KUBE_CONFIG_FILE:-${KUBE_ROOT}/cluster/centos/config-d function deploy_dns { echo "Deploying DNS on Kubernetes" - cp "${KUBE_ROOT}/cluster/addons/dns/kube-dns.yaml.sed" kube-dns.yaml + cp "${KUBE_ROOT}/cluster/addons/dns/kube-dns/kube-dns.yaml.sed" kube-dns.yaml sed -i -e "s/\\\$DNS_DOMAIN/${DNS_DOMAIN}/g" kube-dns.yaml sed -i -e "s/\\\$DNS_SERVER_IP/${DNS_SERVER_IP}/g" kube-dns.yaml diff --git a/cluster/gce/config-default.sh b/cluster/gce/config-default.sh index 86bbbf56c8c..7306f934dbf 100755 --- a/cluster/gce/config-default.sh +++ b/cluster/gce/config-default.sh @@ -180,6 +180,16 @@ if [[ ${NETWORK_POLICY_PROVIDER:-} == "calico" ]]; then NON_MASTER_NODE_LABELS="${NON_MASTER_NODE_LABELS:+${NON_MASTER_NODE_LABELS},}projectcalico.org/ds-ready=true" fi +# Optional: Enable netd. +ENABLE_NETD="${KUBE_ENABLE_NETD:-false}" +CUSTOM_NETD_YAML="${KUBE_CUSTOM_NETD_YAML:-}" + +# To avoid running netd on a node that is not configured appropriately, +# label each Node so that the DaemonSet can run the Pods only on ready Nodes. +if [[ ${ENABLE_NETD:-} == "true" ]]; then + NON_MASTER_NODE_LABELS="${NON_MASTER_NODE_LABELS:+${NON_MASTER_NODE_LABELS},}beta.kubernetes.io/kube-netd-ready=true" +fi + # Enable metadata concealment by firewalling pod traffic to the metadata server # and run a proxy daemonset on nodes. # diff --git a/cluster/gce/config-test.sh b/cluster/gce/config-test.sh index cfefaf937f6..506806a986e 100755 --- a/cluster/gce/config-test.sh +++ b/cluster/gce/config-test.sh @@ -191,11 +191,11 @@ TEST_CLUSTER_RESYNC_PERIOD="${TEST_CLUSTER_RESYNC_PERIOD:---min-resync-period=3m TEST_CLUSTER_API_CONTENT_TYPE="${TEST_CLUSTER_API_CONTENT_TYPE:-}" KUBELET_TEST_ARGS="${KUBELET_TEST_ARGS:-} --serialize-image-pulls=false ${TEST_CLUSTER_API_CONTENT_TYPE}" -if [[ "${NODE_OS_DISTRIBUTION}" == "gci" ]] || [[ "${NODE_OS_DISTRIBUTION}" == "ubuntu" ]] || [[ "${NODE_OS_DISTRIBUTION}" == "custom" ]]; then - NODE_KUBELET_TEST_ARGS=" --experimental-kernel-memcg-notification=true" -fi -if [[ "${MASTER_OS_DISTRIBUTION}" == "gci" ]] || [[ "${MASTER_OS_DISTRIBUTION}" == "ubuntu" ]]; then - MASTER_KUBELET_TEST_ARGS=" --experimental-kernel-memcg-notification=true" +if [[ "${NODE_OS_DISTRIBUTION}" == "gci" ]] || [[ "${NODE_OS_DISTRIBUTION}" == "ubuntu" ]] || [[ "${NODE_OS_DISTRIBUTION}" == "custom" ]]; then + NODE_KUBELET_TEST_ARGS="${NODE_KUBELET_TEST_ARGS:-} --experimental-kernel-memcg-notification=true" +fi +if [[ "${MASTER_OS_DISTRIBUTION}" == "gci" ]] || [[ "${MASTER_OS_DISTRIBUTION}" == "ubuntu" ]]; then + MASTER_KUBELET_TEST_ARGS="${MASTER_KUBELET_TEST_ARGS:-} --experimental-kernel-memcg-notification=true" fi APISERVER_TEST_ARGS="${APISERVER_TEST_ARGS:-} --vmodule=httplog=3 --runtime-config=extensions/v1beta1,scheduling.k8s.io/v1alpha1,settings.k8s.io/v1alpha1 ${TEST_CLUSTER_DELETE_COLLECTION_WORKERS} ${TEST_CLUSTER_MAX_REQUESTS_INFLIGHT}" CONTROLLER_MANAGER_TEST_ARGS="${CONTROLLER_MANAGER_TEST_ARGS:-} ${TEST_CLUSTER_RESYNC_PERIOD} ${TEST_CLUSTER_API_CONTENT_TYPE}" @@ -212,6 +212,16 @@ NODE_LABELS="${KUBE_NODE_LABELS:-beta.kubernetes.io/fluentd-ds-ready=true}" # NON_MASTER_NODE_LABELS are labels will only be applied on non-master nodes. NON_MASTER_NODE_LABELS="${KUBE_NON_MASTER_NODE_LABELS:-}" +# Optional: Enable netd. +ENABLE_NETD="${KUBE_ENABLE_NETD:-false}" +CUSTOM_NETD_YAML="${KUBE_CUSTOM_NETD_YAML:-}" + +# To avoid running netd on a node that is not configured appropriately, +# label each Node so that the DaemonSet can run the Pods only on ready Nodes. +if [[ ${ENABLE_NETD:-} == "true" ]]; then + NON_MASTER_NODE_LABELS="${NON_MASTER_NODE_LABELS:+${NON_MASTER_NODE_LABELS},}beta.kubernetes.io/kube-netd-ready=true" +fi + # To avoid running Calico on a node that is not configured appropriately, # label each Node so that the DaemonSet can run the Pods only on ready Nodes. if [[ ${NETWORK_POLICY_PROVIDER:-} == "calico" ]]; then diff --git a/cluster/gce/gci/configure-helper.sh b/cluster/gce/gci/configure-helper.sh index 0935fc37f2c..977822fa9a8 100644 --- a/cluster/gce/gci/configure-helper.sh +++ b/cluster/gce/gci/configure-helper.sh @@ -545,6 +545,9 @@ function create-master-auth { if [[ -n "${KUBE_SCHEDULER_TOKEN:-}" ]]; then append_or_replace_prefixed_line "${known_tokens_csv}" "${KUBE_SCHEDULER_TOKEN}," "system:kube-scheduler,uid:system:kube-scheduler" fi + if [[ -n "${KUBE_CLUSTER_AUTOSCALER_TOKEN:-}" ]]; then + append_or_replace_prefixed_line "${known_tokens_csv}" "${KUBE_CLUSTER_AUTOSCALER_TOKEN}," "cluster-autoscaler,uid:cluster-autoscaler" + fi if [[ -n "${KUBE_PROXY_TOKEN:-}" ]]; then append_or_replace_prefixed_line "${known_tokens_csv}" "${KUBE_PROXY_TOKEN}," "system:kube-proxy,uid:kube_proxy" fi @@ -1006,6 +1009,30 @@ current-context: kube-scheduler EOF } +function create-clusterautoscaler-kubeconfig { + echo "Creating cluster-autoscaler kubeconfig file" + mkdir -p /etc/srv/kubernetes/cluster-autoscaler + cat </etc/srv/kubernetes/cluster-autoscaler/kubeconfig +apiVersion: v1 +kind: Config +users: +- name: cluster-autoscaler + user: + token: ${KUBE_CLUSTER_AUTOSCALER_TOKEN} +clusters: +- name: local + cluster: + insecure-skip-tls-verify: true + server: https://localhost:443 +contexts: +- context: + cluster: local + user: cluster-autoscaler + name: cluster-autoscaler +current-context: cluster-autoscaler +EOF +} + function create-kubescheduler-policy-config { echo "Creating kube-scheduler policy config file" mkdir -p /etc/srv/kubernetes/kube-scheduler @@ -1207,7 +1234,15 @@ function prepare-kube-proxy-manifest-variables { params+=" --feature-gates=${FEATURE_GATES}" fi if [[ "${KUBE_PROXY_MODE:-}" == "ipvs" ]];then - params+=" --proxy-mode=ipvs --feature-gates=SupportIPVSProxyMode=true" + sudo modprobe -a ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack_ipv4 + if [[ $? -eq 0 ]]; + then + params+=" --proxy-mode=ipvs" + else + # If IPVS modules are not present, make sure the node does not come up as + # healthy. + exit 1 + fi fi params+=" --iptables-sync-period=1m --iptables-min-sync-period=10s --ipvs-sync-period=1m --ipvs-min-sync-period=10s" if [[ -n "${KUBEPROXY_TEST_ARGS:-}" ]]; then @@ -1970,12 +2005,15 @@ function start-kube-scheduler { function start-cluster-autoscaler { if [[ "${ENABLE_CLUSTER_AUTOSCALER:-}" == "true" ]]; then echo "Start kubernetes cluster autoscaler" + setup-addon-manifests "addons" "rbac/cluster-autoscaler" + create-clusterautoscaler-kubeconfig prepare-log-file /var/log/cluster-autoscaler.log # Remove salt comments and replace variables with values local -r src_file="${KUBE_HOME}/kube-manifests/kubernetes/gci-trusty/cluster-autoscaler.manifest" local params="${AUTOSCALER_MIG_CONFIG} ${CLOUD_CONFIG_OPT} ${AUTOSCALER_EXPANDER_CONFIG:---expander=price}" + params+=" --kubeconfig=/etc/srv/kubernetes/cluster-autoscaler/kubeconfig" sed -i -e "s@{{params}}@${params}@g" "${src_file}" sed -i -e "s@{{cloud_config_mount}}@${CLOUD_CONFIG_MOUNT}@g" "${src_file}" sed -i -e "s@{{cloud_config_volume}}@${CLOUD_CONFIG_VOLUME}@g" "${src_file}" @@ -2175,8 +2213,8 @@ 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.yaml" - mv "${dst_dir}/dns/coredns.yaml.in" "${coredns_file}" + local -r coredns_file="${dst_dir}/dns/coredns/coredns.yaml" + mv "${dst_dir}/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}" @@ -2215,8 +2253,8 @@ 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.yaml" - mv "${dst_dir}/dns/kube-dns.yaml.in" "${kubedns_file}" + local -r kubedns_file="${dst_dir}/dns/kube-dns/kube-dns.yaml" + mv "${dst_dir}/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}" < "${netd_file}" </dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null) KUBE_SCHEDULER_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null) + KUBE_CLUSTER_AUTOSCALER_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null) setup-os-params config-ip-firewall diff --git a/cluster/gce/gci/configure.sh b/cluster/gce/gci/configure.sh index c950c045b82..6ef58a87610 100644 --- a/cluster/gce/gci/configure.sh +++ b/cluster/gce/gci/configure.sh @@ -264,6 +264,18 @@ runtime-endpoint: ${CONTAINER_RUNTIME_ENDPOINT:-unix:///var/run/dockershim.sock} EOF } +function install-exec-auth-plugin { + if [[ ! "${EXEC_AUTH_PLUGIN_URL:-}" ]]; then + return + fi + local -r plugin_url="${EXEC_AUTH_PLUGIN_URL}" + local -r plugin_sha1="${EXEC_AUTH_PLUGIN_SHA1}" + + echo "Downloading gke-exec-auth-plugin binary" + download-or-bust "${plugin_sha1}" "${plugin_url}" + mv "${KUBE_HOME}/gke-exec-auth-plugin" "${KUBE_BIN}" +} + function install-kube-manifests { # Put kube-system pods manifests in ${KUBE_HOME}/kube-manifests/. local dst_dir="${KUBE_HOME}/kube-manifests" @@ -403,6 +415,10 @@ function install-kube-binary-config { # Install crictl on each node. install-crictl + if [[ "${KUBERNETES_MASTER:-}" == "false" ]]; then + install-exec-auth-plugin + fi + # Clean up. rm -rf "${KUBE_HOME}/kubernetes" rm -f "${KUBE_HOME}/${server_binary_tar}" diff --git a/cluster/gce/manifests/BUILD b/cluster/gce/manifests/BUILD index d3cfddf1d23..ed258fdc4de 100644 --- a/cluster/gce/manifests/BUILD +++ b/cluster/gce/manifests/BUILD @@ -9,6 +9,7 @@ pkg_tar( mode = "0644", ) +# if you update this, also update function kube::release::package_kube_manifests_tarball() in build/lib/release.sh filegroup( name = "manifests", srcs = [ diff --git a/cluster/gce/manifests/cluster-autoscaler.manifest b/cluster/gce/manifests/cluster-autoscaler.manifest index fc1b406ea6f..553e82c41a6 100644 --- a/cluster/gce/manifests/cluster-autoscaler.manifest +++ b/cluster/gce/manifests/cluster-autoscaler.manifest @@ -7,6 +7,9 @@ "labels": { "tier": "cluster-management", "component": "cluster-autoscaler" + }, + "annotations": { + "seccomp.security.alpha.kubernetes.io/pod": "docker/default" } }, "spec": { @@ -14,7 +17,7 @@ "containers": [ { "name": "cluster-autoscaler", - "image": "k8s.gcr.io/cluster-autoscaler:v1.2.2", + "image": "k8s.gcr.io/cluster-autoscaler:v1.3.0", "livenessProbe": { "httpGet": { "path": "/health-check", @@ -25,7 +28,7 @@ }, "command": [ "./run.sh", - "--kubernetes=http://127.0.0.1:8080?inClusterConfig=f", + "--kubernetes=https://127.0.0.1:443", "--v=4", "--logtostderr=true", "--write-status-configmap=true", @@ -56,6 +59,11 @@ "readOnly": true, "mountPath": "/usr/share/ca-certificates" }, + { + "name": "srvkube", + "readOnly": true, + "mountPath": "/etc/srv/kubernetes/cluster-autoscaler" + }, { "name": "logfile", "mountPath": "/var/log/cluster-autoscaler.log", @@ -80,6 +88,12 @@ "path": "/usr/share/ca-certificates" } }, + { + "name": "srvkube", + "hostPath": { + "path": "/etc/srv/kubernetes/cluster-autoscaler" + } + }, { "name": "logfile", "hostPath": { diff --git a/cluster/gce/manifests/etcd-empty-dir-cleanup.yaml b/cluster/gce/manifests/etcd-empty-dir-cleanup.yaml index 7e1971634ff..9b92d6f40bf 100644 --- a/cluster/gce/manifests/etcd-empty-dir-cleanup.yaml +++ b/cluster/gce/manifests/etcd-empty-dir-cleanup.yaml @@ -5,6 +5,7 @@ metadata: namespace: kube-system annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' labels: k8s-app: etcd-empty-dir-cleanup spec: diff --git a/cluster/gce/manifests/etcd.manifest b/cluster/gce/manifests/etcd.manifest index f6f56abcd40..7413603f74a 100644 --- a/cluster/gce/manifests/etcd.manifest +++ b/cluster/gce/manifests/etcd.manifest @@ -5,7 +5,8 @@ "name":"etcd-server{{ suffix }}", "namespace": "kube-system", "annotations": { - "scheduler.alpha.kubernetes.io/critical-pod": "" + "scheduler.alpha.kubernetes.io/critical-pod": "", + "seccomp.security.alpha.kubernetes.io/pod": "docker/default" } }, "spec":{ @@ -62,7 +63,7 @@ "ports": [ { "name": "serverport", "containerPort": {{ server_port }}, - "hostPort": {{ server_port }} + "hostPort": {{ server_port }} }, { "name": "clientport", "containerPort": {{ port }}, diff --git a/cluster/gce/manifests/glbc.manifest b/cluster/gce/manifests/glbc.manifest index 2c80aa0caad..4401ab0d193 100644 --- a/cluster/gce/manifests/glbc.manifest +++ b/cluster/gce/manifests/glbc.manifest @@ -5,6 +5,7 @@ metadata: namespace: kube-system annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' labels: k8s-app: gcp-lb-controller version: v1.1.1 diff --git a/cluster/gce/manifests/kube-addon-manager.yaml b/cluster/gce/manifests/kube-addon-manager.yaml index c77e914e674..48a3b151939 100644 --- a/cluster/gce/manifests/kube-addon-manager.yaml +++ b/cluster/gce/manifests/kube-addon-manager.yaml @@ -5,6 +5,7 @@ metadata: namespace: kube-system annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' labels: component: kube-addon-manager spec: diff --git a/cluster/gce/manifests/kube-apiserver.manifest b/cluster/gce/manifests/kube-apiserver.manifest index d13dbed70ee..6b9f6bb58a3 100644 --- a/cluster/gce/manifests/kube-apiserver.manifest +++ b/cluster/gce/manifests/kube-apiserver.manifest @@ -5,7 +5,8 @@ "name":"kube-apiserver", "namespace": "kube-system", "annotations": { - "scheduler.alpha.kubernetes.io/critical-pod": "" + "scheduler.alpha.kubernetes.io/critical-pod": "", + "seccomp.security.alpha.kubernetes.io/pod": "docker/default" }, "labels": { "tier": "control-plane", diff --git a/cluster/gce/manifests/kube-controller-manager.manifest b/cluster/gce/manifests/kube-controller-manager.manifest index 353958642e9..1bd5d2d4a7e 100644 --- a/cluster/gce/manifests/kube-controller-manager.manifest +++ b/cluster/gce/manifests/kube-controller-manager.manifest @@ -5,7 +5,8 @@ "name":"kube-controller-manager", "namespace": "kube-system", "annotations": { - "scheduler.alpha.kubernetes.io/critical-pod": "" + "scheduler.alpha.kubernetes.io/critical-pod": "", + "seccomp.security.alpha.kubernetes.io/pod": "docker/default" }, "labels": { "tier": "control-plane", diff --git a/cluster/gce/manifests/kube-scheduler.manifest b/cluster/gce/manifests/kube-scheduler.manifest index a7d496fddd6..af71c049f20 100644 --- a/cluster/gce/manifests/kube-scheduler.manifest +++ b/cluster/gce/manifests/kube-scheduler.manifest @@ -5,7 +5,8 @@ "name":"kube-scheduler", "namespace": "kube-system", "annotations": { - "scheduler.alpha.kubernetes.io/critical-pod": "" + "scheduler.alpha.kubernetes.io/critical-pod": "", + "seccomp.security.alpha.kubernetes.io/pod": "docker/default" }, "labels": { "tier": "control-plane", diff --git a/cluster/gce/util.sh b/cluster/gce/util.sh index 7c909bd0736..fd446852bb5 100755 --- a/cluster/gce/util.sh +++ b/cluster/gce/util.sh @@ -642,7 +642,7 @@ function construct-kubelet-flags { # Network plugin if [[ -n "${NETWORK_PROVIDER:-}" || -n "${NETWORK_POLICY_PROVIDER:-}" ]]; then flags+=" --cni-bin-dir=/home/kubernetes/bin" - if [[ "${NETWORK_POLICY_PROVIDER:-}" == "calico" ]]; then + if [[ "${NETWORK_POLICY_PROVIDER:-}" == "calico" || "${ENABLE_NETD:-}" == "true" ]]; then # Calico uses CNI always. # Note that network policy won't work for master node. if [[ "${master}" == "true" ]]; then @@ -653,15 +653,13 @@ function construct-kubelet-flags { else # Otherwise use the configured value. flags+=" --network-plugin=${NETWORK_PROVIDER}" + fi fi if [[ -n "${NON_MASQUERADE_CIDR:-}" ]]; then flags+=" --non-masquerade-cidr=${NON_MASQUERADE_CIDR}" fi flags+=" --volume-plugin-dir=${VOLUME_PLUGIN_DIR}" - if [[ -n "${ENABLE_CUSTOM_METRICS:-}" ]]; then - flags+=" --enable-custom-metrics=${ENABLE_CUSTOM_METRICS}" - fi local node_labels=$(build-node-labels ${master}) if [[ -n "${node_labels:-}" ]]; then flags+=" --node-labels=${node_labels}" @@ -899,6 +897,9 @@ REGION: $(yaml-quote ${REGION}) VOLUME_PLUGIN_DIR: $(yaml-quote ${VOLUME_PLUGIN_DIR}) KUBELET_ARGS: $(yaml-quote ${KUBELET_ARGS}) REQUIRE_METADATA_KUBELET_CONFIG_FILE: $(yaml-quote true) +ENABLE_NETD: $(yaml-quote ${ENABLE_NETD:-false}) +CUSTOM_NETD_YAML: | +$(echo "${CUSTOM_NETD_YAML:-}" | sed -e "s/'/''/g") EOF if [[ "${master}" == "true" && "${MASTER_OS_DISTRIBUTION}" == "gci" ]] || \ [[ "${master}" == "false" && "${NODE_OS_DISTRIBUTION}" == "gci" ]] || \ diff --git a/cluster/log-dump/log-dump.sh b/cluster/log-dump/log-dump.sh index 719ee31aba0..662001fa63d 100755 --- a/cluster/log-dump/log-dump.sh +++ b/cluster/log-dump/log-dump.sh @@ -294,7 +294,7 @@ function dump_nodes_with_logexporter() { local -r service_account_credentials="$(cat ${GOOGLE_APPLICATION_CREDENTIALS} | base64 | tr -d '\n')" local -r cloud_provider="${KUBERNETES_PROVIDER}" local -r enable_hollow_node_logs="${ENABLE_HOLLOW_NODE_LOGS:-false}" - local -r logexport_sleep_seconds="$(( 90 + NUM_NODES / 5 ))" + local -r logexport_sleep_seconds="$(( 90 + NUM_NODES / 3 ))" # Fill in the parameters in the logexporter daemonset template. sed -i'' -e "s@{{.LogexporterNamespace}}@${logexporter_namespace}@g" "${KUBE_ROOT}/cluster/log-dump/logexporter-daemonset.yaml" @@ -345,6 +345,7 @@ function dump_nodes_with_logexporter() { done # Delete the logexporter resources and dump logs for the failed nodes (if any) through SSH. + "${KUBECTL}" get pods --namespace "${logexporter_namespace}" || true "${KUBECTL}" delete namespace "${logexporter_namespace}" || true if [[ "${#failed_nodes[@]}" != 0 ]]; then echo -e "Dumping logs through SSH for the following nodes:\n${failed_nodes[@]}" diff --git a/cmd/cloud-controller-manager/app/controllermanager.go b/cmd/cloud-controller-manager/app/controllermanager.go index 988bf5edf36..01c4bfe2ba0 100644 --- a/cmd/cloud-controller-manager/app/controllermanager.go +++ b/cmd/cloud-controller-manager/app/controllermanager.go @@ -54,7 +54,11 @@ const ( // NewCloudControllerManagerCommand creates a *cobra.Command object with default parameters func NewCloudControllerManagerCommand() *cobra.Command { - s := options.NewCloudControllerManagerOptions() + s, err := options.NewCloudControllerManagerOptions() + if err != nil { + glog.Fatalf("unable to initialize command options: %v", err) + } + cmd := &cobra.Command{ Use: "cloud-controller-manager", Long: `The Cloud controller manager is a daemon that embeds diff --git a/cmd/cloud-controller-manager/app/options/options.go b/cmd/cloud-controller-manager/app/options/options.go index c29b0ee2f37..2dc7a0534fb 100644 --- a/cmd/cloud-controller-manager/app/options/options.go +++ b/cmd/cloud-controller-manager/app/options/options.go @@ -72,8 +72,11 @@ type CloudControllerManagerOptions struct { } // NewCloudControllerManagerOptions creates a new ExternalCMServer with a default config. -func NewCloudControllerManagerOptions() *CloudControllerManagerOptions { - componentConfig := NewDefaultComponentConfig(ports.InsecureCloudControllerManagerPort) +func NewCloudControllerManagerOptions() (*CloudControllerManagerOptions, error) { + componentConfig, err := NewDefaultComponentConfig(ports.InsecureCloudControllerManagerPort) + if err != nil { + return nil, err + } s := CloudControllerManagerOptions{ CloudProvider: &cmoptions.CloudProviderOptions{}, @@ -101,11 +104,11 @@ func NewCloudControllerManagerOptions() *CloudControllerManagerOptions { // TODO: enable HTTPS by default s.SecureServing.BindPort = 0 - return &s + return &s, nil } // NewDefaultComponentConfig returns cloud-controller manager configuration object. -func NewDefaultComponentConfig(insecurePort int32) componentconfig.CloudControllerManagerConfiguration { +func NewDefaultComponentConfig(insecurePort int32) (componentconfig.CloudControllerManagerConfiguration, error) { scheme := runtime.NewScheme() componentconfigv1alpha1.AddToScheme(scheme) componentconfig.AddToScheme(scheme) @@ -114,9 +117,11 @@ func NewDefaultComponentConfig(insecurePort int32) componentconfig.CloudControll scheme.Default(&versioned) internal := componentconfig.CloudControllerManagerConfiguration{} - scheme.Convert(&versioned, &internal, nil) + if err := scheme.Convert(&versioned, &internal, nil); err != nil { + return internal, err + } internal.KubeCloudShared.Port = insecurePort - return internal + return internal, nil } // AddFlags adds flags for a specific ExternalCMServer to the specified FlagSet diff --git a/cmd/cloud-controller-manager/app/options/options_test.go b/cmd/cloud-controller-manager/app/options/options_test.go index 363731e6598..0f6f54d6eef 100644 --- a/cmd/cloud-controller-manager/app/options/options_test.go +++ b/cmd/cloud-controller-manager/app/options/options_test.go @@ -32,7 +32,7 @@ import ( ) func TestDefaultFlags(t *testing.T) { - s := NewCloudControllerManagerOptions() + s, _ := NewCloudControllerManagerOptions() expected := &CloudControllerManagerOptions{ CloudProvider: &cmoptions.CloudProviderOptions{ @@ -95,7 +95,7 @@ func TestDefaultFlags(t *testing.T) { func TestAddFlags(t *testing.T) { f := pflag.NewFlagSet("addflagstest", pflag.ContinueOnError) - s := NewCloudControllerManagerOptions() + s, _ := NewCloudControllerManagerOptions() s.AddFlags(f) args := []string{ diff --git a/cmd/controller-manager/app/options/BUILD b/cmd/controller-manager/app/options/BUILD index 83b848891f1..26fd4c709ce 100644 --- a/cmd/controller-manager/app/options/BUILD +++ b/cmd/controller-manager/app/options/BUILD @@ -3,29 +3,11 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ - "attachdetachcontroller.go", "cloudprovider.go", - "csrsigningcontroller.go", - "daemonsetcontroller.go", "debugging.go", - "deploymentcontroller.go", - "deprecatedcontroller.go", - "endpointcontroller.go", - "garbagecollectorcontroller.go", "generic.go", - "hpacontroller.go", "insecure_serving.go", - "jobcontroller.go", "kubecloudshared.go", - "namespacecontroller.go", - "nodeipamcontroller.go", - "nodelifecyclecontroller.go", - "persistentvolumebindercontroller.go", - "podgccontroller.go", - "replicasetcontroller.go", - "replicationcontroller.go", - "resourcequotacontroller.go", - "serviceaccountcontroller.go", "servicecontroller.go", ], importpath = "k8s.io/kubernetes/cmd/controller-manager/app/options", diff --git a/cmd/controller-manager/app/options/cloudprovider.go b/cmd/controller-manager/app/options/cloudprovider.go index 17541619d0c..37a340e3b59 100644 --- a/cmd/controller-manager/app/options/cloudprovider.go +++ b/cmd/controller-manager/app/options/cloudprovider.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/debugging.go b/cmd/controller-manager/app/options/debugging.go index fa65caffc53..fefb015918f 100644 --- a/cmd/controller-manager/app/options/debugging.go +++ b/cmd/controller-manager/app/options/debugging.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/generic.go b/cmd/controller-manager/app/options/generic.go index d32b975691a..40d6631749c 100644 --- a/cmd/controller-manager/app/options/generic.go +++ b/cmd/controller-manager/app/options/generic.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/componentconfig" "k8s.io/kubernetes/pkg/client/leaderelectionconfig" diff --git a/cmd/controller-manager/app/options/insecure_serving.go b/cmd/controller-manager/app/options/insecure_serving.go index aecb7044625..ca379f13146 100644 --- a/cmd/controller-manager/app/options/insecure_serving.go +++ b/cmd/controller-manager/app/options/insecure_serving.go @@ -21,6 +21,7 @@ import ( "net" "github.com/spf13/pflag" + "k8s.io/apiserver/pkg/server/options" genericcontrollermanager "k8s.io/kubernetes/cmd/controller-manager/app" ) diff --git a/cmd/controller-manager/app/options/kubecloudshared.go b/cmd/controller-manager/app/options/kubecloudshared.go index d9607bf54b5..92135bd2700 100644 --- a/cmd/controller-manager/app/options/kubecloudshared.go +++ b/cmd/controller-manager/app/options/kubecloudshared.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/componentconfig" ) @@ -36,7 +37,6 @@ type KubeCloudSharedOptions struct { AllocateNodeCIDRs bool CIDRAllocatorType string ConfigureCloudRoutes bool - ServiceAccountKeyFile string NodeSyncPeriod metav1.Duration } @@ -74,9 +74,6 @@ func (o *KubeCloudSharedOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&o.CIDRAllocatorType, "cidr-allocator-type", "RangeAllocator", "Type of CIDR allocator to use") fs.BoolVar(&o.ConfigureCloudRoutes, "configure-cloud-routes", true, "Should CIDRs allocated by allocate-node-cidrs be configured on the cloud provider.") - // TODO: remove --service-account-private-key-file 6 months after 1.8 is released (~1.10) - fs.StringVar(&o.ServiceAccountKeyFile, "service-account-private-key-file", o.ServiceAccountKeyFile, "Filename containing a PEM-encoded private RSA or ECDSA key used to sign service account tokens.") - fs.MarkDeprecated("service-account-private-key-file", "This flag is currently no-op and will be deleted.") fs.DurationVar(&o.NodeSyncPeriod.Duration, "node-sync-period", 0, ""+ "This flag is deprecated and will be removed in future releases. See node-monitor-period for Node health checking or "+ "route-reconciliation-period for cloud provider's route configuration settings.") @@ -100,7 +97,6 @@ func (o *KubeCloudSharedOptions) ApplyTo(cfg *componentconfig.KubeCloudSharedCon cfg.AllocateNodeCIDRs = o.AllocateNodeCIDRs cfg.CIDRAllocatorType = o.CIDRAllocatorType cfg.ConfigureCloudRoutes = o.ConfigureCloudRoutes - cfg.ServiceAccountKeyFile = o.ServiceAccountKeyFile cfg.NodeSyncPeriod = o.NodeSyncPeriod return nil diff --git a/cmd/controller-manager/app/options/servicecontroller.go b/cmd/controller-manager/app/options/servicecontroller.go index 26cdf8a3c72..b14142eca9b 100644 --- a/cmd/controller-manager/app/options/servicecontroller.go +++ b/cmd/controller-manager/app/options/servicecontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/kube-apiserver/app/apiextensions.go b/cmd/kube-apiserver/app/apiextensions.go index 375372a162e..b94b5f311b0 100644 --- a/cmd/kube-apiserver/app/apiextensions.go +++ b/cmd/kube-apiserver/app/apiextensions.go @@ -35,6 +35,7 @@ func createAPIExtensionsConfig( externalInformers kubeexternalinformers.SharedInformerFactory, pluginInitializers []admission.PluginInitializer, commandOptions *options.ServerRunOptions, + masterCount int, ) (*apiextensionsapiserver.Config, error) { // make a shallow copy to let us twiddle a few things // most of the config actually remains the same. We only need to mess with a couple items related to the particulars of the apiextensions @@ -69,6 +70,7 @@ func createAPIExtensionsConfig( }, ExtraConfig: apiextensionsapiserver.ExtraConfig{ CRDRESTOptionsGetter: apiextensionscmd.NewCRDRESTOptionsGetter(etcdOptions), + MasterCount: masterCount, }, } diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index 3fb5ed71bb1..b936c9ece2a 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -165,7 +165,7 @@ func CreateServerChain(completedOptions completedServerRunOptions, stopCh <-chan } // If additional API servers are added, they should be gated. - apiExtensionsConfig, err := createAPIExtensionsConfig(*kubeAPIServerConfig.GenericConfig, versionedInformers, pluginInitializer, completedOptions.ServerRunOptions) + apiExtensionsConfig, err := createAPIExtensionsConfig(*kubeAPIServerConfig.GenericConfig, versionedInformers, pluginInitializer, completedOptions.ServerRunOptions, completedOptions.MasterCount) if err != nil { return nil, err } diff --git a/cmd/kube-controller-manager/app/BUILD b/cmd/kube-controller-manager/app/BUILD index 64c82a719a2..e1a9bd54b58 100644 --- a/cmd/kube-controller-manager/app/BUILD +++ b/cmd/kube-controller-manager/app/BUILD @@ -20,7 +20,6 @@ go_library( visibility = ["//visibility:public"], deps = [ "//cmd/controller-manager/app:go_default_library", - "//cmd/controller-manager/app/options:go_default_library", "//cmd/kube-controller-manager/app/config:go_default_library", "//cmd/kube-controller-manager/app/options:go_default_library", "//pkg/apis/apps/install:go_default_library", diff --git a/cmd/kube-controller-manager/app/certificates.go b/cmd/kube-controller-manager/app/certificates.go index 9e6e70cf3f9..23c1b3c1c4a 100644 --- a/cmd/kube-controller-manager/app/certificates.go +++ b/cmd/kube-controller-manager/app/certificates.go @@ -27,7 +27,7 @@ import ( "github.com/golang/glog" "k8s.io/apimachinery/pkg/runtime/schema" - cmoptions "k8s.io/kubernetes/cmd/controller-manager/app/options" + kubeoptions "k8s.io/kubernetes/cmd/kube-controller-manager/app/options" "k8s.io/kubernetes/pkg/controller/certificates/approver" "k8s.io/kubernetes/pkg/controller/certificates/cleaner" "k8s.io/kubernetes/pkg/controller/certificates/signer" @@ -55,12 +55,12 @@ func startCSRSigningController(ctx ControllerContext) (bool, error) { _, err := os.Stat(ctx.ComponentConfig.CSRSigningController.ClusterSigningCertFile) certFileExists = !os.IsNotExist(err) - certUsesDefault = (ctx.ComponentConfig.CSRSigningController.ClusterSigningCertFile == cmoptions.DefaultClusterSigningCertFile) + certUsesDefault = (ctx.ComponentConfig.CSRSigningController.ClusterSigningCertFile == kubeoptions.DefaultClusterSigningCertFile) _, err = os.Stat(ctx.ComponentConfig.CSRSigningController.ClusterSigningKeyFile) keyFileExists = !os.IsNotExist(err) - keyUsesDefault = (ctx.ComponentConfig.CSRSigningController.ClusterSigningKeyFile == cmoptions.DefaultClusterSigningKeyFile) + keyUsesDefault = (ctx.ComponentConfig.CSRSigningController.ClusterSigningKeyFile == kubeoptions.DefaultClusterSigningKeyFile) switch { case (keyFileExists && keyUsesDefault) || (certFileExists && certUsesDefault): diff --git a/cmd/kube-controller-manager/app/controllermanager.go b/cmd/kube-controller-manager/app/controllermanager.go index b03ba75667e..a235e8a1183 100644 --- a/cmd/kube-controller-manager/app/controllermanager.go +++ b/cmd/kube-controller-manager/app/controllermanager.go @@ -70,7 +70,11 @@ const ( // NewControllerManagerCommand creates a *cobra.Command object with default parameters func NewControllerManagerCommand() *cobra.Command { - s := options.NewKubeControllerManagerOptions() + s, err := options.NewKubeControllerManagerOptions() + if err != nil { + glog.Fatalf("unable to initialize command options: %v", err) + } + cmd := &cobra.Command{ Use: "kube-controller-manager", Long: `The Kubernetes controller manager is a daemon that embeds @@ -146,7 +150,7 @@ func Run(c *config.CompletedConfig) error { } var clientBuilder controller.ControllerClientBuilder if c.ComponentConfig.KubeCloudShared.UseServiceAccountCredentials { - if len(c.ComponentConfig.KubeCloudShared.ServiceAccountKeyFile) == 0 { + if len(c.ComponentConfig.SAController.ServiceAccountKeyFile) == 0 { // It'c possible another controller process is creating the tokens for us. // If one isn't, we'll timeout and exit when our client builder is unable to create the tokens. glog.Warningf("--use-service-account-credentials was specified without providing a --service-account-private-key-file") @@ -480,11 +484,11 @@ func (c serviceAccountTokenControllerStarter) startServiceAccountTokenController return false, nil } - if len(ctx.ComponentConfig.KubeCloudShared.ServiceAccountKeyFile) == 0 { + if len(ctx.ComponentConfig.SAController.ServiceAccountKeyFile) == 0 { glog.Warningf("%q is disabled because there is no private key", saTokenControllerName) return false, nil } - privateKey, err := certutil.PrivateKeyFromFile(ctx.ComponentConfig.KubeCloudShared.ServiceAccountKeyFile) + privateKey, err := certutil.PrivateKeyFromFile(ctx.ComponentConfig.SAController.ServiceAccountKeyFile) if err != nil { return true, fmt.Errorf("error reading key for service account token controller: %v", err) } diff --git a/cmd/kube-controller-manager/app/core.go b/cmd/kube-controller-manager/app/core.go index eee8157152b..4b0b97d5be1 100644 --- a/cmd/kube-controller-manager/app/core.go +++ b/cmd/kube-controller-manager/app/core.go @@ -175,6 +175,7 @@ func startPersistentVolumeBinderController(ctx ControllerContext) (bool, error) ClaimInformer: ctx.InformerFactory.Core().V1().PersistentVolumeClaims(), ClassInformer: ctx.InformerFactory.Storage().V1().StorageClasses(), PodInformer: ctx.InformerFactory.Core().V1().Pods(), + NodeInformer: ctx.InformerFactory.Core().V1().Nodes(), EnableDynamicProvisioning: ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration.EnableDynamicProvisioning, } volumeController, volumeControllerErr := persistentvolumecontroller.NewController(params) diff --git a/cmd/kube-controller-manager/app/options/BUILD b/cmd/kube-controller-manager/app/options/BUILD index 3bba70af884..9822d64a2a2 100644 --- a/cmd/kube-controller-manager/app/options/BUILD +++ b/cmd/kube-controller-manager/app/options/BUILD @@ -8,7 +8,27 @@ load( go_library( name = "go_default_library", - srcs = ["options.go"], + srcs = [ + "attachdetachcontroller.go", + "csrsigningcontroller.go", + "daemonsetcontroller.go", + "deploymentcontroller.go", + "deprecatedcontroller.go", + "endpointcontroller.go", + "garbagecollectorcontroller.go", + "hpacontroller.go", + "jobcontroller.go", + "namespacecontroller.go", + "nodeipamcontroller.go", + "nodelifecyclecontroller.go", + "options.go", + "persistentvolumebindercontroller.go", + "podgccontroller.go", + "replicasetcontroller.go", + "replicationcontroller.go", + "resourcequotacontroller.go", + "serviceaccountcontroller.go", + ], importpath = "k8s.io/kubernetes/cmd/kube-controller-manager/app/options", deps = [ "//cmd/controller-manager/app/options:go_default_library", @@ -22,6 +42,7 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", diff --git a/cmd/controller-manager/app/options/attachdetachcontroller.go b/cmd/kube-controller-manager/app/options/attachdetachcontroller.go similarity index 99% rename from cmd/controller-manager/app/options/attachdetachcontroller.go rename to cmd/kube-controller-manager/app/options/attachdetachcontroller.go index f34d5ea4640..8f620f4b95d 100644 --- a/cmd/controller-manager/app/options/attachdetachcontroller.go +++ b/cmd/kube-controller-manager/app/options/attachdetachcontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/csrsigningcontroller.go b/cmd/kube-controller-manager/app/options/csrsigningcontroller.go similarity index 99% rename from cmd/controller-manager/app/options/csrsigningcontroller.go rename to cmd/kube-controller-manager/app/options/csrsigningcontroller.go index bf55c9df89b..acd9d9be28c 100644 --- a/cmd/controller-manager/app/options/csrsigningcontroller.go +++ b/cmd/kube-controller-manager/app/options/csrsigningcontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/daemonsetcontroller.go b/cmd/kube-controller-manager/app/options/daemonsetcontroller.go similarity index 99% rename from cmd/controller-manager/app/options/daemonsetcontroller.go rename to cmd/kube-controller-manager/app/options/daemonsetcontroller.go index df388edc78d..2d3d3f526ab 100644 --- a/cmd/controller-manager/app/options/daemonsetcontroller.go +++ b/cmd/kube-controller-manager/app/options/daemonsetcontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/deploymentcontroller.go b/cmd/kube-controller-manager/app/options/deploymentcontroller.go similarity index 99% rename from cmd/controller-manager/app/options/deploymentcontroller.go rename to cmd/kube-controller-manager/app/options/deploymentcontroller.go index 5b3db92662d..481ffad4486 100644 --- a/cmd/controller-manager/app/options/deploymentcontroller.go +++ b/cmd/kube-controller-manager/app/options/deploymentcontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/deprecatedcontroller.go b/cmd/kube-controller-manager/app/options/deprecatedcontroller.go similarity index 97% rename from cmd/controller-manager/app/options/deprecatedcontroller.go rename to cmd/kube-controller-manager/app/options/deprecatedcontroller.go index 3b8d0a1cd0d..b65683725ae 100644 --- a/cmd/controller-manager/app/options/deprecatedcontroller.go +++ b/cmd/kube-controller-manager/app/options/deprecatedcontroller.go @@ -18,10 +18,12 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) // DeprecatedControllerOptions holds the DeprecatedController options, those option are deprecated. +// TODO remove these fields once the deprecated flags are removed. type DeprecatedControllerOptions struct { DeletingPodsQPS float32 DeletingPodsBurst int32 diff --git a/cmd/controller-manager/app/options/endpointcontroller.go b/cmd/kube-controller-manager/app/options/endpointcontroller.go similarity index 99% rename from cmd/controller-manager/app/options/endpointcontroller.go rename to cmd/kube-controller-manager/app/options/endpointcontroller.go index 2457650c9e4..37f7f79405d 100644 --- a/cmd/controller-manager/app/options/endpointcontroller.go +++ b/cmd/kube-controller-manager/app/options/endpointcontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/garbagecollectorcontroller.go b/cmd/kube-controller-manager/app/options/garbagecollectorcontroller.go similarity index 99% rename from cmd/controller-manager/app/options/garbagecollectorcontroller.go rename to cmd/kube-controller-manager/app/options/garbagecollectorcontroller.go index 85cf45e9bec..73d4e5fcd58 100644 --- a/cmd/controller-manager/app/options/garbagecollectorcontroller.go +++ b/cmd/kube-controller-manager/app/options/garbagecollectorcontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/hpacontroller.go b/cmd/kube-controller-manager/app/options/hpacontroller.go similarity index 99% rename from cmd/controller-manager/app/options/hpacontroller.go rename to cmd/kube-controller-manager/app/options/hpacontroller.go index 39fae9d9200..cbbb159c0d7 100644 --- a/cmd/controller-manager/app/options/hpacontroller.go +++ b/cmd/kube-controller-manager/app/options/hpacontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/jobcontroller.go b/cmd/kube-controller-manager/app/options/jobcontroller.go similarity index 99% rename from cmd/controller-manager/app/options/jobcontroller.go rename to cmd/kube-controller-manager/app/options/jobcontroller.go index 9269a3682d4..97dc0277289 100644 --- a/cmd/controller-manager/app/options/jobcontroller.go +++ b/cmd/kube-controller-manager/app/options/jobcontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/namespacecontroller.go b/cmd/kube-controller-manager/app/options/namespacecontroller.go similarity index 99% rename from cmd/controller-manager/app/options/namespacecontroller.go rename to cmd/kube-controller-manager/app/options/namespacecontroller.go index 718e7c98bd9..b6cd5e63abb 100644 --- a/cmd/controller-manager/app/options/namespacecontroller.go +++ b/cmd/kube-controller-manager/app/options/namespacecontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/nodeipamcontroller.go b/cmd/kube-controller-manager/app/options/nodeipamcontroller.go similarity index 99% rename from cmd/controller-manager/app/options/nodeipamcontroller.go rename to cmd/kube-controller-manager/app/options/nodeipamcontroller.go index 65cea454b35..3bfad216eb6 100644 --- a/cmd/controller-manager/app/options/nodeipamcontroller.go +++ b/cmd/kube-controller-manager/app/options/nodeipamcontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/nodelifecyclecontroller.go b/cmd/kube-controller-manager/app/options/nodelifecyclecontroller.go similarity index 99% rename from cmd/controller-manager/app/options/nodelifecyclecontroller.go rename to cmd/kube-controller-manager/app/options/nodelifecyclecontroller.go index 0056555764b..6c3ddeb09b4 100644 --- a/cmd/controller-manager/app/options/nodelifecyclecontroller.go +++ b/cmd/kube-controller-manager/app/options/nodelifecyclecontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/kube-controller-manager/app/options/options.go b/cmd/kube-controller-manager/app/options/options.go index 2841dba49e4..d4149aa5bae 100644 --- a/cmd/kube-controller-manager/app/options/options.go +++ b/cmd/kube-controller-manager/app/options/options.go @@ -49,32 +49,37 @@ import ( "github.com/spf13/pflag" ) +const ( + // KubeControllerManagerUserAgent is the userAgent name when starting kube-controller managers. + KubeControllerManagerUserAgent = "kube-controller-manager" +) + // KubeControllerManagerOptions is the main context object for the kube-controller manager. type KubeControllerManagerOptions struct { - CloudProvider *cmoptions.CloudProviderOptions - Debugging *cmoptions.DebuggingOptions - GenericComponent *cmoptions.GenericComponentConfigOptions - KubeCloudShared *cmoptions.KubeCloudSharedOptions + CloudProvider *cmoptions.CloudProviderOptions + Debugging *cmoptions.DebuggingOptions + GenericComponent *cmoptions.GenericComponentConfigOptions + KubeCloudShared *cmoptions.KubeCloudSharedOptions + ServiceController *cmoptions.ServiceControllerOptions - AttachDetachController *cmoptions.AttachDetachControllerOptions - CSRSigningController *cmoptions.CSRSigningControllerOptions - DaemonSetController *cmoptions.DaemonSetControllerOptions - DeploymentController *cmoptions.DeploymentControllerOptions - DeprecatedFlags *cmoptions.DeprecatedControllerOptions - EndPointController *cmoptions.EndPointControllerOptions - GarbageCollectorController *cmoptions.GarbageCollectorControllerOptions - HPAController *cmoptions.HPAControllerOptions - JobController *cmoptions.JobControllerOptions - NamespaceController *cmoptions.NamespaceControllerOptions - NodeIpamController *cmoptions.NodeIpamControllerOptions - NodeLifecycleController *cmoptions.NodeLifecycleControllerOptions - PersistentVolumeBinderController *cmoptions.PersistentVolumeBinderControllerOptions - PodGCController *cmoptions.PodGCControllerOptions - ReplicaSetController *cmoptions.ReplicaSetControllerOptions - ReplicationController *cmoptions.ReplicationControllerOptions - ResourceQuotaController *cmoptions.ResourceQuotaControllerOptions - SAController *cmoptions.SAControllerOptions - ServiceController *cmoptions.ServiceControllerOptions + AttachDetachController *AttachDetachControllerOptions + CSRSigningController *CSRSigningControllerOptions + DaemonSetController *DaemonSetControllerOptions + DeploymentController *DeploymentControllerOptions + DeprecatedFlags *DeprecatedControllerOptions + EndPointController *EndPointControllerOptions + GarbageCollectorController *GarbageCollectorControllerOptions + HPAController *HPAControllerOptions + JobController *JobControllerOptions + NamespaceController *NamespaceControllerOptions + NodeIpamController *NodeIpamControllerOptions + NodeLifecycleController *NodeLifecycleControllerOptions + PersistentVolumeBinderController *PersistentVolumeBinderControllerOptions + PodGCController *PodGCControllerOptions + ReplicaSetController *ReplicaSetControllerOptions + ReplicationController *ReplicationControllerOptions + ResourceQuotaController *ResourceQuotaControllerOptions + SAController *SAControllerOptions Controllers []string ExternalCloudVolumePlugin string @@ -90,79 +95,83 @@ type KubeControllerManagerOptions struct { } // NewKubeControllerManagerOptions creates a new KubeControllerManagerOptions with a default config. -func NewKubeControllerManagerOptions() *KubeControllerManagerOptions { - componentConfig := NewDefaultComponentConfig(ports.InsecureKubeControllerManagerPort) +func NewKubeControllerManagerOptions() (*KubeControllerManagerOptions, error) { + componentConfig, err := NewDefaultComponentConfig(ports.InsecureKubeControllerManagerPort) + if err != nil { + return nil, err + } + s := KubeControllerManagerOptions{ CloudProvider: &cmoptions.CloudProviderOptions{}, Debugging: &cmoptions.DebuggingOptions{}, GenericComponent: cmoptions.NewGenericComponentConfigOptions(componentConfig.GenericComponent), KubeCloudShared: cmoptions.NewKubeCloudSharedOptions(componentConfig.KubeCloudShared), - AttachDetachController: &cmoptions.AttachDetachControllerOptions{ + AttachDetachController: &AttachDetachControllerOptions{ ReconcilerSyncLoopPeriod: componentConfig.AttachDetachController.ReconcilerSyncLoopPeriod, }, - CSRSigningController: &cmoptions.CSRSigningControllerOptions{ + CSRSigningController: &CSRSigningControllerOptions{ ClusterSigningCertFile: componentConfig.CSRSigningController.ClusterSigningCertFile, ClusterSigningKeyFile: componentConfig.CSRSigningController.ClusterSigningKeyFile, ClusterSigningDuration: componentConfig.CSRSigningController.ClusterSigningDuration, }, - DaemonSetController: &cmoptions.DaemonSetControllerOptions{ + DaemonSetController: &DaemonSetControllerOptions{ ConcurrentDaemonSetSyncs: componentConfig.DaemonSetController.ConcurrentDaemonSetSyncs, }, - DeploymentController: &cmoptions.DeploymentControllerOptions{ + DeploymentController: &DeploymentControllerOptions{ ConcurrentDeploymentSyncs: componentConfig.DeploymentController.ConcurrentDeploymentSyncs, DeploymentControllerSyncPeriod: componentConfig.DeploymentController.DeploymentControllerSyncPeriod, }, - DeprecatedFlags: &cmoptions.DeprecatedControllerOptions{ + DeprecatedFlags: &DeprecatedControllerOptions{ RegisterRetryCount: componentConfig.DeprecatedController.RegisterRetryCount, }, - EndPointController: &cmoptions.EndPointControllerOptions{ + EndPointController: &EndPointControllerOptions{ ConcurrentEndpointSyncs: componentConfig.EndPointController.ConcurrentEndpointSyncs, }, - GarbageCollectorController: &cmoptions.GarbageCollectorControllerOptions{ + GarbageCollectorController: &GarbageCollectorControllerOptions{ ConcurrentGCSyncs: componentConfig.GarbageCollectorController.ConcurrentGCSyncs, EnableGarbageCollector: componentConfig.GarbageCollectorController.EnableGarbageCollector, }, - HPAController: &cmoptions.HPAControllerOptions{ + HPAController: &HPAControllerOptions{ HorizontalPodAutoscalerSyncPeriod: componentConfig.HPAController.HorizontalPodAutoscalerSyncPeriod, HorizontalPodAutoscalerUpscaleForbiddenWindow: componentConfig.HPAController.HorizontalPodAutoscalerUpscaleForbiddenWindow, HorizontalPodAutoscalerDownscaleForbiddenWindow: componentConfig.HPAController.HorizontalPodAutoscalerDownscaleForbiddenWindow, HorizontalPodAutoscalerTolerance: componentConfig.HPAController.HorizontalPodAutoscalerTolerance, HorizontalPodAutoscalerUseRESTClients: componentConfig.HPAController.HorizontalPodAutoscalerUseRESTClients, }, - JobController: &cmoptions.JobControllerOptions{ + JobController: &JobControllerOptions{ ConcurrentJobSyncs: componentConfig.JobController.ConcurrentJobSyncs, }, - NamespaceController: &cmoptions.NamespaceControllerOptions{ + NamespaceController: &NamespaceControllerOptions{ NamespaceSyncPeriod: componentConfig.NamespaceController.NamespaceSyncPeriod, ConcurrentNamespaceSyncs: componentConfig.NamespaceController.ConcurrentNamespaceSyncs, }, - NodeIpamController: &cmoptions.NodeIpamControllerOptions{ + NodeIpamController: &NodeIpamControllerOptions{ NodeCIDRMaskSize: componentConfig.NodeIpamController.NodeCIDRMaskSize, }, - NodeLifecycleController: &cmoptions.NodeLifecycleControllerOptions{ + NodeLifecycleController: &NodeLifecycleControllerOptions{ EnableTaintManager: componentConfig.NodeLifecycleController.EnableTaintManager, NodeMonitorGracePeriod: componentConfig.NodeLifecycleController.NodeMonitorGracePeriod, NodeStartupGracePeriod: componentConfig.NodeLifecycleController.NodeStartupGracePeriod, PodEvictionTimeout: componentConfig.NodeLifecycleController.PodEvictionTimeout, }, - PersistentVolumeBinderController: &cmoptions.PersistentVolumeBinderControllerOptions{ + PersistentVolumeBinderController: &PersistentVolumeBinderControllerOptions{ PVClaimBinderSyncPeriod: componentConfig.PersistentVolumeBinderController.PVClaimBinderSyncPeriod, VolumeConfiguration: componentConfig.PersistentVolumeBinderController.VolumeConfiguration, }, - PodGCController: &cmoptions.PodGCControllerOptions{ + PodGCController: &PodGCControllerOptions{ TerminatedPodGCThreshold: componentConfig.PodGCController.TerminatedPodGCThreshold, }, - ReplicaSetController: &cmoptions.ReplicaSetControllerOptions{ + ReplicaSetController: &ReplicaSetControllerOptions{ ConcurrentRSSyncs: componentConfig.ReplicaSetController.ConcurrentRSSyncs, }, - ReplicationController: &cmoptions.ReplicationControllerOptions{ + ReplicationController: &ReplicationControllerOptions{ ConcurrentRCSyncs: componentConfig.ReplicationController.ConcurrentRCSyncs, }, - ResourceQuotaController: &cmoptions.ResourceQuotaControllerOptions{ + ResourceQuotaController: &ResourceQuotaControllerOptions{ ResourceQuotaSyncPeriod: componentConfig.ResourceQuotaController.ResourceQuotaSyncPeriod, ConcurrentResourceQuotaSyncs: componentConfig.ResourceQuotaController.ConcurrentResourceQuotaSyncs, }, - SAController: &cmoptions.SAControllerOptions{ + SAController: &SAControllerOptions{ ConcurrentSATokenSyncs: componentConfig.SAController.ConcurrentSATokenSyncs, }, ServiceController: &cmoptions.ServiceControllerOptions{ @@ -193,11 +202,11 @@ func NewKubeControllerManagerOptions() *KubeControllerManagerOptions { s.GarbageCollectorController.GCIgnoredResources = gcIgnoredResources - return &s + return &s, nil } // NewDefaultComponentConfig returns kube-controller manager configuration object. -func NewDefaultComponentConfig(insecurePort int32) componentconfig.KubeControllerManagerConfiguration { +func NewDefaultComponentConfig(insecurePort int32) (componentconfig.KubeControllerManagerConfiguration, error) { scheme := runtime.NewScheme() componentconfigv1alpha1.AddToScheme(scheme) componentconfig.AddToScheme(scheme) @@ -206,9 +215,11 @@ func NewDefaultComponentConfig(insecurePort int32) componentconfig.KubeControlle scheme.Default(&versioned) internal := componentconfig.KubeControllerManagerConfiguration{} - scheme.Convert(&versioned, &internal, nil) + if err := scheme.Convert(&versioned, &internal, nil); err != nil { + return internal, err + } internal.KubeCloudShared.Port = insecurePort - return internal + return internal, nil } // AddFlags adds flags for a specific KubeControllerManagerOptions to the specified FlagSet @@ -257,7 +268,7 @@ func (s *KubeControllerManagerOptions) AddFlags(fs *pflag.FlagSet, allController } // ApplyTo fills up controller manager config with options. -func (s *KubeControllerManagerOptions) ApplyTo(c *kubecontrollerconfig.Config, userAgent string) error { +func (s *KubeControllerManagerOptions) ApplyTo(c *kubecontrollerconfig.Config) error { if err := s.CloudProvider.ApplyTo(&c.ComponentConfig.CloudProvider); err != nil { return err } @@ -341,32 +352,14 @@ func (s *KubeControllerManagerOptions) ApplyTo(c *kubecontrollerconfig.Config, u } // sync back to component config - // TODO: find more elegant way than synching back the values. + // TODO: find more elegant way than syncing back the values. c.ComponentConfig.KubeCloudShared.Port = int32(s.InsecureServing.BindPort) c.ComponentConfig.KubeCloudShared.Address = s.InsecureServing.BindAddress.String() - var err error - c.Kubeconfig, err = clientcmd.BuildConfigFromFlags(s.Master, s.Kubeconfig) - if err != nil { - return err - } - c.Kubeconfig.ContentConfig.ContentType = s.GenericComponent.ContentType - c.Kubeconfig.QPS = s.GenericComponent.KubeAPIQPS - c.Kubeconfig.Burst = int(s.GenericComponent.KubeAPIBurst) - - c.Client, err = clientset.NewForConfig(restclient.AddUserAgent(c.Kubeconfig, userAgent)) - if err != nil { - return err - } - - c.LeaderElectionClient = clientset.NewForConfigOrDie(restclient.AddUserAgent(c.Kubeconfig, "leader-election")) - - c.EventRecorder = createRecorder(c.Client, userAgent) - c.ComponentConfig.Controllers = s.Controllers c.ComponentConfig.ExternalCloudVolumePlugin = s.ExternalCloudVolumePlugin - return err + return nil } // Validate is used to validate the options and config before launching the controller manager @@ -426,8 +419,30 @@ func (s KubeControllerManagerOptions) Config(allControllers []string, disabledBy return nil, err } - c := &kubecontrollerconfig.Config{} - if err := s.ApplyTo(c, "kube-controller-manager"); err != nil { + kubeconfig, err := clientcmd.BuildConfigFromFlags(s.Master, s.Kubeconfig) + if err != nil { + return nil, err + } + kubeconfig.ContentConfig.ContentType = s.GenericComponent.ContentType + kubeconfig.QPS = s.GenericComponent.KubeAPIQPS + kubeconfig.Burst = int(s.GenericComponent.KubeAPIBurst) + + client, err := clientset.NewForConfig(restclient.AddUserAgent(kubeconfig, KubeControllerManagerUserAgent)) + if err != nil { + return nil, err + } + + leaderElectionClient := clientset.NewForConfigOrDie(restclient.AddUserAgent(kubeconfig, "leader-election")) + + eventRecorder := createRecorder(client, KubeControllerManagerUserAgent) + + c := &kubecontrollerconfig.Config{ + Client: client, + Kubeconfig: kubeconfig, + EventRecorder: eventRecorder, + LeaderElectionClient: leaderElectionClient, + } + if err := s.ApplyTo(c); err != nil { return nil, err } @@ -438,5 +453,6 @@ func createRecorder(kubeClient kubernetes.Interface, userAgent string) record.Ev eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) + // TODO: remove dependency on the legacyscheme return eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: userAgent}) } diff --git a/cmd/kube-controller-manager/app/options/options_test.go b/cmd/kube-controller-manager/app/options/options_test.go index 0e69b91b857..d684fa7badb 100644 --- a/cmd/kube-controller-manager/app/options/options_test.go +++ b/cmd/kube-controller-manager/app/options/options_test.go @@ -34,7 +34,7 @@ import ( func TestAddFlags(t *testing.T) { f := pflag.NewFlagSet("addflagstest", pflag.ContinueOnError) - s := NewKubeControllerManagerOptions() + s, _ := NewKubeControllerManagerOptions() s.AddFlags(f, []string{""}, []string{""}) args := []string{ @@ -149,32 +149,31 @@ func TestAddFlags(t *testing.T) { AllocateNodeCIDRs: true, CIDRAllocatorType: "CloudAllocator", ConfigureCloudRoutes: false, - ServiceAccountKeyFile: "/service-account-private-key", }, - AttachDetachController: &cmoptions.AttachDetachControllerOptions{ + AttachDetachController: &AttachDetachControllerOptions{ ReconcilerSyncLoopPeriod: metav1.Duration{Duration: 30 * time.Second}, DisableAttachDetachReconcilerSync: true, }, - CSRSigningController: &cmoptions.CSRSigningControllerOptions{ + CSRSigningController: &CSRSigningControllerOptions{ ClusterSigningCertFile: "/cluster-signing-cert", ClusterSigningKeyFile: "/cluster-signing-key", ClusterSigningDuration: metav1.Duration{Duration: 10 * time.Hour}, }, - DaemonSetController: &cmoptions.DaemonSetControllerOptions{ + DaemonSetController: &DaemonSetControllerOptions{ ConcurrentDaemonSetSyncs: 2, }, - DeploymentController: &cmoptions.DeploymentControllerOptions{ + DeploymentController: &DeploymentControllerOptions{ ConcurrentDeploymentSyncs: 10, DeploymentControllerSyncPeriod: metav1.Duration{Duration: 45 * time.Second}, }, - DeprecatedFlags: &cmoptions.DeprecatedControllerOptions{ + DeprecatedFlags: &DeprecatedControllerOptions{ DeletingPodsQPS: 0.1, RegisterRetryCount: 10, }, - EndPointController: &cmoptions.EndPointControllerOptions{ + EndPointController: &EndPointControllerOptions{ ConcurrentEndpointSyncs: 10, }, - GarbageCollectorController: &cmoptions.GarbageCollectorControllerOptions{ + GarbageCollectorController: &GarbageCollectorControllerOptions{ ConcurrentGCSyncs: 30, GCIgnoredResources: []componentconfig.GroupResource{ {Group: "extensions", Resource: "replicationcontrollers"}, @@ -191,24 +190,24 @@ func TestAddFlags(t *testing.T) { }, EnableGarbageCollector: false, }, - HPAController: &cmoptions.HPAControllerOptions{ + HPAController: &HPAControllerOptions{ HorizontalPodAutoscalerSyncPeriod: metav1.Duration{Duration: 45 * time.Second}, HorizontalPodAutoscalerUpscaleForbiddenWindow: metav1.Duration{Duration: 1 * time.Minute}, HorizontalPodAutoscalerDownscaleForbiddenWindow: metav1.Duration{Duration: 2 * time.Minute}, HorizontalPodAutoscalerTolerance: 0.1, HorizontalPodAutoscalerUseRESTClients: true, }, - JobController: &cmoptions.JobControllerOptions{ + JobController: &JobControllerOptions{ ConcurrentJobSyncs: 5, }, - NamespaceController: &cmoptions.NamespaceControllerOptions{ + NamespaceController: &NamespaceControllerOptions{ NamespaceSyncPeriod: metav1.Duration{Duration: 10 * time.Minute}, ConcurrentNamespaceSyncs: 20, }, - NodeIpamController: &cmoptions.NodeIpamControllerOptions{ + NodeIpamController: &NodeIpamControllerOptions{ NodeCIDRMaskSize: 48, }, - NodeLifecycleController: &cmoptions.NodeLifecycleControllerOptions{ + NodeLifecycleController: &NodeLifecycleControllerOptions{ EnableTaintManager: false, NodeEvictionRate: 0.2, SecondaryNodeEvictionRate: 0.05, @@ -218,7 +217,7 @@ func TestAddFlags(t *testing.T) { LargeClusterSizeThreshold: 100, UnhealthyZoneThreshold: 0.6, }, - PersistentVolumeBinderController: &cmoptions.PersistentVolumeBinderControllerOptions{ + PersistentVolumeBinderController: &PersistentVolumeBinderControllerOptions{ PVClaimBinderSyncPeriod: metav1.Duration{Duration: 30 * time.Second}, VolumeConfiguration: componentconfig.VolumeConfiguration{ EnableDynamicProvisioning: false, @@ -233,20 +232,21 @@ func TestAddFlags(t *testing.T) { }, }, }, - PodGCController: &cmoptions.PodGCControllerOptions{ + PodGCController: &PodGCControllerOptions{ TerminatedPodGCThreshold: 12000, }, - ReplicaSetController: &cmoptions.ReplicaSetControllerOptions{ + ReplicaSetController: &ReplicaSetControllerOptions{ ConcurrentRSSyncs: 10, }, - ReplicationController: &cmoptions.ReplicationControllerOptions{ + ReplicationController: &ReplicationControllerOptions{ ConcurrentRCSyncs: 10, }, - ResourceQuotaController: &cmoptions.ResourceQuotaControllerOptions{ + ResourceQuotaController: &ResourceQuotaControllerOptions{ ResourceQuotaSyncPeriod: metav1.Duration{Duration: 10 * time.Minute}, ConcurrentResourceQuotaSyncs: 10, }, - SAController: &cmoptions.SAControllerOptions{ + SAController: &SAControllerOptions{ + ServiceAccountKeyFile: "/service-account-private-key", ConcurrentSATokenSyncs: 10, }, ServiceController: &cmoptions.ServiceControllerOptions{ diff --git a/cmd/controller-manager/app/options/persistentvolumebindercontroller.go b/cmd/kube-controller-manager/app/options/persistentvolumebindercontroller.go similarity index 99% rename from cmd/controller-manager/app/options/persistentvolumebindercontroller.go rename to cmd/kube-controller-manager/app/options/persistentvolumebindercontroller.go index 79aba3a2fa5..ba7e05ccc0b 100644 --- a/cmd/controller-manager/app/options/persistentvolumebindercontroller.go +++ b/cmd/kube-controller-manager/app/options/persistentvolumebindercontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/podgccontroller.go b/cmd/kube-controller-manager/app/options/podgccontroller.go similarity index 99% rename from cmd/controller-manager/app/options/podgccontroller.go rename to cmd/kube-controller-manager/app/options/podgccontroller.go index 8eb82f11c7d..9af9c4429ae 100644 --- a/cmd/controller-manager/app/options/podgccontroller.go +++ b/cmd/kube-controller-manager/app/options/podgccontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/replicasetcontroller.go b/cmd/kube-controller-manager/app/options/replicasetcontroller.go similarity index 99% rename from cmd/controller-manager/app/options/replicasetcontroller.go rename to cmd/kube-controller-manager/app/options/replicasetcontroller.go index 23e37d28f3b..67a6acdd007 100644 --- a/cmd/controller-manager/app/options/replicasetcontroller.go +++ b/cmd/kube-controller-manager/app/options/replicasetcontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/replicationcontroller.go b/cmd/kube-controller-manager/app/options/replicationcontroller.go similarity index 99% rename from cmd/controller-manager/app/options/replicationcontroller.go rename to cmd/kube-controller-manager/app/options/replicationcontroller.go index a64b4fe6f3c..0b79bf3340f 100644 --- a/cmd/controller-manager/app/options/replicationcontroller.go +++ b/cmd/kube-controller-manager/app/options/replicationcontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/resourcequotacontroller.go b/cmd/kube-controller-manager/app/options/resourcequotacontroller.go similarity index 99% rename from cmd/controller-manager/app/options/resourcequotacontroller.go rename to cmd/kube-controller-manager/app/options/resourcequotacontroller.go index b684e6e7e32..1d89320e5a1 100644 --- a/cmd/controller-manager/app/options/resourcequotacontroller.go +++ b/cmd/kube-controller-manager/app/options/resourcequotacontroller.go @@ -18,6 +18,7 @@ package options import ( "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/componentconfig" ) diff --git a/cmd/controller-manager/app/options/serviceaccountcontroller.go b/cmd/kube-controller-manager/app/options/serviceaccountcontroller.go similarity index 87% rename from cmd/controller-manager/app/options/serviceaccountcontroller.go rename to cmd/kube-controller-manager/app/options/serviceaccountcontroller.go index cb6f4a90824..e29099199e0 100644 --- a/cmd/controller-manager/app/options/serviceaccountcontroller.go +++ b/cmd/kube-controller-manager/app/options/serviceaccountcontroller.go @@ -18,11 +18,13 @@ package options import ( "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) // SAControllerOptions holds the ServiceAccountController options. type SAControllerOptions struct { + ServiceAccountKeyFile string ConcurrentSATokenSyncs int32 RootCAFile string } @@ -33,6 +35,7 @@ func (o *SAControllerOptions) AddFlags(fs *pflag.FlagSet) { return } + fs.StringVar(&o.ServiceAccountKeyFile, "service-account-private-key-file", o.ServiceAccountKeyFile, "Filename containing a PEM-encoded private RSA or ECDSA key used to sign service account tokens.") fs.Int32Var(&o.ConcurrentSATokenSyncs, "concurrent-serviceaccount-token-syncs", o.ConcurrentSATokenSyncs, "The number of service account token objects that are allowed to sync concurrently. Larger number = more responsive token generation, but more CPU (and network) load") fs.StringVar(&o.RootCAFile, "root-ca-file", o.RootCAFile, "If set, this root certificate authority will be included in service account's token secret. This must be a valid PEM-encoded CA bundle.") } @@ -43,6 +46,7 @@ func (o *SAControllerOptions) ApplyTo(cfg *componentconfig.SAControllerConfigura return nil } + cfg.ServiceAccountKeyFile = o.ServiceAccountKeyFile cfg.ConcurrentSATokenSyncs = o.ConcurrentSATokenSyncs cfg.RootCAFile = o.RootCAFile diff --git a/cmd/kube-proxy/app/BUILD b/cmd/kube-proxy/app/BUILD index 3ae5ab8f044..295102156d6 100644 --- a/cmd/kube-proxy/app/BUILD +++ b/cmd/kube-proxy/app/BUILD @@ -64,7 +64,6 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/informers/informers_generated/internalversion:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubelet/qos:go_default_library", "//pkg/master/ports:go_default_library", "//pkg/proxy:go_default_library", @@ -115,70 +114,60 @@ go_library( "//vendor/k8s.io/utils/exec:go_default_library", ] + select({ "@io_bazel_rules_go//go/platform:android": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:darwin": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:dragonfly": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:freebsd": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:linux": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:nacl": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:netbsd": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:openbsd": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:plan9": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:solaris": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", @@ -236,7 +225,6 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", - "//pkg/features:go_default_library", "//pkg/proxy/apis/kubeproxyconfig:go_default_library", "//pkg/util/configz:go_default_library", "//pkg/util/pointer:go_default_library", @@ -247,52 +235,42 @@ go_test( "@io_bazel_rules_go//go/platform:android": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:darwin": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:dragonfly": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:freebsd": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:linux": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:nacl": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:netbsd": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:openbsd": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:plan9": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:solaris": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "//conditions:default": [], }), diff --git a/cmd/kube-proxy/app/server.go b/cmd/kube-proxy/app/server.go index 60468d6990c..6161f15d9fe 100644 --- a/cmd/kube-proxy/app/server.go +++ b/cmd/kube-proxy/app/server.go @@ -51,7 +51,6 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubelet/qos" "k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/proxy" @@ -353,9 +352,13 @@ with the apiserver API to configure the proxy.`, glog.Fatalf("failed OS init: %v", err) } - cmdutil.CheckErr(opts.Complete()) - cmdutil.CheckErr(opts.Validate(args)) - cmdutil.CheckErr(opts.Run()) + if err := opts.Complete(); err != nil { + glog.Fatalf("failed complete: %v", err) + } + if err := opts.Validate(args); err != nil { + glog.Fatalf("failed validate: %v", err) + } + glog.Fatal(opts.Run()) }, } diff --git a/cmd/kube-proxy/app/server_others.go b/cmd/kube-proxy/app/server_others.go index 1ab70b1ab52..754d654f179 100644 --- a/cmd/kube-proxy/app/server_others.go +++ b/cmd/kube-proxy/app/server_others.go @@ -30,9 +30,7 @@ import ( "k8s.io/apimachinery/pkg/types" utilnet "k8s.io/apimachinery/pkg/util/net" utilruntime "k8s.io/apimachinery/pkg/util/runtime" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/proxy" proxyconfigapi "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig" proxyconfig "k8s.io/kubernetes/pkg/proxy/config" @@ -92,9 +90,11 @@ func newProxyServer( dbus = utildbus.New() iptInterface = utiliptables.New(execer, dbus, protocol) - ipvsInterface = utilipvs.New(execer) kernelHandler = ipvs.NewLinuxKernelHandler() ipsetInterface = utilipset.New(execer) + if canUse, _ := ipvs.CanUseIPVSProxier(kernelHandler, ipsetInterface); canUse { + ipvsInterface = utilipvs.New(execer) + } // We omit creation of pretty much everything if we run in cleanup mode if cleanupAndExit { @@ -276,21 +276,13 @@ func newProxyServer( } func getProxyMode(proxyMode string, iptver iptables.IPTablesVersioner, khandle ipvs.KernelHandler, ipsetver ipvs.IPSetVersioner, kcompat iptables.KernelCompatTester) string { - if proxyMode == proxyModeUserspace { + switch proxyMode { + case proxyModeUserspace: return proxyModeUserspace - } - - if len(proxyMode) > 0 && proxyMode == proxyModeIPTables { + case proxyModeIPTables: return tryIPTablesProxy(iptver, kcompat) - } - - if utilfeature.DefaultFeatureGate.Enabled(features.SupportIPVSProxyMode) { - if proxyMode == proxyModeIPVS { - return tryIPVSProxy(iptver, khandle, ipsetver, kcompat) - } else { - glog.Warningf("Can't use ipvs proxier, trying iptables proxier") - return tryIPTablesProxy(iptver, kcompat) - } + case proxyModeIPVS: + return tryIPVSProxy(iptver, khandle, ipsetver, kcompat) } glog.Warningf("Flag proxy-mode=%q unknown, assuming iptables proxy", proxyMode) return tryIPTablesProxy(iptver, kcompat) diff --git a/cmd/kube-proxy/app/server_others_test.go b/cmd/kube-proxy/app/server_others_test.go index 01cc00dc18b..f439f6186f9 100644 --- a/cmd/kube-proxy/app/server_others_test.go +++ b/cmd/kube-proxy/app/server_others_test.go @@ -22,7 +22,6 @@ import ( "fmt" "testing" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/proxy/ipvs" "k8s.io/kubernetes/pkg/util/iptables" ) @@ -88,19 +87,48 @@ func Test_getProxyMode(t *testing.T) { kernelCompat: true, expected: proxyModeIPTables, }, - { // specify ipvs, feature gateway disabled, iptables version ok, kernel is compatible + { // flag says ipvs, ipset version ok, kernel modules installed + flag: "ipvs", + kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, + ipsetVersion: ipvs.MinIPSetCheckVersion, + expected: proxyModeIPVS, + }, + { // flag says ipvs, ipset version too low, fallback on iptables mode flag: "ipvs", + kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, + ipsetVersion: "0.0", iptablesVersion: iptables.MinCheckVersion, kernelCompat: true, expected: proxyModeIPTables, }, - { // specify ipvs, feature gateway disabled, iptables version too low + { // flag says ipvs, bad ipset version, fallback on iptables mode flag: "ipvs", + kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, + ipsetVersion: "a.b.c", + iptablesVersion: iptables.MinCheckVersion, + kernelCompat: true, + expected: proxyModeIPTables, + }, + { // flag says ipvs, required kernel modules are not installed, fallback on iptables mode + flag: "ipvs", + kmods: []string{"foo", "bar", "baz"}, + ipsetVersion: ipvs.MinIPSetCheckVersion, + iptablesVersion: iptables.MinCheckVersion, + kernelCompat: true, + expected: proxyModeIPTables, + }, + { // flag says ipvs, required kernel modules are not installed, iptables version too old, fallback on userspace mode + flag: "ipvs", + kmods: []string{"foo", "bar", "baz"}, + ipsetVersion: ipvs.MinIPSetCheckVersion, iptablesVersion: "0.0.0", + kernelCompat: true, expected: proxyModeUserspace, }, - { // specify ipvs, feature gateway disabled, iptables version ok, kernel is not compatible + { // flag says ipvs, ipset version too low, iptables version too old, kernel not compatible, fallback on userspace mode flag: "ipvs", + kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, + ipsetVersion: "0.0", iptablesVersion: iptables.MinCheckVersion, kernelCompat: false, expected: proxyModeUserspace, @@ -117,131 +145,3 @@ func Test_getProxyMode(t *testing.T) { } } } - -// This is a coarse test, but it offers some modicum of confidence as the code is evolved. -func Test_getProxyModeEnableFeatureGateway(t *testing.T) { - // enable IPVS feature gateway - utilfeature.DefaultFeatureGate.Set("SupportIPVSProxyMode=true") - - var cases = []struct { - flag string - iptablesVersion string - ipsetVersion string - kernelCompat bool - iptablesError error - ipsetError error - mods []string - expected string - }{ - { // flag says userspace - flag: "userspace", - expected: proxyModeUserspace, - }, - { // flag says iptables, error detecting version - flag: "iptables", - iptablesError: fmt.Errorf("oops!"), - expected: proxyModeUserspace, - }, - { // flag says iptables, version too low - flag: "iptables", - iptablesVersion: "0.0.0", - expected: proxyModeUserspace, - }, - { // flag says iptables, version ok, kernel not compatible - flag: "iptables", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: false, - expected: proxyModeUserspace, - }, - { // flag says iptables, version ok, kernel is compatible - flag: "iptables", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: true, - expected: proxyModeIPTables, - }, - { // detect, error - flag: "", - iptablesError: fmt.Errorf("oops!"), - expected: proxyModeUserspace, - }, - { // detect, version too low - flag: "", - iptablesVersion: "0.0.0", - expected: proxyModeUserspace, - }, - { // detect, version ok, kernel not compatible - flag: "", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: false, - expected: proxyModeUserspace, - }, - { // detect, version ok, kernel is compatible - flag: "", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: true, - expected: proxyModeIPTables, - }, - { // detect, version ok, kernel is compatible - flag: "", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: true, - expected: proxyModeIPTables, - }, - { // flag says ipvs, ipset version ok, kernel modules installed - flag: "ipvs", - mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, - ipsetVersion: ipvs.MinIPSetCheckVersion, - expected: proxyModeIPVS, - }, - { // flag says ipvs, ipset version too low, fallback on iptables mode - flag: "ipvs", - mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, - ipsetVersion: "0.0", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: true, - expected: proxyModeIPTables, - }, - { // flag says ipvs, bad ipset version, fallback on iptables mode - flag: "ipvs", - mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, - ipsetVersion: "a.b.c", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: true, - expected: proxyModeIPTables, - }, - { // flag says ipvs, required kernel modules are not installed, fallback on iptables mode - flag: "ipvs", - mods: []string{"foo", "bar", "baz"}, - ipsetVersion: ipvs.MinIPSetCheckVersion, - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: true, - expected: proxyModeIPTables, - }, - { // flag says ipvs, required kernel modules are not installed, iptables version too old, fallback on userspace mode - flag: "ipvs", - mods: []string{"foo", "bar", "baz"}, - ipsetVersion: ipvs.MinIPSetCheckVersion, - iptablesVersion: "0.0.0", - kernelCompat: true, - expected: proxyModeUserspace, - }, - { // flag says ipvs, ipset version too low, iptables version too old, kernel not compatible, fallback on userspace mode - flag: "ipvs", - mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, - ipsetVersion: "0.0", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: false, - expected: proxyModeUserspace, - }, - } - for i, c := range cases { - versioner := &fakeIPTablesVersioner{c.iptablesVersion, c.iptablesError} - kcompater := &fakeKernelCompatTester{c.kernelCompat} - ipsetver := &fakeIPSetVersioner{c.ipsetVersion, c.ipsetError} - khandle := &fakeKernelHandler{c.mods} - r := getProxyMode(c.flag, versioner, khandle, ipsetver, kcompater) - if r != c.expected { - t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r) - } - } -} diff --git a/cmd/kube-proxy/app/server_test.go b/cmd/kube-proxy/app/server_test.go index 86dd84ba94d..1ee6fddedd4 100644 --- a/cmd/kube-proxy/app/server_test.go +++ b/cmd/kube-proxy/app/server_test.go @@ -29,7 +29,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/diff" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig" "k8s.io/kubernetes/pkg/util/configz" utilpointer "k8s.io/kubernetes/pkg/util/pointer" @@ -189,8 +188,6 @@ conntrack: min: 1 tcpCloseWaitTimeout: 10s tcpEstablishedTimeout: 20s -featureGates: - SupportIPVSProxyMode: true healthzBindAddress: "%s" hostnameOverride: "foo" iptables: @@ -307,7 +304,7 @@ nodePortAddresses: TCPCloseWaitTimeout: &metav1.Duration{Duration: 10 * time.Second}, TCPEstablishedTimeout: &metav1.Duration{Duration: 20 * time.Second}, }, - FeatureGates: map[string]bool{string(features.SupportIPVSProxyMode): true}, + FeatureGates: map[string]bool{}, HealthzBindAddress: tc.healthzBindAddress, HostnameOverride: "foo", IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ diff --git a/cmd/kube-scheduler/app/BUILD b/cmd/kube-scheduler/app/BUILD index d6de2aaef82..a98dc309146 100644 --- a/cmd/kube-scheduler/app/BUILD +++ b/cmd/kube-scheduler/app/BUILD @@ -21,6 +21,7 @@ go_library( "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/api/latest:go_default_library", "//pkg/scheduler/factory:go_default_library", + "//pkg/scheduler/metrics:go_default_library", "//pkg/util/configz:go_default_library", "//pkg/util/flag:go_default_library", "//pkg/version:go_default_library", diff --git a/cmd/kube-scheduler/app/server.go b/cmd/kube-scheduler/app/server.go index 11ace1a983f..ee776c89b6d 100644 --- a/cmd/kube-scheduler/app/server.go +++ b/cmd/kube-scheduler/app/server.go @@ -19,6 +19,7 @@ package app import ( "fmt" + "io" "io/ioutil" "net/http" "os" @@ -51,6 +52,7 @@ import ( schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" "k8s.io/kubernetes/pkg/scheduler/factory" + "k8s.io/kubernetes/pkg/scheduler/metrics" "k8s.io/kubernetes/pkg/util/configz" utilflag "k8s.io/kubernetes/pkg/util/flag" "k8s.io/kubernetes/pkg/version" @@ -221,11 +223,23 @@ func buildHandlerChain(handler http.Handler, authn authenticator.Request, authz return handler } +func installMetricHandler(pathRecorderMux *mux.PathRecorderMux) { + configz.InstallHandler(pathRecorderMux) + defaultMetricsHandler := prometheus.Handler().ServeHTTP + pathRecorderMux.HandleFunc("/metrics", func(w http.ResponseWriter, req *http.Request) { + if req.Method == "DELETE" { + metrics.Reset() + io.WriteString(w, "metrics reset\n") + return + } + defaultMetricsHandler(w, req) + }) +} + // newMetricsHandler builds a metrics server from the config. func newMetricsHandler(config *componentconfig.KubeSchedulerConfiguration) http.Handler { pathRecorderMux := mux.NewPathRecorderMux("kube-scheduler") - configz.InstallHandler(pathRecorderMux) - pathRecorderMux.Handle("/metrics", prometheus.Handler()) + installMetricHandler(pathRecorderMux) if config.EnableProfiling { routes.Profiling{}.Install(pathRecorderMux) if config.EnableContentionProfiling { @@ -242,8 +256,7 @@ func newHealthzHandler(config *componentconfig.KubeSchedulerConfiguration, separ pathRecorderMux := mux.NewPathRecorderMux("kube-scheduler") healthz.InstallHandler(pathRecorderMux) if !separateMetrics { - configz.InstallHandler(pathRecorderMux) - pathRecorderMux.Handle("/metrics", prometheus.Handler()) + installMetricHandler(pathRecorderMux) } if config.EnableProfiling { routes.Profiling{}.Install(pathRecorderMux) diff --git a/cmd/kubeadm/.import-restrictions b/cmd/kubeadm/.import-restrictions index 3b77e68e8e2..a8bcd175b70 100644 --- a/cmd/kubeadm/.import-restrictions +++ b/cmd/kubeadm/.import-restrictions @@ -118,7 +118,7 @@ "k8s.io/kubernetes/pkg/registry/rbac/validation", "k8s.io/kubernetes/pkg/scheduler/algorithm", "k8s.io/kubernetes/pkg/scheduler/api", - "k8s.io/kubernetes/pkg/scheduler/schedulercache", + "k8s.io/kubernetes/pkg/scheduler/cache", "k8s.io/kubernetes/pkg/scheduler/util", "k8s.io/kubernetes/pkg/security/apparmor", "k8s.io/kubernetes/pkg/serviceaccount", diff --git a/cmd/kubeadm/app/BUILD b/cmd/kubeadm/app/BUILD index 60714017fda..8fb20ee373c 100644 --- a/cmd/kubeadm/app/BUILD +++ b/cmd/kubeadm/app/BUILD @@ -13,6 +13,7 @@ go_library( "//cmd/kubeadm/app/cmd:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", ], ) @@ -43,6 +44,7 @@ filegroup( "//cmd/kubeadm/app/phases/kubeconfig:all-srcs", "//cmd/kubeadm/app/phases/kubelet:all-srcs", "//cmd/kubeadm/app/phases/markmaster:all-srcs", + "//cmd/kubeadm/app/phases/patchnode:all-srcs", "//cmd/kubeadm/app/phases/selfhosting:all-srcs", "//cmd/kubeadm/app/phases/upgrade:all-srcs", "//cmd/kubeadm/app/phases/uploadconfig:all-srcs", diff --git a/cmd/kubeadm/app/apis/kubeadm/BUILD b/cmd/kubeadm/app/apis/kubeadm/BUILD index d37bb68e4a7..866e8826f5a 100644 --- a/cmd/kubeadm/app/apis/kubeadm/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/BUILD @@ -3,11 +3,14 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( name = "go_default_library", srcs = [ + "bootstraptokenhelpers.go", + "bootstraptokenstring.go", "doc.go", "register.go", "types.go", @@ -22,6 +25,8 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", ], ) @@ -37,7 +42,6 @@ filegroup( srcs = [ ":package-srcs", "//cmd/kubeadm/app/apis/kubeadm/fuzzer:all-srcs", - "//cmd/kubeadm/app/apis/kubeadm/install:all-srcs", "//cmd/kubeadm/app/apis/kubeadm/scheme:all-srcs", "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:all-srcs", "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:all-srcs", @@ -45,3 +49,16 @@ filegroup( ], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = [ + "bootstraptokenhelpers_test.go", + "bootstraptokenstring_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + ], +) diff --git a/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers.go b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers.go new file mode 100644 index 00000000000..fc18701c616 --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers.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 kubeadm + +import ( + "fmt" + "sort" + "strings" + "time" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" +) + +// ToSecret converts the given BootstrapToken object to its Secret representation that +// may be submitted to the API Server in order to be stored. +func (bt *BootstrapToken) ToSecret() *v1.Secret { + return &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: bootstraputil.BootstrapTokenSecretName(bt.Token.ID), + Namespace: metav1.NamespaceSystem, + }, + Type: v1.SecretType(bootstrapapi.SecretTypeBootstrapToken), + Data: encodeTokenSecretData(bt, time.Now()), + } +} + +// encodeTokenSecretData takes the token discovery object and an optional duration and returns the .Data for the Secret +// now is passed in order to be able to used in unit testing +func encodeTokenSecretData(token *BootstrapToken, now time.Time) map[string][]byte { + data := map[string][]byte{ + bootstrapapi.BootstrapTokenIDKey: []byte(token.Token.ID), + bootstrapapi.BootstrapTokenSecretKey: []byte(token.Token.Secret), + } + + if len(token.Description) > 0 { + data[bootstrapapi.BootstrapTokenDescriptionKey] = []byte(token.Description) + } + + // If for some strange reason both token.TTL and token.Expires would be set + // (they are mutually exlusive in validation so this shouldn't be the case), + // token.Expires has higher priority, as can be seen in the logic here. + if token.Expires != nil { + // Format the expiration date accordingly + // TODO: This maybe should be a helper function in bootstraputil? + expirationString := token.Expires.Time.Format(time.RFC3339) + data[bootstrapapi.BootstrapTokenExpirationKey] = []byte(expirationString) + + } else if token.TTL != nil && token.TTL.Duration > 0 { + // Only if .Expires is unset, TTL might have an effect + // Get the current time, add the specified duration, and format it accordingly + expirationString := now.Add(token.TTL.Duration).Format(time.RFC3339) + data[bootstrapapi.BootstrapTokenExpirationKey] = []byte(expirationString) + } + + for _, usage := range token.Usages { + data[bootstrapapi.BootstrapTokenUsagePrefix+usage] = []byte("true") + } + + if len(token.Groups) > 0 { + data[bootstrapapi.BootstrapTokenExtraGroupsKey] = []byte(strings.Join(token.Groups, ",")) + } + return data +} + +// BootstrapTokenFromSecret returns a BootstrapToken object from the given Secret +func BootstrapTokenFromSecret(secret *v1.Secret) (*BootstrapToken, error) { + // Get the Token ID field from the Secret data + tokenID := getSecretString(secret, bootstrapapi.BootstrapTokenIDKey) + if len(tokenID) == 0 { + return nil, fmt.Errorf("Bootstrap Token Secret has no token-id data: %s", secret.Name) + } + + // Enforce the right naming convention + if secret.Name != bootstraputil.BootstrapTokenSecretName(tokenID) { + return nil, fmt.Errorf("bootstrap token name is not of the form '%s(token-id)'. Actual: %q. Expected: %q", + bootstrapapi.BootstrapTokenSecretPrefix, secret.Name, bootstraputil.BootstrapTokenSecretName(tokenID)) + } + + tokenSecret := getSecretString(secret, bootstrapapi.BootstrapTokenSecretKey) + if len(tokenSecret) == 0 { + return nil, fmt.Errorf("Bootstrap Token Secret has no token-secret data: %s", secret.Name) + } + + // Create the BootstrapTokenString object based on the ID and Secret + bts, err := NewBootstrapTokenStringFromIDAndSecret(tokenID, tokenSecret) + if err != nil { + return nil, fmt.Errorf("Bootstrap Token Secret is invalid and couldn't be parsed: %v", err) + } + + // Get the description (if any) from the Secret + description := getSecretString(secret, bootstrapapi.BootstrapTokenDescriptionKey) + + // Expiration time is optional, if not specified this implies the token + // never expires. + secretExpiration := getSecretString(secret, bootstrapapi.BootstrapTokenExpirationKey) + var expires *metav1.Time + if len(secretExpiration) > 0 { + expTime, err := time.Parse(time.RFC3339, secretExpiration) + if err != nil { + return nil, fmt.Errorf("can't parse expiration time of bootstrap token %q: %v", secret.Name, err) + } + expires = &metav1.Time{Time: expTime} + } + + // Build an usages string slice from the Secret data + var usages []string + for k, v := range secret.Data { + // Skip all fields that don't include this prefix + if !strings.HasPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix) { + continue + } + // Skip those that don't have this usage set to true + if string(v) != "true" { + continue + } + usages = append(usages, strings.TrimPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix)) + } + // Only sort the slice if defined + if usages != nil { + sort.Strings(usages) + } + + // Get the extra groups information from the Secret + // It's done this way to make .Groups be nil in case there is no items, rather than an + // empty slice or an empty slice with a "" string only + var groups []string + groupsString := getSecretString(secret, bootstrapapi.BootstrapTokenExtraGroupsKey) + g := strings.Split(groupsString, ",") + if len(g) > 0 && len(g[0]) > 0 { + groups = g + } + + return &BootstrapToken{ + Token: bts, + Description: description, + Expires: expires, + Usages: usages, + Groups: groups, + }, nil +} + +// getSecretString returns the string value for the given key in the specified Secret +func getSecretString(secret *v1.Secret, key string) string { + if secret.Data == nil { + return "" + } + if val, ok := secret.Data[key]; ok { + return string(val) + } + return "" +} diff --git a/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go new file mode 100644 index 00000000000..153d08e7c33 --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go @@ -0,0 +1,473 @@ +/* +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 kubeadm + +import ( + "encoding/json" + "reflect" + "testing" + "time" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// This timestamp is used as the reference value when computing expiration dates based on TTLs in these unit tests +var refTime = time.Date(1970, time.January, 1, 1, 1, 1, 0, time.UTC) + +func TestToSecret(t *testing.T) { + + var tests = []struct { + bt *BootstrapToken + secret *v1.Secret + }{ + { + &BootstrapToken{ // all together + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + Expires: &metav1.Time{ + Time: refTime, + }, + Usages: []string{"signing", "authentication"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bootstrap-token-abcdef", + Namespace: "kube-system", + }, + Type: v1.SecretType("bootstrap.kubernetes.io/token"), + Data: map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "description": []byte("foo"), + "expiration": []byte(refTime.Format(time.RFC3339)), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + "auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"), + }, + }, + }, + } + 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, + ) + } + } +} + +func TestBootstrapTokenToSecretRoundtrip(t *testing.T) { + var tests = []struct { + bt *BootstrapToken + }{ + { + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + Expires: &metav1.Time{ + Time: refTime, + }, + Usages: []string{"authentication", "signing"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + }, + } + 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, + ) + } + } +} + +func TestEncodeTokenSecretData(t *testing.T) { + var tests = []struct { + bt *BootstrapToken + data map[string][]byte + }{ + { + &BootstrapToken{ // the minimum amount of information needed to be specified + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + }, + }, + { + &BootstrapToken{ // adds description + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "description": []byte("foo"), + }, + }, + { + &BootstrapToken{ // adds ttl + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + TTL: &metav1.Duration{ + Duration: mustParseDuration("2h", t), + }, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "expiration": []byte(refTime.Add(mustParseDuration("2h", t)).Format(time.RFC3339)), + }, + }, + { + &BootstrapToken{ // adds expiration + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Expires: &metav1.Time{ + Time: refTime, + }, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "expiration": []byte(refTime.Format(time.RFC3339)), + }, + }, + { + &BootstrapToken{ // adds ttl and expiration, should favor expiration + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + TTL: &metav1.Duration{ + Duration: mustParseDuration("2h", t), + }, + Expires: &metav1.Time{ + Time: refTime, + }, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "expiration": []byte(refTime.Format(time.RFC3339)), + }, + }, + { + &BootstrapToken{ // adds usages + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Usages: []string{"authentication", "signing"}, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + }, + }, + { + &BootstrapToken{ // adds groups + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"), + }, + }, + { + &BootstrapToken{ // all together + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + TTL: &metav1.Duration{ + Duration: mustParseDuration("2h", t), + }, + Expires: &metav1.Time{ + Time: refTime, + }, + Usages: []string{"authentication", "signing"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "description": []byte("foo"), + "expiration": []byte(refTime.Format(time.RFC3339)), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + "auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"), + }, + }, + } + 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, + ) + } + } +} + +func mustParseDuration(durationStr string, t *testing.T) time.Duration { + d, err := time.ParseDuration(durationStr) + if err != nil { + t.Fatalf("couldn't parse duration %q: %v", durationStr, err) + } + return d +} + +func TestBootstrapTokenFromSecret(t *testing.T) { + var tests = []struct { + name string + data map[string][]byte + bt *BootstrapToken + expectedError bool + }{ + { // minimum information + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + }, + false, + }, + { // invalid token id + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdeF"), + "token-secret": []byte("abcdef0123456789"), + }, + nil, + true, + }, + { // invalid secret naming + "foo", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + }, + nil, + true, + }, + { // invalid token secret + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("ABCDEF0123456789"), + }, + nil, + true, + }, + { // adds description + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "description": []byte("foo"), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + }, + false, + }, + { // adds expiration + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "expiration": []byte(refTime.Format(time.RFC3339)), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Expires: &metav1.Time{ + Time: refTime, + }, + }, + false, + }, + { // invalid expiration + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "expiration": []byte("invalid date"), + }, + nil, + true, + }, + { // adds usages + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Usages: []string{"authentication", "signing"}, + }, + false, + }, + { // should ignore usages that aren't set to true + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + "usage-bootstrap-foo": []byte("false"), + "usage-bootstrap-bar": []byte(""), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Usages: []string{"authentication", "signing"}, + }, + false, + }, + { // adds groups + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + false, + }, + { // all fields set + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "description": []byte("foo"), + "expiration": []byte(refTime.Format(time.RFC3339)), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + "auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + Expires: &metav1.Time{ + Time: refTime, + }, + Usages: []string{"authentication", "signing"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + false, + }, + } + 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.Errorf( + "failed BootstrapTokenFromSecret\n\texpected: %s\n\t actual: %s", + jsonMarshal(rt.bt), + jsonMarshal(actual), + ) + } + } + } +} + +func jsonMarshal(bt *BootstrapToken) string { + b, _ := json.Marshal(*bt) + return string(b) +} + +func TestGetSecretString(t *testing.T) { + var tests = []struct { + secret *v1.Secret + key string + expectedVal string + }{ + { + secret: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Data: map[string][]byte{ + "foo": []byte("bar"), + }, + }, + key: "foo", + expectedVal: "bar", + }, + { + secret: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Data: map[string][]byte{ + "foo": []byte("bar"), + }, + }, + key: "baz", + expectedVal: "", + }, + { + secret: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + }, + key: "foo", + expectedVal: "", + }, + } + 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, + ) + } + } +} diff --git a/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring.go b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring.go new file mode 100644 index 00000000000..440c2534a64 --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring.go @@ -0,0 +1,90 @@ +/* +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 kubeadm holds the internal kubeadm API types +// Note: This file should be kept in sync with the similar one for the external API +// TODO: The BootstrapTokenString object should move out to either k8s.io/client-go or k8s.io/api in the future +// (probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now. +package kubeadm + +import ( + "fmt" + "strings" + + bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" +) + +// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used +// for both validation of the practically of the API server from a joining node's point +// of view and as an authentication method for the node in the bootstrap phase of +// "kubeadm join". This token is and should be short-lived +type BootstrapTokenString struct { + ID string + Secret string +} + +// MarshalJSON implements the json.Marshaler interface. +func (bts BootstrapTokenString) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, bts.String())), nil +} + +// UnmarshalJSON implements the json.Unmarshaller interface. +func (bts *BootstrapTokenString) UnmarshalJSON(b []byte) error { + // If the token is represented as "", just return quickly without an error + if len(b) == 0 { + return nil + } + + // Remove unnecessary " characters coming from the JSON parser + token := strings.Replace(string(b), `"`, ``, -1) + // Convert the string Token to a BootstrapTokenString object + newbts, err := NewBootstrapTokenString(token) + if err != nil { + return err + } + bts.ID = newbts.ID + bts.Secret = newbts.Secret + return nil +} + +// String returns the string representation of the BootstrapTokenString +func (bts BootstrapTokenString) String() string { + if len(bts.ID) > 0 && len(bts.Secret) > 0 { + return bootstraputil.TokenFromIDAndSecret(bts.ID, bts.Secret) + } + return "" +} + +// NewBootstrapTokenString converts the given Bootstrap Token as a string +// to the BootstrapTokenString object used for serialization/deserialization +// and internal usage. It also automatically validates that the given token +// is of the right format +func NewBootstrapTokenString(token string) (*BootstrapTokenString, error) { + substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(token) + // TODO: Add a constant for the 3 value here, and explain better why it's needed (other than because how the regexp parsin works) + if len(substrs) != 3 { + return nil, fmt.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern) + } + + return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil +} + +// NewBootstrapTokenStringFromIDAndSecret is a wrapper around NewBootstrapTokenString +// that allows the caller to specify the ID and Secret separately +func NewBootstrapTokenStringFromIDAndSecret(id, secret string) (*BootstrapTokenString, error) { + return NewBootstrapTokenString(bootstraputil.TokenFromIDAndSecret(id, secret)) +} diff --git a/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.go b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.go new file mode 100644 index 00000000000..8a389f83ec1 --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.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. +*/ + +package kubeadm + +import ( + "encoding/json" + "fmt" + "reflect" + "testing" +) + +func TestMarshalJSON(t *testing.T) { + var tests = []struct { + bts BootstrapTokenString + expected string + }{ + {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`}, + {BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`}, + {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), + ) + } + } +} + +func TestUnmarshalJSON(t *testing.T) { + var tests = []struct { + input string + bts *BootstrapTokenString + expectedError bool + }{ + {`"f.s"`, &BootstrapTokenString{}, true}, + {`"abcdef."`, &BootstrapTokenString{}, true}, + {`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true}, + {`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, + {`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, + {`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true}, + {`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false}, + {`"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, + ) + } + } +} + +func TestJSONRoundtrip(t *testing.T) { + var tests = []struct { + input string + bts *BootstrapTokenString + }{ + {`"abcdef.abcdef0123456789"`, nil}, + {"", &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) + } + } +} + +func roundtrip(input string, bts *BootstrapTokenString) error { + var b []byte + var err error + newbts := &BootstrapTokenString{} + // If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string + if len(input) > 0 { + if err := json.Unmarshal([]byte(input), newbts); err != nil { + return fmt.Errorf("expected no unmarshal error, got error: %v", err) + } + if b, err = json.Marshal(newbts); err != nil { + return fmt.Errorf("expected no marshal error, got error: %v", err) + } + if input != string(b) { + return fmt.Errorf( + "expected token: %s\n\t actual: %s", + input, + string(b), + ) + } + } else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object + if b, err = json.Marshal(bts); err != nil { + return fmt.Errorf("expected no marshal error, got error: %v", err) + } + if err := json.Unmarshal(b, newbts); err != nil { + return fmt.Errorf("expected no unmarshal error, got error: %v", err) + } + if !reflect.DeepEqual(bts, newbts) { + return fmt.Errorf( + "expected object: %v\n\t actual: %v", + bts, + newbts, + ) + } + } + return nil +} + +func TestTokenFromIDAndSecret(t *testing.T) { + var tests = []struct { + bts BootstrapTokenString + expected string + }{ + {BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"}, + {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"}, + {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, + ) + } + } +} + +func TestNewBootstrapTokenString(t *testing.T) { + var tests = []struct { + token string + expectedError bool + bts *BootstrapTokenString + }{ + {token: "", expectedError: true, bts: nil}, + {token: ".", expectedError: true, bts: nil}, + {token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size + {token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {token: "123456.", expectedError: true, bts: nil}, // invalid parcel size + {token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation + {token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation + {token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id + {token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret + {token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character + {token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character + {token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, + {token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, + {token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + {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, + ) + } + } +} + +func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) { + var tests = []struct { + id, secret string + expectedError bool + bts *BootstrapTokenString + }{ + {id: "", secret: "", expectedError: true, bts: nil}, + {id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size + {id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size + {id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id + {id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret + {id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character + {id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character + {id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, + {id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, + {id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + {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, + ) + } + } +} diff --git a/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD b/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD index cea19499314..f78847d71b9 100644 --- a/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD @@ -16,6 +16,7 @@ go_library( "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", "//pkg/util/pointer:go_default_library", "//vendor/github.com/google/gofuzz:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", ], diff --git a/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go b/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go index 2ede4cb22ba..4478c92d1e7 100644 --- a/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go +++ b/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go @@ -21,6 +21,7 @@ import ( fuzz "github.com/google/gofuzz" + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" @@ -42,11 +43,17 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { obj.CertificatesDir = "foo" obj.APIServerCertSANs = []string{"foo"} - obj.Token = "foo" - obj.CRISocket = "foo" - obj.TokenTTL = &metav1.Duration{Duration: 1 * time.Hour} - obj.TokenUsages = []string{"foo"} - obj.TokenGroups = []string{"foo"} + obj.BootstrapTokens = []kubeadm.BootstrapToken{ + { + Token: &kubeadm.BootstrapTokenString{ + ID: "abcdef", + Secret: "abcdef0123456789", + }, + TTL: &metav1.Duration{Duration: 1 * time.Hour}, + Usages: []string{"foo"}, + Groups: []string{"foo"}, + }, + } obj.ImageRepository = "foo" obj.CIImageRepository = "" obj.UnifiedControlPlaneImage = "foo" @@ -59,6 +66,9 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { MountPath: "foo", Writable: false, }} + // Note: We don't set values here for obj.Etcd.External, as these are mutually exlusive. + // And to make sure the fuzzer doesn't set a random value for obj.Etcd.External, we let + // kubeadmapi.Etcd implement fuzz.Interface (we handle that ourselves) obj.Etcd.Local = &kubeadm.LocalEtcd{ Image: "foo", DataDir: "foo", @@ -66,9 +76,11 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { PeerCertSANs: []string{"foo"}, ExtraArgs: map[string]string{"foo": "foo"}, } - // Note: We don't set values here for obj.Etcd.External, as these are mutually exlusive. - // And to make sure the fuzzer doesn't set a random value for obj.Etcd.External, we let - // kubeadmapi.Etcd implement fuzz.Interface (we handle that ourselves) + obj.NodeRegistration = kubeadm.NodeRegistrationOptions{ + CRISocket: "foo", + Name: "foo", + Taints: []v1.Taint{}, + } obj.KubeletConfiguration = kubeadm.KubeletConfiguration{ BaseConfig: &kubeletconfigv1beta1.KubeletConfiguration{ StaticPodPath: "foo", @@ -139,8 +151,11 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { obj.DiscoveryTimeout = &metav1.Duration{Duration: 1} obj.TLSBootstrapToken = "foo" obj.Token = "foo" - obj.CRISocket = "foo" obj.ClusterName = "foo" + obj.NodeRegistration = kubeadm.NodeRegistrationOptions{ + CRISocket: "foo", + Name: "foo", + } }, } } diff --git a/cmd/kubeadm/app/apis/kubeadm/install/BUILD b/cmd/kubeadm/app/apis/kubeadm/install/BUILD deleted file mode 100644 index 7e76248ad95..00000000000 --- a/cmd/kubeadm/app/apis/kubeadm/install/BUILD +++ /dev/null @@ -1,14 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/cmd/kubeadm/app/apis/kubeadm/types.go b/cmd/kubeadm/app/apis/kubeadm/types.go index ea062c62184..4391cfe6447 100644 --- a/cmd/kubeadm/app/apis/kubeadm/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/types.go @@ -32,6 +32,21 @@ import ( type MasterConfiguration struct { metav1.TypeMeta + // `kubeadm init`-only information. These fields are solely used the first time `kubeadm init` runs. + // After that, the information in the fields ARE NOT uploaded to the `kubeadm-config` ConfigMap + // that is used by `kubeadm upgrade` for instance. + + // BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create. + // This information IS NOT uploaded to the kubeadm cluster configmap, partly because of its sensitive nature + BootstrapTokens []BootstrapToken + + // NodeRegistration holds fields that relate to registering the new master node to the cluster + NodeRegistration NodeRegistrationOptions + + // Cluster-wide configuration + // TODO: Move these fields under some kind of ClusterConfiguration or similar struct that describes + // one cluster. Eventually we want this kind of spec to align well with the Cluster API spec. + // API holds configuration for the k8s apiserver. API API // KubeProxy holds configuration for the k8s service proxy. @@ -44,26 +59,6 @@ type MasterConfiguration struct { Networking Networking // KubernetesVersion is the target version of the control plane. KubernetesVersion string - // NodeName is the name of the node that will host the k8s control plane. - // Defaults to the hostname if not provided. - NodeName string - // NoTaintMaster will, if set, suppress the tainting of the - // master node allowing workloads to be run on it (e.g. in - // single node configurations). - NoTaintMaster bool - - // Token is used for establishing bidirectional trust between nodes and masters. - // Used for joining nodes in the cluster. - Token string - // TokenTTL defines the ttl for Token. Defaults to 24h. - TokenTTL *metav1.Duration - // TokenUsages describes the ways in which this token can be used. - TokenUsages []string - // Extra groups that this token will authenticate as when used for authentication - TokenGroups []string - - // CRISocket is used to retrieve container runtime info. - CRISocket string // APIServerExtraArgs is a set of extra flags to pass to the API Server or override // default ones in form of =. @@ -138,16 +133,26 @@ type API struct { BindPort int32 } -// TokenDiscovery contains elements needed for token discovery. -type TokenDiscovery struct { - // ID is the first part of a bootstrap token. Considered public information. - // It is used when referring to a token without leaking the secret part. - ID string - // Secret is the second part of a bootstrap token. Should only be shared - // with trusted parties. - Secret string - // TODO: Seems unused. Remove? - // Addresses []string +// NodeRegistrationOptions holds fields that relate to registering a new master or node to the cluster, either via "kubeadm init" or "kubeadm join" +type NodeRegistrationOptions struct { + + // Name is the `.Metadata.Name` field of the Node API object that will be created in this `kubeadm init` or `kubeadm joiń` operation. + // This field is also used in the CommonName field of the kubelet's client certificate to the API server. + // Defaults to the hostname of the node if not provided. + Name string + + // CRISocket is used to retrieve container runtime info. This information will be annotated to the Node API object, for later re-use + CRISocket string + + // Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the `kubeadm init` process + // it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your master node, set this field to an + // empty slice, i.e. `taints: {}` in the YAML file. This field is solely used for Node registration. + Taints []v1.Taint + + // KubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file + // kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap + // Flags have higher higher priority when parsing. These values are local and specific to the node kubeadm is executing on. + KubeletExtraArgs map[string]string } // Networking contains elements describing cluster's networking configuration. @@ -160,6 +165,30 @@ type Networking struct { DNSDomain string } +// BootstrapToken describes one bootstrap token, stored as a Secret in the cluster +// TODO: The BootstrapToken object should move out to either k8s.io/client-go or k8s.io/api in the future +// (probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now. +type BootstrapToken struct { + // Token is used for establishing bidirectional trust between nodes and masters. + // Used for joining nodes in the cluster. + Token *BootstrapTokenString + // Description sets a human-friendly message why this token exists and what it's used + // for, so other administrators can know its purpose. + Description string + // TTL defines the time to live for this token. Defaults to 24h. + // Expires and TTL are mutually exclusive. + TTL *metav1.Duration + // Expires specifies the timestamp when this token expires. Defaults to being set + // dynamically at runtime based on the TTL. Expires and TTL are mutually exclusive. + Expires *metav1.Time + // Usages describes the ways in which this token can be used. Can by default be used + // for establishing bidirectional trust, but that can be changed here. + Usages []string + // Groups specifies the extra groups that this token will authenticate as when/if + // used for authentication + Groups []string +} + // Etcd contains elements describing Etcd configuration. type Etcd struct { @@ -223,6 +252,9 @@ type ExternalEtcd struct { type NodeConfiguration struct { metav1.TypeMeta + // NodeRegistration holds fields that relate to registering the new master node to the cluster + NodeRegistration NodeRegistrationOptions + // CACertPath is the path to the SSL certificate authority used to // secure comunications between node and master. // Defaults to "/etc/kubernetes/pki/ca.crt". @@ -239,16 +271,11 @@ type NodeConfiguration struct { DiscoveryTokenAPIServers []string // DiscoveryTimeout modifies the discovery timeout DiscoveryTimeout *metav1.Duration - // NodeName is the name of the node to join the cluster. Defaults - // to the name of the host. - NodeName string // TLSBootstrapToken is a token used for TLS bootstrapping. // Defaults to Token. TLSBootstrapToken string // Token is used for both discovery and TLS bootstrapping. Token string - // CRISocket is used to retrieve container runtime info. - CRISocket string // The cluster name ClusterName string @@ -332,13 +359,13 @@ type CommonConfiguration interface { // GetCRISocket will return the CRISocket that is defined for the MasterConfiguration. // This is used internally to deduplicate the kubeadm preflight checks. func (cfg *MasterConfiguration) GetCRISocket() string { - return cfg.CRISocket + return cfg.NodeRegistration.CRISocket } // GetNodeName will return the NodeName that is defined for the MasterConfiguration. // This is used internally to deduplicate the kubeadm preflight checks. func (cfg *MasterConfiguration) GetNodeName() string { - return cfg.NodeName + return cfg.NodeRegistration.Name } // GetKubernetesVersion will return the KubernetesVersion that is defined for the MasterConfiguration. @@ -350,13 +377,13 @@ func (cfg *MasterConfiguration) GetKubernetesVersion() string { // GetCRISocket will return the CRISocket that is defined for the NodeConfiguration. // This is used internally to deduplicate the kubeadm preflight checks. func (cfg *NodeConfiguration) GetCRISocket() string { - return cfg.CRISocket + return cfg.NodeRegistration.CRISocket } // GetNodeName will return the NodeName that is defined for the NodeConfiguration. // This is used internally to deduplicate the kubeadm preflight checks. func (cfg *NodeConfiguration) GetNodeName() string { - return cfg.NodeName + return cfg.NodeRegistration.Name } // GetKubernetesVersion will return an empty string since KubernetesVersion is not a diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD index 7b6140cf55c..8315ddde7d4 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD @@ -58,7 +58,6 @@ go_library( "//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", "//pkg/util/pointer:go_default_library", - "//vendor/github.com/json-iterator/go:go_default_library", "//vendor/github.com/ugorji/go/codec:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -91,3 +90,13 @@ go_test( embed = [":go_default_library"], deps = ["//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library"], ) + +go_test( + name = "go_default_xtest", + srcs = ["conversion_test.go"], + deps = [ + ":go_default_library", + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + ], +) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion.go index d5492c3333a..3bbad16e79d 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion.go @@ -17,18 +17,24 @@ limitations under the License. package v1alpha1 import ( + "fmt" "reflect" "strings" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) func addConversionFuncs(scheme *runtime.Scheme) error { // Add non-generated conversion functions err := scheme.AddConversionFuncs( Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration, + Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration, + Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration, + Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration, Convert_v1alpha1_Etcd_To_kubeadm_Etcd, Convert_kubeadm_Etcd_To_v1alpha1_Etcd, ) @@ -39,6 +45,8 @@ func addConversionFuncs(scheme *runtime.Scheme) error { return nil } +// Upgrades below + func Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error { if err := autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in, out, s); err != nil { return err @@ -46,12 +54,29 @@ func Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in *Mas UpgradeCloudProvider(in, out) UpgradeAuthorizationModes(in, out) + UpgradeNodeRegistrationOptionsForMaster(in, out) + if err := UpgradeBootstrapTokens(in, out); err != nil { + return err + } // We don't support migrating information from the .PrivilegedPods field which was removed in v1alpha2 // We don't support migrating information from the .ImagePullPolicy field which was removed in v1alpha2 return nil } +func Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error { + if err := autoConvert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in, out, s); err != nil { + return err + } + + // .NodeName has moved to .NodeRegistration.Name + out.NodeRegistration.Name = in.NodeName + // .CRISocket has moved to .NodeRegistration.CRISocket + out.NodeRegistration.CRISocket = in.CRISocket + + return nil +} + func Convert_v1alpha1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error { if err := autoConvert_v1alpha1_Etcd_To_kubeadm_Etcd(in, out, s); err != nil { return err @@ -79,8 +104,110 @@ func Convert_v1alpha1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conver return nil } -// no-op, as we don't support converting from newer API to old alpha API +// UpgradeCloudProvider handles the removal of .CloudProvider as smoothly as possible +func UpgradeCloudProvider(in *MasterConfiguration, out *kubeadm.MasterConfiguration) { + if len(in.CloudProvider) != 0 { + if out.APIServerExtraArgs == nil { + out.APIServerExtraArgs = map[string]string{} + } + if out.ControllerManagerExtraArgs == nil { + out.ControllerManagerExtraArgs = map[string]string{} + } + if out.NodeRegistration.KubeletExtraArgs == nil { + out.NodeRegistration.KubeletExtraArgs = map[string]string{} + } + + out.APIServerExtraArgs["cloud-provider"] = in.CloudProvider + out.ControllerManagerExtraArgs["cloud-provider"] = in.CloudProvider + out.NodeRegistration.KubeletExtraArgs["cloud-provider"] = in.CloudProvider + } +} + +func UpgradeAuthorizationModes(in *MasterConfiguration, out *kubeadm.MasterConfiguration) { + // If .AuthorizationModes was set to something else than the default, preserve the information via extraargs + if !reflect.DeepEqual(in.AuthorizationModes, strings.Split(DefaultAuthorizationModes, ",")) { + + if out.APIServerExtraArgs == nil { + out.APIServerExtraArgs = map[string]string{} + } + out.APIServerExtraArgs["authorization-mode"] = strings.Join(in.AuthorizationModes, ",") + } +} + +func UpgradeNodeRegistrationOptionsForMaster(in *MasterConfiguration, out *kubeadm.MasterConfiguration) { + // .NodeName has moved to .NodeRegistration.Name + out.NodeRegistration.Name = in.NodeName + + // .CRISocket has moved to .NodeRegistration.CRISocket + out.NodeRegistration.CRISocket = in.CRISocket + + // Transfer the information from .NoTaintMaster to the new layout + if in.NoTaintMaster { + out.NodeRegistration.Taints = []v1.Taint{} + } else { + out.NodeRegistration.Taints = []v1.Taint{constants.MasterTaint} + } +} + +// UpgradeBootstrapTokens should create at least one empty bootstrap token in the out config. +func UpgradeBootstrapTokens(in *MasterConfiguration, out *kubeadm.MasterConfiguration) error { + bts, err := kubeadm.NewBootstrapTokenString(in.Token) + // Ignore the error if the incoming token was empty. + if err != nil && in.Token != "" { + return fmt.Errorf("can't parse .Token, and hence can't convert v1alpha1 API to a newer version: %v", err) + } + + out.BootstrapTokens = []kubeadm.BootstrapToken{ + { + Token: bts, + TTL: in.TokenTTL, + Usages: in.TokenUsages, + Groups: in.TokenGroups, + }, + } + return nil +} + +// Downgrades below + +// This downgrade path IS NOT SUPPORTED. This is just here for roundtripping purposes at the moment. +func Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error { + if err := autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in, out, s); err != nil { + return err + } + + // Converting from newer API version to an older API version isn't supported. This is here only for the roundtrip tests meanwhile. + out.NodeName = in.NodeRegistration.Name + out.CRISocket = in.NodeRegistration.CRISocket + out.NoTaintMaster = in.NodeRegistration.Taints != nil && len(in.NodeRegistration.Taints) == 0 + + if len(in.BootstrapTokens) > 0 { + out.Token = in.BootstrapTokens[0].Token.String() + out.TokenTTL = in.BootstrapTokens[0].TTL + out.TokenUsages = in.BootstrapTokens[0].Usages + out.TokenGroups = in.BootstrapTokens[0].Groups + } + + return nil +} + +// This downgrade path IS NOT SUPPORTED. This is just here for roundtripping purposes at the moment. +func Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error { + if err := autoConvert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in, out, s); err != nil { + return err + } + + // Converting from newer API version to an older API version isn't supported. This is here only for the roundtrip tests meanwhile. + out.NodeName = in.NodeRegistration.Name + out.CRISocket = in.NodeRegistration.CRISocket + return nil +} + +// This downgrade path IS NOT SUPPORTED. This is just here for roundtripping purposes at the moment. func Convert_kubeadm_Etcd_To_v1alpha1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error { + if err := autoConvert_kubeadm_Etcd_To_v1alpha1_Etcd(in, out, s); err != nil { + return err + } if in.External != nil { out.Endpoints = in.External.Endpoints @@ -97,29 +224,3 @@ func Convert_kubeadm_Etcd_To_v1alpha1_Etcd(in *kubeadm.Etcd, out *Etcd, s conver return nil } - -// UpgradeCloudProvider handles the removal of .CloudProvider as smoothly as possible -func UpgradeCloudProvider(in *MasterConfiguration, out *kubeadm.MasterConfiguration) { - if len(in.CloudProvider) != 0 { - if out.APIServerExtraArgs == nil { - out.APIServerExtraArgs = map[string]string{} - } - if out.ControllerManagerExtraArgs == nil { - out.ControllerManagerExtraArgs = map[string]string{} - } - - out.APIServerExtraArgs["cloud-provider"] = in.CloudProvider - out.ControllerManagerExtraArgs["cloud-provider"] = in.CloudProvider - } -} - -func UpgradeAuthorizationModes(in *MasterConfiguration, out *kubeadm.MasterConfiguration) { - // If .AuthorizationModes was set to something else than the default, preserve the information via extraargs - if !reflect.DeepEqual(in.AuthorizationModes, strings.Split(DefaultAuthorizationModes, ",")) { - - if out.APIServerExtraArgs == nil { - out.APIServerExtraArgs = map[string]string{} - } - out.APIServerExtraArgs["authorization-mode"] = strings.Join(in.AuthorizationModes, ",") - } -} diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion_test.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion_test.go new file mode 100644 index 00000000000..52fcc3db807 --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion_test.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 v1alpha1_test + +import ( + "reflect" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" +) + +func TestUpgradeBootstrapTokens(t *testing.T) { + testcases := []struct { + name string + in *v1alpha1.MasterConfiguration + expectedOut *kubeadm.MasterConfiguration + expectError bool + }{ + { + name: "empty configs should create at least one token", + in: &v1alpha1.MasterConfiguration{}, + expectedOut: &kubeadm.MasterConfiguration{ + BootstrapTokens: []kubeadm.BootstrapToken{ + { + Token: nil, + }, + }, + }, + expectError: false, + }, + { + name: "fail at parsing incoming token", + in: &v1alpha1.MasterConfiguration{ + Token: "some fake token", + }, + expectError: true, + }, + { + name: "input has values", + in: &v1alpha1.MasterConfiguration{ + Token: "abcdef.abcdefghijklmnop", + TokenTTL: &metav1.Duration{ + Duration: time.Duration(10 * time.Hour), + }, + TokenUsages: []string{"action"}, + TokenGroups: []string{"group", "group2"}, + }, + expectedOut: &kubeadm.MasterConfiguration{ + BootstrapTokens: []kubeadm.BootstrapToken{ + { + Token: &kubeadm.BootstrapTokenString{ + ID: "abcdef", + Secret: "abcdefghijklmnop", + }, + TTL: &metav1.Duration{ + Duration: time.Duration(10 * time.Hour), + }, + Usages: []string{"action"}, + Groups: []string{"group", "group2"}, + }, + }, + }, + expectError: false, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + out := &kubeadm.MasterConfiguration{} + err := v1alpha1.UpgradeBootstrapTokens(tc.in, out) + + if tc.expectError { + if err == nil { + t.Fatal("expected an error but did not get one.") + } + // do not continue if we got an expected error + return + } + + if !reflect.DeepEqual(out.BootstrapTokens, tc.expectedOut.BootstrapTokens) { + t.Fatalf("\nexpected: %v\ngot: %v", tc.expectedOut.BootstrapTokens, out.BootstrapTokens) + } + }) + } + +} diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go index c0439cbc07a..bb30de78c39 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go @@ -39,7 +39,7 @@ const ( // DefaultClusterDNSIP defines default DNS IP DefaultClusterDNSIP = "10.96.0.10" // DefaultKubernetesVersion defines default kubernetes version - DefaultKubernetesVersion = "stable-1.10" + DefaultKubernetesVersion = "stable-1.11" // DefaultAPIBindPort defines default API port DefaultAPIBindPort = 6443 // DefaultAuthorizationModes defines default authorization modes diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade.go index 5e94ff558da..7c3dd133feb 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade.go @@ -23,7 +23,6 @@ import ( "strconv" "strings" - jsoniter "github.com/json-iterator/go" "github.com/ugorji/go/codec" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -31,8 +30,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer" ) -var json = jsoniter.ConfigCompatibleWithStandardLibrary - type configMutationFunc func(map[string]interface{}) error // These migrations are a stop-gap until we get a properly-versioned configuration file for MasterConfiguration. diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.conversion.go index e602d3aaafb..66fa3997405 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.conversion.go @@ -58,8 +58,6 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_kubeadm_Networking_To_v1alpha1_Networking, Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration, Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration, - Convert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery, - Convert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery, ) } @@ -217,15 +215,15 @@ func autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in } out.KubernetesVersion = in.KubernetesVersion // WARNING: in.CloudProvider requires manual conversion: does not exist in peer-type - out.NodeName = in.NodeName + // WARNING: in.NodeName requires manual conversion: does not exist in peer-type // WARNING: in.AuthorizationModes requires manual conversion: does not exist in peer-type - out.NoTaintMaster = in.NoTaintMaster + // WARNING: in.NoTaintMaster requires manual conversion: does not exist in peer-type // WARNING: in.PrivilegedPods requires manual conversion: does not exist in peer-type - out.Token = in.Token - out.TokenTTL = (*meta_v1.Duration)(unsafe.Pointer(in.TokenTTL)) - out.TokenUsages = *(*[]string)(unsafe.Pointer(&in.TokenUsages)) - out.TokenGroups = *(*[]string)(unsafe.Pointer(&in.TokenGroups)) - out.CRISocket = in.CRISocket + // WARNING: in.Token requires manual conversion: does not exist in peer-type + // WARNING: in.TokenTTL requires manual conversion: does not exist in peer-type + // WARNING: in.TokenUsages requires manual conversion: does not exist in peer-type + // WARNING: in.TokenGroups requires manual conversion: does not exist in peer-type + // WARNING: in.CRISocket requires manual conversion: does not exist in peer-type out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs)) out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs)) out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs)) @@ -246,6 +244,8 @@ func autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in } func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error { + // WARNING: in.BootstrapTokens requires manual conversion: does not exist in peer-type + // WARNING: in.NodeRegistration requires manual conversion: does not exist in peer-type if err := Convert_kubeadm_API_To_v1alpha1_API(&in.API, &out.API, s); err != nil { return err } @@ -262,13 +262,6 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in return err } out.KubernetesVersion = in.KubernetesVersion - out.NodeName = in.NodeName - out.NoTaintMaster = in.NoTaintMaster - out.Token = in.Token - out.TokenTTL = (*meta_v1.Duration)(unsafe.Pointer(in.TokenTTL)) - out.TokenUsages = *(*[]string)(unsafe.Pointer(&in.TokenUsages)) - out.TokenGroups = *(*[]string)(unsafe.Pointer(&in.TokenGroups)) - out.CRISocket = in.CRISocket out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs)) out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs)) out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs)) @@ -288,11 +281,6 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in return nil } -// Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration is an autogenerated conversion function. -func Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error { - return autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in, out, s) -} - func autoConvert_v1alpha1_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error { out.ServiceSubnet = in.ServiceSubnet out.PodSubnet = in.PodSubnet @@ -323,10 +311,10 @@ func autoConvert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in *Nod out.DiscoveryToken = in.DiscoveryToken out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers)) out.DiscoveryTimeout = (*meta_v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout)) - out.NodeName = in.NodeName + // WARNING: in.NodeName requires manual conversion: does not exist in peer-type out.TLSBootstrapToken = in.TLSBootstrapToken out.Token = in.Token - out.CRISocket = in.CRISocket + // WARNING: in.CRISocket requires manual conversion: does not exist in peer-type out.ClusterName = in.ClusterName out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes)) out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification @@ -334,51 +322,18 @@ func autoConvert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in *Nod return nil } -// Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration is an autogenerated conversion function. -func Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error { - return autoConvert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in, out, s) -} - func autoConvert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error { + // WARNING: in.NodeRegistration requires manual conversion: does not exist in peer-type out.CACertPath = in.CACertPath out.DiscoveryFile = in.DiscoveryFile out.DiscoveryToken = in.DiscoveryToken out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers)) out.DiscoveryTimeout = (*meta_v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout)) - out.NodeName = in.NodeName out.TLSBootstrapToken = in.TLSBootstrapToken out.Token = in.Token - out.CRISocket = in.CRISocket out.ClusterName = in.ClusterName out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes)) out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) return nil } - -// Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration is an autogenerated conversion function. -func Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error { - return autoConvert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in, out, s) -} - -func autoConvert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery(in *TokenDiscovery, out *kubeadm.TokenDiscovery, s conversion.Scope) error { - out.ID = in.ID - out.Secret = in.Secret - return nil -} - -// Convert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery is an autogenerated conversion function. -func Convert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery(in *TokenDiscovery, out *kubeadm.TokenDiscovery, s conversion.Scope) error { - return autoConvert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery(in, out, s) -} - -func autoConvert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery(in *kubeadm.TokenDiscovery, out *TokenDiscovery, s conversion.Scope) error { - out.ID = in.ID - out.Secret = in.Secret - return nil -} - -// Convert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery is an autogenerated conversion function. -func Convert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery(in *kubeadm.TokenDiscovery, out *TokenDiscovery, s conversion.Scope) error { - return autoConvert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery(in, out, s) -} diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD index 841c006d451..380b5b6d844 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD @@ -1,8 +1,9 @@ -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", srcs = [ + "bootstraptokenstring.go", "defaults.go", "doc.go", "register.go", @@ -61,6 +62,8 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", ], ) @@ -77,3 +80,9 @@ filegroup( tags = ["automanaged"], visibility = ["//visibility:public"], ) + +go_test( + name = "go_default_test", + srcs = ["bootstraptokenstring_test.go"], + embed = [":go_default_library"], +) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring.go new file mode 100644 index 00000000000..d62d5a7438c --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring.go @@ -0,0 +1,90 @@ +/* +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 v1alpha2 holds the external kubeadm API types of version v1alpha2 +// Note: This file should be kept in sync with the similar one for the internal API +// TODO: The BootstrapTokenString object should move out to either k8s.io/client-go or k8s.io/api in the future +// (probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now. +package v1alpha2 + +import ( + "fmt" + "strings" + + bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" +) + +// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used +// for both validation of the practically of the API server from a joining node's point +// of view and as an authentication method for the node in the bootstrap phase of +// "kubeadm join". This token is and should be short-lived +type BootstrapTokenString struct { + ID string + Secret string +} + +// MarshalJSON implements the json.Marshaler interface. +func (bts BootstrapTokenString) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, bts.String())), nil +} + +// UnmarshalJSON implements the json.Unmarshaller interface. +func (bts *BootstrapTokenString) UnmarshalJSON(b []byte) error { + // If the token is represented as "", just return quickly without an error + if len(b) == 0 { + return nil + } + + // Remove unnecessary " characters coming from the JSON parser + token := strings.Replace(string(b), `"`, ``, -1) + // Convert the string Token to a BootstrapTokenString object + newbts, err := NewBootstrapTokenString(token) + if err != nil { + return err + } + bts.ID = newbts.ID + bts.Secret = newbts.Secret + return nil +} + +// String returns the string representation of the BootstrapTokenString +func (bts BootstrapTokenString) String() string { + if len(bts.ID) > 0 && len(bts.Secret) > 0 { + return bootstraputil.TokenFromIDAndSecret(bts.ID, bts.Secret) + } + return "" +} + +// NewBootstrapTokenString converts the given Bootstrap Token as a string +// to the BootstrapTokenString object used for serialization/deserialization +// and internal usage. It also automatically validates that the given token +// is of the right format +func NewBootstrapTokenString(token string) (*BootstrapTokenString, error) { + substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(token) + // TODO: Add a constant for the 3 value here, and explain better why it's needed (other than because how the regexp parsin works) + if len(substrs) != 3 { + return nil, fmt.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern) + } + + return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil +} + +// NewBootstrapTokenStringFromIDAndSecret is a wrapper around NewBootstrapTokenString +// that allows the caller to specify the ID and Secret separately +func NewBootstrapTokenStringFromIDAndSecret(id, secret string) (*BootstrapTokenString, error) { + return NewBootstrapTokenString(bootstraputil.TokenFromIDAndSecret(id, secret)) +} diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring_test.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring_test.go new file mode 100644 index 00000000000..0d06bd153e3 --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring_test.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. +*/ + +package v1alpha2 + +import ( + "encoding/json" + "fmt" + "reflect" + "testing" +) + +func TestMarshalJSON(t *testing.T) { + var tests = []struct { + bts BootstrapTokenString + expected string + }{ + {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`}, + {BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`}, + {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), + ) + } + } +} + +func TestUnmarshalJSON(t *testing.T) { + var tests = []struct { + input string + bts *BootstrapTokenString + expectedError bool + }{ + {`"f.s"`, &BootstrapTokenString{}, true}, + {`"abcdef."`, &BootstrapTokenString{}, true}, + {`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true}, + {`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, + {`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, + {`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true}, + {`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false}, + {`"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, + ) + } + } +} + +func TestJSONRoundtrip(t *testing.T) { + var tests = []struct { + input string + bts *BootstrapTokenString + }{ + {`"abcdef.abcdef0123456789"`, nil}, + {"", &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) + } + } +} + +func roundtrip(input string, bts *BootstrapTokenString) error { + var b []byte + var err error + newbts := &BootstrapTokenString{} + // If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string + if len(input) > 0 { + if err := json.Unmarshal([]byte(input), newbts); err != nil { + return fmt.Errorf("expected no unmarshal error, got error: %v", err) + } + if b, err = json.Marshal(newbts); err != nil { + return fmt.Errorf("expected no marshal error, got error: %v", err) + } + if input != string(b) { + return fmt.Errorf( + "expected token: %s\n\t actual: %s", + input, + string(b), + ) + } + } else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object + if b, err = json.Marshal(bts); err != nil { + return fmt.Errorf("expected no marshal error, got error: %v", err) + } + if err := json.Unmarshal(b, newbts); err != nil { + return fmt.Errorf("expected no unmarshal error, got error: %v", err) + } + if !reflect.DeepEqual(bts, newbts) { + return fmt.Errorf( + "expected object: %v\n\t actual: %v", + bts, + newbts, + ) + } + } + return nil +} + +func TestTokenFromIDAndSecret(t *testing.T) { + var tests = []struct { + bts BootstrapTokenString + expected string + }{ + {BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"}, + {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"}, + {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, + ) + } + } +} + +func TestNewBootstrapTokenString(t *testing.T) { + var tests = []struct { + token string + expectedError bool + bts *BootstrapTokenString + }{ + {token: "", expectedError: true, bts: nil}, + {token: ".", expectedError: true, bts: nil}, + {token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size + {token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {token: "123456.", expectedError: true, bts: nil}, // invalid parcel size + {token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation + {token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation + {token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id + {token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret + {token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character + {token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character + {token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, + {token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, + {token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + {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, + ) + } + } +} + +func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) { + var tests = []struct { + id, secret string + expectedError bool + bts *BootstrapTokenString + }{ + {id: "", secret: "", expectedError: true, bts: nil}, + {id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size + {id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size + {id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id + {id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret + {id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character + {id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character + {id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, + {id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, + {id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + {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, + ) + } + } +} diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go index f9c4000198f..c9b8980bdcd 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go @@ -38,7 +38,7 @@ const ( // DefaultClusterDNSIP defines default DNS IP DefaultClusterDNSIP = "10.96.0.10" // DefaultKubernetesVersion defines default kubernetes version - DefaultKubernetesVersion = "stable-1.10" + DefaultKubernetesVersion = "stable-1.11" // DefaultAPIBindPort defines default API port DefaultAPIBindPort = 6443 // DefaultCertificatesDir defines default certificate directory @@ -97,24 +97,6 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) { obj.CertificatesDir = DefaultCertificatesDir } - if obj.TokenTTL == nil { - obj.TokenTTL = &metav1.Duration{ - Duration: constants.DefaultTokenDuration, - } - } - - if obj.CRISocket == "" { - obj.CRISocket = DefaultCRISocket - } - - if len(obj.TokenUsages) == 0 { - obj.TokenUsages = constants.DefaultTokenUsages - } - - if len(obj.TokenGroups) == 0 { - obj.TokenGroups = constants.DefaultTokenGroups - } - if obj.ImageRepository == "" { obj.ImageRepository = DefaultImageRepository } @@ -123,6 +105,8 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) { obj.ClusterName = DefaultClusterName } + SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration) + SetDefaults_BootstrapTokens(obj) SetDefaults_KubeletConfiguration(obj) SetDefaults_Etcd(obj) SetDefaults_ProxyConfiguration(obj) @@ -168,9 +152,6 @@ func SetDefaults_NodeConfiguration(obj *NodeConfiguration) { if len(obj.DiscoveryToken) == 0 && len(obj.DiscoveryFile) == 0 { obj.DiscoveryToken = obj.Token } - if obj.CRISocket == "" { - obj.CRISocket = DefaultCRISocket - } // Make sure file URLs become paths if len(obj.DiscoveryFile) != 0 { u, err := url.Parse(obj.DiscoveryFile) @@ -186,6 +167,8 @@ func SetDefaults_NodeConfiguration(obj *NodeConfiguration) { if obj.ClusterName == "" { obj.ClusterName = DefaultClusterName } + + SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration) } // SetDefaults_KubeletConfiguration assigns default values to kubelet @@ -237,6 +220,12 @@ func SetDefaults_KubeletConfiguration(obj *MasterConfiguration) { } } +func SetDefaults_NodeRegistrationOptions(obj *NodeRegistrationOptions) { + if obj.CRISocket == "" { + obj.CRISocket = DefaultCRISocket + } +} + // SetDefaults_AuditPolicyConfiguration sets default values for the AuditPolicyConfiguration func SetDefaults_AuditPolicyConfiguration(obj *MasterConfiguration) { if obj.AuditPolicyConfiguration.LogDir == "" { @@ -246,3 +235,35 @@ func SetDefaults_AuditPolicyConfiguration(obj *MasterConfiguration) { obj.AuditPolicyConfiguration.LogMaxAge = &DefaultAuditPolicyLogMaxAge } } + +// SetDefaults_BootstrapTokens sets the defaults for the .BootstrapTokens field +// If the slice is empty, it's defaulted with one token. Otherwise it just loops +// through the slice and sets the defaults for the omitempty fields that are TTL, +// Usages and Groups. Token is NOT defaulted with a random one in the API defaulting +// layer, but set to a random value later at runtime if not set before. +func SetDefaults_BootstrapTokens(obj *MasterConfiguration) { + + if obj.BootstrapTokens == nil || len(obj.BootstrapTokens) == 0 { + obj.BootstrapTokens = []BootstrapToken{{}} + } + + for _, bt := range obj.BootstrapTokens { + SetDefaults_BootstrapToken(&bt) + } +} + +// SetDefaults_BootstrapToken sets the defaults for an individual Bootstrap Token +func SetDefaults_BootstrapToken(bt *BootstrapToken) { + if bt.TTL == nil { + bt.TTL = &metav1.Duration{ + Duration: constants.DefaultTokenDuration, + } + } + if len(bt.Usages) == 0 { + bt.Usages = constants.DefaultTokenUsages + } + + if len(bt.Groups) == 0 { + bt.Groups = constants.DefaultTokenGroups + } +} diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/types.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/types.go index dd48f2b9277..7af1f79bea3 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/types.go @@ -30,6 +30,21 @@ import ( type MasterConfiguration struct { metav1.TypeMeta `json:",inline"` + // `kubeadm init`-only information. These fields are solely used the first time `kubeadm init` runs. + // After that, the information in the fields ARE NOT uploaded to the `kubeadm-config` ConfigMap + // that is used by `kubeadm upgrade` for instance. These fields must be omitempty. + + // BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create. + // This information IS NOT uploaded to the kubeadm cluster configmap, partly because of its sensitive nature + BootstrapTokens []BootstrapToken `json:"bootstrapTokens,omitempty"` + + // NodeRegistration holds fields that relate to registering the new master node to the cluster + NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty"` + + // Cluster-wide configuration + // TODO: Move these fields under some kind of ClusterConfiguration or similar struct that describes + // one cluster. Eventually we want this kind of spec to align well with the Cluster API spec. + // API holds configuration for the k8s apiserver. API API `json:"api"` // KubeProxy holds configuration for the k8s service proxy. @@ -40,28 +55,9 @@ type MasterConfiguration struct { KubeletConfiguration KubeletConfiguration `json:"kubeletConfiguration"` // Networking holds configuration for the networking topology of the cluster. Networking Networking `json:"networking"` + // KubernetesVersion is the target version of the control plane. KubernetesVersion string `json:"kubernetesVersion"` - // NodeName is the name of the node that will host the k8s control plane. - // Defaults to the hostname if not provided. - NodeName string `json:"nodeName"` - // NoTaintMaster will, if set, suppress the tainting of the - // master node allowing workloads to be run on it (e.g. in - // single node configurations). - NoTaintMaster bool `json:"noTaintMaster,omitempty"` - - // Token is used for establishing bidirectional trust between nodes and masters. - // Used for joining nodes in the cluster. - Token string `json:"token"` - // TokenTTL defines the ttl for Token. Defaults to 24h. - TokenTTL *metav1.Duration `json:"tokenTTL,omitempty"` - // TokenUsages describes the ways in which this token can be used. - TokenUsages []string `json:"tokenUsages,omitempty"` - // Extra groups that this token will authenticate as when used for authentication - TokenGroups []string `json:"tokenGroups,omitempty"` - - // CRISocket is used to retrieve container runtime info. - CRISocket string `json:"criSocket,omitempty"` // APIServerExtraArgs is a set of extra flags to pass to the API Server or override // default ones in form of =. @@ -129,16 +125,26 @@ type API struct { BindPort int32 `json:"bindPort"` } -// TokenDiscovery contains elements needed for token discovery. -type TokenDiscovery struct { - // ID is the first part of a bootstrap token. Considered public information. - // It is used when referring to a token without leaking the secret part. - ID string `json:"id"` - // Secret is the second part of a bootstrap token. Should only be shared - // with trusted parties. - Secret string `json:"secret"` - // TODO: Seems unused. Remove? - // Addresses []string `json:"addresses"` +// NodeRegistrationOptions holds fields that relate to registering a new master or node to the cluster, either via "kubeadm init" or "kubeadm join" +type NodeRegistrationOptions struct { + + // Name is the `.Metadata.Name` field of the Node API object that will be created in this `kubeadm init` or `kubeadm joiń` operation. + // This field is also used in the CommonName field of the kubelet's client certificate to the API server. + // Defaults to the hostname of the node if not provided. + Name string `json:"name,omitempty"` + + // CRISocket is used to retrieve container runtime info. This information will be annotated to the Node API object, for later re-use + CRISocket string `json:"criSocket,omitempty"` + + // Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the `kubeadm init` process + // it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your master node, set this field to an + // empty slice, i.e. `taints: {}` in the YAML file. This field is solely used for Node registration. + Taints []v1.Taint `json:"taints,omitempty"` + + // KubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file + // kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap + // Flags have higher higher priority when parsing. These values are local and specific to the node kubeadm is executing on. + KubeletExtraArgs map[string]string `json:"kubeletExtraArgs,omitempty"` } // Networking contains elements describing cluster's networking configuration @@ -151,6 +157,28 @@ type Networking struct { DNSDomain string `json:"dnsDomain"` } +// BootstrapToken describes one bootstrap token, stored as a Secret in the cluster +type BootstrapToken struct { + // Token is used for establishing bidirectional trust between nodes and masters. + // Used for joining nodes in the cluster. + Token *BootstrapTokenString `json:"token"` + // Description sets a human-friendly message why this token exists and what it's used + // for, so other administrators can know its purpose. + Description string `json:"description,omitempty"` + // TTL defines the time to live for this token. Defaults to 24h. + // Expires and TTL are mutually exclusive. + TTL *metav1.Duration `json:"ttl,omitempty"` + // Expires specifies the timestamp when this token expires. Defaults to being set + // dynamically at runtime based on the TTL. Expires and TTL are mutually exclusive. + Expires *metav1.Time `json:"expires,omitempty"` + // Usages describes the ways in which this token can be used. Can by default be used + // for establishing bidirectional trust, but that can be changed here. + Usages []string `json:"usages,omitempty"` + // Groups specifies the extra groups that this token will authenticate as when/if + // used for authentication + Groups []string `json:"groups,omitempty"` +} + // Etcd contains elements describing Etcd configuration. type Etcd struct { @@ -206,6 +234,9 @@ type ExternalEtcd struct { type NodeConfiguration struct { metav1.TypeMeta `json:",inline"` + // NodeRegistration holds fields that relate to registering the new master node to the cluster + NodeRegistration NodeRegistrationOptions `json:"nodeRegistration"` + // CACertPath is the path to the SSL certificate authority used to // secure comunications between node and master. // Defaults to "/etc/kubernetes/pki/ca.crt". @@ -222,16 +253,12 @@ type NodeConfiguration struct { DiscoveryTokenAPIServers []string `json:"discoveryTokenAPIServers,omitempty"` // DiscoveryTimeout modifies the discovery timeout DiscoveryTimeout *metav1.Duration `json:"discoveryTimeout,omitempty"` - // NodeName is the name of the node to join the cluster. Defaults - // to the name of the host. - NodeName string `json:"nodeName"` // TLSBootstrapToken is a token used for TLS bootstrapping. // Defaults to Token. TLSBootstrapToken string `json:"tlsBootstrapToken"` // Token is used for both discovery and TLS bootstrapping. Token string `json:"token"` - // CRISocket is used to retrieve container runtime info. - CRISocket string `json:"criSocket,omitempty"` + // ClusterName is the name for the cluster in kubeconfig. ClusterName string `json:"clusterName,omitempty"` diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.conversion.go index dd661e08773..22ef44a1464 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.conversion.go @@ -23,8 +23,8 @@ package v1alpha2 import ( unsafe "unsafe" - v1 "k8s.io/api/core/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + core_v1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" @@ -44,6 +44,10 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_kubeadm_API_To_v1alpha2_API, Convert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration, Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration, + Convert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken, + Convert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken, + Convert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString, + Convert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString, Convert_v1alpha2_Etcd_To_kubeadm_Etcd, Convert_kubeadm_Etcd_To_v1alpha2_Etcd, Convert_v1alpha2_ExternalEtcd_To_kubeadm_ExternalEtcd, @@ -62,8 +66,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_kubeadm_Networking_To_v1alpha2_Networking, Convert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration, Convert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration, - Convert_v1alpha2_TokenDiscovery_To_kubeadm_TokenDiscovery, - Convert_kubeadm_TokenDiscovery_To_v1alpha2_TokenDiscovery, + Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions, + Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions, ) } @@ -115,6 +119,58 @@ func Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfigurati return autoConvert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration(in, out, s) } +func autoConvert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error { + out.Token = (*kubeadm.BootstrapTokenString)(unsafe.Pointer(in.Token)) + out.Description = in.Description + out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL)) + out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires)) + out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages)) + out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups)) + return nil +} + +// Convert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken is an autogenerated conversion function. +func Convert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error { + return autoConvert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken(in, out, s) +} + +func autoConvert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error { + out.Token = (*BootstrapTokenString)(unsafe.Pointer(in.Token)) + out.Description = in.Description + out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL)) + out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires)) + out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages)) + out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups)) + return nil +} + +// Convert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken is an autogenerated conversion function. +func Convert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error { + return autoConvert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken(in, out, s) +} + +func autoConvert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error { + out.ID = in.ID + out.Secret = in.Secret + return nil +} + +// Convert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString is an autogenerated conversion function. +func Convert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error { + return autoConvert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in, out, s) +} + +func autoConvert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error { + out.ID = in.ID + out.Secret = in.Secret + return nil +} + +// Convert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString is an autogenerated conversion function. +func Convert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error { + return autoConvert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString(in, out, s) +} + func autoConvert_v1alpha2_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error { out.Local = (*kubeadm.LocalEtcd)(unsafe.Pointer(in.Local)) out.External = (*kubeadm.ExternalEtcd)(unsafe.Pointer(in.External)) @@ -168,7 +224,7 @@ func autoConvert_v1alpha2_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMou out.HostPath = in.HostPath out.MountPath = in.MountPath out.Writable = in.Writable - out.PathType = v1.HostPathType(in.PathType) + out.PathType = core_v1.HostPathType(in.PathType) return nil } @@ -182,7 +238,7 @@ func autoConvert_kubeadm_HostPathMount_To_v1alpha2_HostPathMount(in *kubeadm.Hos out.HostPath = in.HostPath out.MountPath = in.MountPath out.Writable = in.Writable - out.PathType = v1.HostPathType(in.PathType) + out.PathType = core_v1.HostPathType(in.PathType) return nil } @@ -260,6 +316,10 @@ func Convert_kubeadm_LocalEtcd_To_v1alpha2_LocalEtcd(in *kubeadm.LocalEtcd, out } func autoConvert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error { + out.BootstrapTokens = *(*[]kubeadm.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens)) + if err := Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { + return err + } if err := Convert_v1alpha2_API_To_kubeadm_API(&in.API, &out.API, s); err != nil { return err } @@ -276,13 +336,6 @@ func autoConvert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in return err } out.KubernetesVersion = in.KubernetesVersion - out.NodeName = in.NodeName - out.NoTaintMaster = in.NoTaintMaster - out.Token = in.Token - out.TokenTTL = (*meta_v1.Duration)(unsafe.Pointer(in.TokenTTL)) - out.TokenUsages = *(*[]string)(unsafe.Pointer(&in.TokenUsages)) - out.TokenGroups = *(*[]string)(unsafe.Pointer(&in.TokenGroups)) - out.CRISocket = in.CRISocket out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs)) out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs)) out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs)) @@ -307,6 +360,10 @@ func Convert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in *Mas } func autoConvert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error { + out.BootstrapTokens = *(*[]BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens)) + if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { + return err + } if err := Convert_kubeadm_API_To_v1alpha2_API(&in.API, &out.API, s); err != nil { return err } @@ -323,13 +380,6 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in return err } out.KubernetesVersion = in.KubernetesVersion - out.NodeName = in.NodeName - out.NoTaintMaster = in.NoTaintMaster - out.Token = in.Token - out.TokenTTL = (*meta_v1.Duration)(unsafe.Pointer(in.TokenTTL)) - out.TokenUsages = *(*[]string)(unsafe.Pointer(&in.TokenUsages)) - out.TokenGroups = *(*[]string)(unsafe.Pointer(&in.TokenGroups)) - out.CRISocket = in.CRISocket out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs)) out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs)) out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs)) @@ -379,15 +429,16 @@ func Convert_kubeadm_Networking_To_v1alpha2_Networking(in *kubeadm.Networking, o } func autoConvert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error { + if err := Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { + return err + } out.CACertPath = in.CACertPath out.DiscoveryFile = in.DiscoveryFile out.DiscoveryToken = in.DiscoveryToken out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers)) - out.DiscoveryTimeout = (*meta_v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout)) - out.NodeName = in.NodeName + out.DiscoveryTimeout = (*v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout)) out.TLSBootstrapToken = in.TLSBootstrapToken out.Token = in.Token - out.CRISocket = in.CRISocket out.ClusterName = in.ClusterName out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes)) out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification @@ -401,15 +452,16 @@ func Convert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeCon } func autoConvert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error { + if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { + return err + } out.CACertPath = in.CACertPath out.DiscoveryFile = in.DiscoveryFile out.DiscoveryToken = in.DiscoveryToken out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers)) - out.DiscoveryTimeout = (*meta_v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout)) - out.NodeName = in.NodeName + out.DiscoveryTimeout = (*v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout)) out.TLSBootstrapToken = in.TLSBootstrapToken out.Token = in.Token - out.CRISocket = in.CRISocket out.ClusterName = in.ClusterName out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes)) out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification @@ -422,24 +474,28 @@ func Convert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration(in *kubeadm return autoConvert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration(in, out, s) } -func autoConvert_v1alpha2_TokenDiscovery_To_kubeadm_TokenDiscovery(in *TokenDiscovery, out *kubeadm.TokenDiscovery, s conversion.Scope) error { - out.ID = in.ID - out.Secret = in.Secret +func autoConvert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error { + out.Name = in.Name + out.CRISocket = in.CRISocket + out.Taints = *(*[]core_v1.Taint)(unsafe.Pointer(&in.Taints)) + out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs)) return nil } -// Convert_v1alpha2_TokenDiscovery_To_kubeadm_TokenDiscovery is an autogenerated conversion function. -func Convert_v1alpha2_TokenDiscovery_To_kubeadm_TokenDiscovery(in *TokenDiscovery, out *kubeadm.TokenDiscovery, s conversion.Scope) error { - return autoConvert_v1alpha2_TokenDiscovery_To_kubeadm_TokenDiscovery(in, out, s) +// Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions is an autogenerated conversion function. +func Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error { + return autoConvert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in, out, s) } -func autoConvert_kubeadm_TokenDiscovery_To_v1alpha2_TokenDiscovery(in *kubeadm.TokenDiscovery, out *TokenDiscovery, s conversion.Scope) error { - out.ID = in.ID - out.Secret = in.Secret +func autoConvert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error { + out.Name = in.Name + out.CRISocket = in.CRISocket + out.Taints = *(*[]core_v1.Taint)(unsafe.Pointer(&in.Taints)) + out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs)) return nil } -// Convert_kubeadm_TokenDiscovery_To_v1alpha2_TokenDiscovery is an autogenerated conversion function. -func Convert_kubeadm_TokenDiscovery_To_v1alpha2_TokenDiscovery(in *kubeadm.TokenDiscovery, out *TokenDiscovery, s conversion.Scope) error { - return autoConvert_kubeadm_TokenDiscovery_To_v1alpha2_TokenDiscovery(in, out, s) +// Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions is an autogenerated conversion function. +func Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error { + return autoConvert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(in, out, s) } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.deepcopy.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.deepcopy.go index af11b89b973..d63be5c14c8 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.deepcopy.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.deepcopy.go @@ -21,6 +21,7 @@ limitations under the License. package v1alpha2 import ( + core_v1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" @@ -68,6 +69,74 @@ func (in *AuditPolicyConfiguration) DeepCopy() *AuditPolicyConfiguration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) { + *out = *in + if in.Token != nil { + in, out := &in.Token, &out.Token + if *in == nil { + *out = nil + } else { + *out = new(BootstrapTokenString) + **out = **in + } + } + if in.TTL != nil { + in, out := &in.TTL, &out.TTL + if *in == nil { + *out = nil + } else { + *out = new(v1.Duration) + **out = **in + } + } + if in.Expires != nil { + in, out := &in.Expires, &out.Expires + if *in == nil { + *out = nil + } else { + *out = (*in).DeepCopy() + } + } + if in.Usages != nil { + in, out := &in.Usages, &out.Usages + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Groups != nil { + in, out := &in.Groups, &out.Groups + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken. +func (in *BootstrapToken) DeepCopy() *BootstrapToken { + if in == nil { + return nil + } + out := new(BootstrapToken) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BootstrapTokenString) DeepCopyInto(out *BootstrapTokenString) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenString. +func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString { + if in == nil { + return nil + } + out := new(BootstrapTokenString) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Etcd) DeepCopyInto(out *Etcd) { *out = *in @@ -226,30 +295,19 @@ func (in *LocalEtcd) DeepCopy() *LocalEtcd { func (in *MasterConfiguration) DeepCopyInto(out *MasterConfiguration) { *out = *in out.TypeMeta = in.TypeMeta + if in.BootstrapTokens != nil { + in, out := &in.BootstrapTokens, &out.BootstrapTokens + *out = make([]BootstrapToken, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.NodeRegistration.DeepCopyInto(&out.NodeRegistration) out.API = in.API in.KubeProxy.DeepCopyInto(&out.KubeProxy) in.Etcd.DeepCopyInto(&out.Etcd) in.KubeletConfiguration.DeepCopyInto(&out.KubeletConfiguration) out.Networking = in.Networking - if in.TokenTTL != nil { - in, out := &in.TokenTTL, &out.TokenTTL - if *in == nil { - *out = nil - } else { - *out = new(v1.Duration) - **out = **in - } - } - if in.TokenUsages != nil { - in, out := &in.TokenUsages, &out.TokenUsages - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.TokenGroups != nil { - in, out := &in.TokenGroups, &out.TokenGroups - *out = make([]string, len(*in)) - copy(*out, *in) - } if in.APIServerExtraArgs != nil { in, out := &in.APIServerExtraArgs, &out.APIServerExtraArgs *out = make(map[string]string, len(*in)) @@ -340,6 +398,7 @@ func (in *Networking) DeepCopy() *Networking { func (in *NodeConfiguration) DeepCopyInto(out *NodeConfiguration) { *out = *in out.TypeMeta = in.TypeMeta + in.NodeRegistration.DeepCopyInto(&out.NodeRegistration) if in.DiscoveryTokenAPIServers != nil { in, out := &in.DiscoveryTokenAPIServers, &out.DiscoveryTokenAPIServers *out = make([]string, len(*in)) @@ -388,17 +447,31 @@ func (in *NodeConfiguration) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TokenDiscovery) DeepCopyInto(out *TokenDiscovery) { +func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) { *out = *in + if in.Taints != nil { + in, out := &in.Taints, &out.Taints + *out = make([]core_v1.Taint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.KubeletExtraArgs != nil { + in, out := &in.KubeletExtraArgs, &out.KubeletExtraArgs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenDiscovery. -func (in *TokenDiscovery) DeepCopy() *TokenDiscovery { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRegistrationOptions. +func (in *NodeRegistrationOptions) DeepCopy() *NodeRegistrationOptions { if in == nil { return nil } - out := new(TokenDiscovery) + out := new(NodeRegistrationOptions) in.DeepCopyInto(out) return out } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.defaults.go index 7218ab95912..940e5621f8c 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.defaults.go @@ -37,6 +37,11 @@ func RegisterDefaults(scheme *runtime.Scheme) error { func SetObjectDefaults_MasterConfiguration(in *MasterConfiguration) { SetDefaults_MasterConfiguration(in) + for i := range in.BootstrapTokens { + a := &in.BootstrapTokens[i] + SetDefaults_BootstrapToken(a) + } + SetDefaults_NodeRegistrationOptions(&in.NodeRegistration) if in.KubeProxy.Config != nil { v1alpha1.SetDefaults_KubeProxyConfiguration(in.KubeProxy.Config) } @@ -47,4 +52,5 @@ func SetObjectDefaults_MasterConfiguration(in *MasterConfiguration) { func SetObjectDefaults_NodeConfiguration(in *NodeConfiguration) { SetDefaults_NodeConfiguration(in) + SetDefaults_NodeRegistrationOptions(&in.NodeRegistration) } diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/BUILD b/cmd/kubeadm/app/apis/kubeadm/validation/BUILD index 12cb119844f..abff6526c40 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/validation/BUILD @@ -10,7 +10,6 @@ go_library( "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", - "//cmd/kubeadm/app/util/token:go_default_library", "//pkg/apis/core/validation:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", @@ -20,7 +19,6 @@ go_library( "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/validation:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", - "//pkg/util/node:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go index 116bfce6c8d..a85ba40a04f 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go +++ b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go @@ -35,7 +35,6 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" - tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token" apivalidation "k8s.io/kubernetes/pkg/apis/core/validation" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" @@ -45,7 +44,6 @@ import ( kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" proxyvalidation "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation" "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" - "k8s.io/kubernetes/pkg/util/node" ) // ValidateMasterConfiguration validates master configuration and collects all encountered errors @@ -54,17 +52,13 @@ func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList allErrs = append(allErrs, ValidateNetworking(&c.Networking, field.NewPath("networking"))...) allErrs = append(allErrs, ValidateCertSANs(c.APIServerCertSANs, field.NewPath("apiServerCertSANs"))...) allErrs = append(allErrs, ValidateAbsolutePath(c.CertificatesDir, field.NewPath("certificatesDir"))...) - allErrs = append(allErrs, ValidateNodeName(c.NodeName, field.NewPath("nodeName"))...) - allErrs = append(allErrs, ValidateToken(c.Token, field.NewPath("token"))...) - allErrs = append(allErrs, ValidateTokenUsages(c.TokenUsages, field.NewPath("tokenUsages"))...) - allErrs = append(allErrs, ValidateTokenGroups(c.TokenUsages, c.TokenGroups, field.NewPath("tokenGroups"))...) + allErrs = append(allErrs, ValidateNodeRegistrationOptions(&c.NodeRegistration, field.NewPath("nodeRegistration"))...) + allErrs = append(allErrs, ValidateBootstrapTokens(c.BootstrapTokens, field.NewPath("bootstrapTokens"))...) allErrs = append(allErrs, ValidateFeatureGates(c.FeatureGates, field.NewPath("featureGates"))...) allErrs = append(allErrs, ValidateAPIEndpoint(&c.API, field.NewPath("api"))...) allErrs = append(allErrs, ValidateProxy(c.KubeProxy.Config, field.NewPath("kubeProxy").Child("config"))...) allErrs = append(allErrs, ValidateEtcd(&c.Etcd, field.NewPath("etcd"))...) - if features.Enabled(c.FeatureGates, features.DynamicKubeletConfig) { - allErrs = append(allErrs, ValidateKubeletConfiguration(&c.KubeletConfiguration, field.NewPath("kubeletConfiguration"))...) - } + allErrs = append(allErrs, ValidateKubeletConfiguration(&c.KubeletConfiguration, field.NewPath("kubeletConfiguration"))...) return allErrs } @@ -86,6 +80,7 @@ func ValidateProxy(c *kubeproxyconfigv1alpha1.KubeProxyConfiguration, fldPath *f func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, ValidateDiscovery(c)...) + allErrs = append(allErrs, ValidateNodeRegistrationOptions(&c.NodeRegistration, field.NewPath("nodeRegistration"))...) if !filepath.IsAbs(c.CACertPath) || !strings.HasSuffix(c.CACertPath, ".crt") { allErrs = append(allErrs, field.Invalid(field.NewPath("caCertPath"), c.CACertPath, "the ca certificate path must be an absolute path")) @@ -93,6 +88,19 @@ func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList { return allErrs } +// ValidateNodeRegistrationOptions validates the NodeRegistrationOptions object +func ValidateNodeRegistrationOptions(nro *kubeadm.NodeRegistrationOptions, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if len(nro.Name) == 0 { + allErrs = append(allErrs, field.Required(fldPath, "--node-name or .nodeRegistration.name in the config file is a required value. It seems like this value couldn't be automatically detected in your environment, please specify the desired value using the CLI or config file.")) + } else { + allErrs = append(allErrs, apivalidation.ValidateDNS1123Subdomain(nro.Name, field.NewPath("name"))...) + } + allErrs = append(allErrs, ValidateAbsolutePath(nro.CRISocket, fldPath.Child("criSocket"))...) + // TODO: Maybe validate .Taints as well in the future using something like validateNodeTaints() in pkg/apis/core/validation + return allErrs +} + // ValidateDiscovery validates discovery related configuration and collects all encountered errors func ValidateDiscovery(c *kubeadm.NodeConfiguration) field.ErrorList { allErrs := field.ErrorList{} @@ -173,18 +181,30 @@ func ValidateDiscoveryFile(discoveryFile string, fldPath *field.Path) field.Erro return allErrs } -// ValidateToken validates token -func ValidateToken(t string, fldPath *field.Path) field.ErrorList { +// ValidateBootstrapTokens validates a slice of BootstrapToken objects +func ValidateBootstrapTokens(bts []kubeadm.BootstrapToken, fldPath *field.Path) field.ErrorList { + 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"))...) + + if bt.Expires != nil && bt.TTL != nil { + allErrs = append(allErrs, field.Invalid(btPath, "", "the BootstrapToken .TTL and .Expires fields are mutually exclusive")) + } + } + return allErrs +} + +// ValidateToken validates a Bootstrap Token +func ValidateToken(token string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} - id, secret, err := tokenutil.ParseToken(t) - if err != nil { - allErrs = append(allErrs, field.Invalid(fldPath, t, err.Error())) + if !bootstraputil.IsValidBootstrapToken(token) { + allErrs = append(allErrs, field.Invalid(fldPath, token, "the bootstrap token is invalid")) } - if len(id) == 0 || len(secret) == 0 { - allErrs = append(allErrs, field.Invalid(fldPath, t, "token must be of form '[a-z0-9]{6}.[a-z0-9]{16}'")) - } return allErrs } @@ -339,15 +359,6 @@ func ValidateAbsolutePath(path string, fldPath *field.Path) field.ErrorList { return allErrs } -// ValidateNodeName validates the name of a node -func ValidateNodeName(nodename string, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - if node.GetHostname(nodename) != nodename { - allErrs = append(allErrs, field.Invalid(fldPath, nodename, "nodename is not valid, must be lower case")) - } - return allErrs -} - // ValidateMixedArguments validates passed arguments func ValidateMixedArguments(flag *pflag.FlagSet) error { // If --config isn't set, we have nothing to validate @@ -422,6 +433,10 @@ func ValidateIgnorePreflightErrors(ignorePreflightErrors []string, skipPreflight func ValidateKubeletConfiguration(c *kubeadm.KubeletConfiguration, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} + if c.BaseConfig == nil { + return allErrs + } + scheme, _, err := kubeletscheme.NewSchemeAndCodecs() if err != nil { allErrs = append(allErrs, field.Invalid(fldPath, "kubeletConfiguration", err.Error())) diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go b/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go index b0dd24a683b..151cde50b0a 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go +++ b/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go @@ -33,7 +33,7 @@ import ( utilpointer "k8s.io/kubernetes/pkg/util/pointer" ) -func TestValidateTokenDiscovery(t *testing.T) { +func TestValidateToken(t *testing.T) { var tests = []struct { c *kubeadm.NodeConfiguration f *field.Path @@ -51,7 +51,7 @@ func TestValidateTokenDiscovery(t *testing.T) { err := ValidateToken(rt.c.Token, rt.f).ToAggregate() if (err == nil) != rt.expected { t.Errorf( - "failed ValidateTokenDiscovery:\n\texpected: %t\n\t actual: %t", + "failed ValidateToken:\n\texpected: %t\n\t actual: %t", rt.expected, (err == nil), ) @@ -104,24 +104,31 @@ func TestValidateTokenGroups(t *testing.T) { } } -func TestValidateNodeName(t *testing.T) { +func TestValidateNodeRegistrationOptions(t *testing.T) { var tests = []struct { - s string - f *field.Path - expected bool + nodeName string + criSocket string + expectedErrors bool }{ - {"", nil, false}, // ok if not provided - {"1234", nil, true}, // supported - {"valid-nodename", nil, true}, // supported - {"INVALID-NODENAME", nil, false}, // Upper cases is invalid + {"", "/some/path", true}, // node name can't be empty + {"valid-nodename", "", true}, // crisocket can't be empty + {"INVALID-NODENAME", "/some/path", true}, // Upper cases is invalid + {"invalid-nodename-", "/some/path", true}, // Can't have trailing dashes + {"invalid-node?name", "/some/path", true}, // Unsupported characters + {"valid-nodename", "relative/path", true}, // crisocket must be an absolute path + {"valid-nodename", "/some/path", false}, // supported + {"valid-nodename-with-numbers01234", "/some/path/with/numbers/01234/", false}, // supported, with numbers as well } for _, rt := range tests { - actual := ValidateNodeName(rt.s, rt.f) - if (len(actual) == 0) != rt.expected { + nro := kubeadm.NodeRegistrationOptions{Name: rt.nodeName, CRISocket: rt.criSocket} + actual := ValidateNodeRegistrationOptions(&nro, field.NewPath("nodeRegistration")) + actualErrors := len(actual) > 0 + if actualErrors != rt.expectedErrors { t.Errorf( - "failed ValidateNodeName:\n\texpected: %t\n\t actual: %t", - rt.expected, - (len(actual) == 0), + "failed ValidateNodeRegistrationOptions: value: %v\n\texpected: %t\n\t actual: %t", + nro, + rt.expectedErrors, + actualErrors, ) } } @@ -407,8 +414,8 @@ func TestValidateMasterConfiguration(t *testing.T) { ServiceSubnet: "10.96.0.1/12", DNSDomain: "cluster.local", }, - CertificatesDir: "/some/cert/dir", - NodeName: nodename, + CertificatesDir: "/some/cert/dir", + NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"}, }, false}, {"invalid missing token with IPv6 service subnet", &kubeadm.MasterConfiguration{ @@ -420,8 +427,8 @@ func TestValidateMasterConfiguration(t *testing.T) { ServiceSubnet: "2001:db8::1/98", DNSDomain: "cluster.local", }, - CertificatesDir: "/some/cert/dir", - NodeName: nodename, + CertificatesDir: "/some/cert/dir", + NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"}, }, false}, {"invalid missing node name", &kubeadm.MasterConfiguration{ @@ -434,7 +441,6 @@ func TestValidateMasterConfiguration(t *testing.T) { DNSDomain: "cluster.local", }, CertificatesDir: "/some/other/cert/dir", - Token: "abcdef.0123456789abcdef", }, false}, {"valid master configuration with incorrect IPv4 pod subnet", &kubeadm.MasterConfiguration{ @@ -447,9 +453,8 @@ func TestValidateMasterConfiguration(t *testing.T) { DNSDomain: "cluster.local", PodSubnet: "10.0.1.15", }, - CertificatesDir: "/some/other/cert/dir", - Token: "abcdef.0123456789abcdef", - NodeName: nodename, + CertificatesDir: "/some/other/cert/dir", + NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"}, }, false}, {"valid master configuration with IPv4 service subnet", &kubeadm.MasterConfiguration{ @@ -493,9 +498,8 @@ func TestValidateMasterConfiguration(t *testing.T) { DNSDomain: "cluster.local", PodSubnet: "10.0.1.15/16", }, - CertificatesDir: "/some/other/cert/dir", - Token: "abcdef.0123456789abcdef", - NodeName: nodename, + CertificatesDir: "/some/other/cert/dir", + NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"}, }, true}, {"valid master configuration using IPv6 service subnet", &kubeadm.MasterConfiguration{ @@ -538,9 +542,8 @@ func TestValidateMasterConfiguration(t *testing.T) { ServiceSubnet: "2001:db8::1/98", DNSDomain: "cluster.local", }, - CertificatesDir: "/some/other/cert/dir", - Token: "abcdef.0123456789abcdef", - NodeName: nodename, + CertificatesDir: "/some/other/cert/dir", + NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"}, }, true}, } for _, rt := range tests { diff --git a/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go b/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go index ce680355710..2295df2419f 100644 --- a/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go +++ b/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go @@ -21,6 +21,7 @@ limitations under the License. package kubeadm import ( + core_v1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" @@ -68,6 +69,74 @@ func (in *AuditPolicyConfiguration) DeepCopy() *AuditPolicyConfiguration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) { + *out = *in + if in.Token != nil { + in, out := &in.Token, &out.Token + if *in == nil { + *out = nil + } else { + *out = new(BootstrapTokenString) + **out = **in + } + } + if in.TTL != nil { + in, out := &in.TTL, &out.TTL + if *in == nil { + *out = nil + } else { + *out = new(v1.Duration) + **out = **in + } + } + if in.Expires != nil { + in, out := &in.Expires, &out.Expires + if *in == nil { + *out = nil + } else { + *out = (*in).DeepCopy() + } + } + if in.Usages != nil { + in, out := &in.Usages, &out.Usages + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Groups != nil { + in, out := &in.Groups, &out.Groups + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken. +func (in *BootstrapToken) DeepCopy() *BootstrapToken { + if in == nil { + return nil + } + out := new(BootstrapToken) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BootstrapTokenString) DeepCopyInto(out *BootstrapTokenString) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenString. +func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString { + if in == nil { + return nil + } + out := new(BootstrapTokenString) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Etcd) DeepCopyInto(out *Etcd) { *out = *in @@ -226,30 +295,19 @@ func (in *LocalEtcd) DeepCopy() *LocalEtcd { func (in *MasterConfiguration) DeepCopyInto(out *MasterConfiguration) { *out = *in out.TypeMeta = in.TypeMeta + if in.BootstrapTokens != nil { + in, out := &in.BootstrapTokens, &out.BootstrapTokens + *out = make([]BootstrapToken, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.NodeRegistration.DeepCopyInto(&out.NodeRegistration) out.API = in.API in.KubeProxy.DeepCopyInto(&out.KubeProxy) in.Etcd.DeepCopyInto(&out.Etcd) in.KubeletConfiguration.DeepCopyInto(&out.KubeletConfiguration) out.Networking = in.Networking - if in.TokenTTL != nil { - in, out := &in.TokenTTL, &out.TokenTTL - if *in == nil { - *out = nil - } else { - *out = new(v1.Duration) - **out = **in - } - } - if in.TokenUsages != nil { - in, out := &in.TokenUsages, &out.TokenUsages - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.TokenGroups != nil { - in, out := &in.TokenGroups, &out.TokenGroups - *out = make([]string, len(*in)) - copy(*out, *in) - } if in.APIServerExtraArgs != nil { in, out := &in.APIServerExtraArgs, &out.APIServerExtraArgs *out = make(map[string]string, len(*in)) @@ -340,6 +398,7 @@ func (in *Networking) DeepCopy() *Networking { func (in *NodeConfiguration) DeepCopyInto(out *NodeConfiguration) { *out = *in out.TypeMeta = in.TypeMeta + in.NodeRegistration.DeepCopyInto(&out.NodeRegistration) if in.DiscoveryTokenAPIServers != nil { in, out := &in.DiscoveryTokenAPIServers, &out.DiscoveryTokenAPIServers *out = make([]string, len(*in)) @@ -388,17 +447,31 @@ func (in *NodeConfiguration) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TokenDiscovery) DeepCopyInto(out *TokenDiscovery) { +func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) { *out = *in + if in.Taints != nil { + in, out := &in.Taints, &out.Taints + *out = make([]core_v1.Taint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.KubeletExtraArgs != nil { + in, out := &in.KubeletExtraArgs, &out.KubeletExtraArgs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenDiscovery. -func (in *TokenDiscovery) DeepCopy() *TokenDiscovery { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRegistrationOptions. +func (in *NodeRegistrationOptions) DeepCopy() *NodeRegistrationOptions { if in == nil { return nil } - out := new(TokenDiscovery) + out := new(NodeRegistrationOptions) in.DeepCopyInto(out) return out } diff --git a/cmd/kubeadm/app/cmd/BUILD b/cmd/kubeadm/app/cmd/BUILD index a07a39e42ce..171dc94d455 100644 --- a/cmd/kubeadm/app/cmd/BUILD +++ b/cmd/kubeadm/app/cmd/BUILD @@ -22,8 +22,10 @@ go_library( deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha2: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:go_default_library", "//cmd/kubeadm/app/cmd/upgrade:go_default_library", "//cmd/kubeadm/app/cmd/util:go_default_library", @@ -41,6 +43,7 @@ go_library( "//cmd/kubeadm/app/phases/kubeconfig:go_default_library", "//cmd/kubeadm/app/phases/kubelet:go_default_library", "//cmd/kubeadm/app/phases/markmaster:go_default_library", + "//cmd/kubeadm/app/phases/patchnode:go_default_library", "//cmd/kubeadm/app/phases/selfhosting:go_default_library", "//cmd/kubeadm/app/phases/uploadconfig:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", @@ -50,8 +53,6 @@ go_library( "//cmd/kubeadm/app/util/config:go_default_library", "//cmd/kubeadm/app/util/dryrun:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", - "//cmd/kubeadm/app/util/token:go_default_library", - "//pkg/apis/core:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", "//pkg/util/initsystem:go_default_library", "//pkg/version:go_default_library", @@ -60,15 +61,15 @@ go_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/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/duration:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", "//vendor/k8s.io/client-go/util/cert:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", @@ -118,6 +119,7 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", + "//cmd/kubeadm/app/cmd/options:all-srcs", "//cmd/kubeadm/app/cmd/phases:all-srcs", "//cmd/kubeadm/app/cmd/upgrade:all-srcs", "//cmd/kubeadm/app/cmd/util:all-srcs", @@ -132,6 +134,7 @@ go_test( ":go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/features:go_default_library", + "//cmd/kubeadm/app/util/config:go_default_library", "//vendor/github.com/renstrom/dedent:go_default_library", ], ) diff --git a/cmd/kubeadm/app/cmd/cmd.go b/cmd/kubeadm/app/cmd/cmd.go index c633122b683..d968e53732c 100644 --- a/cmd/kubeadm/app/cmd/cmd.go +++ b/cmd/kubeadm/app/cmd/cmd.go @@ -22,7 +22,6 @@ import ( "github.com/renstrom/dedent" "github.com/spf13/cobra" - "k8s.io/apiserver/pkg/util/flag" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade" // Register the kubeadm configuration types because CLI flag generation @@ -69,7 +68,6 @@ func NewKubeadmCommand(in io.Reader, out, err io.Writer) *cobra.Command { } cmds.ResetFlags() - cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc) cmds.AddCommand(NewCmdCompletion(out, "")) cmds.AddCommand(NewCmdConfig(out)) diff --git a/cmd/kubeadm/app/cmd/completion.go b/cmd/kubeadm/app/cmd/completion.go index 33d5526f9a8..9e7722b7fbb 100644 --- a/cmd/kubeadm/app/cmd/completion.go +++ b/cmd/kubeadm/app/cmd/completion.go @@ -51,17 +51,18 @@ var ( The shell code must be evaluated to provide interactive completion of kubeadm commands. This can be done by sourcing it from the .bash_profile. + + Note: this requires the bash-completion framework. - Note: this requires the bash-completion framework, which is not installed - by default on Mac. This can be installed by using homebrew: - + To install it on Mac use homebrew: $ brew install bash-completion - Once installed, bash_completion must be evaluated. This can be done by adding the following line to the .bash_profile - $ source $(brew --prefix)/etc/bash_completion + If bash-completion is not installed on Linux, please install the 'bash-completion' package + via your distribution's package manager. + Note for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2`) completionExample = dedent.Dedent(` diff --git a/cmd/kubeadm/app/cmd/config.go b/cmd/kubeadm/app/cmd/config.go index a06cc315d37..91cb0963274 100644 --- a/cmd/kubeadm/app/cmd/config.go +++ b/cmd/kubeadm/app/cmd/config.go @@ -19,6 +19,7 @@ package cmd import ( "fmt" "io" + "io/ioutil" "strings" "github.com/golang/glog" @@ -30,6 +31,7 @@ import ( clientset "k8s.io/client-go/kubernetes" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" "k8s.io/kubernetes/cmd/kubeadm/app/constants" @@ -43,12 +45,21 @@ import ( ) const ( + // TODO: Figure out how to get these constants from the API machinery masterConfig = "MasterConfiguration" nodeConfig = "NodeConfiguration" - sillyToken = "abcdef.0123456789abcdef" ) -var availableAPIObjects = []string{masterConfig, nodeConfig} +var ( + availableAPIObjects = []string{masterConfig, nodeConfig} + // sillyToken is only set statically to make kubeadm not randomize the token on every run + sillyToken = kubeadmapiv1alpha2.BootstrapToken{ + Token: &kubeadmapiv1alpha2.BootstrapTokenString{ + ID: "abcdef", + Secret: "0123456789abcdef", + }, + } +) // NewCmdConfig returns cobra.Command for "kubeadm config" command func NewCmdConfig(out io.Writer) *cobra.Command { @@ -74,6 +85,7 @@ func NewCmdConfig(out io.Writer) *cobra.Command { cmd.PersistentFlags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster.") cmd.AddCommand(NewCmdConfigPrintDefault(out)) + cmd.AddCommand(NewCmdConfigMigrate(out)) cmd.AddCommand(NewCmdConfigUpload(out, &kubeConfigFile)) cmd.AddCommand(NewCmdConfigView(out, &kubeConfigFile)) cmd.AddCommand(NewCmdConfigImages(out)) @@ -119,7 +131,7 @@ func getDefaultAPIObjectBytes(apiObject string) ([]byte, error) { if apiObject == masterConfig { internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1alpha2.MasterConfiguration{ - Token: sillyToken, + BootstrapTokens: []kubeadmapiv1alpha2.BootstrapToken{sillyToken}, }) kubeadmutil.CheckErr(err) @@ -127,7 +139,7 @@ func getDefaultAPIObjectBytes(apiObject string) ([]byte, error) { } if apiObject == nodeConfig { internalcfg, err := configutil.NodeConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1alpha2.NodeConfiguration{ - Token: sillyToken, + Token: sillyToken.Token.String(), DiscoveryTokenAPIServers: []string{"kube-apiserver:6443"}, DiscoveryTokenUnsafeSkipCAVerification: true, }) @@ -138,6 +150,71 @@ func getDefaultAPIObjectBytes(apiObject string) ([]byte, error) { return []byte{}, fmt.Errorf("--api-object needs to be one of %v", availableAPIObjects) } +// NewCmdConfigMigrate returns cobra.Command for "kubeadm config migrate" command +func NewCmdConfigMigrate(out io.Writer) *cobra.Command { + var oldCfgPath, newCfgPath string + cmd := &cobra.Command{ + Use: "migrate", + Short: "Read an older version of the kubeadm configuration API types from a file, and output the similar config object for the newer version.", + Long: fmt.Sprintf(dedent.Dedent(` + This command lets you convert configuration objects of older versions to the latest supported version, + locally in the CLI tool without ever touching anything in the cluster. + In this version of kubeadm, the following API versions are supported: + - %s + - %s + + Further, kubeadm can only write out config of version %q, but read both types. + So regardless of what version you pass to the --old-config parameter here, the API object will be + read, deserialized, defaulted, converted, validated, and re-serialized when written to stdout or + --new-config if specified. + + In other words, the output of this command is what kubeadm actually would read internally if you + submitted this file to "kubeadm init" + `), kubeadmapiv1alpha2.SchemeGroupVersion.String(), kubeadmapiv1alpha1.SchemeGroupVersion.String(), kubeadmapiv1alpha2.SchemeGroupVersion.String()), + Run: func(cmd *cobra.Command, args []string) { + if len(oldCfgPath) == 0 { + kubeadmutil.CheckErr(fmt.Errorf("The --old-config flag is mandatory")) + } + + b, err := ioutil.ReadFile(oldCfgPath) + kubeadmutil.CheckErr(err) + + var outputBytes []byte + gvk, err := kubeadmutil.GroupVersionKindFromBytes(b, kubeadmscheme.Codecs) + kubeadmutil.CheckErr(err) + + switch gvk.Kind { + case masterConfig: + internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(oldCfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) + kubeadmutil.CheckErr(err) + + outputBytes, err = kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmscheme.Codecs) + kubeadmutil.CheckErr(err) + case nodeConfig: + internalcfg, err := configutil.NodeConfigFileAndDefaultsToInternalConfig(oldCfgPath, &kubeadmapiv1alpha2.NodeConfiguration{}) + kubeadmutil.CheckErr(err) + + // TODO: In the future we might not want to duplicate these two lines of code for every case here. + outputBytes, err = kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmscheme.Codecs) + kubeadmutil.CheckErr(err) + default: + kubeadmutil.CheckErr(fmt.Errorf("Didn't recognize type with GroupVersionKind: %v", gvk)) + } + + if newCfgPath == "" { + fmt.Fprint(out, string(outputBytes)) + } else { + if err := ioutil.WriteFile(newCfgPath, outputBytes, 0644); err != nil { + kubeadmutil.CheckErr(fmt.Errorf("failed to write the new configuration to the file %q: %v", newCfgPath, err)) + } + } + }, + } + cmd.Flags().StringVar(&oldCfgPath, "old-config", "", "Path to the kubeadm config file that is using an old API version and should be converted. This flag is mandatory.") + cmd.Flags().StringVar(&newCfgPath, "new-config", "", "Path to the resulting equivalent kubeadm config file using the new API version. Optional, if not specified output will be sent to STDOUT.") + return cmd +} + // NewCmdConfigUpload returns cobra.Command for "kubeadm config upload" command func NewCmdConfigUpload(out io.Writer, kubeConfigFile *string) *cobra.Command { cmd := &cobra.Command{ @@ -281,7 +358,7 @@ func NewCmdConfigImages(out io.Writer) *cobra.Command { Short: "Interact with container images used by kubeadm.", RunE: cmdutil.SubCmdRunE("images"), } - cmd.AddCommand(NewCmdConfigImagesList(out)) + cmd.AddCommand(NewCmdConfigImagesList(out, nil)) cmd.AddCommand(NewCmdConfigImagesPull()) return cmd } @@ -301,7 +378,7 @@ func NewCmdConfigImagesPull() *cobra.Command { kubeadmutil.CheckErr(err) internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg) kubeadmutil.CheckErr(err) - puller, err := images.NewImagePuller(utilsexec.New(), internalcfg.GetCRISocket()) + puller, err := images.NewCRInterfacer(utilsexec.New(), internalcfg.GetCRISocket()) kubeadmutil.CheckErr(err) imagesPull := NewImagesPull(puller, images.GetAllImages(internalcfg)) kubeadmutil.CheckErr(imagesPull.PullAll()) @@ -333,18 +410,24 @@ func (ip *ImagesPull) PullAll() error { if err := ip.puller.Pull(image); err != nil { return fmt.Errorf("failed to pull image %q: %v", image, err) } - glog.Infof("[config/images] Pulled %s\n", image) + fmt.Printf("[config/images] Pulled %s\n", image) } return nil } // NewCmdConfigImagesList returns the "kubeadm config images list" command -func NewCmdConfigImagesList(out io.Writer) *cobra.Command { +func NewCmdConfigImagesList(out io.Writer, mockK8sVersion *string) *cobra.Command { cfg := &kubeadmapiv1alpha2.MasterConfiguration{} kubeadmscheme.Scheme.Default(cfg) var cfgPath, featureGatesString string var err error + // This just sets the kubernetes version for unit testing so kubeadm won't try to + // lookup the latest release from the internet. + if mockK8sVersion != nil { + cfg.KubernetesVersion = *mockK8sVersion + } + cmd := &cobra.Command{ Use: "list", Short: "Print a list of images kubeadm will use. The configuration file is used in case any images or image repositories are customized.", @@ -401,5 +484,5 @@ func AddImagesCommonConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.M // AddImagesPullFlags adds flags related to the `kubeadm config images pull` command func AddImagesPullFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.MasterConfiguration) { - flagSet.StringVar(&cfg.CRISocket, "cri-socket-path", cfg.CRISocket, "Path to the CRI socket.") + flagSet.StringVar(&cfg.NodeRegistration.CRISocket, "cri-socket-path", cfg.NodeRegistration.CRISocket, "Path to the CRI socket.") } diff --git a/cmd/kubeadm/app/cmd/config_test.go b/cmd/kubeadm/app/cmd/config_test.go index 622d6983e26..18db0ec99ca 100644 --- a/cmd/kubeadm/app/cmd/config_test.go +++ b/cmd/kubeadm/app/cmd/config_test.go @@ -29,15 +29,20 @@ import ( kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/cmd" "k8s.io/kubernetes/cmd/kubeadm/app/features" + "k8s.io/kubernetes/cmd/kubeadm/app/util/config" ) 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.10.0" ) func TestNewCmdConfigImagesList(t *testing.T) { var output bytes.Buffer - images := cmd.NewCmdConfigImagesList(&output) + mockK8sVersion := dummyKubernetesVersion + images := cmd.NewCmdConfigImagesList(&output, &mockK8sVersion) images.Run(nil, nil) actual := strings.Split(output.String(), "\n") if len(actual) != defaultNumberOfImages { @@ -53,11 +58,6 @@ func TestImagesListRunWithCustomConfigPath(t *testing.T) { expectedImageSubstrings []string configContents []byte }{ - { - name: "empty config contents", - expectedImageCount: defaultNumberOfImages, - configContents: []byte{}, - }, { name: "set k8s version", expectedImageCount: defaultNumberOfImages, @@ -67,7 +67,7 @@ func TestImagesListRunWithCustomConfigPath(t *testing.T) { configContents: []byte(dedent.Dedent(` apiVersion: kubeadm.k8s.io/v1alpha2 kind: MasterConfiguration - kubernetesVersion: 1.10.1 + kubernetesVersion: v1.10.1 `)), }, { @@ -79,8 +79,9 @@ func TestImagesListRunWithCustomConfigPath(t *testing.T) { configContents: []byte(dedent.Dedent(` apiVersion: kubeadm.k8s.io/v1alpha2 kind: MasterConfiguration + kubernetesVersion: v1.11.0 featureGates: - CoreDNS: True + CoreDNS: True `)), }, } @@ -99,7 +100,9 @@ func TestImagesListRunWithCustomConfigPath(t *testing.T) { t.Fatalf("Failed writing a config file: %v", err) } - i, err := cmd.NewImagesList(configFilePath, &kubeadmapiv1alpha2.MasterConfiguration{}) + i, err := cmd.NewImagesList(configFilePath, &kubeadmapiv1alpha2.MasterConfiguration{ + KubernetesVersion: dummyKubernetesVersion, + }) if err != nil { t.Fatalf("Failed getting the kubeadm images command: %v", err) } @@ -130,6 +133,9 @@ func TestConfigImagesListRunWithoutPath(t *testing.T) { { name: "empty config", expectedImages: defaultNumberOfImages, + cfg: kubeadmapiv1alpha2.MasterConfiguration{ + KubernetesVersion: dummyKubernetesVersion, + }, }, { name: "external etcd configuration", @@ -139,6 +145,7 @@ func TestConfigImagesListRunWithoutPath(t *testing.T) { Endpoints: []string{"https://some.etcd.com:2379"}, }, }, + KubernetesVersion: dummyKubernetesVersion, }, expectedImages: defaultNumberOfImages - 1, }, @@ -148,6 +155,7 @@ func TestConfigImagesListRunWithoutPath(t *testing.T) { FeatureGates: map[string]bool{ features.CoreDNS: true, }, + KubernetesVersion: dummyKubernetesVersion, }, expectedImages: defaultNumberOfImages, }, @@ -196,3 +204,43 @@ func TestImagesPull(t *testing.T) { t.Fatalf("expected 2 but found %v", puller.count["a"]) } } + +func TestMigrate(t *testing.T) { + cfg := []byte(dedent.Dedent(` + apiVersion: kubeadm.k8s.io/v1alpha2 + kind: MasterConfiguration + kubernetesVersion: v1.10.0 + `)) + configFile, cleanup := tempConfig(t, cfg) + defer cleanup() + + var output bytes.Buffer + command := cmd.NewCmdConfigMigrate(&output) + err := command.Flags().Set("old-config", configFile) + if err != nil { + t.Fatalf("failed to set old-config flag") + } + command.Run(nil, nil) + _, err = config.BytesToInternalConfig(output.Bytes()) + if err != nil { + t.Fatalf("Could not read output back into internal type: %v", err) + } +} + +// Returns the name of the file created and a cleanup callback +func tempConfig(t *testing.T, config []byte) (string, func()) { + t.Helper() + tmpDir, err := ioutil.TempDir("", "kubeadm-migration-test") + if err != nil { + t.Fatalf("Unable to create temporary directory: %v", err) + } + configFilePath := filepath.Join(tmpDir, "test-config-file") + err = ioutil.WriteFile(configFilePath, config, 0644) + if err != nil { + os.RemoveAll(tmpDir) + t.Fatalf("Failed writing a config file: %v", err) + } + return configFilePath, func() { + os.RemoveAll(tmpDir) + } +} diff --git a/cmd/kubeadm/app/cmd/init.go b/cmd/kubeadm/app/cmd/init.go index e763d8fd7c0..5467b59956e 100644 --- a/cmd/kubeadm/app/cmd/init.go +++ b/cmd/kubeadm/app/cmd/init.go @@ -37,6 +37,7 @@ import ( kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" @@ -51,6 +52,7 @@ import ( kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" markmasterphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster" + patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode" selfhostingphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting" uploadconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig" "k8s.io/kubernetes/cmd/kubeadm/app/preflight" @@ -123,6 +125,9 @@ func NewCmdInit(out io.Writer) *cobra.Command { var dryRun bool var featureGatesString string var ignorePreflightErrors []string + // Create the options object for the bootstrap token-related flags, and override the default value for .Description + bto := options.NewBootstrapTokenOptions() + bto.Description = "The default bootstrap token generated by 'kubeadm init'." cmd := &cobra.Command{ Use: "init", @@ -142,6 +147,9 @@ func NewCmdInit(out io.Writer) *cobra.Command { err = validation.ValidateMixedArguments(cmd.Flags()) kubeadmutil.CheckErr(err) + err = bto.ApplyTo(externalcfg) + kubeadmutil.CheckErr(err) + i, err := NewInit(cfgPath, externalcfg, ignorePreflightErrorsSet, skipTokenPrint, dryRun) kubeadmutil.CheckErr(err) kubeadmutil.CheckErr(i.Run(out)) @@ -150,6 +158,8 @@ func NewCmdInit(out io.Writer) *cobra.Command { AddInitConfigFlags(cmd.PersistentFlags(), externalcfg, &featureGatesString) AddInitOtherFlags(cmd.PersistentFlags(), &cfgPath, &skipPreFlight, &skipTokenPrint, &dryRun, &ignorePreflightErrors) + bto.AddTokenFlag(cmd.PersistentFlags()) + bto.AddTTLFlag(cmd.PersistentFlags()) return cmd } @@ -189,24 +199,15 @@ func AddInitConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.MasterCon `Optional extra Subject Alternative Names (SANs) to use for the API Server serving certificate. Can be both IP addresses and DNS names.`, ) flagSet.StringVar( - &cfg.NodeName, "node-name", cfg.NodeName, + &cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name, `Specify the node name.`, ) flagSet.StringVar( - &cfg.Token, "token", cfg.Token, - "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", - ) - flagSet.DurationVar( - &cfg.TokenTTL.Duration, "token-ttl", cfg.TokenTTL.Duration, - "The duration before the bootstrap token is automatically deleted. If set to '0', the token will never expire.", - ) - flagSet.StringVar( - &cfg.CRISocket, "cri-socket", cfg.CRISocket, + &cfg.NodeRegistration.CRISocket, "cri-socket", cfg.NodeRegistration.CRISocket, `Specify the CRI socket to connect to.`, ) flagSet.StringVar(featureGatesString, "feature-gates", *featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+ "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) - } // AddInitOtherFlags adds init flags that are not bound to a configuration file to the given flagset @@ -251,14 +252,25 @@ func NewInit(cfgPath string, externalcfg *kubeadmapiv1alpha2.MasterConfiguration return nil, err } - glog.Infof("[init] using Kubernetes version: %s\n", cfg.KubernetesVersion) + fmt.Printf("[init] using Kubernetes version: %s\n", cfg.KubernetesVersion) - glog.Infoln("[preflight] running pre-flight checks") + fmt.Println("[preflight] running pre-flight checks") if err := preflight.RunInitMasterChecks(utilsexec.New(), cfg, ignorePreflightErrors); err != nil { return nil, err } + if !dryRun { + fmt.Println("[preflight/images] Pulling images required for setting up a Kubernetes cluster") + fmt.Println("[preflight/images] This might take a minute or two, depending on the speed of your internet connection") + fmt.Println("[preflight/images] You can also perform this action in beforehand using 'kubeadm config images pull'") + if err := preflight.RunPullImagesCheck(utilsexec.New(), cfg, ignorePreflightErrors); err != nil { + return nil, err + } + } else { + fmt.Println("[preflight/images] Would pull the required images (like 'kubeadm config images pull')") + } + return &Init{cfg: cfg, skipTokenPrint: skipTokenPrint, dryRun: dryRun, ignorePreflightErrors: ignorePreflightErrors}, nil } @@ -273,22 +285,39 @@ type Init struct { // Run executes master node provisioning, including certificates, needed static pod manifests, etc. func (i *Init) Run(out io.Writer) error { - // Write env file with flags for the kubelet to use - if err := kubeletphase.WriteKubeletDynamicEnvFile(i.cfg); err != nil { - return err - } - - // Try to start the kubelet service in case it's inactive - glog.V(1).Infof("Starting kubelet") - preflight.TryStartKubelet(i.ignorePreflightErrors) - // Get directories to write files to; can be faked if we're dry-running glog.V(1).Infof("[init] Getting certificates directory from configuration") realCertsDir := i.cfg.CertificatesDir - certsDirToWriteTo, kubeConfigDir, manifestDir, err := getDirectoriesToUse(i.dryRun, i.cfg.CertificatesDir) + certsDirToWriteTo, kubeConfigDir, manifestDir, kubeletDir, err := getDirectoriesToUse(i.dryRun, i.cfg.CertificatesDir) if err != nil { return fmt.Errorf("error getting directories to use: %v", err) } + + // First off, configure the kubelet. In this short timeframe, kubeadm is trying to stop/restart the kubelet + // Try to stop the kubelet service so no race conditions occur when configuring it + if !i.dryRun { + glog.V(1).Infof("Stopping the kubelet") + preflight.TryStopKubelet() + } + + // Write env file with flags for the kubelet to use. We do not need to write the --register-with-taints for the master, + // 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(&i.cfg.NodeRegistration, i.cfg.FeatureGates, false, kubeletDir); err != nil { + return fmt.Errorf("error writing a dynamic environment file for the kubelet: %v", err) + } + + // Write the kubelet configuration file to disk. + if err := kubeletphase.WriteConfigToDisk(i.cfg.KubeletConfiguration.BaseConfig, kubeletDir); err != nil { + return fmt.Errorf("error writing kubelet configuration to disk: %v", err) + } + + if !i.dryRun { + // Try to start the kubelet service in case it's inactive + glog.V(1).Infof("Starting the kubelet") + preflight.TryStartKubelet() + } + // certsDirToWriteTo is gonna equal cfg.CertificatesDir in the normal case, but gonna be a temp directory if dryrunning i.cfg.CertificatesDir = certsDirToWriteTo @@ -309,7 +338,7 @@ func (i *Init) Run(out io.Writer) error { } } else { - glog.Infoln("[externalca] the file 'ca.key' was not found, yet all other certificates are present. Using external CA mode - certificates or kubeconfig will not be generated") + fmt.Println("[externalca] the file 'ca.key' was not found, yet all other certificates are present. Using external CA mode - certificates or kubeconfig will not be generated") } if features.Enabled(i.cfg.FeatureGates, features.Auditing) { @@ -353,16 +382,6 @@ func (i *Init) Run(out io.Writer) error { return fmt.Errorf("error printing files on dryrun: %v", err) } - kubeletVersion, err := preflight.GetKubeletVersion(utilsexec.New()) - if err != nil { - return err - } - - // Write the kubelet configuration to disk. - if err := kubeletphase.WriteConfigToDisk(i.cfg.KubeletConfiguration.BaseConfig, kubeletVersion); err != nil { - return fmt.Errorf("error writing kubelet configuration to disk: %v", err) - } - // Create a kubernetes client and wait for the API server to be healthy (if not dryrunning) glog.V(1).Infof("creating Kubernetes client") client, err := createClient(i.cfg, i.dryRun) @@ -374,7 +393,10 @@ func (i *Init) Run(out io.Writer) error { glog.V(1).Infof("[init] waiting for the API server to be healthy") waiter := getWaiter(i, client) - if err := waitForAPIAndKubelet(waiter); err != nil { + fmt.Printf("[init] waiting for the kubelet to boot up the control plane as Static Pods from directory %q \n", kubeadmconstants.GetStaticPodDirectory()) + fmt.Println("[init] this might take a minute or longer if the control plane images have to be pulled") + + if err := waitForKubeletAndFunc(waiter, waiter.WaitForAPI); err != nil { ctx := map[string]string{ "Error": fmt.Sprintf("%v", err), "APIServerImage": images.GetCoreImage(kubeadmconstants.KubeAPIServer, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage), @@ -408,28 +430,44 @@ func (i *Init) Run(out io.Writer) error { // PHASE 4: Mark the master with the right label/taint glog.V(1).Infof("[init] marking the master with right label") - if err := markmasterphase.MarkMaster(client, i.cfg.NodeName, !i.cfg.NoTaintMaster); err != nil { + if err := markmasterphase.MarkMaster(client, i.cfg.NodeRegistration.Name, i.cfg.NodeRegistration.Taints); err != nil { return fmt.Errorf("error marking master: %v", err) } - // NOTE: flag "--dynamic-config-dir" should be specified in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf - // This feature is disabled by default, as it is alpha still + glog.V(1).Infof("[init] preserving the crisocket information for the master") + if err := patchnodephase.AnnotateCRISocket(client, i.cfg.NodeRegistration.Name, i.cfg.NodeRegistration.CRISocket); err != nil { + return fmt.Errorf("error uploading crisocket: %v", err) + } + + // This feature is disabled by default if features.Enabled(i.cfg.FeatureGates, features.DynamicKubeletConfig) { + kubeletVersion, err := preflight.GetKubeletVersion(utilsexec.New()) + if err != nil { + return err + } + // Enable dynamic kubelet configuration for the node. - if err := kubeletphase.EnableDynamicConfigForNode(client, i.cfg.NodeName, kubeletVersion); err != nil { + if err := kubeletphase.EnableDynamicConfigForNode(client, i.cfg.NodeRegistration.Name, kubeletVersion); err != nil { return fmt.Errorf("error enabling dynamic kubelet configuration: %v", err) } } // PHASE 5: Set up the node bootstrap tokens + tokens := []string{} + for _, bt := range i.cfg.BootstrapTokens { + tokens = append(tokens, bt.Token.String()) + } if !i.skipTokenPrint { - glog.Infof("[bootstraptoken] using token: %s\n", i.cfg.Token) + if len(tokens) == 1 { + fmt.Printf("[bootstraptoken] using token: %s\n", tokens[0]) + } else if len(tokens) > 1 { + fmt.Printf("[bootstraptoken] using tokens: %v\n", tokens) + } } // Create the default node bootstrap token glog.V(1).Infof("[init] creating RBAC rules to generate default bootstrap token") - tokenDescription := "The default bootstrap token generated by 'kubeadm init'." - if err := nodebootstraptokenphase.UpdateOrCreateToken(client, i.cfg.Token, false, i.cfg.TokenTTL.Duration, i.cfg.TokenUsages, i.cfg.TokenGroups, tokenDescription); err != nil { + if err := nodebootstraptokenphase.UpdateOrCreateTokens(client, false, i.cfg.BootstrapTokens); err != nil { return fmt.Errorf("error updating or creating token: %v", err) } // Create RBAC rules that makes the bootstrap tokens able to post CSRs @@ -470,11 +508,11 @@ func (i *Init) Run(out io.Writer) error { } // PHASE 7: Make the control plane self-hosted if feature gate is enabled - glog.V(1).Infof("[init] feature gate is enabled. Making control plane self-hosted") if features.Enabled(i.cfg.FeatureGates, features.SelfHosting) { + glog.V(1).Infof("[init] feature gate is enabled. Making control plane self-hosted") // Temporary control plane is up, now we create our self hosted control // plane components and remove the static manifests: - glog.Infoln("[self-hosted] creating self-hosted control plane") + fmt.Println("[self-hosted] creating self-hosted control plane") if err := selfhostingphase.CreateSelfHostedControlPlane(manifestDir, kubeConfigDir, i.cfg, client, waiter, i.dryRun); err != nil { return fmt.Errorf("error creating self hosted control plane: %v", err) } @@ -486,10 +524,19 @@ func (i *Init) Run(out io.Writer) error { return nil } - // Gets the join command - joinCommand, err := cmdutil.GetJoinCommand(kubeadmconstants.GetAdminKubeConfigPath(), i.cfg.Token, i.skipTokenPrint) + // Prints the join command, multiple times in case the user has multiple tokens + for _, token := range tokens { + if err := printJoinCommand(out, adminKubeConfigPath, token, i.skipTokenPrint); err != nil { + return fmt.Errorf("failed to print join command: %v", err) + } + } + return nil +} + +func printJoinCommand(out io.Writer, adminKubeConfigPath, token string, skipTokenPrint bool) error { + joinCommand, err := cmdutil.GetJoinCommand(adminKubeConfigPath, token, skipTokenPrint) if err != nil { - return fmt.Errorf("failed to get join command: %v", err) + return err } ctx := map[string]string{ @@ -504,7 +551,7 @@ func (i *Init) Run(out io.Writer) error { func createClient(cfg *kubeadmapi.MasterConfiguration, dryRun bool) (clientset.Interface, error) { if dryRun { // If we're dry-running; we should create a faked client that answers some GETs in order to be able to do the full init flow and just logs the rest of requests - dryRunGetter := apiclient.NewInitDryRunGetter(cfg.NodeName, cfg.Networking.ServiceSubnet) + dryRunGetter := apiclient.NewInitDryRunGetter(cfg.NodeRegistration.Name, cfg.Networking.ServiceSubnet) return apiclient.NewDryRunClient(dryRunGetter, os.Stdout), nil } @@ -514,17 +561,17 @@ func createClient(cfg *kubeadmapi.MasterConfiguration, dryRun bool) (clientset.I // getDirectoriesToUse returns the (in order) certificates, kubeconfig and Static Pod manifest directories, followed by a possible error // This behaves differently when dry-running vs the normal flow -func getDirectoriesToUse(dryRun bool, defaultPkiDir string) (string, string, string, error) { +func getDirectoriesToUse(dryRun bool, defaultPkiDir string) (string, string, string, string, error) { if dryRun { dryRunDir, err := ioutil.TempDir("", "kubeadm-init-dryrun") if err != nil { - return "", "", "", fmt.Errorf("couldn't create a temporary directory: %v", err) + return "", "", "", "", fmt.Errorf("couldn't create a temporary directory: %v", err) } // Use the same temp dir for all - return dryRunDir, dryRunDir, dryRunDir, nil + return dryRunDir, dryRunDir, dryRunDir, dryRunDir, nil } - return defaultPkiDir, kubeadmconstants.KubernetesDir, kubeadmconstants.GetStaticPodDirectory(), nil + return defaultPkiDir, kubeadmconstants.KubernetesDir, kubeadmconstants.GetStaticPodDirectory(), kubeadmconstants.KubeletRunDirectory, nil } // printFilesIfDryRunning prints the Static Pod manifests to stdout and informs about the temporary directory to go and lookup @@ -533,17 +580,25 @@ func printFilesIfDryRunning(dryRun bool, manifestDir string) error { return nil } - glog.Infof("[dryrun] wrote certificates, kubeconfig files and control plane manifests to the %q directory\n", manifestDir) - glog.Infoln("[dryrun] the certificates or kubeconfig files would not be printed due to their sensitive nature") - glog.Infof("[dryrun] please examine the %q directory for details about what would be written\n", manifestDir) + fmt.Printf("[dryrun] wrote certificates, kubeconfig files and control plane manifests to the %q directory\n", manifestDir) + fmt.Println("[dryrun] the certificates or kubeconfig files would not be printed due to their sensitive nature") + fmt.Printf("[dryrun] please examine the %q directory for details about what would be written\n", manifestDir) // Print the contents of the upgraded manifests and pretend like they were in /etc/kubernetes/manifests files := []dryrunutil.FileToPrint{} + // Print static pod manifests for _, component := range kubeadmconstants.MasterComponents { realPath := kubeadmconstants.GetStaticPodFilepath(component, manifestDir) outputPath := kubeadmconstants.GetStaticPodFilepath(component, kubeadmconstants.GetStaticPodDirectory()) files = append(files, dryrunutil.NewFileToPrint(realPath, outputPath)) } + // Print kubelet config manifests + kubeletConfigFiles := []string{kubeadmconstants.KubeletConfigurationFileName, kubeadmconstants.KubeletEnvFileName} + for _, filename := range kubeletConfigFiles { + realPath := filepath.Join(manifestDir, filename) + outputPath := filepath.Join(kubeadmconstants.KubeletRunDirectory, filename) + files = append(files, dryrunutil.NewFileToPrint(realPath, outputPath)) + } return dryrunutil.PrintDryRunFiles(files, os.Stdout) } @@ -554,32 +609,30 @@ func getWaiter(i *Init, client clientset.Interface) apiclient.Waiter { return dryrunutil.NewWaiter() } - // TODO: List images locally using `crictl` and pull in preflight checks if not available - // When we do that, we can always assume the images exist at this point and have a shorter timeout. - timeout := 30 * time.Minute + // We know that the images should be cached locally already as we have pulled them using + // crictl in the preflight checks. Hence we can have a pretty short timeout for the kubelet + // to start creating Static Pods. + timeout := 4 * time.Minute return apiclient.NewKubeWaiter(client, timeout, os.Stdout) } -// waitForAPIAndKubelet waits primarily for the API server to come up. If that takes a long time, and the kubelet -// /healthz and /healthz/syncloop endpoints continuously are unhealthy, kubeadm will error out after a period of -// backoffing exponentially -func waitForAPIAndKubelet(waiter apiclient.Waiter) error { +// waitForKubeletAndFunc waits primarily for the function f to execute, even though it might take some time. If that takes a long time, and the kubelet +// /healthz continuously are unhealthy, kubeadm will error out after a period of exponential backoff +func waitForKubeletAndFunc(waiter apiclient.Waiter, f func() error) error { errorChan := make(chan error) - glog.Infof("[init] waiting for the kubelet to boot up the control plane as Static Pods from directory %q \n", kubeadmconstants.GetStaticPodDirectory()) - glog.Infoln("[init] this might take a minute or longer if the control plane images have to be pulled") - go func(errC chan error, waiter apiclient.Waiter) { // This goroutine can only make kubeadm init fail. If this check succeeds, it won't do anything special + // TODO: Make 10248 a constant somewhere if err := waiter.WaitForHealthyKubelet(40*time.Second, "http://localhost:10248/healthz"); err != nil { errC <- err } }(errorChan, waiter) go func(errC chan error, waiter apiclient.Waiter) { - // This main goroutine sends whatever WaitForAPI returns (error or not) to the channel - // This in order to continue on success (nil error), or just fail if - errC <- waiter.WaitForAPI() + // This main goroutine sends whatever the f function returns (error or not) to the channel + // This in order to continue on success (nil error), or just fail if the function returns an error + errC <- f() }(errorChan, waiter) // This call is blocking until one of the goroutines sends to errorChan diff --git a/cmd/kubeadm/app/cmd/join.go b/cmd/kubeadm/app/cmd/join.go index 77fcb6697ca..20ccfb4f048 100644 --- a/cmd/kubeadm/app/cmd/join.go +++ b/cmd/kubeadm/app/cmd/join.go @@ -19,6 +19,7 @@ package cmd import ( "fmt" "io" + "os" "path/filepath" "strings" @@ -28,6 +29,7 @@ import ( flag "github.com/spf13/pflag" "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/wait" certutil "k8s.io/client-go/util/cert" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" @@ -37,8 +39,10 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/discovery" "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" + patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode" "k8s.io/kubernetes/cmd/kubeadm/app/preflight" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" utilsexec "k8s.io/utils/exec" @@ -96,6 +100,19 @@ var ( Often times the same token is used for both parts. In this case, the --token flag can be used instead of specifying each token individually. `) + + kubeadmJoinFailMsgf = dedent.Dedent(` + Unfortunately, an error has occurred: + %v + + This error is likely caused by: + - The kubelet is not running + - The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled) + + If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands: + - 'systemctl status kubelet' + - 'journalctl -xeu kubelet' + `) ) // NewCmdJoin returns "kubeadm join" command. @@ -155,7 +172,7 @@ func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.NodeConfi &cfg.DiscoveryToken, "discovery-token", "", "A token used to validate cluster information fetched from the master.") flagSet.StringVar( - &cfg.NodeName, "node-name", "", + &cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name, "Specify the node name.") flagSet.StringVar( &cfg.TLSBootstrapToken, "tls-bootstrap-token", "", @@ -174,7 +191,7 @@ func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.NodeConfi "A set of key=value pairs that describe feature gates for various features. "+ "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) flagSet.StringVar( - &cfg.CRISocket, "cri-socket", cfg.CRISocket, + &cfg.NodeRegistration.CRISocket, "cri-socket", cfg.NodeRegistration.CRISocket, `Specify the CRI socket to connect to.`, ) } @@ -198,13 +215,14 @@ func AddJoinOtherFlags(flagSet *flag.FlagSet, cfgPath *string, skipPreFlight *bo // Join defines struct used by kubeadm join command type Join struct { - cfg *kubeadmapi.NodeConfiguration + cfg *kubeadmapi.NodeConfiguration + ignorePreflightErrors sets.String } // NewJoin instantiates Join struct with given arguments func NewJoin(cfgPath string, args []string, defaultcfg *kubeadmapiv1alpha2.NodeConfiguration, ignorePreflightErrors sets.String) (*Join, error) { - if defaultcfg.NodeName == "" { + if defaultcfg.NodeRegistration.Name == "" { glog.V(1).Infoln("[join] found NodeName empty") glog.V(1).Infoln("[join] considered OS hostname as NodeName") } @@ -214,7 +232,7 @@ func NewJoin(cfgPath string, args []string, defaultcfg *kubeadmapiv1alpha2.NodeC return nil, err } - glog.Infoln("[preflight] running pre-flight checks") + fmt.Println("[preflight] running pre-flight checks") // Then continue with the others... glog.V(1).Infoln("[preflight] running various checks on all nodes") @@ -222,33 +240,31 @@ func NewJoin(cfgPath string, args []string, defaultcfg *kubeadmapiv1alpha2.NodeC return nil, err } - // Try to start the kubelet service in case it's inactive - glog.V(1).Infoln("[preflight] starting kubelet service if it's inactive") - preflight.TryStartKubelet(ignorePreflightErrors) - - return &Join{cfg: internalcfg}, nil + return &Join{cfg: internalcfg, ignorePreflightErrors: ignorePreflightErrors}, nil } // Run executes worker node provisioning and tries to join an existing cluster. func (j *Join) Run(out io.Writer) error { + + // Perform the Discovery, which turns a Bootstrap Token and optionally (and preferably) a CA cert hash into a KubeConfig + // file that may be used for the TLS Bootstrapping process the kubelet performs using the Certificates API. glog.V(1).Infoln("[join] retrieving KubeConfig objects") cfg, err := discovery.For(j.cfg) if err != nil { return err } - kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletBootstrapKubeConfigFileName) + bootstrapKubeConfigFile := kubeadmconstants.GetBootstrapKubeletKubeConfigPath() // Write the bootstrap kubelet config file or the TLS-Boostrapped kubelet config file down to disk - glog.V(1).Infoln("[join] writing bootstrap kubelet config file at", kubeconfigFile) - if err := kubeconfigutil.WriteToDisk(kubeconfigFile, cfg); err != nil { + glog.V(1).Infoln("[join] writing bootstrap kubelet config file at", bootstrapKubeConfigFile) + if err := kubeconfigutil.WriteToDisk(bootstrapKubeConfigFile, cfg); err != nil { return fmt.Errorf("couldn't save bootstrap-kubelet.conf to disk: %v", err) } // Write the ca certificate to disk so kubelet can use it for authentication cluster := cfg.Contexts[cfg.CurrentContext].Cluster - err = certutil.WriteCert(j.cfg.CACertPath, cfg.Clusters[cluster].CertificateAuthorityData) - if err != nil { + if err := certutil.WriteCert(j.cfg.CACertPath, cfg.Clusters[cluster].CertificateAuthorityData); err != nil { return fmt.Errorf("couldn't save the CA certificate to disk: %v", err) } @@ -257,23 +273,53 @@ func (j *Join) Run(out io.Writer) error { return err } - // Write the configuration for the kubelet down to disk so the kubelet can start - if err := kubeletphase.DownloadConfig(kubeconfigFile, kubeletVersion); err != nil { + bootstrapClient, err := kubeconfigutil.ClientSetFromFile(bootstrapKubeConfigFile) + if err != nil { + return fmt.Errorf("couldn't create client from kubeconfig file %q", bootstrapKubeConfigFile) + } + + // Configure the kubelet. In this short timeframe, kubeadm is trying to stop/restart the kubelet + // Try to stop the kubelet service so no race conditions occur when configuring it + glog.V(1).Infof("Stopping the kubelet") + preflight.TryStopKubelet() + + // Write the configuration for the kubelet (using the bootstrap token credentials) to disk so the kubelet can start + if err := kubeletphase.DownloadConfig(bootstrapClient, kubeletVersion, kubeadmconstants.KubeletRunDirectory); err != nil { return err } - // Now the kubelet will perform the TLS Bootstrap, transforming bootstrap-kubeconfig.conf to kubeconfig.conf in /etc/kubernetes + // Write env file with flags for the kubelet to use. Also register taints + if err := kubeletphase.WriteKubeletDynamicEnvFile(&j.cfg.NodeRegistration, j.cfg.FeatureGates, true, kubeadmconstants.KubeletRunDirectory); err != nil { + return err + } - // NOTE: the "--dynamic-config-dir" flag should be specified in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf for this to work - // This feature is disabled by default, as it is alpha still - glog.V(1).Infoln("[join] enabling dynamic kubelet configuration") + // Try to start the kubelet service in case it's inactive + glog.V(1).Infof("Starting the kubelet") + preflight.TryStartKubelet() + + // Now the kubelet will perform the TLS Bootstrap, transforming /etc/kubernetes/bootstrap-kubelet.conf to /etc/kubernetes/kubelet.conf + // Wait for the kubelet to create the /etc/kubernetes/kubelet.conf KubeConfig file. If this process + // times out, display a somewhat user-friendly message. + waiter := apiclient.NewKubeWaiter(nil, kubeadmconstants.TLSBootstrapTimeout, os.Stdout) + if err := waitForKubeletAndFunc(waiter, waitForTLSBootstrappedClient); err != nil { + fmt.Printf(kubeadmJoinFailMsgf, err) + return err + } + + // When we know the /etc/kubernetes/kubelet.conf file is available, get the client + client, err := kubeconfigutil.ClientSetFromFile(kubeadmconstants.GetKubeletKubeConfigPath()) + if err != nil { + return err + } + + glog.V(1).Infof("[join] preserving the crisocket information for the node") + if err := patchnodephase.AnnotateCRISocket(client, j.cfg.NodeRegistration.Name, j.cfg.NodeRegistration.CRISocket); err != nil { + return fmt.Errorf("error uploading crisocket: %v", err) + } + + // This feature is disabled by default in kubeadm if features.Enabled(j.cfg.FeatureGates, features.DynamicKubeletConfig) { - client, err := kubeletphase.GetLocalNodeTLSBootstrappedClient() - if err != nil { - return err - } - - if err := kubeletphase.EnableDynamicConfigForNode(client, j.cfg.NodeName, kubeletVersion); err != nil { + if err := kubeletphase.EnableDynamicConfigForNode(client, j.cfg.NodeRegistration.Name, kubeletVersion); err != nil { return fmt.Errorf("error consuming base kubelet configuration: %v", err) } } @@ -281,3 +327,15 @@ func (j *Join) Run(out io.Writer) error { fmt.Fprintf(out, joinDoneMsgf) return nil } + +// waitForTLSBootstrappedClient waits for the /etc/kubernetes/kubelet.conf file to be available +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) + return (err == nil), nil + }) +} diff --git a/cmd/kubeadm/app/cmd/options/BUILD b/cmd/kubeadm/app/cmd/options/BUILD new file mode 100644 index 00000000000..c04f725e520 --- /dev/null +++ b/cmd/kubeadm/app/cmd/options/BUILD @@ -0,0 +1,31 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "generic.go", + "token.go", + ], + importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options", + visibility = ["//visibility:public"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/api: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/cmd/kubeadm/app/cmd/options/generic.go b/cmd/kubeadm/app/cmd/options/generic.go new file mode 100644 index 00000000000..7aa8d82f98c --- /dev/null +++ b/cmd/kubeadm/app/cmd/options/generic.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 options + +import "github.com/spf13/pflag" + +// AddKubeConfigFlag adds the --kubeconfig flag to the given flagset +func AddKubeConfigFlag(fs *pflag.FlagSet, kubeConfigFile *string) { + fs.StringVar(kubeConfigFile, "kubeconfig", *kubeConfigFile, "The KubeConfig file to use when talking to the cluster") +} + +// AddConfigFlag adds the --config flag to the given flagset +func AddConfigFlag(fs *pflag.FlagSet, cfgPath *string) { + fs.StringVar(cfgPath, "config", *cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)") +} diff --git a/cmd/kubeadm/app/cmd/options/token.go b/cmd/kubeadm/app/cmd/options/token.go new file mode 100644 index 00000000000..d875eb9d5a5 --- /dev/null +++ b/cmd/kubeadm/app/cmd/options/token.go @@ -0,0 +1,104 @@ +/* +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 options + +import ( + "fmt" + "strings" + + "github.com/spf13/pflag" + + bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" +) + +// NewBootstrapTokenOptions creates a new BootstrapTokenOptions object with the default values +func NewBootstrapTokenOptions() *BootstrapTokenOptions { + bto := &BootstrapTokenOptions{&kubeadmapiv1alpha2.BootstrapToken{}, ""} + kubeadmapiv1alpha2.SetDefaults_BootstrapToken(bto.BootstrapToken) + return bto +} + +// BootstrapTokenOptions is a wrapper struct for adding bootstrap token-related flags to a FlagSet +// and applying the parsed flags to a MasterConfiguration object later at runtime +// TODO: In the future, we might want to group the flags in a better way than adding them all individually like this +type BootstrapTokenOptions struct { + *kubeadmapiv1alpha2.BootstrapToken + TokenStr string +} + +// AddTokenFlag adds the --token flag to the given flagset +func (bto *BootstrapTokenOptions) AddTokenFlag(fs *pflag.FlagSet) { + fs.StringVar( + &bto.TokenStr, "token", "", + "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") +} + +// AddTTLFlagWithName adds the --token-ttl flag with a custom flag name given flagset +func (bto *BootstrapTokenOptions) AddTTLFlagWithName(fs *pflag.FlagSet, flagName string) { + fs.DurationVar( + &bto.TTL.Duration, flagName, bto.TTL.Duration, + "The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire", + ) +} + +// AddUsagesFlag adds the --usages flag to the given flagset +func (bto *BootstrapTokenOptions) AddUsagesFlag(fs *pflag.FlagSet) { + fs.StringSliceVar( + &bto.Usages, "usages", 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, ",")), + ) +} + +// AddGroupsFlag adds the --groups flag to the given flagset +func (bto *BootstrapTokenOptions) AddGroupsFlag(fs *pflag.FlagSet) { + fs.StringSliceVar( + &bto.Groups, "groups", bto.Groups, + fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q", bootstrapapi.BootstrapGroupPattern), + ) +} + +// AddDescriptionFlag adds the --description flag to the given flagset +func (bto *BootstrapTokenOptions) AddDescriptionFlag(fs *pflag.FlagSet) { + fs.StringVar( + &bto.Description, "description", bto.Description, + "A human friendly description of how this token is used.", + ) +} + +// ApplyTo applies the values set internally in the BootstrapTokenOptions object to a MasterConfiguration object at runtime +// If --token was specified in the CLI (as a string), it's parsed and validated before it's added to the BootstrapToken object. +func (bto *BootstrapTokenOptions) ApplyTo(cfg *kubeadmapiv1alpha2.MasterConfiguration) error { + if len(bto.TokenStr) > 0 { + var err error + bto.Token, err = kubeadmapiv1alpha2.NewBootstrapTokenString(bto.TokenStr) + if err != nil { + return err + } + } + + // Set the token specified by the flags as the first and only token to create in case --config is not specified + cfg.BootstrapTokens = []kubeadmapiv1alpha2.BootstrapToken{*bto.BootstrapToken} + return nil +} diff --git a/cmd/kubeadm/app/cmd/phases/BUILD b/cmd/kubeadm/app/cmd/phases/BUILD index faa232fb266..4644b86b5e7 100644 --- a/cmd/kubeadm/app/cmd/phases/BUILD +++ b/cmd/kubeadm/app/cmd/phases/BUILD @@ -24,6 +24,7 @@ go_library( "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", + "//cmd/kubeadm/app/cmd/options:go_default_library", "//cmd/kubeadm/app/cmd/util:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", diff --git a/cmd/kubeadm/app/cmd/phases/addons.go b/cmd/kubeadm/app/cmd/phases/addons.go index 4951b233827..26ce873ab9e 100644 --- a/cmd/kubeadm/app/cmd/phases/addons.go +++ b/cmd/kubeadm/app/cmd/phases/addons.go @@ -39,24 +39,24 @@ import ( var ( allAddonsLongDesc = normalizer.LongDesc(` - Installs the kube-dns and the kube-proxys addons components via the API server. + Installs the CoreDNS and the kube-proxys addons components via the API server. Please note that although the DNS server is deployed, it will not be scheduled until CNI is installed. ` + cmdutil.AlphaDisclaimer) allAddonsExample = normalizer.Examples(` - # Installs the kube-dns and the kube-proxys addons components via the API server, + # Installs the CoreDNS and the kube-proxys addons components via the API server, # functionally equivalent to what installed by kubeadm init. kubeadm alpha phase selfhosting from-staticpods `) - kubednsAddonsLongDesc = normalizer.LongDesc(` - Installs the kube-dns addon components via the API server. + corednsAddonsLongDesc = normalizer.LongDesc(` + Installs the CoreDNS addon components via the API server. Please note that although the DNS server is deployed, it will not be scheduled until CNI is installed. ` + cmdutil.AlphaDisclaimer) kubeproxyAddonsLongDesc = normalizer.LongDesc(` - Installs the kube-proxy addon components via the API server. + Installs the kube-proxy addon components via the API server. ` + cmdutil.AlphaDisclaimer) ) @@ -116,9 +116,9 @@ func getAddonsSubCommands() []*cobra.Command { cmdFunc: EnsureAllAddons, }, { - use: "kube-dns", - short: "Installs the kube-dns addon to a Kubernetes cluster", - long: kubednsAddonsLongDesc, + use: "coredns", + short: "Installs the CoreDNS addon to a Kubernetes cluster", + long: corednsAddonsLongDesc, cmdFunc: dnsaddon.EnsureDNSAddon, }, { @@ -151,7 +151,7 @@ func getAddonsSubCommands() []*cobra.Command { cmd.Flags().StringVar(&cfg.Networking.PodSubnet, "pod-network-cidr", cfg.Networking.PodSubnet, `The range of IP addresses used for the Pod network`) } - if properties.use == "all" || properties.use == "kube-dns" { + if properties.use == "all" || properties.use == "coredns" { cmd.Flags().StringVar(&cfg.Networking.DNSDomain, "service-dns-domain", cfg.Networking.DNSDomain, `Alternative domain for services`) cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, `The range of IP address used for service VIPs`) cmd.Flags().StringVar(&featureGatesString, "feature-gates", featureGatesString, "A set of key=value pairs that describe feature gates for various features."+ diff --git a/cmd/kubeadm/app/cmd/phases/addons_test.go b/cmd/kubeadm/app/cmd/phases/addons_test.go index e2333ec305b..713e7f8dbda 100644 --- a/cmd/kubeadm/app/cmd/phases/addons_test.go +++ b/cmd/kubeadm/app/cmd/phases/addons_test.go @@ -56,7 +56,7 @@ func TestAddonsSubCommandsHasFlags(t *testing.T) { }, }, { - command: "kube-dns", + command: "coredns", additionalFlags: []string{ "service-dns-domain", "service-cidr", diff --git a/cmd/kubeadm/app/cmd/phases/bootstraptoken.go b/cmd/kubeadm/app/cmd/phases/bootstraptoken.go index 30c43652c86..02034e5d364 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" - "strings" "github.com/golang/glog" "github.com/spf13/cobra" @@ -30,8 +29,8 @@ import ( kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo" "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" @@ -42,7 +41,7 @@ import ( var ( allTokenLongDesc = normalizer.LongDesc(` - Bootstrap tokens are used for establishing bidirectional trust between a node joining + Bootstrap tokens are used for establishing bidirectional trust between a node joining the cluster and a the master node. This command makes all the configurations required to make bootstrap tokens works @@ -50,21 +49,21 @@ var ( ` + cmdutil.AlphaDisclaimer) allTokenExamples = normalizer.Examples(` - # Makes all the bootstrap token configurations and creates an initial token, functionally + # Makes all the bootstrap token configurations and creates an initial token, functionally # equivalent to what generated by kubeadm init. kubeadm alpha phase bootstrap-token all `) createTokenLongDesc = normalizer.LongDesc(` Creates a bootstrap token. If no token value is given, kubeadm will generate a random token instead. - + Alternatively, you can use kubeadm token. ` + cmdutil.AlphaDisclaimer) clusterInfoLongDesc = fmt.Sprintf(normalizer.LongDesc(` - Uploads the %q ConfigMap in the %q namespace, populating it with cluster information extracted from the - given kubeconfig file. The ConfigMap is used for the node bootstrap process in its initial phases, - before the client trusts the API server. + Uploads the %q ConfigMap in the %q namespace, populating it with cluster information extracted from the + given kubeconfig file. The ConfigMap is used for the node bootstrap process in its initial phases, + before the client trusts the API server. See online documentation about Authenticating with Bootstrap Tokens for more details. `+cmdutil.AlphaDisclaimer), bootstrapapi.ConfigMapClusterInfo, metav1.NamespacePublic) @@ -77,10 +76,10 @@ var ( ` + cmdutil.AlphaDisclaimer) nodeAutoApproveLongDesc = normalizer.LongDesc(` - Configures RBAC rules to allow the csrapprover controller to automatically approve + Configures RBAC rules to allow the csrapprover controller to automatically approve certificate signing requests generated by nodes joining the cluster. It configures also RBAC rules for certificates rotation (with auto approval of new certificates). - + See online documentation about TLS bootstrapping for more details. ` + cmdutil.AlphaDisclaimer) ) @@ -111,14 +110,15 @@ func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command { cfg := &kubeadmapiv1alpha2.MasterConfiguration{ // KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig - KubernetesVersion: "v1.9.0", + KubernetesVersion: "v1.10.0", } // Default values for the cobra help text kubeadmscheme.Scheme.Default(cfg) - var cfgPath, description string + var cfgPath string var skipTokenPrint bool + bto := options.NewBootstrapTokenOptions() cmd := &cobra.Command{ Use: "all", @@ -129,11 +129,14 @@ func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command { err := validation.ValidateMixedArguments(cmd.Flags()) kubeadmutil.CheckErr(err) + err = bto.ApplyTo(cfg) + kubeadmutil.CheckErr(err) + client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile) kubeadmutil.CheckErr(err) // Creates the bootstap token - err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, skipTokenPrint) + err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, skipTokenPrint) kubeadmutil.CheckErr(err) // Create the cluster-info ConfigMap or update if it already exists @@ -159,7 +162,12 @@ func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command { } // Adds flags to the command - addBootstrapTokenFlags(cmd.Flags(), cfg, &cfgPath, &description, &skipTokenPrint) + addGenericFlags(cmd.Flags(), &cfgPath, &skipTokenPrint) + bto.AddTokenFlag(cmd.Flags()) + bto.AddTTLFlag(cmd.Flags()) + bto.AddUsagesFlag(cmd.Flags()) + bto.AddGroupsFlag(cmd.Flags()) + bto.AddDescriptionFlag(cmd.Flags()) return cmd } @@ -169,14 +177,15 @@ func NewSubCmdBootstrapToken(kubeConfigFile *string) *cobra.Command { cfg := &kubeadmapiv1alpha2.MasterConfiguration{ // KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig - KubernetesVersion: "v1.9.0", + KubernetesVersion: "v1.10.0", } // Default values for the cobra help text kubeadmscheme.Scheme.Default(cfg) - var cfgPath, description string + var cfgPath string var skipTokenPrint bool + bto := options.NewBootstrapTokenOptions() cmd := &cobra.Command{ Use: "create", @@ -186,16 +195,24 @@ func NewSubCmdBootstrapToken(kubeConfigFile *string) *cobra.Command { err := validation.ValidateMixedArguments(cmd.Flags()) kubeadmutil.CheckErr(err) + err = bto.ApplyTo(cfg) + kubeadmutil.CheckErr(err) + client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile) kubeadmutil.CheckErr(err) - err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, skipTokenPrint) + err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, skipTokenPrint) kubeadmutil.CheckErr(err) }, } // Adds flags to the command - addBootstrapTokenFlags(cmd.Flags(), cfg, &cfgPath, &description, &skipTokenPrint) + addGenericFlags(cmd.Flags(), &cfgPath, &skipTokenPrint) + bto.AddTokenFlag(cmd.Flags()) + bto.AddTTLFlag(cmd.Flags()) + bto.AddUsagesFlag(cmd.Flags()) + bto.AddGroupsFlag(cmd.Flags()) + bto.AddDescriptionFlag(cmd.Flags()) return cmd } @@ -278,38 +295,18 @@ func NewSubCmdNodeBootstrapTokenAutoApprove(kubeConfigFile *string) *cobra.Comma return cmd } -func addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiv1alpha2.MasterConfiguration, cfgPath, description *string, skipTokenPrint *bool) { +func addGenericFlags(flagSet *pflag.FlagSet, cfgPath *string, skipTokenPrint *bool) { flagSet.StringVar( cfgPath, "config", *cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental", ) - flagSet.StringVar( - &cfg.Token, "token", cfg.Token, - "The token to use for establishing bidirectional trust between nodes and masters", - ) - flagSet.DurationVar( - &cfg.TokenTTL.Duration, "ttl", cfg.TokenTTL.Duration, - "The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire", - ) - flagSet.StringSliceVar( - &cfg.TokenUsages, "usages", cfg.TokenUsages, - 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, ",")), - ) - flagSet.StringSliceVar( - &cfg.TokenGroups, "groups", cfg.TokenGroups, - fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q", bootstrapapi.BootstrapGroupPattern), - ) - flagSet.StringVar( - description, "description", "The default bootstrap token generated by 'kubeadm init'.", - "A human friendly description of how this token is used.", - ) flagSet.BoolVar( skipTokenPrint, "skip-token-print", *skipTokenPrint, "Skip printing of the bootstrap token", ) } -func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfgPath string, cfg *kubeadmapiv1alpha2.MasterConfiguration, description string, skipTokenPrint bool) error { +func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfgPath string, cfg *kubeadmapiv1alpha2.MasterConfiguration, skipTokenPrint bool) error { // 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) @@ -319,18 +316,19 @@ func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfg glog.V(1).Infoln("[bootstraptoken] creating/updating token") // Creates or updates the token - if err := node.UpdateOrCreateToken(client, internalcfg.Token, false, internalcfg.TokenTTL.Duration, internalcfg.TokenUsages, internalcfg.TokenGroups, description); err != nil { + if err := node.UpdateOrCreateTokens(client, false, internalcfg.BootstrapTokens); err != nil { return err } - glog.Infoln("[bootstraptoken] bootstrap token created") - glog.Infoln("[bootstraptoken] you can now join any number of machines by running:") + fmt.Println("[bootstraptoken] bootstrap token created") + fmt.Println("[bootstraptoken] you can now join any number of machines by running:") - joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.Token, skipTokenPrint) - if err != nil { - return fmt.Errorf("failed to get join command: %v", err) + if len(internalcfg.BootstrapTokens) > 0 { + joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.BootstrapTokens[0].Token.String(), skipTokenPrint) + if err != nil { + return fmt.Errorf("failed to get join command: %v", err) + } + fmt.Println(joinCommand) } - glog.Infoln(joinCommand) - return nil } diff --git a/cmd/kubeadm/app/cmd/phases/certs_test.go b/cmd/kubeadm/app/cmd/phases/certs_test.go index 0b35c435650..32b90027479 100644 --- a/cmd/kubeadm/app/cmd/phases/certs_test.go +++ b/cmd/kubeadm/app/cmd/phases/certs_test.go @@ -254,9 +254,9 @@ func TestSubCmdCertsCreateFilesWithConfigFile(t *testing.T) { certdir := tmpdir cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234}, - CertificatesDir: certdir, - NodeName: "valid-node-name", + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234}, + CertificatesDir: certdir, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"}, } configPath := testutil.SetupMasterConfigurationFile(t, tmpdir, cfg) diff --git a/cmd/kubeadm/app/cmd/phases/kubeconfig.go b/cmd/kubeadm/app/cmd/phases/kubeconfig.go index 3f3e185299d..7a0dcb0ce5b 100644 --- a/cmd/kubeadm/app/cmd/phases/kubeconfig.go +++ b/cmd/kubeadm/app/cmd/phases/kubeconfig.go @@ -184,7 +184,7 @@ func getKubeConfigSubCommands(out io.Writer, outDir, defaultKubernetesVersion st cmd.Flags().Int32Var(&cfg.API.BindPort, "apiserver-bind-port", cfg.API.BindPort, "The port the API server is accessible on") cmd.Flags().StringVar(&outDir, "kubeconfig-dir", outDir, "The path where to save the kubeconfig file") if properties.use == "all" || properties.use == "kubelet" { - cmd.Flags().StringVar(&cfg.NodeName, "node-name", cfg.NodeName, `The node name that should be used for the kubelet client certificate`) + cmd.Flags().StringVar(&cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name, `The node name that should be used for the kubelet client certificate`) } if properties.use == "user" { cmd.Flags().StringVar(&token, "token", token, "The token that should be used as the authentication mechanism for this kubeconfig, instead of client certificates") diff --git a/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go b/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go index 309a5922a4a..f74538a6aab 100644 --- a/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go +++ b/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go @@ -277,9 +277,9 @@ func TestKubeConfigSubCommandsThatCreateFilesWithConfigFile(t *testing.T) { // Adds a master configuration file cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234}, - CertificatesDir: pkidir, - NodeName: "valid-node-name", + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234}, + CertificatesDir: pkidir, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"}, } cfgPath := testutil.SetupMasterConfigurationFile(t, tmpdir, cfg) diff --git a/cmd/kubeadm/app/cmd/phases/kubelet.go b/cmd/kubeadm/app/cmd/phases/kubelet.go index c07257d9b7f..f18171370e0 100644 --- a/cmd/kubeadm/app/cmd/phases/kubelet.go +++ b/cmd/kubeadm/app/cmd/phases/kubelet.go @@ -18,45 +18,81 @@ package phases import ( "fmt" - "os" + "io/ioutil" "github.com/spf13/cobra" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" + "k8s.io/kubernetes/cmd/kubeadm/app/preflight" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" "k8s.io/kubernetes/pkg/util/normalizer" "k8s.io/kubernetes/pkg/util/version" + utilsexec "k8s.io/utils/exec" +) + +const ( + // TODO: Figure out how to get these constants from the API machinery + masterConfig = "MasterConfiguration" + nodeConfig = "NodeConfiguration" ) var ( - kubeletWriteConfigToDiskLongDesc = normalizer.LongDesc(` - Writes kubelet configuration to disk, either based on the kubelet-config-1.X ConfigMap in the cluster, or from the - configuration passed to the command via "--config". + kubeletWriteEnvFileLongDesc = normalizer.LongDesc(` + Writes an environment file with flags that should be passed to the kubelet executing on the master or node. + This --config flag can either consume a MasterConfiguration object or a NodeConfiguration one, as this + function is used for both "kubeadm init" and "kubeadm join". ` + cmdutil.AlphaDisclaimer) - kubeletWriteConfigToDiskExample = normalizer.Examples(` - # Writes kubelet configuration for a node to disk. The information is fetched from the cluster ConfigMap - kubeadm alpha phase kubelet write-config-to-disk --kubelet-version v1.11.0 --kubeconfig /etc/kubernetes/kubelet.conf + kubeletWriteEnvFileExample = normalizer.Examples(` + # Writes a dynamic environment file with kubelet flags from a MasterConfiguration file. + kubeadm alpha phase kubelet write-env-file --config masterconfig.yaml - # Writes kubelet configuration down to disk, based on the configuration flag passed to --config - kubeadm alpha phase kubelet write-config-to-disk --kubelet-version v1.11.0 --config kubeadm.yaml + # Writes a dynamic environment file with kubelet flags from a NodeConfiguration file. + kubeadm alpha phase kubelet write-env-file --config nodeConfig.yaml `) - kubeletUploadDynamicConfigLongDesc = normalizer.LongDesc(` + kubeletConfigUploadLongDesc = normalizer.LongDesc(` Uploads kubelet configuration extracted from the kubeadm MasterConfiguration object to a ConfigMap - of the form kubelet-config-1.X in the cluster, where X is the minor version of the current Kubernetes version + of the form kubelet-config-1.X in the cluster, where X is the minor version of the current (API Server) Kubernetes version. ` + cmdutil.AlphaDisclaimer) - kubeletUploadDynamicConfigExample = normalizer.Examples(` + kubeletConfigUploadExample = normalizer.Examples(` # Uploads the kubelet configuration from the kubeadm Config file to a ConfigMap in the cluster. - kubeadm alpha phase kubelet upload-config --config kubeadm.yaml + kubeadm alpha phase kubelet config upload --config kubeadm.yaml `) - kubeletEnableDynamicConfigLongDesc = normalizer.LongDesc(` + kubeletConfigDownloadLongDesc = normalizer.LongDesc(` + Downloads the kubelet configuration from a ConfigMap of the form "kubelet-config-1.X" in the cluster, + where X is the minor version of the kubelet. Either kubeadm autodetects the kubelet version by exec-ing + "kubelet --version" or respects the --kubelet-version parameter. + ` + cmdutil.AlphaDisclaimer) + + kubeletConfigDownloadExample = normalizer.Examples(` + # 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.11.0 + `) + + kubeletConfigWriteToDiskLongDesc = normalizer.LongDesc(` + Writes kubelet configuration to disk, based on the kubeadm configuration passed via "--config". + ` + cmdutil.AlphaDisclaimer) + + kubeletConfigWriteToDiskExample = normalizer.Examples(` + # Extracts the kubelet configuration from a kubeadm configuration file + kubeadm alpha phase kubelet config write-to-disk --config kubeadm.yaml + `) + + kubeletConfigEnableDynamicLongDesc = normalizer.LongDesc(` Enables or updates dynamic kubelet configuration for a Node, against the kubelet-config-1.X ConfigMap in the cluster, where X is the minor version of the desired kubelet version. @@ -65,7 +101,7 @@ var ( ` + cmdutil.AlphaDisclaimer) - kubeletEnableDynamicConfigExample = normalizer.Examples(` + kubeletConfigEnableDynamicExample = normalizer.Examples(` # Enables dynamic kubelet configuration for a Node. kubeadm alpha phase kubelet enable-dynamic-config --node-name node-1 --kubelet-version v1.11.0 @@ -74,32 +110,110 @@ var ( `) ) -// NewCmdKubelet returns main command for Kubelet phase +// NewCmdKubelet returns command for `kubeadm phase kubelet` func NewCmdKubelet() *cobra.Command { - var kubeConfigFile string cmd := &cobra.Command{ Use: "kubelet", + Short: "Commands related to handling the kubelet.", + Long: cmdutil.MacroCommandLongDescription, + } + + cmd.AddCommand(NewCmdKubeletConfig()) + cmd.AddCommand(NewCmdKubeletWriteEnvFile()) + return cmd +} + +// NewCmdKubeletWriteEnvFile calls cobra.Command for writing the dynamic kubelet env file based on a MasterConfiguration or NodeConfiguration object +func NewCmdKubeletWriteEnvFile() *cobra.Command { + var cfgPath string + + cmd := &cobra.Command{ + Use: "write-env-file", + Short: "Writes an environment file with runtime flags for the kubelet.", + Long: kubeletWriteEnvFileLongDesc, + Example: kubeletWriteEnvFileExample, + Run: func(cmd *cobra.Command, args []string) { + err := RunKubeletWriteEnvFile(cfgPath) + kubeadmutil.CheckErr(err) + }, + } + + options.AddConfigFlag(cmd.Flags(), &cfgPath) + return cmd +} + +// RunKubeletWriteEnvFile is the function that is run when "kubeadm phase kubelet write-env-file" is executed +func RunKubeletWriteEnvFile(cfgPath string) error { + b, err := ioutil.ReadFile(cfgPath) + if err != nil { + return err + } + + gvk, err := kubeadmutil.GroupVersionKindFromBytes(b, kubeadmscheme.Codecs) + if err != nil { + return err + } + + var nodeRegistrationObj *kubeadmapi.NodeRegistrationOptions + var featureGates map[string]bool + var registerWithTaints bool + switch gvk.Kind { + case masterConfig: + internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) + if err != nil { + return err + } + nodeRegistrationObj = &internalcfg.NodeRegistration + featureGates = internalcfg.FeatureGates + registerWithTaints = false + case nodeConfig: + internalcfg, err := configutil.NodeConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.NodeConfiguration{}) + if err != nil { + return err + } + nodeRegistrationObj = &internalcfg.NodeRegistration + featureGates = internalcfg.FeatureGates + registerWithTaints = true + default: + if err != nil { + return fmt.Errorf("Didn't recognize type with GroupVersionKind: %v", gvk) + } + } + if nodeRegistrationObj == nil { + return fmt.Errorf("couldn't load nodeRegistration field from config file") + } + + if err := kubeletphase.WriteKubeletDynamicEnvFile(nodeRegistrationObj, featureGates, registerWithTaints, constants.KubeletRunDirectory); err != nil { + return fmt.Errorf("error writing a dynamic environment file for the kubelet: %v", err) + } + return nil +} + +// NewCmdKubeletConfig returns command for `kubeadm phase kubelet config` +func NewCmdKubeletConfig() *cobra.Command { + cmd := &cobra.Command{ + Use: "config", Short: "Handles kubelet configuration.", Long: cmdutil.MacroCommandLongDescription, } - cmd.PersistentFlags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster") - - cmd.AddCommand(NewCmdKubeletWriteConfigToDisk(&kubeConfigFile)) - cmd.AddCommand(NewCmdKubeletUploadConfig(&kubeConfigFile)) - cmd.AddCommand(NewCmdKubeletEnableDynamicConfig(&kubeConfigFile)) + cmd.AddCommand(NewCmdKubeletConfigUpload()) + cmd.AddCommand(NewCmdKubeletConfigDownload()) + cmd.AddCommand(NewCmdKubeletConfigWriteToDisk()) + cmd.AddCommand(NewCmdKubeletConfigEnableDynamic()) return cmd } -// NewCmdKubeletUploadConfig calls cobra.Command for uploading dynamic kubelet configuration -func NewCmdKubeletUploadConfig(kubeConfigFile *string) *cobra.Command { +// NewCmdKubeletConfigUpload calls cobra.Command for uploading dynamic kubelet configuration +func NewCmdKubeletConfigUpload() *cobra.Command { var cfgPath string + kubeConfigFile := constants.GetAdminKubeConfigPath() cmd := &cobra.Command{ - Use: "upload-config", - Short: "Uploads kubelet configuration to a ConfigMap", - Long: kubeletUploadDynamicConfigLongDesc, - Example: kubeletUploadDynamicConfigExample, + Use: "upload", + Short: "Uploads kubelet configuration to a ConfigMap based on a kubeadm MasterConfiguration file.", + Long: kubeletConfigUploadLongDesc, + Example: kubeletConfigUploadExample, Run: func(cmd *cobra.Command, args []string) { if len(cfgPath) == 0 { kubeadmutil.CheckErr(fmt.Errorf("The --config argument is required")) @@ -109,7 +223,7 @@ func NewCmdKubeletUploadConfig(kubeConfigFile *string) *cobra.Command { internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) kubeadmutil.CheckErr(err) - client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile) + client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile) kubeadmutil.CheckErr(err) err = kubeletphase.CreateConfigMap(internalcfg, client) @@ -117,53 +231,83 @@ func NewCmdKubeletUploadConfig(kubeConfigFile *string) *cobra.Command { }, } - cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)") + options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile) + options.AddConfigFlag(cmd.Flags(), &cfgPath) return cmd } -// NewCmdKubeletWriteConfigToDisk calls cobra.Command for writing init kubelet configuration -func NewCmdKubeletWriteConfigToDisk(kubeConfigFile *string) *cobra.Command { - var cfgPath, kubeletVersionStr string +// NewCmdKubeletConfigDownload calls cobra.Command for downloading the kubelet configuration from the kubelet-config-1.X ConfigMap in the cluster +func NewCmdKubeletConfigDownload() *cobra.Command { + var kubeletVersionStr string + // TODO: Be smarter about this and be able to load multiple kubeconfig files in different orders of precedence + kubeConfigFile := constants.GetKubeletKubeConfigPath() + cmd := &cobra.Command{ - Use: "write-config-to-disk", - Short: "Writes kubelet configuration to disk, either based on the --config argument or the kubeadm-config ConfigMap.", - Long: kubeletWriteConfigToDiskLongDesc, - Example: kubeletWriteConfigToDiskExample, + Use: "download", + Short: "Downloads the kubelet configuration from the cluster ConfigMap kubelet-config-1.X, where X is the minor version of the kubelet.", + Long: kubeletConfigDownloadLongDesc, + Example: kubeletConfigDownloadExample, Run: func(cmd *cobra.Command, args []string) { - if len(kubeletVersionStr) == 0 { - kubeadmutil.CheckErr(fmt.Errorf("The --kubelet-version argument is required")) - } - - kubeletVersion, err := version.ParseSemantic(kubeletVersionStr) + kubeletVersion, err := getKubeletVersion(kubeletVersionStr) kubeadmutil.CheckErr(err) - client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile) + client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile) kubeadmutil.CheckErr(err) - // This call returns the ready-to-use configuration based on the configuration file - internalcfg, err := configutil.FetchConfigFromFileOrCluster(client, os.Stdout, "kubelet", cfgPath) - kubeadmutil.CheckErr(err) - - err = kubeletphase.WriteConfigToDisk(internalcfg.KubeletConfiguration.BaseConfig, kubeletVersion) + err = kubeletphase.DownloadConfig(client, kubeletVersion, constants.KubeletRunDirectory) kubeadmutil.CheckErr(err) }, } - cmd.Flags().StringVar(&kubeletVersionStr, "kubelet-version", kubeletVersionStr, "The desired version for the kubelet") - cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)") + options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile) + cmd.Flags().StringVar(&kubeletVersionStr, "kubelet-version", kubeletVersionStr, "The desired version for the kubelet. Defaults to being autodetected from 'kubelet --version'.") return cmd } -// NewCmdKubeletEnableDynamicConfig calls cobra.Command for enabling dynamic kubelet configuration on node +func getKubeletVersion(kubeletVersionStr string) (*version.Version, error) { + if len(kubeletVersionStr) > 0 { + return version.ParseSemantic(kubeletVersionStr) + } + return preflight.GetKubeletVersion(utilsexec.New()) +} + +// NewCmdKubeletConfigWriteToDisk calls cobra.Command for writing init kubelet configuration +func NewCmdKubeletConfigWriteToDisk() *cobra.Command { + var cfgPath string + cmd := &cobra.Command{ + Use: "write-to-disk", + Short: "Writes kubelet configuration to disk, either based on the --config argument.", + Long: kubeletConfigWriteToDiskLongDesc, + Example: kubeletConfigWriteToDiskExample, + Run: func(cmd *cobra.Command, args []string) { + if len(cfgPath) == 0 { + kubeadmutil.CheckErr(fmt.Errorf("The --config argument is required")) + } + + // This call returns the ready-to-use configuration based on the configuration file + internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) + kubeadmutil.CheckErr(err) + + err = kubeletphase.WriteConfigToDisk(internalcfg.KubeletConfiguration.BaseConfig, constants.KubeletRunDirectory) + kubeadmutil.CheckErr(err) + }, + } + + options.AddConfigFlag(cmd.Flags(), &cfgPath) + return cmd +} + +// NewCmdKubeletConfigEnableDynamic calls cobra.Command for enabling dynamic kubelet configuration on node // This feature is still in alpha and an experimental state -func NewCmdKubeletEnableDynamicConfig(kubeConfigFile *string) *cobra.Command { +func NewCmdKubeletConfigEnableDynamic() *cobra.Command { var nodeName, kubeletVersionStr string + kubeConfigFile := constants.GetAdminKubeConfigPath() cmd := &cobra.Command{ - Use: "enable-dynamic-config", + Use: "enable-dynamic", Short: "EXPERIMENTAL: Enables or updates dynamic kubelet configuration for a Node", - Long: kubeletEnableDynamicConfigLongDesc, - Example: kubeletEnableDynamicConfigExample, + Long: kubeletConfigEnableDynamicLongDesc, + Example: kubeletConfigEnableDynamicExample, Run: func(cmd *cobra.Command, args []string) { if len(nodeName) == 0 { kubeadmutil.CheckErr(fmt.Errorf("The --node-name argument is required")) @@ -175,7 +319,7 @@ func NewCmdKubeletEnableDynamicConfig(kubeConfigFile *string) *cobra.Command { kubeletVersion, err := version.ParseSemantic(kubeletVersionStr) kubeadmutil.CheckErr(err) - client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile) + client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile) kubeadmutil.CheckErr(err) err = kubeletphase.EnableDynamicConfigForNode(client, nodeName, kubeletVersion) @@ -183,6 +327,7 @@ func NewCmdKubeletEnableDynamicConfig(kubeConfigFile *string) *cobra.Command { }, } + options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile) cmd.Flags().StringVar(&nodeName, "node-name", nodeName, "Name of the node that should enable the dynamic kubelet configuration") cmd.Flags().StringVar(&kubeletVersionStr, "kubelet-version", kubeletVersionStr, "The desired version for the kubelet") return cmd diff --git a/cmd/kubeadm/app/cmd/phases/kubelet_test.go b/cmd/kubeadm/app/cmd/phases/kubelet_test.go index 89159d26105..4abfdd5d7cb 100644 --- a/cmd/kubeadm/app/cmd/phases/kubelet_test.go +++ b/cmd/kubeadm/app/cmd/phases/kubelet_test.go @@ -25,11 +25,12 @@ import ( ) func TestKubeletSubCommandsHasFlags(t *testing.T) { - kubeConfigFile := "foo" subCmds := []*cobra.Command{ - NewCmdKubeletUploadConfig(&kubeConfigFile), - NewCmdKubeletWriteConfigToDisk(&kubeConfigFile), - NewCmdKubeletEnableDynamicConfig(&kubeConfigFile), + NewCmdKubeletWriteEnvFile(), + NewCmdKubeletConfigUpload(), + NewCmdKubeletConfigDownload(), + NewCmdKubeletConfigWriteToDisk(), + NewCmdKubeletConfigEnableDynamic(), } commonFlags := []string{} @@ -39,21 +40,35 @@ func TestKubeletSubCommandsHasFlags(t *testing.T) { additionalFlags []string }{ { - command: "upload-config", + command: "write-env-file", additionalFlags: []string{ "config", }, }, { - command: "write-config-to-disk", + command: "upload", additionalFlags: []string{ + "kubeconfig", + "config", + }, + }, + { + command: "download", + additionalFlags: []string{ + "kubeconfig", "kubelet-version", + }, + }, + { + command: "write-to-disk", + additionalFlags: []string{ "config", }, }, { - command: "enable-dynamic-config", + command: "enable-dynamic", additionalFlags: []string{ + "kubeconfig", "node-name", "kubelet-version", }, diff --git a/cmd/kubeadm/app/cmd/phases/markmaster.go b/cmd/kubeadm/app/cmd/phases/markmaster.go index 5a2f11ddbb5..9ba104e0839 100644 --- a/cmd/kubeadm/app/cmd/phases/markmaster.go +++ b/cmd/kubeadm/app/cmd/phases/markmaster.go @@ -50,7 +50,7 @@ func NewCmdMarkMaster() *cobra.Command { cfg := &kubeadmapiv1alpha2.MasterConfiguration{ // KubernetesVersion is not used by mark master, but we set this explicitly to avoid // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig - KubernetesVersion: "v1.9.0", + KubernetesVersion: "v1.10.0", } // Default values for the cobra help text @@ -75,14 +75,14 @@ func NewCmdMarkMaster() *cobra.Command { client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile) kubeadmutil.CheckErr(err) - err = markmasterphase.MarkMaster(client, internalcfg.NodeName, !internalcfg.NoTaintMaster) + err = markmasterphase.MarkMaster(client, internalcfg.NodeRegistration.Name, internalcfg.NodeRegistration.Taints) kubeadmutil.CheckErr(err) }, } cmd.Flags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster") cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental") - cmd.Flags().StringVar(&cfg.NodeName, "node-name", cfg.NodeName, `The node name to which label and taints should apply`) + cmd.Flags().StringVar(&cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name, `The node name to which label and taints should apply`) return cmd } diff --git a/cmd/kubeadm/app/cmd/reset.go b/cmd/kubeadm/app/cmd/reset.go index 81d2cc83cc0..0dfee95e739 100644 --- a/cmd/kubeadm/app/cmd/reset.go +++ b/cmd/kubeadm/app/cmd/reset.go @@ -80,8 +80,8 @@ func NewCmdReset(in io.Reader, out io.Writer) *cobra.Command { "The path to the CRI socket to use with crictl when cleaning up containers.", ) - cmd.PersistentFlags().BoolVar( - &forceReset, "force", false, + cmd.PersistentFlags().BoolVarP( + &forceReset, "force", "f", false, "Reset the node without prompting for confirmation.", ) @@ -109,7 +109,7 @@ func NewReset(in io.Reader, ignorePreflightErrors sets.String, forceReset bool, } } - glog.Infoln("[preflight] running pre-flight checks") + fmt.Println("[preflight] running pre-flight checks") if err := preflight.RunRootCheckOnly(ignorePreflightErrors); err != nil { return nil, err } @@ -130,7 +130,7 @@ func (r *Reset) Run(out io.Writer) error { glog.Warningln("[reset] the kubelet service could not be stopped by kubeadm. Unable to detect a supported init system!") glog.Warningln("[reset] please ensure kubelet is stopped manually") } else { - glog.Infoln("[reset] stopping the kubelet service") + fmt.Println("[reset] stopping the kubelet service") if err := initSystem.ServiceStop("kubelet"); err != nil { glog.Warningf("[reset] the kubelet service could not be stopped by kubeadm: [%v]\n", err) glog.Warningln("[reset] please ensure kubelet is stopped manually") @@ -138,7 +138,7 @@ func (r *Reset) Run(out io.Writer) error { } // Try to unmount mounted directories under /var/lib/kubelet in order to be able to remove the /var/lib/kubelet directory later - glog.Infof("[reset] unmounting mounted directories in %q\n", "/var/lib/kubelet") + fmt.Printf("[reset] unmounting mounted directories in %q\n", "/var/lib/kubelet") umountDirsCmd := "awk '$2 ~ path {print $2}' path=/var/lib/kubelet /proc/mounts | xargs -r umount" glog.V(1).Infof("[reset] executing command %q", umountDirsCmd) @@ -147,7 +147,7 @@ func (r *Reset) Run(out io.Writer) error { glog.Errorf("[reset] failed to unmount mounted directories in /var/lib/kubelet: %s\n", string(umountOutputBytes)) } - glog.Infoln("[reset] removing kubernetes-managed containers") + fmt.Println("[reset] removing kubernetes-managed containers") dockerCheck := preflight.ServiceCheck{Service: "docker", CheckIfActive: true} execer := utilsexec.New() @@ -156,18 +156,18 @@ func (r *Reset) Run(out io.Writer) error { dirsToClean := []string{"/var/lib/kubelet", "/etc/cni/net.d", "/var/lib/dockershim", "/var/run/kubernetes"} // Only clear etcd data when the etcd manifest is found. In case it is not found, we must assume that the user - // provided external etcd endpoints. In that case, it is his own responsibility to reset etcd + // provided external etcd endpoints. In that case, it is their own responsibility to reset etcd etcdManifestPath := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName, "etcd.yaml") glog.V(1).Infof("[reset] checking for etcd manifest") if _, err := os.Stat(etcdManifestPath); err == nil { glog.V(1).Infof("Found one at %s", etcdManifestPath) dirsToClean = append(dirsToClean, "/var/lib/etcd") } else { - glog.Infof("[reset] no etcd manifest found in %q. Assuming external etcd\n", etcdManifestPath) + fmt.Printf("[reset] no etcd manifest found in %q. Assuming external etcd\n", etcdManifestPath) } // Then clean contents from the stateful kubelet, etcd and cni directories - glog.Infof("[reset] deleting contents of stateful directories: %v\n", dirsToClean) + fmt.Printf("[reset] deleting contents of stateful directories: %v\n", dirsToClean) for _, dir := range dirsToClean { glog.V(1).Infof("[reset] deleting content of %s", dir) cleanDir(dir) @@ -198,24 +198,24 @@ func resetWithDocker(execer utilsexec.Interface, dockerCheck preflight.Checker) glog.Errorln("[reset] failed to stop the running containers") } } else { - glog.Infoln("[reset] docker doesn't seem to be running. Skipping the removal of running Kubernetes containers") + fmt.Println("[reset] docker doesn't seem to be running. Skipping the removal of running Kubernetes containers") } } func resetWithCrictl(execer utilsexec.Interface, dockerCheck preflight.Checker, criSocketPath, crictlPath string) { if criSocketPath != "" { - glog.Infof("[reset] cleaning up running containers using crictl with socket %s\n", criSocketPath) + fmt.Printf("[reset] cleaning up running containers using crictl with socket %s\n", criSocketPath) glog.V(1).Infoln("[reset] listing running pods using crictl") params := []string{"-r", criSocketPath, "pods", "--quiet"} glog.V(1).Infof("[reset] Executing command %s %s", crictlPath, strings.Join(params, " ")) output, err := execer.Command(crictlPath, params...).CombinedOutput() if err != nil { - glog.Infof("[reset] failed to list running pods using crictl: %v. Trying to use docker instead", err) + fmt.Printf("[reset] failed to list running pods using crictl: %v. Trying to use docker instead", err) resetWithDocker(execer, dockerCheck) return } - sandboxes := strings.Split(string(output), " ") + sandboxes := strings.Fields(string(output)) glog.V(1).Infoln("[reset] Stopping and removing running containers using crictl") for _, s := range sandboxes { if strings.TrimSpace(s) == "" { @@ -224,20 +224,20 @@ func resetWithCrictl(execer utilsexec.Interface, dockerCheck preflight.Checker, params = []string{"-r", criSocketPath, "stopp", s} glog.V(1).Infof("[reset] Executing command %s %s", crictlPath, strings.Join(params, " ")) if err := execer.Command(crictlPath, params...).Run(); err != nil { - glog.Infof("[reset] failed to stop the running containers using crictl: %v. Trying to use docker instead", err) + fmt.Printf("[reset] failed to stop the running containers using crictl: %v. Trying to use docker instead", err) resetWithDocker(execer, dockerCheck) return } params = []string{"-r", criSocketPath, "rmp", s} glog.V(1).Infof("[reset] Executing command %s %s", crictlPath, strings.Join(params, " ")) if err := execer.Command(crictlPath, params...).Run(); err != nil { - glog.Infof("[reset] failed to remove the running containers using crictl: %v. Trying to use docker instead", err) + fmt.Printf("[reset] failed to remove the running containers using crictl: %v. Trying to use docker instead", err) resetWithDocker(execer, dockerCheck) return } } } else { - glog.Infoln("[reset] CRI socket path not provided for crictl. Trying to use docker instead") + fmt.Println("[reset] CRI socket path not provided for crictl. Trying to use docker instead") resetWithDocker(execer, dockerCheck) } } @@ -273,7 +273,7 @@ func resetConfigDir(configPathDir, pkiPathDir string) { filepath.Join(configPathDir, kubeadmconstants.ManifestsSubDirName), pkiPathDir, } - glog.Infof("[reset] deleting contents of config directories: %v\n", dirsToClean) + fmt.Printf("[reset] deleting contents of config directories: %v\n", dirsToClean) for _, dir := range dirsToClean { if err := cleanDir(dir); err != nil { glog.Errorf("[reset] failed to remove directory: %q [%v]\n", dir, err) @@ -287,7 +287,7 @@ func resetConfigDir(configPathDir, pkiPathDir string) { filepath.Join(configPathDir, kubeadmconstants.ControllerManagerKubeConfigFileName), filepath.Join(configPathDir, kubeadmconstants.SchedulerKubeConfigFileName), } - glog.Infof("[reset] deleting files: %v\n", filesToClean) + fmt.Printf("[reset] deleting files: %v\n", filesToClean) for _, path := range filesToClean { if err := os.RemoveAll(path); err != nil { glog.Errorf("[reset] failed to remove file: %q [%v]\n", path, err) diff --git a/cmd/kubeadm/app/cmd/token.go b/cmd/kubeadm/app/cmd/token.go index 67e7e4608b1..9368a656a84 100644 --- a/cmd/kubeadm/app/cmd/token.go +++ b/cmd/kubeadm/app/cmd/token.go @@ -20,7 +20,6 @@ import ( "fmt" "io" "os" - "sort" "strings" "text/tabwriter" "time" @@ -29,26 +28,24 @@ import ( "github.com/renstrom/dedent" "github.com/spf13/cobra" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/util/duration" clientset "k8s.io/client-go/kubernetes" bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" "k8s.io/client-go/tools/clientcmd" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" tokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" - tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token" - api "k8s.io/kubernetes/pkg/apis/core" ) const defaultKubeConfig = "/etc/kubernetes/admin.conf" @@ -95,14 +92,16 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command { cfg := &kubeadmapiv1alpha2.MasterConfiguration{ // KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig - KubernetesVersion: "v1.9.0", + KubernetesVersion: "v1.10.0", } // Default values for the cobra help text kubeadmscheme.Scheme.Default(cfg) - var cfgPath, description string + var cfgPath string var printJoinCommand bool + bto := options.NewBootstrapTokenOptions() + createCmd := &cobra.Command{ Use: "create [token]", DisableFlagsInUseLine: true, @@ -116,37 +115,35 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command { If no [token] is given, kubeadm will generate a random token instead. `), Run: func(tokenCmd *cobra.Command, args []string) { - if len(args) != 0 { - cfg.Token = args[0] + if len(args) > 0 { + bto.TokenStr = args[0] } glog.V(1).Infoln("[token] validating mixed arguments") err := validation.ValidateMixedArguments(tokenCmd.Flags()) kubeadmutil.CheckErr(err) + err = bto.ApplyTo(cfg) + kubeadmutil.CheckErr(err) + glog.V(1).Infoln("[token] getting Clientsets from KubeConfig file") kubeConfigFile = findExistingKubeConfig(kubeConfigFile) client, err := getClientset(kubeConfigFile, dryRun) kubeadmutil.CheckErr(err) - err = RunCreateToken(out, client, cfgPath, cfg, description, printJoinCommand, kubeConfigFile) + err = RunCreateToken(out, client, cfgPath, cfg, printJoinCommand, kubeConfigFile) kubeadmutil.CheckErr(err) }, } createCmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)") - createCmd.Flags().DurationVar(&cfg.TokenTTL.Duration, - "ttl", cfg.TokenTTL.Duration, "The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire.") - createCmd.Flags().StringSliceVar(&cfg.TokenUsages, - "usages", cfg.TokenUsages, 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, ","))) - createCmd.Flags().StringSliceVar(&cfg.TokenGroups, - "groups", cfg.TokenGroups, - fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q.", bootstrapapi.BootstrapGroupPattern)) - createCmd.Flags().StringVar(&description, - "description", "", "A human friendly description of how this token is used.") createCmd.Flags().BoolVar(&printJoinCommand, "print-join-command", false, "Instead of printing only the token, print the full 'kubeadm join' flag needed to join the cluster using the token.") - tokenCmd.AddCommand(createCmd) + bto.AddTTLFlagWithName(createCmd.Flags(), "ttl") + bto.AddUsagesFlag(createCmd.Flags()) + bto.AddGroupsFlag(createCmd.Flags()) + bto.AddDescriptionFlag(createCmd.Flags()) + tokenCmd.AddCommand(createCmd) tokenCmd.AddCommand(NewCmdTokenGenerate(out)) listCmd := &cobra.Command{ @@ -178,7 +175,7 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command { `), Run: func(tokenCmd *cobra.Command, args []string) { if len(args) < 1 { - kubeadmutil.CheckErr(fmt.Errorf("missing subcommand; 'token delete' is missing token of form [%q]", tokenutil.TokenIDRegexpString)) + kubeadmutil.CheckErr(fmt.Errorf("missing subcommand; 'token delete' is missing token of form %q", bootstrapapi.BootstrapTokenIDPattern)) } kubeConfigFile = findExistingKubeConfig(kubeConfigFile) client, err := getClientset(kubeConfigFile, dryRun) @@ -217,7 +214,7 @@ func NewCmdTokenGenerate(out io.Writer) *cobra.Command { } // RunCreateToken generates a new bootstrap token and stores it as a secret on the server. -func RunCreateToken(out io.Writer, client clientset.Interface, cfgPath string, cfg *kubeadmapiv1alpha2.MasterConfiguration, description string, printJoinCommand bool, kubeConfigFile string) error { +func RunCreateToken(out io.Writer, client clientset.Interface, cfgPath string, cfg *kubeadmapiv1alpha2.MasterConfiguration, printJoinCommand bool, kubeConfigFile string) error { // 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 glog.V(1).Infoln("[token] loading configurations") internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg) @@ -226,21 +223,20 @@ func RunCreateToken(out io.Writer, client clientset.Interface, cfgPath string, c } glog.V(1).Infoln("[token] creating token") - err = tokenphase.CreateNewToken(client, internalcfg.Token, internalcfg.TokenTTL.Duration, internalcfg.TokenUsages, internalcfg.TokenGroups, description) - if err != nil { + if err := tokenphase.CreateNewTokens(client, internalcfg.BootstrapTokens); err != nil { return err } // if --print-join-command was specified, print the full `kubeadm join` command // otherwise, just print the token if printJoinCommand { - joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.Token, false) + joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.BootstrapTokens[0].Token.String(), false) if err != nil { return fmt.Errorf("failed to get join command: %v", err) } fmt.Fprintln(out, joinCommand) } else { - fmt.Fprintln(out, internalcfg.Token) + fmt.Fprintln(out, internalcfg.BootstrapTokens[0].Token.String()) } return nil @@ -248,8 +244,8 @@ func RunCreateToken(out io.Writer, client clientset.Interface, cfgPath string, c // RunGenerateToken just generates a random token for the user func RunGenerateToken(out io.Writer) error { - glog.V(1).Infoln("[token] generating randodm token") - token, err := tokenutil.GenerateToken() + glog.V(1).Infoln("[token] generating random token") + token, err := bootstraputil.GenerateBootstrapToken() if err != nil { return err } @@ -264,7 +260,10 @@ func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface) er glog.V(1).Infoln("[token] preparing selector for bootstrap token") tokenSelector := fields.SelectorFromSet( map[string]string{ - api.SecretTypeField: string(bootstrapapi.SecretTypeBootstrapToken), + // TODO: We hard-code "type" here until `field_constants.go` that is + // currently in `pkg/apis/core/` exists in the external API, i.e. + // k8s.io/api/v1. Should be v1.SecretTypeField + "type": string(bootstrapapi.SecretTypeBootstrapToken), }, ) listOptions := metav1.ListOptions{ @@ -280,68 +279,17 @@ func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface) er w := tabwriter.NewWriter(out, 10, 4, 3, ' ', 0) fmt.Fprintln(w, "TOKEN\tTTL\tEXPIRES\tUSAGES\tDESCRIPTION\tEXTRA GROUPS") for _, secret := range secrets.Items { - tokenID := getSecretString(&secret, bootstrapapi.BootstrapTokenIDKey) - if len(tokenID) == 0 { - fmt.Fprintf(errW, "bootstrap token has no token-id data: %s\n", secret.Name) + + // Get the BootstrapToken struct representation from the Secret object + token, err := kubeadmapi.BootstrapTokenFromSecret(&secret) + if err != nil { + fmt.Fprintf(errW, "%v", err) continue } - // enforce the right naming convention - if secret.Name != fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenID) { - fmt.Fprintf(errW, "bootstrap token name is not of the form '%s(token-id)': %s\n", bootstrapapi.BootstrapTokenSecretPrefix, secret.Name) - continue - } - - tokenSecret := getSecretString(&secret, bootstrapapi.BootstrapTokenSecretKey) - if len(tokenSecret) == 0 { - fmt.Fprintf(errW, "bootstrap token has no token-secret data: %s\n", secret.Name) - continue - } - td := &kubeadmapi.TokenDiscovery{ID: tokenID, Secret: tokenSecret} - - // Expiration time is optional, if not specified this implies the token - // never expires. - ttl := "" - expires := "" - secretExpiration := getSecretString(&secret, bootstrapapi.BootstrapTokenExpirationKey) - if len(secretExpiration) > 0 { - expireTime, err := time.Parse(time.RFC3339, secretExpiration) - if err != nil { - fmt.Fprintf(errW, "can't parse expiration time of bootstrap token %s\n", secret.Name) - continue - } - ttl = duration.ShortHumanDuration(expireTime.Sub(time.Now())) - expires = expireTime.Format(time.RFC3339) - } - - usages := []string{} - for k, v := range secret.Data { - // Skip all fields that don't include this prefix - if !strings.HasPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix) { - continue - } - // Skip those that don't have this usage set to true - if string(v) != "true" { - continue - } - usages = append(usages, strings.TrimPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix)) - } - sort.Strings(usages) - usageString := strings.Join(usages, ",") - if len(usageString) == 0 { - usageString = "" - } - - description := getSecretString(&secret, bootstrapapi.BootstrapTokenDescriptionKey) - if len(description) == 0 { - description = "" - } - - groups := getSecretString(&secret, bootstrapapi.BootstrapTokenExtraGroupsKey) - if len(groups) == 0 { - groups = "" - } - fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n", tokenutil.BearerToken(td), ttl, expires, usageString, description, groups) + // Get the human-friendly string representation for the token + humanFriendlyTokenOutput := humanReadableBootstrapToken(token) + fmt.Fprintln(w, humanFriendlyTokenOutput) } w.Flush() return nil @@ -352,13 +300,16 @@ func RunDeleteToken(out io.Writer, client clientset.Interface, tokenIDOrToken st // Assume the given first argument is a token id and try to parse it tokenID := tokenIDOrToken glog.V(1).Infoln("[token] parsing token ID") - if err := tokenutil.ParseTokenID(tokenIDOrToken); err != nil { - if tokenID, _, err = tokenutil.ParseToken(tokenIDOrToken); err != nil { - return fmt.Errorf("given token or token id %q didn't match pattern [%q] or [%q]", tokenIDOrToken, tokenutil.TokenIDRegexpString, tokenutil.TokenRegexpString) + if !bootstraputil.IsValidBootstrapTokenID(tokenIDOrToken) { + // Okay, the full token with both id and secret was probably passed. Parse it and extract the ID only + bts, err := kubeadmapiv1alpha2.NewBootstrapTokenString(tokenIDOrToken) + if err != nil { + return fmt.Errorf("given token or token id %q didn't match pattern %q or %q", tokenIDOrToken, bootstrapapi.BootstrapTokenIDPattern, bootstrapapi.BootstrapTokenIDPattern) } + tokenID = bts.ID } - tokenSecretName := fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenID) + tokenSecretName := bootstraputil.BootstrapTokenSecretName(tokenID) glog.V(1).Infoln("[token] deleting token") if err := client.CoreV1().Secrets(metav1.NamespaceSystem).Delete(tokenSecretName, nil); err != nil { return fmt.Errorf("failed to delete bootstrap token [%v]", err) @@ -367,14 +318,30 @@ func RunDeleteToken(out io.Writer, client clientset.Interface, tokenIDOrToken st return nil } -func getSecretString(secret *v1.Secret, key string) string { - if secret.Data == nil { - return "" +func humanReadableBootstrapToken(token *kubeadmapi.BootstrapToken) string { + description := token.Description + if len(description) == 0 { + description = "" } - if val, ok := secret.Data[key]; ok { - return string(val) + + ttl := "" + expires := "" + if token.Expires != nil { + ttl = duration.ShortHumanDuration(token.Expires.Sub(time.Now())) + expires = token.Expires.Format(time.RFC3339) } - return "" + + usagesString := strings.Join(token.Usages, ",") + if len(usagesString) == 0 { + usagesString = "" + } + + groupsString := strings.Join(token.Groups, ",") + if len(groupsString) == 0 { + groupsString = "" + } + + return fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s\n", token.Token.String(), ttl, expires, usagesString, description, groupsString) } func getClientset(file string, dryRun bool) (clientset.Interface, error) { diff --git a/cmd/kubeadm/app/cmd/token_test.go b/cmd/kubeadm/app/cmd/token_test.go index 74b3bc8614c..c919583a918 100644 --- a/cmd/kubeadm/app/cmd/token_test.go +++ b/cmd/kubeadm/app/cmd/token_test.go @@ -135,13 +135,6 @@ func TestRunCreateToken(t *testing.T) { extraGroups: []string{}, expectedError: false, }, - { - name: "invalid: incorrect token", - token: "123456.AABBCCDDEEFFGGHH", - usages: []string{"signing", "authentication"}, - extraGroups: []string{}, - expectedError: true, - }, { name: "invalid: incorrect extraGroups", token: "abcdef.1234567890123456", @@ -180,18 +173,27 @@ func TestRunCreateToken(t *testing.T) { }, } for _, tc := range testCases { + bts, err := kubeadmapiv1alpha2.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 := &kubeadmapiv1alpha2.MasterConfiguration{ // KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig KubernetesVersion: "v1.10.0", - Token: tc.token, - TokenTTL: &metav1.Duration{Duration: 0}, - TokenUsages: tc.usages, - TokenGroups: tc.extraGroups, + BootstrapTokens: []kubeadmapiv1alpha2.BootstrapToken{ + { + Token: bts, + TTL: &metav1.Duration{Duration: 0}, + Usages: tc.usages, + Groups: tc.extraGroups, + }, + }, } - err := RunCreateToken(&buf, fakeClient, "", cfg, "", tc.printJoin, "") + 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)) } @@ -277,22 +279,6 @@ func TestNewCmdToken(t *testing.T) { } } -func TestGetSecretString(t *testing.T) { - secret := v1.Secret{} - key := "test-key" - if str := getSecretString(&secret, key); str != "" { - t.Errorf("getSecretString() did not return empty string for a nil v1.Secret.Data") - } - secret.Data = make(map[string][]byte) - if str := getSecretString(&secret, key); str != "" { - t.Errorf("getSecretString() did not return empty string for missing v1.Secret.Data key") - } - secret.Data[key] = []byte("test-value") - if str := getSecretString(&secret, key); str == "" { - t.Errorf("getSecretString() failed for a valid v1.Secret.Data key") - } -} - func TestGetClientset(t *testing.T) { testConfigTokenFile := "test-config-file" diff --git a/cmd/kubeadm/app/cmd/upgrade/BUILD b/cmd/kubeadm/app/cmd/upgrade/BUILD index 9a74d83aa07..c55c9c6d1a3 100644 --- a/cmd/kubeadm/app/cmd/upgrade/BUILD +++ b/cmd/kubeadm/app/cmd/upgrade/BUILD @@ -6,6 +6,7 @@ go_library( "apply.go", "common.go", "diff.go", + "node.go", "plan.go", "upgrade.go", ], @@ -20,6 +21,7 @@ go_library( "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/phases/controlplane:go_default_library", + "//cmd/kubeadm/app/phases/kubelet:go_default_library", "//cmd/kubeadm/app/phases/upgrade:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", "//cmd/kubeadm/app/util:go_default_library", @@ -28,10 +30,12 @@ go_library( "//cmd/kubeadm/app/util/dryrun:go_default_library", "//cmd/kubeadm/app/util/etcd:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", + "//pkg/util/normalizer:go_default_library", "//pkg/util/version:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/pmezard/go-difflib/difflib:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -53,6 +57,7 @@ go_test( embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/phases/upgrade:go_default_library", ], ) diff --git a/cmd/kubeadm/app/cmd/upgrade/apply.go b/cmd/kubeadm/app/cmd/upgrade/apply.go index 1acb2f895b1..e5922edb97a 100644 --- a/cmd/kubeadm/app/cmd/upgrade/apply.go +++ b/cmd/kubeadm/app/cmd/upgrade/apply.go @@ -37,23 +37,28 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun" + etcdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd" "k8s.io/kubernetes/pkg/util/version" ) const ( - upgradeManifestTimeout = 1 * time.Minute + upgradeManifestTimeout = 5 * time.Minute + + defaultImagePullTimeout = 15 * time.Minute ) // applyFlags holds the information about the flags that can be passed to apply type applyFlags struct { + *applyPlanFlags + nonInteractiveMode bool force bool dryRun bool etcdUpgrade bool + criSocket string newK8sVersionStr string newK8sVersion *version.Version imagePullTimeout time.Duration - parent *cmdUpgradeFlags } // SessionIsInteractive returns true if the session is of an interactive type (the default, can be opted out of with -y, -f or --dry-run) @@ -62,11 +67,12 @@ func (f *applyFlags) SessionIsInteractive() bool { } // NewCmdApply returns the cobra command for `kubeadm upgrade apply` -func NewCmdApply(parentFlags *cmdUpgradeFlags) *cobra.Command { +func NewCmdApply(apf *applyPlanFlags) *cobra.Command { flags := &applyFlags{ - parent: parentFlags, - imagePullTimeout: 15 * time.Minute, + applyPlanFlags: apf, + imagePullTimeout: defaultImagePullTimeout, etcdUpgrade: true, + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, } cmd := &cobra.Command{ @@ -75,18 +81,18 @@ func NewCmdApply(parentFlags *cmdUpgradeFlags) *cobra.Command { Short: "Upgrade your Kubernetes cluster to the specified version.", Run: func(cmd *cobra.Command, args []string) { var err error - flags.parent.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(flags.parent.ignorePreflightErrors, flags.parent.skipPreFlight) + flags.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(flags.ignorePreflightErrors, flags.skipPreFlight) kubeadmutil.CheckErr(err) // Ensure the user is root glog.V(1).Infof("running preflight checks") - err = runPreflightChecks(flags.parent.ignorePreflightErrorsSet) + err = runPreflightChecks(flags.ignorePreflightErrorsSet) kubeadmutil.CheckErr(err) // If the version is specified in config file, pick up that value. - if flags.parent.cfgPath != "" { - glog.V(1).Infof("fetching configuration from file", flags.parent.cfgPath) - cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(parentFlags.cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) + if flags.cfgPath != "" { + glog.V(1).Infof("fetching configuration from file", flags.cfgPath) + cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(flags.cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) kubeadmutil.CheckErr(err) if cfg.KubernetesVersion != "" { @@ -114,13 +120,16 @@ func NewCmdApply(parentFlags *cmdUpgradeFlags) *cobra.Command { }, } + // Register the common flags for apply and plan + addApplyPlanFlags(cmd.Flags(), flags.applyPlanFlags) // Specify the valid flags specific for apply cmd.Flags().BoolVarP(&flags.nonInteractiveMode, "yes", "y", flags.nonInteractiveMode, "Perform the upgrade and do not prompt for confirmation (non-interactive mode).") cmd.Flags().BoolVarP(&flags.force, "force", "f", flags.force, "Force upgrading although some requirements might not be met. This also implies non-interactive mode.") cmd.Flags().BoolVar(&flags.dryRun, "dry-run", flags.dryRun, "Do not change any state, just output what actions would be performed.") cmd.Flags().BoolVar(&flags.etcdUpgrade, "etcd-upgrade", flags.etcdUpgrade, "Perform the upgrade of etcd.") cmd.Flags().DurationVar(&flags.imagePullTimeout, "image-pull-timeout", flags.imagePullTimeout, "The maximum amount of time to wait for the control plane pods to be downloaded.") - + // TODO: Register this flag in a generic place + cmd.Flags().StringVar(&flags.criSocket, "cri-socket", flags.criSocket, "Specify the CRI socket to connect to.") return cmd } @@ -141,11 +150,16 @@ func RunApply(flags *applyFlags) error { // Start with the basics, verify that the cluster is healthy and get the configuration from the cluster (using the ConfigMap) glog.V(1).Infof("[upgrade/apply] verifying health of cluster") glog.V(1).Infof("[upgrade/apply] retrieving configuration from cluster") - upgradeVars, err := enforceRequirements(flags.parent, flags.dryRun, flags.newK8sVersionStr) + upgradeVars, err := enforceRequirements(flags.applyPlanFlags, flags.dryRun, flags.newK8sVersionStr) if err != nil { return err } + if len(flags.criSocket) != 0 { + fmt.Println("[upgrade/apply] Respecting the --cri-socket flag that is set with higher priority than the config file.") + upgradeVars.cfg.NodeRegistration.CRISocket = flags.criSocket + } + // Validate requested and validate actual version glog.V(1).Infof("[upgrade/apply] validating requested and actual version") if err := configutil.NormalizeKubernetesVersion(upgradeVars.cfg); err != nil { @@ -196,14 +210,14 @@ func RunApply(flags *applyFlags) error { } if flags.dryRun { - glog.Infoln("[dryrun] Finished dryrunning successfully!") + fmt.Println("[dryrun] Finished dryrunning successfully!") return nil } - glog.Infoln("") - glog.Infof("[upgrade/successful] SUCCESS! Your cluster was upgraded to %q. Enjoy!\n", flags.newK8sVersionStr) - glog.Infoln("") - glog.Infoln("[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.") + fmt.Println("") + fmt.Printf("[upgrade/successful] SUCCESS! Your cluster was upgraded to %q. Enjoy!\n", flags.newK8sVersionStr) + fmt.Println("") + fmt.Println("[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.") return nil } @@ -225,9 +239,9 @@ func SetImplicitFlags(flags *applyFlags) error { // EnforceVersionPolicies makes sure that the version the user specified is valid to upgrade to // There are both fatal and skippable (with --force) errors func EnforceVersionPolicies(flags *applyFlags, versionGetter upgrade.VersionGetter) error { - glog.Infof("[upgrade/version] You have chosen to change the cluster version to %q\n", flags.newK8sVersionStr) + fmt.Printf("[upgrade/version] You have chosen to change the cluster version to %q\n", flags.newK8sVersionStr) - versionSkewErrs := upgrade.EnforceVersionPolicies(versionGetter, flags.newK8sVersionStr, flags.newK8sVersion, flags.parent.allowExperimentalUpgrades, flags.parent.allowRCUpgrades) + versionSkewErrs := upgrade.EnforceVersionPolicies(versionGetter, flags.newK8sVersionStr, flags.newK8sVersion, flags.allowExperimentalUpgrades, flags.allowRCUpgrades) if versionSkewErrs != nil { if len(versionSkewErrs.Mandatory) > 0 { @@ -240,7 +254,7 @@ func EnforceVersionPolicies(flags *applyFlags, versionGetter upgrade.VersionGett return fmt.Errorf("The --version argument is invalid due to these errors:\n\n%v\nCan be bypassed if you pass the --force flag", kubeadmutil.FormatErrMsg(versionSkewErrs.Skippable)) } // Soft errors found, but --force was specified - glog.Infof("[upgrade/version] Found %d potential version compatibility errors but skipping since the --force flag is set: \n\n%v", len(versionSkewErrs.Skippable), kubeadmutil.FormatErrMsg(versionSkewErrs.Skippable)) + fmt.Printf("[upgrade/version] Found %d potential version compatibility errors but skipping since the --force flag is set: \n\n%v", len(versionSkewErrs.Skippable), kubeadmutil.FormatErrMsg(versionSkewErrs.Skippable)) } } return nil @@ -266,12 +280,19 @@ func PerformControlPlaneUpgrade(flags *applyFlags, client clientset.Interface, w return DryRunStaticPodUpgrade(internalcfg) } + // Don't save etcd backup directory if etcd is HA, as this could cause corruption return PerformStaticPodUpgrade(client, waiter, internalcfg, flags.etcdUpgrade) } +// GetPathManagerForUpgrade returns a path manager properly configured for the given MasterConfiguration. +func GetPathManagerForUpgrade(internalcfg *kubeadmapi.MasterConfiguration, etcdUpgrade bool) (upgrade.StaticPodPathManager, error) { + isHAEtcd := etcdutil.CheckConfigurationIsHA(&internalcfg.Etcd) + return upgrade.NewKubeStaticPodPathManagerUsingTempDirs(constants.GetStaticPodDirectory(), true, etcdUpgrade && !isHAEtcd) +} + // PerformStaticPodUpgrade performs the upgrade of the control plane components for a static pod hosted cluster func PerformStaticPodUpgrade(client clientset.Interface, waiter apiclient.Waiter, internalcfg *kubeadmapi.MasterConfiguration, etcdUpgrade bool) error { - pathManager, err := upgrade.NewKubeStaticPodPathManagerUsingTempDirs(constants.GetStaticPodDirectory()) + pathManager, err := GetPathManagerForUpgrade(internalcfg, etcdUpgrade) if err != nil { return err } diff --git a/cmd/kubeadm/app/cmd/upgrade/apply_test.go b/cmd/kubeadm/app/cmd/upgrade/apply_test.go index 24d1778f8be..a7cd2394b5f 100644 --- a/cmd/kubeadm/app/cmd/upgrade/apply_test.go +++ b/cmd/kubeadm/app/cmd/upgrade/apply_test.go @@ -17,8 +17,13 @@ limitations under the License. package upgrade import ( + "io/ioutil" + "os" "reflect" "testing" + + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) func TestSetImplicitFlags(t *testing.T) { @@ -145,3 +150,90 @@ func TestSetImplicitFlags(t *testing.T) { } } } + +func TestGetPathManagerForUpgrade(t *testing.T) { + + haEtcd := &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + External: &kubeadmapi.ExternalEtcd{ + Endpoints: []string{"10.100.0.1:2379", "10.100.0.2:2379", "10.100.0.3:2379"}, + }, + }, + } + + noHAEtcd := &kubeadmapi.MasterConfiguration{} + + tests := []struct { + name string + cfg *kubeadmapi.MasterConfiguration + etcdUpgrade bool + shouldDeleteEtcd bool + }{ + { + name: "ha etcd but no etcd upgrade", + cfg: haEtcd, + etcdUpgrade: false, + shouldDeleteEtcd: true, + }, + { + name: "non-ha etcd with etcd upgrade", + cfg: noHAEtcd, + etcdUpgrade: true, + shouldDeleteEtcd: false, + }, + { + name: "ha etcd and etcd upgrade", + cfg: haEtcd, + etcdUpgrade: true, + shouldDeleteEtcd: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + // Use a temporary directory + tmpdir, err := ioutil.TempDir("", "TestGetPathManagerForUpgrade") + if err != nil { + t.Fatalf("unexpected error making temporary directory: %v", err) + } + oldK8sDir := constants.KubernetesDir + constants.KubernetesDir = tmpdir + defer func() { + constants.KubernetesDir = oldK8sDir + os.RemoveAll(tmpdir) + }() + + pathmgr, err := GetPathManagerForUpgrade(test.cfg, test.etcdUpgrade) + if err != nil { + t.Fatalf("unexpected error creating path manager: %v", err) + } + + if _, err := os.Stat(pathmgr.BackupManifestDir()); os.IsNotExist(err) { + t.Errorf("expected manifest dir %s to exist, but it did not (%v)", pathmgr.BackupManifestDir(), err) + } + + if _, err := os.Stat(pathmgr.BackupEtcdDir()); os.IsNotExist(err) { + t.Errorf("expected etcd dir %s to exist, but it did not (%v)", pathmgr.BackupEtcdDir(), err) + } + + if err := pathmgr.CleanupDirs(); err != nil { + t.Fatalf("unexpected error cleaning up directories: %v", err) + } + + if _, err := os.Stat(pathmgr.BackupManifestDir()); os.IsNotExist(err) { + t.Errorf("expected manifest dir %s to exist, but it did not (%v)", pathmgr.BackupManifestDir(), err) + } + + if test.shouldDeleteEtcd { + if _, err := os.Stat(pathmgr.BackupEtcdDir()); !os.IsNotExist(err) { + t.Errorf("expected etcd dir %s not to exist, but it did (%v)", pathmgr.BackupEtcdDir(), err) + } + } else { + if _, err := os.Stat(pathmgr.BackupEtcdDir()); os.IsNotExist(err) { + t.Errorf("expected etcd dir %s to exist, but it did not", pathmgr.BackupEtcdDir()) + } + } + }) + } + +} diff --git a/cmd/kubeadm/app/cmd/upgrade/common.go b/cmd/kubeadm/app/cmd/upgrade/common.go index 1f5f2336ca8..9480c46611f 100644 --- a/cmd/kubeadm/app/cmd/upgrade/common.go +++ b/cmd/kubeadm/app/cmd/upgrade/common.go @@ -53,7 +53,8 @@ type upgradeVariables struct { } // enforceRequirements verifies that it's okay to upgrade and then returns the variables needed for the rest of the procedure -func enforceRequirements(flags *cmdUpgradeFlags, dryRun bool, newK8sVersion string) (*upgradeVariables, error) { +func enforceRequirements(flags *applyPlanFlags, dryRun bool, newK8sVersion string) (*upgradeVariables, error) { + client, err := getClient(flags.kubeConfigPath, dryRun) if err != nil { return nil, fmt.Errorf("couldn't create a Kubernetes client from file %q: %v", flags.kubeConfigPath, err) @@ -154,7 +155,10 @@ func getClient(file string, dryRun bool) (clientset.Interface, error) { } // Get the fake clientset - fakeclient := apiclient.NewDryRunClient(dryRunGetter, os.Stdout) + dryRunOpts := apiclient.GetDefaultDryRunClientOptions(dryRunGetter, os.Stdout) + // Print GET and LIST requests + dryRunOpts.PrintGETAndLIST = true + fakeclient := apiclient.NewDryRunClientWithOpts(dryRunOpts) // As we know the return of Discovery() of the fake clientset is of type *fakediscovery.FakeDiscovery // we can convert it to that struct. fakeclientDiscovery, ok := fakeclient.Discovery().(*fakediscovery.FakeDiscovery) diff --git a/cmd/kubeadm/app/cmd/upgrade/common_test.go b/cmd/kubeadm/app/cmd/upgrade/common_test.go index ac170b04bb6..7c0465515b5 100644 --- a/cmd/kubeadm/app/cmd/upgrade/common_test.go +++ b/cmd/kubeadm/app/cmd/upgrade/common_test.go @@ -65,8 +65,7 @@ func TestPrintConfiguration(t *testing.T) { dnsDomain: "" podSubnet: "" serviceSubnet: "" - nodeName: "" - token: "" + nodeRegistration: {} unifiedControlPlaneImage: "" `), }, @@ -108,8 +107,7 @@ func TestPrintConfiguration(t *testing.T) { dnsDomain: "" podSubnet: "" serviceSubnet: 10.96.0.1/12 - nodeName: "" - token: "" + nodeRegistration: {} unifiedControlPlaneImage: "" `), }, diff --git a/cmd/kubeadm/app/cmd/upgrade/diff.go b/cmd/kubeadm/app/cmd/upgrade/diff.go index cf87756c678..47180a54f09 100644 --- a/cmd/kubeadm/app/cmd/upgrade/diff.go +++ b/cmd/kubeadm/app/cmd/upgrade/diff.go @@ -18,6 +18,7 @@ package upgrade import ( "fmt" + "io" "io/ioutil" "github.com/golang/glog" @@ -39,7 +40,8 @@ type diffFlags struct { schedulerManifestPath string newK8sVersionStr string contextLines int - parent *cmdUpgradeFlags + cfgPath string + out io.Writer } var ( @@ -49,19 +51,22 @@ var ( ) // NewCmdDiff returns the cobra command for `kubeadm upgrade diff` -func NewCmdDiff(parentflags *cmdUpgradeFlags) *cobra.Command { +func NewCmdDiff(out io.Writer) *cobra.Command { flags := &diffFlags{ - parent: parentflags, + out: out, } cmd := &cobra.Command{ Use: "diff [version]", Short: "Show what differences would be applied to existing static pod manifests. See also: kubeadm upgrade apply --dry-run", Run: func(cmd *cobra.Command, args []string) { + // TODO: Run preflight checks for diff to check that the manifests already exist. kubeadmutil.CheckErr(runDiff(flags, args)) }, } + // TODO: Use the generic options.AddConfigFlag method instead + cmd.Flags().StringVar(&flags.cfgPath, "config", flags.cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental!") cmd.Flags().StringVar(&flags.apiServerManifestPath, "api-server-manifest", defaultAPIServerManifestPath, "path to API server manifest") cmd.Flags().StringVar(&flags.controllerManagerManifestPath, "controller-manager-manifest", defaultControllerManagerManifestPath, "path to controller manifest") cmd.Flags().StringVar(&flags.schedulerManifestPath, "scheduler-manifest", defaultSchedulerManifestPath, "path to scheduler manifest") @@ -73,8 +78,8 @@ func NewCmdDiff(parentflags *cmdUpgradeFlags) *cobra.Command { func runDiff(flags *diffFlags, args []string) error { // If the version is specified in config file, pick up that value. - glog.V(1).Infof("fetching configuration from file", flags.parent.cfgPath) - cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(flags.parent.cfgPath, &kubeadmv1alpha2.MasterConfiguration{}) + glog.V(1).Infof("fetching configuration from file", flags.cfgPath) + cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(flags.cfgPath, &kubeadmv1alpha2.MasterConfiguration{}) if err != nil { return err } @@ -136,7 +141,7 @@ func runDiff(flags *diffFlags, args []string) error { Context: flags.contextLines, } - difflib.WriteUnifiedDiff(flags.parent.out, diff) + difflib.WriteUnifiedDiff(flags.out, diff) } return nil } diff --git a/cmd/kubeadm/app/cmd/upgrade/diff_test.go b/cmd/kubeadm/app/cmd/upgrade/diff_test.go index 2c7e2834399..a4de23b1048 100644 --- a/cmd/kubeadm/app/cmd/upgrade/diff_test.go +++ b/cmd/kubeadm/app/cmd/upgrade/diff_test.go @@ -27,13 +27,10 @@ const ( ) func TestRunDiff(t *testing.T) { - parentFlags := &cmdUpgradeFlags{ + flags := &diffFlags{ cfgPath: "", out: ioutil.Discard, } - flags := &diffFlags{ - parent: parentFlags, - } testCases := []struct { name string @@ -79,7 +76,7 @@ func TestRunDiff(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - parentFlags.cfgPath = tc.cfgPath + flags.cfgPath = tc.cfgPath if tc.setManifestPath { flags.apiServerManifestPath = tc.manifestPath flags.controllerManagerManifestPath = tc.manifestPath diff --git a/cmd/kubeadm/app/cmd/upgrade/node.go b/cmd/kubeadm/app/cmd/upgrade/node.go new file mode 100644 index 00000000000..0c51d7cb7d0 --- /dev/null +++ b/cmd/kubeadm/app/cmd/upgrade/node.go @@ -0,0 +1,158 @@ +/* +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 upgrade + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "github.com/spf13/cobra" + + cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun" + "k8s.io/kubernetes/pkg/util/normalizer" + "k8s.io/kubernetes/pkg/util/version" +) + +var ( + upgradeNodeConfigLongDesc = normalizer.LongDesc(` + Downloads the kubelet configuration from a ConfigMap of the form "kubelet-config-1.X" in the cluster, + where X is the minor version of the kubelet. kubeadm uses the --kubelet-version parameter to determine + what the _desired_ kubelet version is. Give + `) + + upgradeNodeConfigExample = normalizer.Examples(` + # Downloads the kubelet configuration from the ConfigMap in the cluster. Uses a specific desired kubelet version. + kubeadm upgrade node config --kubelet-version v1.11.0 + + # 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.11.0 --dry-run + `) +) + +type nodeUpgradeFlags struct { + kubeConfigPath string + kubeletVersionStr string + dryRun bool +} + +// NewCmdNode returns the cobra command for `kubeadm upgrade node` +func NewCmdNode() *cobra.Command { + cmd := &cobra.Command{ + Use: "node", + Short: "Upgrade commands for a node in the cluster. Currently only supports upgrading the configuration, not the kubelet itself.", + RunE: cmdutil.SubCmdRunE("node"), + } + cmd.AddCommand(NewCmdUpgradeNodeConfig()) + return cmd +} + +// NewCmdUpgradeNodeConfig returns the cobra.Command for downloading the new/upgrading the kubelet configuration from the kubelet-config-1.X +// ConfigMap in the cluster +func NewCmdUpgradeNodeConfig() *cobra.Command { + flags := &nodeUpgradeFlags{ + kubeConfigPath: constants.GetKubeletKubeConfigPath(), + kubeletVersionStr: "", + dryRun: false, + } + + cmd := &cobra.Command{ + Use: "config", + Short: "Downloads the kubelet configuration from the cluster ConfigMap kubelet-config-1.X, where X is the minor version of the kubelet.", + Long: upgradeNodeConfigLongDesc, + Example: upgradeNodeConfigExample, + Run: func(cmd *cobra.Command, args []string) { + err := RunUpgradeNodeConfig(flags) + kubeadmutil.CheckErr(err) + }, + } + + // TODO: Unify the registration of common flags and e.g. use the generic options.AddKubeConfigFlag method instead + cmd.Flags().StringVar(&flags.kubeConfigPath, "kubeconfig", flags.kubeConfigPath, "The KubeConfig file to use when talking to the cluster.") + cmd.Flags().BoolVar(&flags.dryRun, "dry-run", flags.dryRun, "Do not change any state, just output the actions that would be performed.") + cmd.Flags().StringVar(&flags.kubeletVersionStr, "kubelet-version", flags.kubeletVersionStr, "The *desired* version for the kubelet after the upgrade.") + return cmd +} + +// RunUpgradeNodeConfig is executed when `kubeadm upgrade node config` runs. +func RunUpgradeNodeConfig(flags *nodeUpgradeFlags) error { + if len(flags.kubeletVersionStr) == 0 { + return fmt.Errorf("The --kubelet-version argument is required") + } + + // Set up the kubelet directory to use. If dry-running, use a fake directory + kubeletDir, err := getKubeletDir(flags.dryRun) + if err != nil { + return err + } + + client, err := getClient(flags.kubeConfigPath, flags.dryRun) + if err != nil { + return fmt.Errorf("couldn't create a Kubernetes client from file %q: %v", flags.kubeConfigPath, err) + } + + // Parse the desired kubelet version + kubeletVersion, err := version.ParseSemantic(flags.kubeletVersionStr) + if err != nil { + return err + } + // TODO: Checkpoint the current configuration first so that if something goes wrong it can be recovered + if err := kubeletphase.DownloadConfig(client, kubeletVersion, kubeletDir); err != nil { + return err + } + + // If we're dry-running, print the generated manifests, otherwise do nothing + if err := printFilesIfDryRunning(flags.dryRun, kubeletDir); err != nil { + return fmt.Errorf("error printing files on dryrun: %v", err) + } + + fmt.Println("[upgrade] The configuration for this node was successfully updated!") + fmt.Println("[upgrade] Now you should go ahead and upgrade the kubelet package using your package manager.") + return nil +} + +// getKubeletDir gets the kubelet directory based on whether the user is dry-running this command or not. +func getKubeletDir(dryRun bool) (string, error) { + if dryRun { + dryRunDir, err := ioutil.TempDir("", "kubeadm-init-dryrun") + if err != nil { + return "", fmt.Errorf("couldn't create a temporary directory: %v", err) + } + return dryRunDir, nil + } + return constants.KubeletRunDirectory, nil +} + +// printFilesIfDryRunning prints the Static Pod manifests to stdout and informs about the temporary directory to go and lookup +func printFilesIfDryRunning(dryRun bool, kubeletDir string) error { + if !dryRun { + return nil + } + + // Print the contents of the upgraded file and pretend like they were in kubeadmconstants.KubeletRunDirectory + fileToPrint := dryrunutil.FileToPrint{ + RealPath: filepath.Join(kubeletDir, constants.KubeletConfigurationFileName), + PrintPath: filepath.Join(constants.KubeletRunDirectory, constants.KubeletConfigurationFileName), + } + return dryrunutil.PrintDryRunFiles([]dryrunutil.FileToPrint{fileToPrint}, os.Stdout) +} diff --git a/cmd/kubeadm/app/cmd/upgrade/plan.go b/cmd/kubeadm/app/cmd/upgrade/plan.go index b769709f370..c0409229cdd 100644 --- a/cmd/kubeadm/app/cmd/upgrade/plan.go +++ b/cmd/kubeadm/app/cmd/upgrade/plan.go @@ -36,14 +36,15 @@ import ( ) type planFlags struct { + *applyPlanFlags + newK8sVersionStr string - parent *cmdUpgradeFlags } // NewCmdPlan returns the cobra command for `kubeadm upgrade plan` -func NewCmdPlan(parentFlags *cmdUpgradeFlags) *cobra.Command { +func NewCmdPlan(apf *applyPlanFlags) *cobra.Command { flags := &planFlags{ - parent: parentFlags, + applyPlanFlags: apf, } cmd := &cobra.Command{ @@ -51,16 +52,16 @@ func NewCmdPlan(parentFlags *cmdUpgradeFlags) *cobra.Command { Short: "Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. To skip the internet check, pass in the optional [version] parameter.", Run: func(_ *cobra.Command, args []string) { var err error - parentFlags.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(parentFlags.ignorePreflightErrors, parentFlags.skipPreFlight) + flags.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(flags.ignorePreflightErrors, flags.skipPreFlight) kubeadmutil.CheckErr(err) // Ensure the user is root - err = runPreflightChecks(parentFlags.ignorePreflightErrorsSet) + err = runPreflightChecks(flags.ignorePreflightErrorsSet) kubeadmutil.CheckErr(err) // If the version is specified in config file, pick up that value. - if parentFlags.cfgPath != "" { - glog.V(1).Infof("fetching configuration from file", parentFlags.cfgPath) - cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(parentFlags.cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) + if flags.cfgPath != "" { + glog.V(1).Infof("fetching configuration from file", flags.cfgPath) + cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(flags.cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) kubeadmutil.CheckErr(err) if cfg.KubernetesVersion != "" { @@ -77,6 +78,8 @@ func NewCmdPlan(parentFlags *cmdUpgradeFlags) *cobra.Command { }, } + // Register the common flags for apply and plan + addApplyPlanFlags(cmd.Flags(), flags.applyPlanFlags) return cmd } @@ -85,7 +88,7 @@ func RunPlan(flags *planFlags) error { // Start with the basics, verify that the cluster is healthy, build a client and a versionGetter. Never dry-run when planning. glog.V(1).Infof("[upgrade/plan] verifying health of cluster") glog.V(1).Infof("[upgrade/plan] retrieving configuration from cluster") - upgradeVars, err := enforceRequirements(flags.parent, false, flags.newK8sVersionStr) + upgradeVars, err := enforceRequirements(flags.applyPlanFlags, false, flags.newK8sVersionStr) if err != nil { return err } @@ -119,7 +122,7 @@ func RunPlan(flags *planFlags) error { // Compute which upgrade possibilities there are glog.V(1).Infof("[upgrade/plan] computing upgrade possibilities") - availUpgrades, err := upgrade.GetAvailableUpgrades(upgradeVars.versionGetter, flags.parent.allowExperimentalUpgrades, flags.parent.allowRCUpgrades, etcdClient, upgradeVars.cfg.FeatureGates, upgradeVars.client) + availUpgrades, err := upgrade.GetAvailableUpgrades(upgradeVars.versionGetter, flags.allowExperimentalUpgrades, flags.allowRCUpgrades, etcdClient, upgradeVars.cfg.FeatureGates, upgradeVars.client) if err != nil { return fmt.Errorf("[upgrade/versions] FATAL: %v", err) } diff --git a/cmd/kubeadm/app/cmd/upgrade/upgrade.go b/cmd/kubeadm/app/cmd/upgrade/upgrade.go index a7928aa01bc..f361be6029e 100644 --- a/cmd/kubeadm/app/cmd/upgrade/upgrade.go +++ b/cmd/kubeadm/app/cmd/upgrade/upgrade.go @@ -21,13 +21,15 @@ import ( "strings" "github.com/spf13/cobra" + "github.com/spf13/pflag" + "k8s.io/apimachinery/pkg/util/sets" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" "k8s.io/kubernetes/cmd/kubeadm/app/features" ) -// cmdUpgradeFlags holds the values for the common flags in `kubeadm upgrade` -type cmdUpgradeFlags struct { +// applyPlanFlags holds the values for the common flags in `kubeadm upgrade apply` and `kubeadm upgrade plan` +type applyPlanFlags struct { kubeConfigPath string cfgPath string featureGatesString string @@ -42,7 +44,7 @@ type cmdUpgradeFlags struct { // NewCmdUpgrade returns the cobra command for `kubeadm upgrade` func NewCmdUpgrade(out io.Writer) *cobra.Command { - flags := &cmdUpgradeFlags{ + flags := &applyPlanFlags{ kubeConfigPath: "/etc/kubernetes/admin.conf", cfgPath: "", featureGatesString: "", @@ -60,20 +62,24 @@ func NewCmdUpgrade(out io.Writer) *cobra.Command { RunE: cmdutil.SubCmdRunE("upgrade"), } - cmd.PersistentFlags().StringVar(&flags.kubeConfigPath, "kubeconfig", flags.kubeConfigPath, "The KubeConfig file to use when talking to the cluster.") - cmd.PersistentFlags().StringVar(&flags.cfgPath, "config", flags.cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental!") - cmd.PersistentFlags().BoolVar(&flags.allowExperimentalUpgrades, "allow-experimental-upgrades", flags.allowExperimentalUpgrades, "Show unstable versions of Kubernetes as an upgrade alternative and allow upgrading to an alpha/beta/release candidate versions of Kubernetes.") - cmd.PersistentFlags().BoolVar(&flags.allowRCUpgrades, "allow-release-candidate-upgrades", flags.allowRCUpgrades, "Show release candidate versions of Kubernetes as an upgrade alternative and allow upgrading to a release candidate versions of Kubernetes.") - cmd.PersistentFlags().BoolVar(&flags.printConfig, "print-config", flags.printConfig, "Specifies whether the configuration file that will be used in the upgrade should be printed or not.") - cmd.PersistentFlags().StringSliceVar(&flags.ignorePreflightErrors, "ignore-preflight-errors", flags.ignorePreflightErrors, "A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.") - cmd.PersistentFlags().BoolVar(&flags.skipPreFlight, "skip-preflight-checks", flags.skipPreFlight, "Skip preflight checks that normally run before modifying the system.") - cmd.PersistentFlags().MarkDeprecated("skip-preflight-checks", "it is now equivalent to --ignore-preflight-errors=all") - cmd.PersistentFlags().StringVar(&flags.featureGatesString, "feature-gates", flags.featureGatesString, "A set of key=value pairs that describe feature gates for various features."+ - "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) - cmd.AddCommand(NewCmdApply(flags)) cmd.AddCommand(NewCmdPlan(flags)) - cmd.AddCommand(NewCmdDiff(flags)) - + cmd.AddCommand(NewCmdDiff(out)) + cmd.AddCommand(NewCmdNode()) return cmd } + +func addApplyPlanFlags(fs *pflag.FlagSet, flags *applyPlanFlags) { + // TODO: Use the generic options.AddKubeConfigFlag and options.AddConfigFlag methods instead + fs.StringVar(&flags.kubeConfigPath, "kubeconfig", flags.kubeConfigPath, "The KubeConfig file to use when talking to the cluster.") + fs.StringVar(&flags.cfgPath, "config", flags.cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental!") + + fs.BoolVar(&flags.allowExperimentalUpgrades, "allow-experimental-upgrades", flags.allowExperimentalUpgrades, "Show unstable versions of Kubernetes as an upgrade alternative and allow upgrading to an alpha/beta/release candidate versions of Kubernetes.") + fs.BoolVar(&flags.allowRCUpgrades, "allow-release-candidate-upgrades", flags.allowRCUpgrades, "Show release candidate versions of Kubernetes as an upgrade alternative and allow upgrading to a release candidate versions of Kubernetes.") + fs.BoolVar(&flags.printConfig, "print-config", flags.printConfig, "Specifies whether the configuration file that will be used in the upgrade should be printed or not.") + fs.StringSliceVar(&flags.ignorePreflightErrors, "ignore-preflight-errors", flags.ignorePreflightErrors, "A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.") + fs.BoolVar(&flags.skipPreFlight, "skip-preflight-checks", flags.skipPreFlight, "Skip preflight checks that normally run before modifying the system.") + fs.MarkDeprecated("skip-preflight-checks", "it is now equivalent to --ignore-preflight-errors=all") + fs.StringVar(&flags.featureGatesString, "feature-gates", flags.featureGatesString, "A set of key=value pairs that describe feature gates for various features."+ + "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) +} diff --git a/cmd/kubeadm/app/constants/constants.go b/cmd/kubeadm/app/constants/constants.go index afd5ce5ba5c..dcffdd069c1 100644 --- a/cmd/kubeadm/app/constants/constants.go +++ b/cmd/kubeadm/app/constants/constants.go @@ -21,6 +21,7 @@ import ( "io/ioutil" "net" "os" + "path" "path/filepath" "time" @@ -38,7 +39,8 @@ const ( // ManifestsSubDirName defines directory name to store manifests ManifestsSubDirName = "manifests" // TempDirForKubeadm defines temporary directory for kubeadm - TempDirForKubeadm = "/etc/kubernetes/tmp" + // should be joined with KubernetesDir. + TempDirForKubeadm = "tmp" // CACertAndKeyBaseName defines certificate authority base name CACertAndKeyBaseName = "ca" @@ -78,8 +80,6 @@ const ( EtcdServerCertName = "etcd/server.crt" // EtcdServerKeyName defines etcd's server key name EtcdServerKeyName = "etcd/server.key" - // EtcdServerCertCommonName defines etcd's server certificate common name (CN) - EtcdServerCertCommonName = "kube-etcd" // EtcdPeerCertAndKeyBaseName defines etcd's peer certificate and key base name EtcdPeerCertAndKeyBaseName = "etcd/peer" @@ -87,8 +87,6 @@ const ( EtcdPeerCertName = "etcd/peer.crt" // EtcdPeerKeyName defines etcd's peer key name EtcdPeerKeyName = "etcd/peer.key" - // EtcdPeerCertCommonName defines etcd's peer certificate common name (CN) - EtcdPeerCertCommonName = "kube-etcd-peer" // EtcdHealthcheckClientCertAndKeyBaseName defines etcd's healthcheck client certificate and key base name EtcdHealthcheckClientCertAndKeyBaseName = "etcd/healthcheck-client" @@ -165,10 +163,12 @@ const ( APICallRetryInterval = 500 * time.Millisecond // DiscoveryRetryInterval specifies how long kubeadm should wait before retrying to connect to the master when doing discovery DiscoveryRetryInterval = 5 * time.Second - // MarkMasterTimeout specifies how long kubeadm should wait for applying the label and taint on the master before timing out - MarkMasterTimeout = 2 * time.Minute + // PatchNodeTimeout specifies how long kubeadm should wait for applying the label and taint on the master before timing out + PatchNodeTimeout = 2 * time.Minute // UpdateNodeTimeout specifies how long kubeadm should wait for updating node with the initial remote configuration of kubelet before timing out UpdateNodeTimeout = 2 * time.Minute + // TLSBootstrapTimeout specifies how long kubeadm should wait for the kubelet to perform the TLS Bootstrap + TLSBootstrapTimeout = 2 * time.Minute // MinimumAddressesInServiceSubnet defines minimum amount of nodes the Service subnet should allow. // We need at least ten, because the DNS service is always at the tenth cluster clusterIP @@ -182,6 +182,10 @@ const ( // This is a duplicate definition of the constant in pkg/controller/service/service_controller.go LabelNodeRoleMaster = "node-role.kubernetes.io/master" + // AnnotationKubeadmCRISocket specifies the annotation kubeadm uses to preserve the crisocket information given to kubeadm at + // init/join time for use later. kubeadm annotates the node object with this information + AnnotationKubeadmCRISocket = "kubeadm.alpha.kubernetes.io/cri-socket" + // MasterConfigurationConfigMap specifies in what ConfigMap in the kube-system namespace the `kubeadm init` configuration should be stored MasterConfigurationConfigMap = "kubeadm-config" @@ -197,8 +201,26 @@ const ( // KubeletBaseConfigMapRolePrefix defines the base kubelet configuration ConfigMap. KubeletBaseConfigMapRolePrefix = "kubeadm:kubelet-config-" - // KubeletConfigurationFile specifies the file name on the node which stores initial remote configuration of kubelet - KubeletConfigurationFile = "/var/lib/kubelet/config.yaml" + // KubeletRunDirectory specifies the directory where the kubelet runtime information is stored. + // TODO: Make hard-coded "/var/lib/kubelet" strings reference this constant. + KubeletRunDirectory = "/var/lib/kubelet" + + // KubeletConfigurationFileName specifies the file name on the node which stores initial remote configuration of kubelet + // This file should exist under KubeletRunDirectory + KubeletConfigurationFileName = "config.yaml" + + // DynamicKubeletConfigurationDirectoryName specifies the directory which stores the dynamic configuration checkpoints for the kubelet + // This directory should exist under KubeletRunDirectory + DynamicKubeletConfigurationDirectoryName = "dynamic-config" + + // KubeletEnvFileName is a file "kubeadm init" writes at runtime. Using that interface, kubeadm can customize certain + // kubelet flags conditionally based on the environment at runtime. Also, parameters given to the configuration file + // might be passed through this file. "kubeadm init" writes one variable, with the name ${KubeletEnvFileVariableName}. + // This file should exist under KubeletRunDirectory + KubeletEnvFileName = "kubeadm-flags.env" + + // KubeletEnvFileVariableName specifies the shell script variable name "kubeadm init" should write a value to in KubeletEnvFile + KubeletEnvFileVariableName = "KUBELET_KUBEADM_ARGS" // MinExternalEtcdVersion indicates minimum external etcd version which kubeadm supports MinExternalEtcdVersion = "3.2.17" @@ -258,13 +280,11 @@ const ( // TODO: Import this constant from a consts only package, that does not pull any further dependencies. LeaseEndpointReconcilerType = "lease" - // KubeletEnvFile is a file "kubeadm init" writes at runtime. Using that interface, kubeadm can customize certain - // kubelet flags conditionally based on the environment at runtime. Also, parameters given to the configuration file - // might be passed through this file. "kubeadm init" writes one variable, with the name ${KubeletEnvFileVariableName}. - KubeletEnvFile = "/var/lib/kubelet/kubeadm-flags.env" + // KubeDNSVersion is the version of kube-dns to be deployed if it is used + KubeDNSVersion = "1.14.10" - // KubeletEnvFileVariableName specifies the shell script variable name "kubeadm init" should write a value to in KubeletEnvFile - KubeletEnvFileVariableName = "KUBELET_KUBEADM_ARGS" + // CoreDNSVersion is the version of CoreDNS to be deployed if it is used + CoreDNSVersion = "1.1.3" ) var ( @@ -295,9 +315,6 @@ var ( // MinimumKubeletVersion specifies the minimum version of kubelet which kubeadm supports MinimumKubeletVersion = version.MustParseSemantic("v1.10.0") - // MinimumKubeletConfigVersion specifies the minimum version of Kubernetes where kubeadm supports specifying --config to the kubelet - MinimumKubeletConfigVersion = version.MustParseSemantic("v1.11.0-alpha.1") - // SupportedEtcdVersion lists officially supported etcd versions with corresponding kubernetes releases SupportedEtcdVersion = map[uint8]string{ 10: "3.1.12", @@ -339,6 +356,16 @@ func GetAdminKubeConfigPath() string { return filepath.Join(KubernetesDir, AdminKubeConfigFileName) } +// GetBootstrapKubeletKubeConfigPath returns the location on the disk where bootstrap kubelet kubeconfig is located by default +func GetBootstrapKubeletKubeConfigPath() string { + return filepath.Join(KubernetesDir, KubeletBootstrapKubeConfigFileName) +} + +// GetKubeletKubeConfigPath returns the location on the disk where kubelet kubeconfig is located by default +func GetKubeletKubeConfigPath() string { + return filepath.Join(KubernetesDir, KubeletKubeConfigFileName) +} + // AddSelfHostedPrefix adds the self-hosted- prefix to the component name func AddSelfHostedPrefix(componentName string) string { return fmt.Sprintf("%s%s", SelfHostingPrefix, componentName) @@ -346,18 +373,36 @@ func AddSelfHostedPrefix(componentName string) string { // CreateTempDirForKubeadm is a function that creates a temporary directory under /etc/kubernetes/tmp (not using /tmp as that would potentially be dangerous) func CreateTempDirForKubeadm(dirName string) (string, error) { + tempDir := path.Join(KubernetesDir, TempDirForKubeadm) // creates target folder if not already exists - if err := os.MkdirAll(TempDirForKubeadm, 0700); err != nil { - return "", fmt.Errorf("failed to create directory %q: %v", TempDirForKubeadm, err) + if err := os.MkdirAll(tempDir, 0700); err != nil { + return "", fmt.Errorf("failed to create directory %q: %v", tempDir, err) } - tempDir, err := ioutil.TempDir(TempDirForKubeadm, dirName) + tempDir, err := ioutil.TempDir(tempDir, dirName) if err != nil { return "", fmt.Errorf("couldn't create a temporary directory: %v", err) } return tempDir, nil } +// CreateTimestampDirForKubeadm is a function that creates a temporary directory under /etc/kubernetes/tmp formatted with the current date +func CreateTimestampDirForKubeadm(dirName string) (string, error) { + tempDir := path.Join(KubernetesDir, TempDirForKubeadm) + // creates target folder if not already exists + if err := os.MkdirAll(tempDir, 0700); err != nil { + return "", fmt.Errorf("failed to create directory %q: %v", tempDir, err) + } + + timestampDirName := fmt.Sprintf("%s-%s", dirName, time.Now().Format("2006-01-02-15-04-05")) + timestampDir := path.Join(tempDir, timestampDirName) + if err := os.Mkdir(timestampDir, 0700); err != nil { + return "", fmt.Errorf("could not create timestamp directory: %v", err) + } + + return timestampDir, nil +} + // GetDNSIP returns a dnsIP, which is 10th IP in svcSubnet CIDR range func GetDNSIP(svcSubnet string) (net.IP, error) { // Get the service subnet CIDR @@ -379,3 +424,13 @@ func GetDNSIP(svcSubnet string) (net.IP, error) { func GetStaticPodAuditPolicyFile() string { return filepath.Join(KubernetesDir, AuditPolicyDir, AuditPolicyFile) } + +// GetDNSVersion is a handy function that returns the DNS version by DNS type +func GetDNSVersion(dnsType string) string { + switch dnsType { + case CoreDNS: + return CoreDNSVersion + default: + return KubeDNSVersion + } +} diff --git a/cmd/kubeadm/app/constants/constants_test.go b/cmd/kubeadm/app/constants/constants_test.go index 0ab842d3cdd..7bcec426224 100644 --- a/cmd/kubeadm/app/constants/constants_test.go +++ b/cmd/kubeadm/app/constants/constants_test.go @@ -50,6 +50,32 @@ func TestGetAdminKubeConfigPath(t *testing.T) { } } +func TestGetBootstrapKubeletKubeConfigPath(t *testing.T) { + expected := "/etc/kubernetes/bootstrap-kubelet.conf" + actual := GetBootstrapKubeletKubeConfigPath() + + if actual != expected { + t.Errorf( + "failed GetBootstrapKubeletKubeConfigPath:\n\texpected: %s\n\t actual: %s", + expected, + actual, + ) + } +} + +func TestGetKubeletKubeConfigPath(t *testing.T) { + expected := "/etc/kubernetes/kubelet.conf" + actual := GetKubeletKubeConfigPath() + + if actual != expected { + t.Errorf( + "failed GetKubeletKubeConfigPath:\n\texpected: %s\n\t actual: %s", + expected, + actual, + ) + } +} + func TestGetStaticPodFilepath(t *testing.T) { var tests = []struct { componentName, manifestsDir, expected string @@ -172,3 +198,29 @@ func TestEtcdSupportedVersion(t *testing.T) { } } } + +func TestGetKubeDNSVersion(t *testing.T) { + var tests = []struct { + dns string + expected string + }{ + { + dns: KubeDNS, + expected: KubeDNSVersion, + }, + { + dns: CoreDNS, + expected: CoreDNSVersion, + }, + } + 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, + ) + } + } +} diff --git a/cmd/kubeadm/app/discovery/token/BUILD b/cmd/kubeadm/app/discovery/token/BUILD index 5ddffb3e440..e5a9bba7797 100644 --- a/cmd/kubeadm/app/discovery/token/BUILD +++ b/cmd/kubeadm/app/discovery/token/BUILD @@ -15,7 +15,6 @@ go_library( "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", "//cmd/kubeadm/app/util/pubkeypin:go_default_library", - "//cmd/kubeadm/app/util/token:go_default_library", "//pkg/controller/bootstrap:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/cmd/kubeadm/app/discovery/token/token.go b/cmd/kubeadm/app/discovery/token/token.go index a1c537a0b28..bd2d3b88a62 100644 --- a/cmd/kubeadm/app/discovery/token/token.go +++ b/cmd/kubeadm/app/discovery/token/token.go @@ -34,7 +34,6 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" "k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin" - tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token" "k8s.io/kubernetes/pkg/controller/bootstrap" ) @@ -45,7 +44,7 @@ const BootstrapUser = "token-bootstrap-client" // It then makes sure it can trust the API Server by looking at the JWS-signed tokens and (if cfg.DiscoveryTokenCACertHashes is not empty) // validating the cluster CA against a set of pinned public keys func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Cluster, error) { - tokenID, tokenSecret, err := tokenutil.ParseToken(cfg.DiscoveryToken) + token, err := kubeadmapi.NewBootstrapTokenString(cfg.DiscoveryToken) if err != nil { return nil, err } @@ -88,11 +87,11 @@ func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmd if !ok || len(insecureKubeconfigString) == 0 { return nil, fmt.Errorf("there is no %s key in the %s ConfigMap. This API Server isn't set up for token bootstrapping, can't connect", bootstrapapi.KubeConfigKey, bootstrapapi.ConfigMapClusterInfo) } - detachedJWSToken, ok := insecureClusterInfo.Data[bootstrapapi.JWSSignatureKeyPrefix+tokenID] + detachedJWSToken, ok := insecureClusterInfo.Data[bootstrapapi.JWSSignatureKeyPrefix+token.ID] if !ok || len(detachedJWSToken) == 0 { - return nil, fmt.Errorf("token id %q is invalid for this cluster or it has expired. Use \"kubeadm token create\" on the master node to creating a new valid token", tokenID) + return nil, fmt.Errorf("token id %q is invalid for this cluster or it has expired. Use \"kubeadm token create\" on the master node to creating a new valid token", token.ID) } - if !bootstrap.DetachedTokenIsValid(detachedJWSToken, insecureKubeconfigString, tokenID, tokenSecret) { + if !bootstrap.DetachedTokenIsValid(detachedJWSToken, insecureKubeconfigString, token.ID, token.Secret) { return nil, fmt.Errorf("failed to verify JWS signature of received cluster info object, can't trust this API Server") } insecureKubeconfigBytes := []byte(insecureKubeconfigString) diff --git a/cmd/kubeadm/app/images/BUILD b/cmd/kubeadm/app/images/BUILD index 27e970e71d4..48752117684 100644 --- a/cmd/kubeadm/app/images/BUILD +++ b/cmd/kubeadm/app/images/BUILD @@ -10,15 +10,14 @@ go_library( name = "go_default_library", srcs = [ "images.go", - "puller.go", + "interface.go", ], importpath = "k8s.io/kubernetes/cmd/kubeadm/app/images", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", - "//cmd/kubeadm/app/phases/addons/dns:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ], @@ -28,7 +27,10 @@ go_test( name = "go_default_test", srcs = ["images_test.go"], embed = [":go_default_library"], - deps = ["//cmd/kubeadm/app/constants:go_default_library"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", + ], ) filegroup( @@ -46,10 +48,10 @@ filegroup( go_test( name = "go_default_xtest", - srcs = ["puller_test.go"], + srcs = ["interface_test.go"], deps = [ ":go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ], ) diff --git a/cmd/kubeadm/app/images/images.go b/cmd/kubeadm/app/images/images.go index 999180828cd..f9260148c80 100644 --- a/cmd/kubeadm/app/images/images.go +++ b/cmd/kubeadm/app/images/images.go @@ -23,7 +23,6 @@ import ( kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" - "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" ) @@ -48,11 +47,14 @@ func GetCoreImage(image, repoPrefix, k8sVersion, overrideImage string) string { // GetAllImages returns a list of container images kubeadm expects to use on a control plane node func GetAllImages(cfg *kubeadmapi.MasterConfiguration) []string { + repoPrefix := cfg.GetControlPlaneImageRepository() imgs := []string{} - imgs = append(imgs, GetCoreImage(constants.KubeAPIServer, cfg.ImageRepository, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage)) - imgs = append(imgs, GetCoreImage(constants.KubeControllerManager, cfg.ImageRepository, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage)) - imgs = append(imgs, GetCoreImage(constants.KubeScheduler, cfg.ImageRepository, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage)) - imgs = append(imgs, fmt.Sprintf("%v/%v-%v:%v", cfg.ImageRepository, constants.KubeProxy, runtime.GOARCH, kubeadmutil.KubernetesVersionToImageTag(cfg.KubernetesVersion))) + imgs = append(imgs, GetCoreImage(constants.KubeAPIServer, repoPrefix, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage)) + imgs = append(imgs, GetCoreImage(constants.KubeControllerManager, repoPrefix, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage)) + imgs = append(imgs, GetCoreImage(constants.KubeScheduler, repoPrefix, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage)) + imgs = append(imgs, fmt.Sprintf("%v/%v-%v:%v", repoPrefix, constants.KubeProxy, runtime.GOARCH, kubeadmutil.KubernetesVersionToImageTag(cfg.KubernetesVersion))) + + // pause, etcd and kube-dns are not available on the ci image repository so use the default image repository. imgs = append(imgs, fmt.Sprintf("%v/pause-%v:%v", cfg.ImageRepository, runtime.GOARCH, "3.1")) // if etcd is not external then add the image as it will be required @@ -60,9 +62,9 @@ func GetAllImages(cfg *kubeadmapi.MasterConfiguration) []string { imgs = append(imgs, GetCoreImage(constants.Etcd, cfg.ImageRepository, cfg.KubernetesVersion, cfg.Etcd.Local.Image)) } - dnsImage := fmt.Sprintf("%v/k8s-dns-kube-dns-%v:%v", cfg.ImageRepository, runtime.GOARCH, dns.GetDNSVersion(nil, constants.KubeDNS)) + dnsImage := fmt.Sprintf("%v/k8s-dns-kube-dns-%v:%v", cfg.ImageRepository, runtime.GOARCH, constants.KubeDNSVersion) if features.Enabled(cfg.FeatureGates, features.CoreDNS) { - dnsImage = fmt.Sprintf("coredns/coredns:%v", dns.GetDNSVersion(nil, constants.CoreDNS)) + dnsImage = fmt.Sprintf("%v/coredns:%v", cfg.ImageRepository, constants.CoreDNSVersion) } imgs = append(imgs, dnsImage) return imgs diff --git a/cmd/kubeadm/app/images/images_test.go b/cmd/kubeadm/app/images/images_test.go index 466f204500d..38f237cc9d7 100644 --- a/cmd/kubeadm/app/images/images_test.go +++ b/cmd/kubeadm/app/images/images_test.go @@ -19,8 +19,10 @@ package images import ( "fmt" "runtime" + "strings" "testing" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) @@ -73,3 +75,46 @@ func TestGetCoreImage(t *testing.T) { } } } + +func TestGetAllImages(t *testing.T) { + testcases := []struct { + name string + cfg *kubeadmapi.MasterConfiguration + expect string + }{ + { + name: "defined CIImageRepository", + cfg: &kubeadmapi.MasterConfiguration{ + CIImageRepository: "test.repo", + }, + expect: "test.repo", + }, + { + name: "undefined CIImagerRepository should contain the default image prefix", + cfg: &kubeadmapi.MasterConfiguration{ + ImageRepository: "real.repo", + }, + expect: "real.repo", + }, + { + name: "test that etcd is returned when it is not external", + cfg: &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{}, + }, + }, + expect: constants.Etcd, + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + imgs := GetAllImages(tc.cfg) + for _, img := range imgs { + if strings.Contains(img, tc.expect) { + return + } + } + t.Fatalf("did not find %q in %q", tc.expect, imgs) + }) + } +} diff --git a/cmd/kubeadm/app/images/interface.go b/cmd/kubeadm/app/images/interface.go new file mode 100644 index 00000000000..c9bd6b16fa8 --- /dev/null +++ b/cmd/kubeadm/app/images/interface.go @@ -0,0 +1,89 @@ +/* +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 images + +import ( + "fmt" + + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + utilsexec "k8s.io/utils/exec" +) + +// Puller is an interface for pulling images +type Puller interface { + Pull(string) error +} + +// Existence is an interface to determine if an image exists on the system +// A nil error means the image was found +type Existence interface { + Exists(string) error +} + +// Images defines the set of behaviors needed for images relating to the CRI +type Images interface { + Puller + Existence +} + +// CRInterfacer is a struct that interfaces with the container runtime +type CRInterfacer struct { + criSocket string + exec utilsexec.Interface + crictlPath string + dockerPath string +} + +// NewCRInterfacer sets up and returns a CRInterfacer +func NewCRInterfacer(execer utilsexec.Interface, criSocket string) (*CRInterfacer, error) { + var crictlPath, dockerPath string + var err error + if criSocket != kubeadmapiv1alpha2.DefaultCRISocket { + if crictlPath, err = execer.LookPath("crictl"); err != nil { + return nil, fmt.Errorf("crictl is required for non docker container runtimes: %v", err) + } + } else { + // use the dockershim + if dockerPath, err = execer.LookPath("docker"); err != nil { + return nil, fmt.Errorf("`docker` is required when docker is the container runtime and the kubelet is not running: %v", err) + } + } + + return &CRInterfacer{ + exec: execer, + criSocket: criSocket, + crictlPath: crictlPath, + dockerPath: dockerPath, + }, nil +} + +// Pull pulls the actual image using either crictl or docker +func (cri *CRInterfacer) Pull(image string) error { + if cri.criSocket != kubeadmapiv1alpha2.DefaultCRISocket { + return cri.exec.Command(cri.crictlPath, "-r", cri.criSocket, "pull", image).Run() + } + return cri.exec.Command(cri.dockerPath, "pull", image).Run() +} + +// Exists checks to see if the image exists on the system already +// Returns an error if the image is not found. +func (cri *CRInterfacer) Exists(image string) error { + if cri.criSocket != kubeadmapiv1alpha2.DefaultCRISocket { + return cri.exec.Command(cri.crictlPath, "-r", cri.criSocket, "inspecti", image).Run() + } + return cri.exec.Command(cri.dockerPath, "inspect", image).Run() +} diff --git a/cmd/kubeadm/app/images/interface_test.go b/cmd/kubeadm/app/images/interface_test.go new file mode 100644 index 00000000000..54e176aaf6a --- /dev/null +++ b/cmd/kubeadm/app/images/interface_test.go @@ -0,0 +1,266 @@ +/* +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 images_test + +import ( + "context" + "errors" + "io" + "testing" + + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + "k8s.io/kubernetes/cmd/kubeadm/app/images" + "k8s.io/utils/exec" +) + +type fakeCmd struct { + err error +} + +func (f *fakeCmd) Run() error { + return f.err +} +func (f *fakeCmd) CombinedOutput() ([]byte, error) { return nil, nil } +func (f *fakeCmd) Output() ([]byte, error) { return nil, nil } +func (f *fakeCmd) SetDir(dir string) {} +func (f *fakeCmd) SetStdin(in io.Reader) {} +func (f *fakeCmd) SetStdout(out io.Writer) {} +func (f *fakeCmd) SetStderr(out io.Writer) {} +func (f *fakeCmd) Stop() {} + +type fakeExecer struct { + cmd exec.Cmd + findCrictl bool + findDocker bool +} + +func (f *fakeExecer) Command(cmd string, args ...string) exec.Cmd { return f.cmd } +func (f *fakeExecer) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd { + return f.cmd +} +func (f *fakeExecer) LookPath(file string) (string, error) { + if file == "crictl" { + if f.findCrictl { + return "/path", nil + } + return "", errors.New("no crictl for you") + } + if file == "docker" { + if f.findDocker { + return "/path", nil + } + return "", errors.New("no docker for you") + } + return "", errors.New("unknown binary") +} + +func TestNewCRInterfacer(t *testing.T) { + testcases := []struct { + name string + criSocket string + findCrictl bool + findDocker bool + expectError bool + }{ + { + name: "need crictl but can only find docker should return an error", + criSocket: "/not/docker", + findCrictl: false, + findDocker: true, + expectError: true, + }, + { + name: "need crictl and cannot find either should return an error", + criSocket: "/not/docker", + findCrictl: false, + findDocker: false, + expectError: true, + }, + { + name: "need crictl and cannot find docker should return no error", + criSocket: "/not/docker", + findCrictl: true, + findDocker: false, + expectError: false, + }, + { + name: "need crictl and can find both should return no error", + criSocket: "/not/docker", + findCrictl: true, + findDocker: true, + expectError: false, + }, + { + name: "need docker and cannot find crictl should return no error", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + findCrictl: false, + findDocker: true, + expectError: false, + }, + { + name: "need docker and cannot find docker should return an error", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + findCrictl: false, + findDocker: false, + expectError: true, + }, + { + name: "need docker and can find both should return no error", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + findCrictl: true, + findDocker: true, + expectError: false, + }, + { + name: "need docker and can only find crictl should return an error", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + findCrictl: true, + findDocker: false, + expectError: true, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + fe := &fakeExecer{ + findCrictl: tc.findCrictl, + findDocker: tc.findDocker, + } + _, err := images.NewCRInterfacer(fe, tc.criSocket) + if tc.expectError && err == nil { + t.Fatal("expected an error but did not get one") + } + if !tc.expectError && err != nil { + t.Fatalf("did not expedt an error but got an error: %v", err) + } + }) + } +} + +func TestImagePuller(t *testing.T) { + testcases := []struct { + name string + criSocket string + pullFails bool + errorExpected bool + }{ + { + name: "using docker and pull fails", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + pullFails: true, + errorExpected: true, + }, + { + name: "using docker and pull succeeds", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + pullFails: false, + errorExpected: false, + }, + { + name: "using crictl pull fails", + criSocket: "/not/default", + pullFails: true, + errorExpected: true, + }, + { + name: "using crictl and pull succeeds", + criSocket: "/not/default", + pullFails: false, + errorExpected: false, + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + var err error + if tc.pullFails { + err = errors.New("error") + } + + fe := &fakeExecer{ + cmd: &fakeCmd{err}, + findCrictl: true, + findDocker: true, + } + ip, _ := images.NewCRInterfacer(fe, tc.criSocket) + + err = ip.Pull("imageName") + if tc.errorExpected && err == nil { + t.Fatal("expected an error and did not get one") + } + if !tc.errorExpected && err != nil { + t.Fatalf("expected no error but got one: %v", err) + } + }) + } +} + +func TestImageExists(t *testing.T) { + testcases := []struct { + name string + criSocket string + existFails bool + errorExpected bool + }{ + { + name: "using docker and exist fails", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + existFails: true, + errorExpected: true, + }, + { + name: "using docker and exist succeeds", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + existFails: false, + errorExpected: false, + }, + { + name: "using crictl exist fails", + criSocket: "/not/default", + existFails: true, + errorExpected: true, + }, + { + name: "using crictl and exist succeeds", + criSocket: "/not/default", + existFails: false, + errorExpected: false, + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + var err error + if tc.existFails { + err = errors.New("error") + } + + fe := &fakeExecer{ + cmd: &fakeCmd{err}, + findCrictl: true, + findDocker: true, + } + ip, _ := images.NewCRInterfacer(fe, tc.criSocket) + + err = ip.Exists("imageName") + if tc.errorExpected && err == nil { + t.Fatal("expected an error and did not get one") + } + if !tc.errorExpected && err != nil { + t.Fatalf("expected no error but got one: %v", err) + } + }) + } +} diff --git a/cmd/kubeadm/app/images/puller.go b/cmd/kubeadm/app/images/puller.go deleted file mode 100644 index 71db11e481f..00000000000 --- a/cmd/kubeadm/app/images/puller.go +++ /dev/null @@ -1,57 +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 images - -import ( - "fmt" - - kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" - utilsexec "k8s.io/utils/exec" -) - -// Puller is an interface for pulling images -type Puller interface { - Pull(string) error -} - -// ImagePuller is a struct that can pull images and hides the implementation (crictl vs docker) -type ImagePuller struct { - criSocket string - exec utilsexec.Interface - crictlPath string -} - -// NewImagePuller returns a ready to go ImagePuller -func NewImagePuller(execer utilsexec.Interface, criSocket string) (*ImagePuller, error) { - crictlPath, err := execer.LookPath("crictl") - if err != nil && criSocket != kubeadmapiv1alpha1.DefaultCRISocket { - return nil, fmt.Errorf("crictl is required for non docker container runtimes: %v", err) - } - return &ImagePuller{ - exec: execer, - criSocket: criSocket, - crictlPath: crictlPath, - }, nil -} - -// Pull pulls the actual image using either crictl or docker -func (ip *ImagePuller) Pull(image string) error { - if ip.criSocket != kubeadmapiv1alpha1.DefaultCRISocket { - return ip.exec.Command(ip.crictlPath, "-r", ip.criSocket, "pull", image).Run() - } - return ip.exec.Command("sh", "-c", fmt.Sprintf("docker pull %v", image)).Run() -} diff --git a/cmd/kubeadm/app/images/puller_test.go b/cmd/kubeadm/app/images/puller_test.go deleted file mode 100644 index 6a27ec03276..00000000000 --- a/cmd/kubeadm/app/images/puller_test.go +++ /dev/null @@ -1,138 +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 images_test - -import ( - "bytes" - "context" - "errors" - "fmt" - "io" - "os" - "strings" - "testing" - - kubeadmdefaults "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" - "k8s.io/kubernetes/cmd/kubeadm/app/images" - "k8s.io/utils/exec" -) - -type fakeCmd struct { - cmd string - args []string - out io.Writer -} - -func (f *fakeCmd) Run() error { - fmt.Fprintf(f.out, "%v %v", f.cmd, strings.Join(f.args, " ")) - return nil -} -func (f *fakeCmd) CombinedOutput() ([]byte, error) { return nil, nil } -func (f *fakeCmd) Output() ([]byte, error) { return nil, nil } -func (f *fakeCmd) SetDir(dir string) {} -func (f *fakeCmd) SetStdin(in io.Reader) {} -func (f *fakeCmd) SetStdout(out io.Writer) { - f.out = out -} -func (f *fakeCmd) SetStderr(out io.Writer) {} -func (f *fakeCmd) Stop() {} - -type fakeExecer struct { - cmd exec.Cmd - lookPathSucceeds bool -} - -func (f *fakeExecer) Command(cmd string, args ...string) exec.Cmd { return f.cmd } -func (f *fakeExecer) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd { - return f.cmd -} -func (f *fakeExecer) LookPath(file string) (string, error) { - if f.lookPathSucceeds { - return file, nil - } - return "", &os.PathError{Err: errors.New("does not exist")} -} - -func TestImagePuller(t *testing.T) { - testcases := []struct { - name string - criSocket string - cmd exec.Cmd - findCrictl bool - expected string - errorExpected bool - }{ - { - name: "New succeeds even if crictl is not in path", - criSocket: kubeadmdefaults.DefaultCRISocket, - cmd: &fakeCmd{ - cmd: "hello", - args: []string{"world", "and", "friends"}, - }, - findCrictl: false, - expected: "hello world and friends", - }, - { - name: "New succeeds with crictl in path", - criSocket: "/not/default", - cmd: &fakeCmd{ - cmd: "crictl", - args: []string{"-r", "/some/socket", "imagename"}, - }, - findCrictl: true, - expected: "crictl -r /some/socket imagename", - }, - { - name: "New fails with crictl not in path but is required", - criSocket: "/not/docker", - cmd: &fakeCmd{ - cmd: "crictl", - args: []string{"-r", "/not/docker", "an image"}, - }, - findCrictl: false, - errorExpected: true, - }, - } - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - var b bytes.Buffer - tc.cmd.SetStdout(&b) - fe := &fakeExecer{ - cmd: tc.cmd, - lookPathSucceeds: tc.findCrictl, - } - ip, err := images.NewImagePuller(fe, tc.criSocket) - - if tc.errorExpected { - if err == nil { - t.Fatalf("expected an error but found nil: %v", fe) - } - return - } - - if err != nil { - t.Fatalf("expected nil but found an error: %v", err) - } - if err = ip.Pull("imageName"); err != nil { - t.Fatalf("expected nil pulling an image but found: %v", err) - } - if b.String() != tc.expected { - t.Fatalf("expected %v but got: %v", tc.expected, b.String()) - } - }) - } -} diff --git a/cmd/kubeadm/app/kubeadm.go b/cmd/kubeadm/app/kubeadm.go index df299180815..fddda590260 100644 --- a/cmd/kubeadm/app/kubeadm.go +++ b/cmd/kubeadm/app/kubeadm.go @@ -23,18 +23,27 @@ import ( _ "github.com/golang/glog" "github.com/spf13/pflag" + utilflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/kubernetes/cmd/kubeadm/app/cmd" ) // Run creates and executes new kubeadm command func Run() error { - // We do not want these flags to show up in --help - pflag.CommandLine.MarkHidden("version") - pflag.CommandLine.MarkHidden("google-json-key") - pflag.CommandLine.MarkHidden("log-flush-frequency") + pflag.CommandLine.SetNormalizeFunc(utilflag.WordSepNormalizeFunc) pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.Set("logtostderr", "true") + // We do not want these flags to show up in --help + // These MarkHidden calls must be after the lines above + pflag.CommandLine.MarkHidden("version") + pflag.CommandLine.MarkHidden("google-json-key") + pflag.CommandLine.MarkHidden("log-flush-frequency") + pflag.CommandLine.MarkHidden("alsologtostderr") + pflag.CommandLine.MarkHidden("log-backtrace-at") + pflag.CommandLine.MarkHidden("log-dir") + pflag.CommandLine.MarkHidden("logtostderr") + pflag.CommandLine.MarkHidden("stderrthreshold") + pflag.CommandLine.MarkHidden("vmodule") cmd := cmd.NewKubeadmCommand(os.Stdin, os.Stdout, os.Stderr) return cmd.Execute() diff --git a/cmd/kubeadm/app/phases/addons/dns/BUILD b/cmd/kubeadm/app/phases/addons/dns/BUILD index 530a04e121c..bb38323ee95 100644 --- a/cmd/kubeadm/app/phases/addons/dns/BUILD +++ b/cmd/kubeadm/app/phases/addons/dns/BUILD @@ -8,16 +8,12 @@ load( go_test( name = "go_default_test", - srcs = [ - "dns_test.go", - "versions_test.go", - ], + srcs = ["dns_test.go"], embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/util/version:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -32,7 +28,6 @@ go_library( srcs = [ "dns.go", "manifests.go", - "versions.go", ], importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns", deps = [ @@ -41,7 +36,6 @@ go_library( "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//pkg/util/version:go_default_library", "//vendor/github.com/mholt/caddy/caddyfile:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", diff --git a/cmd/kubeadm/app/phases/addons/dns/dns.go b/cmd/kubeadm/app/phases/addons/dns/dns.go index d0207f1b433..50c2577e149 100644 --- a/cmd/kubeadm/app/phases/addons/dns/dns.go +++ b/cmd/kubeadm/app/phases/addons/dns/dns.go @@ -37,7 +37,6 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" - "k8s.io/kubernetes/pkg/util/version" ) const ( @@ -72,17 +71,13 @@ func DeployedDNSAddon(client clientset.Interface) (string, string, error) { // EnsureDNSAddon creates the kube-dns or CoreDNS addon func EnsureDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { - k8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion) - if err != nil { - return fmt.Errorf("couldn't parse kubernetes version %q: %v", cfg.KubernetesVersion, err) - } if features.Enabled(cfg.FeatureGates, features.CoreDNS) { - return coreDNSAddon(cfg, client, k8sVersion) + return coreDNSAddon(cfg, client) } - return kubeDNSAddon(cfg, client, k8sVersion) + return kubeDNSAddon(cfg, client) } -func kubeDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface, k8sVersion *version.Version) error { +func kubeDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { if err := CreateServiceAccount(client); err != nil { return err } @@ -101,18 +96,15 @@ func kubeDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interfac dnsProbeAddr = dnsBindAddr } - // Get the YAML manifest conditionally based on the k8s version - kubeDNSDeploymentBytes := GetKubeDNSManifest(k8sVersion) - dnsDeploymentBytes, err := kubeadmutil.ParseTemplate(kubeDNSDeploymentBytes, + dnsDeploymentBytes, err := kubeadmutil.ParseTemplate(KubeDNSDeployment, struct{ ImageRepository, Arch, Version, DNSBindAddr, DNSProbeAddr, DNSDomain, MasterTaintKey string }{ ImageRepository: cfg.ImageRepository, Arch: runtime.GOARCH, - // Get the kube-dns version conditionally based on the k8s version - Version: GetDNSVersion(k8sVersion, kubeadmconstants.KubeDNS), - DNSBindAddr: dnsBindAddr, - DNSProbeAddr: dnsProbeAddr, - DNSDomain: cfg.Networking.DNSDomain, - MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster, + Version: kubeadmconstants.KubeDNSVersion, + DNSBindAddr: dnsBindAddr, + DNSProbeAddr: dnsProbeAddr, + DNSDomain: cfg.Networking.DNSDomain, + MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster, }) if err != nil { return fmt.Errorf("error when parsing kube-dns deployment template: %v", err) @@ -158,12 +150,12 @@ func createKubeDNSAddon(deploymentBytes, serviceBytes []byte, client clientset.I return createDNSService(kubednsService, serviceBytes, client) } -func coreDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface, k8sVersion *version.Version) error { - // Get the YAML manifest conditionally based on the k8s version - dnsDeploymentBytes := GetCoreDNSManifest(k8sVersion) - coreDNSDeploymentBytes, err := kubeadmutil.ParseTemplate(dnsDeploymentBytes, struct{ MasterTaintKey, Version string }{ - MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster, - Version: GetDNSVersion(k8sVersion, kubeadmconstants.CoreDNS), +func coreDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { + // Get the YAML manifest + coreDNSDeploymentBytes, err := kubeadmutil.ParseTemplate(CoreDNSDeployment, struct{ ImageRepository, MasterTaintKey, Version string }{ + ImageRepository: cfg.ImageRepository, + MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster, + Version: kubeadmconstants.CoreDNSVersion, }) if err != nil { return fmt.Errorf("error when parsing CoreDNS deployment template: %v", err) @@ -300,6 +292,10 @@ func createDNSService(dnsService *v1.Service, serviceBytes []byte, client client // translateStubDomainOfKubeDNSToProxyCoreDNS translates StubDomain Data in kube-dns ConfigMap // in the form of Proxy for the CoreDNS Corefile. func translateStubDomainOfKubeDNSToProxyCoreDNS(dataField string, kubeDNSConfigMap *v1.ConfigMap) (string, error) { + if kubeDNSConfigMap == nil { + return "", nil + } + if proxy, ok := kubeDNSConfigMap.Data[dataField]; ok { stubDomainData := make(map[string][]string) err := json.Unmarshal([]byte(proxy), &stubDomainData) @@ -336,6 +332,10 @@ func translateStubDomainOfKubeDNSToProxyCoreDNS(dataField string, kubeDNSConfigM // translateUpstreamNameServerOfKubeDNSToUpstreamProxyCoreDNS translates UpstreamNameServer Data in kube-dns ConfigMap // in the form of Proxy for the CoreDNS Corefile. func translateUpstreamNameServerOfKubeDNSToUpstreamProxyCoreDNS(dataField string, kubeDNSConfigMap *v1.ConfigMap) (string, error) { + if kubeDNSConfigMap == nil { + return "", nil + } + if upstreamValues, ok := kubeDNSConfigMap.Data[dataField]; ok { var upstreamProxyIP []string @@ -353,6 +353,10 @@ func translateUpstreamNameServerOfKubeDNSToUpstreamProxyCoreDNS(dataField string // translateFederationsofKubeDNSToCoreDNS translates Federations Data in kube-dns ConfigMap // to Federation for CoreDNS Corefile. func translateFederationsofKubeDNSToCoreDNS(dataField, coreDNSDomain string, kubeDNSConfigMap *v1.ConfigMap) (string, error) { + if kubeDNSConfigMap == nil { + return "", nil + } + if federation, ok := kubeDNSConfigMap.Data[dataField]; ok { var ( federationStanza []interface{} diff --git a/cmd/kubeadm/app/phases/addons/dns/dns_test.go b/cmd/kubeadm/app/phases/addons/dns/dns_test.go index 5a9f3c0435b..d28219ff610 100644 --- a/cmd/kubeadm/app/phases/addons/dns/dns_test.go +++ b/cmd/kubeadm/app/phases/addons/dns/dns_test.go @@ -115,9 +115,10 @@ func TestCompileManifests(t *testing.T) { }, { manifest: CoreDNSDeployment, - data: struct{ MasterTaintKey, Version string }{ - MasterTaintKey: "foo", - Version: "foo", + data: struct{ ImageRepository, MasterTaintKey, Version string }{ + ImageRepository: "foo", + MasterTaintKey: "foo", + Version: "foo", }, expected: true, }, diff --git a/cmd/kubeadm/app/phases/addons/dns/manifests.go b/cmd/kubeadm/app/phases/addons/dns/manifests.go index 4184555da68..cc853257e38 100644 --- a/cmd/kubeadm/app/phases/addons/dns/manifests.go +++ b/cmd/kubeadm/app/phases/addons/dns/manifests.go @@ -173,16 +173,8 @@ spec: operator: Exists - key: {{ .MasterTaintKey }} effect: NoSchedule - # TODO: Remove this affinity field as soon as we are using manifest lists - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - {{ .Arch }} + nodeSelector: + beta.kubernetes.io/arch: {{ .Arch }} ` // KubeDNSService is the kube-dns Service manifest @@ -196,6 +188,8 @@ metadata: kubernetes.io/name: "KubeDNS" name: kube-dns namespace: kube-system + annotations: + prometheus.io/scrape: "true" # Without this resourceVersion value, an update of the Service between versions will yield: # Service "kube-dns" is invalid: metadata.resourceVersion: Invalid value: "": must be specified for an update resourceVersion: "0" @@ -245,7 +239,7 @@ spec: effect: NoSchedule containers: - name: coredns - image: coredns/coredns:{{ .Version }} + image: {{ .ImageRepository }}/coredns:{{ .Version }} imagePullPolicy: IfNotPresent resources: limits: @@ -257,6 +251,7 @@ spec: volumeMounts: - name: config-volume mountPath: /etc/coredns + readOnly: true ports: - containerPort: 53 name: dns @@ -264,6 +259,9 @@ spec: - containerPort: 53 name: dns-tcp protocol: TCP + - containerPort: 9153 + name: metrics + protocol: TCP livenessProbe: httpGet: path: /health @@ -273,6 +271,14 @@ spec: timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - all + readOnlyRootFilesystem: true dnsPolicy: Default volumes: - name: config-volume @@ -303,6 +309,7 @@ data: prometheus :9153 proxy . {{ .UpstreamNameserver }} cache 30 + reload }{{ .StubDomain }} ` // CoreDNSClusterRole is the CoreDNS ClusterRole manifest diff --git a/cmd/kubeadm/app/phases/addons/dns/versions.go b/cmd/kubeadm/app/phases/addons/dns/versions.go deleted file mode 100644 index e72eb325fb3..00000000000 --- a/cmd/kubeadm/app/phases/addons/dns/versions.go +++ /dev/null @@ -1,57 +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 dns - -import ( - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/pkg/util/version" -) - -const ( - kubeDNSVersion = "1.14.10" - coreDNSVersion = "1.0.6" -) - -// GetDNSVersion returns the right kube-dns version for a specific k8s version -func GetDNSVersion(kubeVersion *version.Version, dns string) string { - // v1.9.0+ uses kube-dns 1.14.10 - // v1.9.0+ uses CoreDNS 1.0.6 if feature gate "CoreDNS" is enabled. - - // In the future when the version is bumped at HEAD; add conditional logic to return the right versions - // Also, the version might be bumped for different k8s releases on the same branch - switch dns { - case kubeadmconstants.CoreDNS: - // return the CoreDNS version - return coreDNSVersion - default: - return kubeDNSVersion - } -} - -// GetKubeDNSManifest returns the right kube-dns YAML manifest for a specific k8s version -func GetKubeDNSManifest(kubeVersion *version.Version) string { - // v1.8.0+ has only one known YAML manifest spec, just return that here - // In the future when the kube-dns version is bumped at HEAD; add conditional logic to return the right manifest - return KubeDNSDeployment -} - -// GetCoreDNSManifest returns the right CoreDNS YAML manifest for a specific k8s version -func GetCoreDNSManifest(kubeVersion *version.Version) string { - // v1.9.0+ has only one known YAML manifest spec, just return that here - // In the future when the CoreDNS version is bumped at HEAD; add conditional logic to return the right manifest - return CoreDNSDeployment -} diff --git a/cmd/kubeadm/app/phases/addons/dns/versions_test.go b/cmd/kubeadm/app/phases/addons/dns/versions_test.go deleted file mode 100644 index 63845548ddf..00000000000 --- a/cmd/kubeadm/app/phases/addons/dns/versions_test.go +++ /dev/null @@ -1,68 +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 dns - -import ( - "testing" - - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/pkg/util/version" -) - -func TestGetKubeDNSVersion(t *testing.T) { - var tests = []struct { - k8sVersion string - dns string - expected string - }{ - { - k8sVersion: "v1.9.0", - dns: kubeadmconstants.KubeDNS, - expected: kubeDNSVersion, - }, - { - k8sVersion: "v1.10.0", - dns: kubeadmconstants.KubeDNS, - expected: kubeDNSVersion, - }, - { - k8sVersion: "v1.9.0", - dns: kubeadmconstants.CoreDNS, - expected: coreDNSVersion, - }, - { - k8sVersion: "v1.10.0", - dns: kubeadmconstants.CoreDNS, - expected: coreDNSVersion, - }, - } - for _, rt := range tests { - k8sVersion, err := version.ParseSemantic(rt.k8sVersion) - if err != nil { - t.Fatalf("couldn't parse kubernetes version %q: %v", rt.k8sVersion, err) - } - - actualDNSVersion := GetDNSVersion(k8sVersion, 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/phases/addons/proxy/BUILD b/cmd/kubeadm/app/phases/addons/proxy/BUILD index 612ca29d555..87f1650a5b4 100644 --- a/cmd/kubeadm/app/phases/addons/proxy/BUILD +++ b/cmd/kubeadm/app/phases/addons/proxy/BUILD @@ -34,6 +34,7 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy", deps = [ "//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/apiclient:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library", diff --git a/cmd/kubeadm/app/phases/addons/proxy/manifests.go b/cmd/kubeadm/app/phases/addons/proxy/manifests.go index c0bc3b8f0bb..ef3a1512b14 100644 --- a/cmd/kubeadm/app/phases/addons/proxy/manifests.go +++ b/cmd/kubeadm/app/phases/addons/proxy/manifests.go @@ -90,8 +90,6 @@ spec: readOnly: true hostNetwork: true serviceAccountName: kube-proxy - tolerations: - - operator: Exists volumes: - name: kube-proxy configMap: @@ -103,5 +101,12 @@ spec: - name: lib-modules hostPath: path: /lib/modules + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - key: {{ .MasterTaintKey }} + effect: NoSchedule + nodeSelector: + beta.kubernetes.io/arch: {{ .Arch }} ` ) diff --git a/cmd/kubeadm/app/phases/addons/proxy/proxy.go b/cmd/kubeadm/app/phases/addons/proxy/proxy.go index cde76c4391c..0de99d04fd5 100644 --- a/cmd/kubeadm/app/phases/addons/proxy/proxy.go +++ b/cmd/kubeadm/app/phases/addons/proxy/proxy.go @@ -29,6 +29,7 @@ import ( clientset "k8s.io/client-go/kubernetes" clientsetscheme "k8s.io/client-go/kubernetes/scheme" 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" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" kubeproxyconfigscheme "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/scheme" @@ -75,11 +76,12 @@ func EnsureProxyAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Inte if err != nil { return fmt.Errorf("error when parsing kube-proxy configmap template: %v", err) } - proxyDaemonSetBytes, err = kubeadmutil.ParseTemplate(KubeProxyDaemonSet19, struct{ ImageRepository, Arch, Version, ImageOverride string }{ + proxyDaemonSetBytes, err = kubeadmutil.ParseTemplate(KubeProxyDaemonSet19, struct{ ImageRepository, Arch, Version, ImageOverride, MasterTaintKey string }{ ImageRepository: cfg.GetControlPlaneImageRepository(), Arch: runtime.GOARCH, Version: kubeadmutil.KubernetesVersionToImageTag(cfg.KubernetesVersion), ImageOverride: cfg.UnifiedControlPlaneImage, + MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster, }) if err != nil { return fmt.Errorf("error when parsing kube-proxy daemonset template: %v", err) diff --git a/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go b/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go index 85398c4a5ce..badd2c71289 100644 --- a/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go +++ b/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go @@ -40,7 +40,7 @@ const ( // CreateBootstrapConfigMapIfNotExists creates the kube-public ConfigMap if it doesn't exist already func CreateBootstrapConfigMapIfNotExists(client clientset.Interface, file string) error { - glog.Infof("[bootstraptoken] creating the %q ConfigMap in the %q namespace\n", bootstrapapi.ConfigMapClusterInfo, metav1.NamespacePublic) + fmt.Printf("[bootstraptoken] creating the %q ConfigMap in the %q namespace\n", bootstrapapi.ConfigMapClusterInfo, metav1.NamespacePublic) glog.V(1).Infoln("[bootstraptoken] loading admin kubeconfig") adminConfig, err := clientcmd.LoadFromFile(file) diff --git a/cmd/kubeadm/app/phases/bootstraptoken/node/BUILD b/cmd/kubeadm/app/phases/bootstraptoken/node/BUILD index ea40478a792..c39f9ac2c59 100644 --- a/cmd/kubeadm/app/phases/bootstraptoken/node/BUILD +++ b/cmd/kubeadm/app/phases/bootstraptoken/node/BUILD @@ -3,14 +3,6 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["token_test.go"], - embed = [":go_default_library"], - deps = ["//cmd/kubeadm/app/apis/kubeadm:go_default_library"], ) go_library( @@ -21,16 +13,12 @@ go_library( ], importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node", deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//cmd/kubeadm/app/util/token:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/rbac/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", "//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", ], ) diff --git a/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go b/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go index acd0dddb039..334d6afdcc5 100644 --- a/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go +++ b/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go @@ -17,7 +17,7 @@ limitations under the License. package node import ( - "github.com/golang/glog" + "fmt" rbac "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -47,7 +47,7 @@ const ( // AllowBootstrapTokensToPostCSRs creates RBAC rules in a way the makes Node Bootstrap Tokens able to post CSRs func AllowBootstrapTokensToPostCSRs(client clientset.Interface) error { - glog.Infoln("[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials") + fmt.Println("[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials") return apiclient.CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ @@ -69,7 +69,7 @@ func AllowBootstrapTokensToPostCSRs(client clientset.Interface) error { // AutoApproveNodeBootstrapTokens creates RBAC rules in a way that makes Node Bootstrap Tokens' CSR auto-approved by the csrapprover controller func AutoApproveNodeBootstrapTokens(client clientset.Interface) error { - glog.Infoln("[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token") + fmt.Println("[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token") // Always create this kubeadm-specific binding though return apiclient.CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{ @@ -92,7 +92,7 @@ func AutoApproveNodeBootstrapTokens(client clientset.Interface) error { // AutoApproveNodeCertificateRotation creates RBAC rules in a way that makes Node certificate rotation CSR auto-approved by the csrapprover controller func AutoApproveNodeCertificateRotation(client clientset.Interface) error { - glog.Infoln("[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster") + fmt.Println("[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster") return apiclient.CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ diff --git a/cmd/kubeadm/app/phases/bootstraptoken/node/token.go b/cmd/kubeadm/app/phases/bootstraptoken/node/token.go index 02f63b7ce51..f24629865a6 100644 --- a/cmd/kubeadm/app/phases/bootstraptoken/node/token.go +++ b/cmd/kubeadm/app/phases/bootstraptoken/node/token.go @@ -18,109 +18,43 @@ package node import ( "fmt" - "strings" - "time" - "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" - bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" - tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" ) -const tokenCreateRetries = 5 +// TODO(mattmoyer): Move CreateNewTokens, UpdateOrCreateTokens out of this package to client-go for a generic abstraction and client for a Bootstrap Token -// TODO(mattmoyer): Move CreateNewToken, UpdateOrCreateToken and encodeTokenSecretData out of this package to client-go for a generic abstraction and client for a Bootstrap Token - -// CreateNewToken tries to create a token and fails if one with the same ID already exists -func CreateNewToken(client clientset.Interface, token string, tokenDuration time.Duration, usages []string, extraGroups []string, description string) error { - return UpdateOrCreateToken(client, token, true, tokenDuration, usages, extraGroups, description) +// CreateNewTokens tries to create a token and fails if one with the same ID already exists +func CreateNewTokens(client clientset.Interface, tokens []kubeadmapi.BootstrapToken) error { + return UpdateOrCreateTokens(client, true, tokens) } -// UpdateOrCreateToken attempts to update a token with the given ID, or create if it does not already exist. -func UpdateOrCreateToken(client clientset.Interface, token string, failIfExists bool, tokenDuration time.Duration, usages []string, extraGroups []string, description string) error { - tokenID, tokenSecret, err := tokenutil.ParseToken(token) - if err != nil { - return err - } - secretName := fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenID) - var lastErr error - for i := 0; i < tokenCreateRetries; i++ { +// UpdateOrCreateTokens attempts to update a token with the given ID, or create if it does not already exist. +func UpdateOrCreateTokens(client clientset.Interface, failIfExists bool, tokens []kubeadmapi.BootstrapToken) error { + + for _, token := range tokens { + + secretName := bootstraputil.BootstrapTokenSecretName(token.Token.ID) secret, err := client.CoreV1().Secrets(metav1.NamespaceSystem).Get(secretName, metav1.GetOptions{}) - if err == nil { - if failIfExists { - return fmt.Errorf("a token with id %q already exists", tokenID) - } - // Secret with this ID already exists, update it: - tokenSecretData, err := encodeTokenSecretData(tokenID, tokenSecret, tokenDuration, usages, extraGroups, description) - if err != nil { - return err - } - secret.Data = tokenSecretData - if _, err := client.CoreV1().Secrets(metav1.NamespaceSystem).Update(secret); err == nil { - return nil - } - lastErr = err - continue + if secret != nil && err == nil && failIfExists { + return fmt.Errorf("a token with id %q already exists", token.Token.ID) } - // Secret does not already exist: - if apierrors.IsNotFound(err) { - tokenSecretData, err := encodeTokenSecretData(tokenID, tokenSecret, tokenDuration, usages, extraGroups, description) - if err != nil { - return err + updatedOrNewSecret := token.ToSecret() + // Try to create or update the token with an exponential backoff + err = apiclient.TryRunCommand(func() error { + if err := apiclient.CreateOrUpdateSecret(client, updatedOrNewSecret); err != nil { + return fmt.Errorf("failed to create or update bootstrap token with name %s: %v", secretName, err) } - - secret = &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretName, - }, - Type: v1.SecretType(bootstrapapi.SecretTypeBootstrapToken), - Data: tokenSecretData, - } - if _, err := client.CoreV1().Secrets(metav1.NamespaceSystem).Create(secret); err == nil { - return nil - } - lastErr = err - continue + return nil + }, 5) + if err != nil { + return err } - } - return fmt.Errorf( - "unable to create bootstrap token after %d attempts [%v]", - tokenCreateRetries, - lastErr, - ) -} - -// encodeTokenSecretData takes the token discovery object and an optional duration and returns the .Data for the Secret -func encodeTokenSecretData(tokenID, tokenSecret string, duration time.Duration, usages []string, extraGroups []string, description string) (map[string][]byte, error) { - data := map[string][]byte{ - bootstrapapi.BootstrapTokenIDKey: []byte(tokenID), - bootstrapapi.BootstrapTokenSecretKey: []byte(tokenSecret), - } - - if len(extraGroups) > 0 { - data[bootstrapapi.BootstrapTokenExtraGroupsKey] = []byte(strings.Join(extraGroups, ",")) - } - - if duration > 0 { - // Get the current time, add the specified duration, and format it accordingly - durationString := time.Now().Add(duration).Format(time.RFC3339) - data[bootstrapapi.BootstrapTokenExpirationKey] = []byte(durationString) - } - if len(description) > 0 { - data[bootstrapapi.BootstrapTokenDescriptionKey] = []byte(description) - } - - // validate usages - if err := bootstraputil.ValidateUsages(usages); err != nil { - return nil, err - } - for _, usage := range usages { - data[bootstrapapi.BootstrapTokenUsagePrefix+usage] = []byte("true") - } - return data, nil + return nil } diff --git a/cmd/kubeadm/app/phases/bootstraptoken/node/token_test.go b/cmd/kubeadm/app/phases/bootstraptoken/node/token_test.go deleted file mode 100644 index 48bc8c1f168..00000000000 --- a/cmd/kubeadm/app/phases/bootstraptoken/node/token_test.go +++ /dev/null @@ -1,59 +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 node - -import ( - "bytes" - "testing" - "time" - - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" -) - -func TestEncodeTokenSecretData(t *testing.T) { - var tests = []struct { - token *kubeadmapi.TokenDiscovery - t time.Duration - }{ - {token: &kubeadmapi.TokenDiscovery{ID: "foo", Secret: "bar"}}, // should use default - {token: &kubeadmapi.TokenDiscovery{ID: "foo", Secret: "bar"}, t: time.Second}, // should use default - } - for _, rt := range tests { - actual, _ := encodeTokenSecretData(rt.token.ID, rt.token.Secret, rt.t, []string{}, []string{}, "") - if !bytes.Equal(actual["token-id"], []byte(rt.token.ID)) { - t.Errorf( - "failed EncodeTokenSecretData:\n\texpected: %s\n\t actual: %s", - rt.token.ID, - actual["token-id"], - ) - } - if !bytes.Equal(actual["token-secret"], []byte(rt.token.Secret)) { - t.Errorf( - "failed EncodeTokenSecretData:\n\texpected: %s\n\t actual: %s", - rt.token.Secret, - actual["token-secret"], - ) - } - if rt.t > 0 { - if actual["expiration"] == nil { - t.Errorf( - "failed EncodeTokenSecretData, duration was not added to time", - ) - } - } - } -} diff --git a/cmd/kubeadm/app/phases/certs/certs.go b/cmd/kubeadm/app/phases/certs/certs.go index b4d27a2e0db..fe0ae21b722 100644 --- a/cmd/kubeadm/app/phases/certs/certs.go +++ b/cmd/kubeadm/app/phases/certs/certs.go @@ -62,7 +62,7 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration) error { } } - glog.Infof("[certificates] valid certificates and keys now exist in %q\n", cfg.CertificatesDir) + fmt.Printf("[certificates] valid certificates and keys now exist in %q\n", cfg.CertificatesDir) return nil } @@ -375,9 +375,9 @@ func NewEtcdServerCertAndKey(cfg *kubeadmapi.MasterConfiguration, caCert *x509.C } config := certutil.Config{ - CommonName: kubeadmconstants.EtcdServerCertCommonName, + CommonName: cfg.NodeRegistration.Name, AltNames: *altNames, - Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, } etcdServerCert, etcdServerKey, err := pkiutil.NewCertAndKey(caCert, caKey, config) if err != nil { @@ -396,7 +396,7 @@ func NewEtcdPeerCertAndKey(cfg *kubeadmapi.MasterConfiguration, caCert *x509.Cer } config := certutil.Config{ - CommonName: kubeadmconstants.EtcdPeerCertCommonName, + CommonName: cfg.NodeRegistration.Name, AltNames: *altNames, Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, } diff --git a/cmd/kubeadm/app/phases/certs/certs_test.go b/cmd/kubeadm/app/phases/certs/certs_test.go index c6fbdcca840..f3db29c11c6 100644 --- a/cmd/kubeadm/app/phases/certs/certs_test.go +++ b/cmd/kubeadm/app/phases/certs/certs_test.go @@ -273,9 +273,9 @@ func TestNewAPIServerCertAndKey(t *testing.T) { advertiseAddresses := []string{"1.2.3.4", "1:2:3::4"} for _, addr := range advertiseAddresses { cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: addr}, - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: hostname, + API: kubeadmapi.API{AdvertiseAddress: addr}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: hostname}, } caCert, caKey, err := NewCACertAndKey() if err != nil { @@ -324,6 +324,9 @@ func TestNewEtcdServerCertAndKey(t *testing.T) { proxyIP := "10.10.10.100" cfg := &kubeadmapi.MasterConfiguration{ + NodeRegistration: kubeadmapi.NodeRegistrationOptions{ + Name: "etcd-server-cert", + }, Etcd: kubeadmapi.Etcd{ Local: &kubeadmapi.LocalEtcd{ ServerCertSANs: []string{ @@ -357,8 +360,8 @@ func TestNewEtcdPeerCertAndKey(t *testing.T) { advertiseAddresses := []string{"1.2.3.4", "1:2:3::4"} for _, addr := range advertiseAddresses { cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: addr}, - NodeName: hostname, + API: kubeadmapi.API{AdvertiseAddress: addr}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: hostname}, Etcd: kubeadmapi.Etcd{ Local: &kubeadmapi.LocalEtcd{ PeerCertSANs: []string{ @@ -481,10 +484,10 @@ func TestUsingExternalCA(t *testing.T) { defer os.RemoveAll(dir) cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", - CertificatesDir: dir, + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, + CertificatesDir: dir, } for _, f := range test.setupFuncs { @@ -564,10 +567,10 @@ func TestValidateMethods(t *testing.T) { test.loc.pkiDir = dir cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", - CertificatesDir: dir, + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, + CertificatesDir: dir, } fmt.Println("Testing", test.name) @@ -696,11 +699,11 @@ func TestCreateCertificateFilesMethods(t *testing.T) { defer os.RemoveAll(tmpdir) cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, - Etcd: kubeadmapi.Etcd{Local: &kubeadmapi.LocalEtcd{}}, - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", - CertificatesDir: tmpdir, + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, + Etcd: kubeadmapi.Etcd{Local: &kubeadmapi.LocalEtcd{}}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, + CertificatesDir: tmpdir, } if test.externalEtcd { diff --git a/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers.go b/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers.go index 39ca139cba7..e1d456b395f 100644 --- a/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers.go +++ b/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers.go @@ -275,7 +275,7 @@ func GetAPIServerAltNames(cfg *kubeadmapi.MasterConfiguration) (*certutil.AltNam // create AltNames with defaults DNSNames/IPs altNames := &certutil.AltNames{ DNSNames: []string{ - cfg.NodeName, + cfg.NodeRegistration.Name, "kubernetes", "kubernetes.default", "kubernetes.default.svc", @@ -312,8 +312,8 @@ func GetAPIServerAltNames(cfg *kubeadmapi.MasterConfiguration) (*certutil.AltNam func GetEtcdAltNames(cfg *kubeadmapi.MasterConfiguration) (*certutil.AltNames, error) { // create AltNames with defaults DNSNames/IPs altNames := &certutil.AltNames{ - DNSNames: []string{"localhost"}, - IPs: []net.IP{net.IPv4(127, 0, 0, 1)}, + DNSNames: []string{cfg.NodeRegistration.Name, "localhost"}, + IPs: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback}, } if cfg.Etcd.Local != nil { @@ -336,8 +336,8 @@ func GetEtcdPeerAltNames(cfg *kubeadmapi.MasterConfiguration) (*certutil.AltName // create AltNames with defaults DNSNames/IPs altNames := &certutil.AltNames{ - DNSNames: []string{cfg.NodeName}, - IPs: []net.IP{advertiseAddress}, + DNSNames: []string{cfg.NodeRegistration.Name, "localhost"}, + IPs: []net.IP{advertiseAddress, net.IPv4(127, 0, 0, 1), net.IPv6loopback}, } if cfg.Etcd.Local != nil { diff --git a/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers_test.go b/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers_test.go index 9ff34b0b20a..cc2a5cb3790 100644 --- a/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers_test.go +++ b/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers_test.go @@ -448,7 +448,7 @@ func TestGetAPIServerAltNames(t *testing.T) { cfg: &kubeadmapi.MasterConfiguration{ API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "api.k8s.io:6443"}, Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, APIServerCertSANs: []string{"10.1.245.94", "10.1.245.95", "1.2.3.L", "invalid,commas,in,DNS"}, }, expectedDNSNames: []string{"valid-hostname", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.local", "api.k8s.io"}, @@ -459,7 +459,7 @@ func TestGetAPIServerAltNames(t *testing.T) { cfg: &kubeadmapi.MasterConfiguration{ API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "4.5.6.7:6443"}, Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, APIServerCertSANs: []string{"10.1.245.94", "10.1.245.95", "1.2.3.L", "invalid,commas,in,DNS"}, }, expectedDNSNames: []string{"valid-hostname", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.local"}, @@ -539,7 +539,7 @@ func TestGetEtcdAltNames(t *testing.T) { } } - expectedIPAddresses := []string{"127.0.0.1", proxyIP} + expectedIPAddresses := []string{"127.0.0.1", net.IPv6loopback.String(), proxyIP} for _, IPAddress := range expectedIPAddresses { found := false for _, val := range altNames.IPs { @@ -561,8 +561,8 @@ func TestGetEtcdPeerAltNames(t *testing.T) { proxyIP := "10.10.10.100" advertiseIP := "1.2.3.4" cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: advertiseIP}, - NodeName: hostname, + API: kubeadmapi.API{AdvertiseAddress: advertiseIP}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: hostname}, Etcd: kubeadmapi.Etcd{ Local: &kubeadmapi.LocalEtcd{ PeerCertSANs: []string{ diff --git a/cmd/kubeadm/app/phases/controlplane/manifests.go b/cmd/kubeadm/app/phases/controlplane/manifests.go index 17ff9de4390..1295ab5df78 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests.go @@ -39,8 +39,6 @@ import ( "k8s.io/kubernetes/pkg/util/version" ) -const defaultAdmissionControl = "NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota" - // CreateInitStaticPodManifestFiles will write all static pod manifest files needed to bring up the control plane. func CreateInitStaticPodManifestFiles(manifestDir string, cfg *kubeadmapi.MasterConfiguration) error { glog.V(1).Infoln("[controlplane] creating static pod files") @@ -132,7 +130,7 @@ func createStaticPodFiles(manifestDir string, cfg *kubeadmapi.MasterConfiguratio return fmt.Errorf("failed to create static pod manifest file for %q: %v", componentName, err) } - glog.Infof("[controlplane] wrote Static Pod manifest for component %s to %q\n", componentName, kubeadmconstants.GetStaticPodFilepath(componentName, manifestDir)) + fmt.Printf("[controlplane] wrote Static Pod manifest for component %s to %q\n", componentName, kubeadmconstants.GetStaticPodFilepath(componentName, manifestDir)) } return nil @@ -141,9 +139,14 @@ func createStaticPodFiles(manifestDir string, cfg *kubeadmapi.MasterConfiguratio // getAPIServerCommand builds the right API server command from the given config object and version func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string { defaultArguments := map[string]string{ - "advertise-address": cfg.API.AdvertiseAddress, - "insecure-port": "0", - "admission-control": defaultAdmissionControl, + "advertise-address": cfg.API.AdvertiseAddress, + "insecure-port": "0", + "enable-admission-plugins": "NodeRestriction", + // TODO: remove `PersistentVolumeLabel` in kubeadm v1.11, as it's automatically disabled in v1.11. + // ref: https://github.com/kubernetes/kubernetes/pull/64326 + // we can't skip it now as we support v1.10 clusters still. + // remove it from the unit tests too. + "disable-admission-plugins": "PersistentVolumeLabel", "service-cluster-ip-range": cfg.Networking.ServiceSubnet, "service-account-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPublicKeyName), "client-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName), diff --git a/cmd/kubeadm/app/phases/controlplane/manifests_test.go b/cmd/kubeadm/app/phases/controlplane/manifests_test.go index 3e1a7325d33..58b81636874 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests_test.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests_test.go @@ -154,7 +154,8 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -196,7 +197,8 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -233,7 +235,8 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -279,7 +282,8 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -322,7 +326,8 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -360,7 +365,8 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -402,7 +408,8 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -447,7 +454,8 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=baz", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -491,7 +499,8 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -531,7 +540,8 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=1234", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -571,7 +581,8 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -827,7 +838,7 @@ func TestGetControllerManagerCommandExternalCA(t *testing.T) { KubernetesVersion: "v1.7.0", API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, }, caKeyPresent: false, expectedArgFunc: func(tmpdir string) []string { @@ -851,7 +862,7 @@ func TestGetControllerManagerCommandExternalCA(t *testing.T) { KubernetesVersion: "v1.7.0", API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, }, caKeyPresent: true, expectedArgFunc: func(tmpdir string) []string { diff --git a/cmd/kubeadm/app/phases/etcd/local.go b/cmd/kubeadm/app/phases/etcd/local.go index 80000dabe1c..5240d335748 100644 --- a/cmd/kubeadm/app/phases/etcd/local.go +++ b/cmd/kubeadm/app/phases/etcd/local.go @@ -77,18 +77,22 @@ func GetEtcdPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.Pod { // getEtcdCommand builds the right etcd command from the given config object func getEtcdCommand(cfg *kubeadmapi.MasterConfiguration) []string { defaultArguments := map[string]string{ - "listen-client-urls": "https://127.0.0.1:2379", - "advertise-client-urls": "https://127.0.0.1:2379", - "data-dir": cfg.Etcd.Local.DataDir, - "cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerCertName), - "key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerKeyName), - "trusted-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName), - "client-cert-auth": "true", - "peer-cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerCertName), - "peer-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerKeyName), - "peer-trusted-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName), - "peer-client-cert-auth": "true", - "snapshot-count": "10000", + "name": cfg.GetNodeName(), + "listen-client-urls": "https://127.0.0.1:2379", + "advertise-client-urls": "https://127.0.0.1:2379", + "listen-peer-urls": "https://127.0.0.1:2380", + "initial-advertise-peer-urls": "https://127.0.0.1:2380", + "data-dir": cfg.Etcd.Local.DataDir, + "cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerCertName), + "key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerKeyName), + "trusted-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName), + "client-cert-auth": "true", + "peer-cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerCertName), + "peer-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerKeyName), + "peer-trusted-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName), + "peer-client-cert-auth": "true", + "snapshot-count": "10000", + "initial-cluster": fmt.Sprintf("%s=https://127.0.0.1:2380", cfg.GetNodeName()), } command := []string{"etcd"} diff --git a/cmd/kubeadm/app/phases/etcd/local_test.go b/cmd/kubeadm/app/phases/etcd/local_test.go index 7c884abc53b..83f5f45ad41 100644 --- a/cmd/kubeadm/app/phases/etcd/local_test.go +++ b/cmd/kubeadm/app/phases/etcd/local_test.go @@ -87,12 +87,22 @@ func TestGetEtcdCommand(t *testing.T) { }{ { cfg: &kubeadmapi.MasterConfiguration{ - Etcd: kubeadmapi.Etcd{Local: &kubeadmapi.LocalEtcd{DataDir: "/var/lib/etcd"}}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{ + Name: "foo", + }, + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + DataDir: "/var/lib/etcd", + }, + }, }, expected: []string{ "etcd", + "--name=foo", "--listen-client-urls=https://127.0.0.1:2379", "--advertise-client-urls=https://127.0.0.1:2379", + "--listen-peer-urls=https://127.0.0.1:2380", + "--initial-advertise-peer-urls=https://127.0.0.1:2380", "--data-dir=/var/lib/etcd", "--cert-file=" + kubeadmconstants.EtcdServerCertName, "--key-file=" + kubeadmconstants.EtcdServerKeyName, @@ -103,10 +113,14 @@ func TestGetEtcdCommand(t *testing.T) { "--peer-trusted-ca-file=" + kubeadmconstants.EtcdCACertName, "--snapshot-count=10000", "--peer-client-cert-auth=true", + "--initial-cluster=foo=https://127.0.0.1:2380", }, }, { cfg: &kubeadmapi.MasterConfiguration{ + NodeRegistration: kubeadmapi.NodeRegistrationOptions{ + Name: "bar", + }, Etcd: kubeadmapi.Etcd{ Local: &kubeadmapi.LocalEtcd{ DataDir: "/var/lib/etcd", @@ -119,8 +133,11 @@ func TestGetEtcdCommand(t *testing.T) { }, expected: []string{ "etcd", + "--name=bar", "--listen-client-urls=https://10.0.1.10:2379", "--advertise-client-urls=https://10.0.1.10:2379", + "--listen-peer-urls=https://127.0.0.1:2380", + "--initial-advertise-peer-urls=https://127.0.0.1:2380", "--data-dir=/var/lib/etcd", "--cert-file=" + kubeadmconstants.EtcdServerCertName, "--key-file=" + kubeadmconstants.EtcdServerKeyName, @@ -131,16 +148,27 @@ func TestGetEtcdCommand(t *testing.T) { "--peer-trusted-ca-file=" + kubeadmconstants.EtcdCACertName, "--snapshot-count=10000", "--peer-client-cert-auth=true", + "--initial-cluster=bar=https://127.0.0.1:2380", }, }, { cfg: &kubeadmapi.MasterConfiguration{ - Etcd: kubeadmapi.Etcd{Local: &kubeadmapi.LocalEtcd{DataDir: "/etc/foo"}}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{ + Name: "wombat", + }, + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + DataDir: "/etc/foo", + }, + }, }, expected: []string{ "etcd", + "--name=wombat", "--listen-client-urls=https://127.0.0.1:2379", "--advertise-client-urls=https://127.0.0.1:2379", + "--listen-peer-urls=https://127.0.0.1:2380", + "--initial-advertise-peer-urls=https://127.0.0.1:2380", "--data-dir=/etc/foo", "--cert-file=" + kubeadmconstants.EtcdServerCertName, "--key-file=" + kubeadmconstants.EtcdServerKeyName, @@ -151,6 +179,7 @@ func TestGetEtcdCommand(t *testing.T) { "--peer-trusted-ca-file=" + kubeadmconstants.EtcdCACertName, "--snapshot-count=10000", "--peer-client-cert-auth=true", + "--initial-cluster=wombat=https://127.0.0.1:2380", }, }, } diff --git a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go index 02194885a97..6a21c8f772d 100644 --- a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go +++ b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go @@ -160,7 +160,7 @@ func getKubeConfigSpecs(cfg *kubeadmapi.MasterConfiguration) (map[string]*kubeCo kubeadmconstants.KubeletKubeConfigFileName: { CACert: caCert, APIServer: masterEndpoint, - ClientName: fmt.Sprintf("system:node:%s", cfg.NodeName), + ClientName: fmt.Sprintf("system:node:%s", cfg.NodeRegistration.Name), ClientCertAuth: &clientCertAuth{ CAKey: caKey, Organizations: []string{kubeadmconstants.NodesGroup}, diff --git a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go index 3b47f4e627f..ced29c30e3f 100644 --- a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go +++ b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go @@ -67,29 +67,29 @@ func TestGetKubeConfigSpecs(t *testing.T) { // Creates Master Configurations pointing to the pkidir folder cfgs := []*kubeadmapi.MasterConfiguration{ { - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234}, - CertificatesDir: pkidir, - NodeName: "valid-node-name", + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234}, + CertificatesDir: pkidir, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"}, }, { - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "api.k8s.io", BindPort: 1234}, - CertificatesDir: pkidir, - NodeName: "valid-node-name", + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "api.k8s.io", BindPort: 1234}, + CertificatesDir: pkidir, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"}, }, { - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "api.k8s.io:4321", BindPort: 1234}, - CertificatesDir: pkidir, - NodeName: "valid-node-name", + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "api.k8s.io:4321", BindPort: 1234}, + CertificatesDir: pkidir, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"}, }, { - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "api.k8s.io", BindPort: 1234}, - CertificatesDir: pkidir, - NodeName: "valid-node-name", + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "api.k8s.io", BindPort: 1234}, + CertificatesDir: pkidir, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"}, }, { - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "api.k8s.io:4321", BindPort: 1234}, - CertificatesDir: pkidir, - NodeName: "valid-node-name", + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "api.k8s.io:4321", BindPort: 1234}, + CertificatesDir: pkidir, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"}, }, } @@ -106,7 +106,7 @@ func TestGetKubeConfigSpecs(t *testing.T) { }, { kubeConfigFile: kubeadmconstants.KubeletKubeConfigFileName, - clientName: fmt.Sprintf("system:node:%s", cfg.NodeName), + clientName: fmt.Sprintf("system:node:%s", cfg.NodeRegistration.Name), organizations: []string{kubeadmconstants.NodesGroup}, }, { diff --git a/cmd/kubeadm/app/phases/kubelet/BUILD b/cmd/kubeadm/app/phases/kubelet/BUILD index 0dc4429f902..ef5848e5a9e 100644 --- a/cmd/kubeadm/app/phases/kubelet/BUILD +++ b/cmd/kubeadm/app/phases/kubelet/BUILD @@ -13,21 +13,23 @@ go_library( "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//cmd/kubeadm/app/util/kubeconfig:go_default_library", "//pkg/apis/rbac/v1:go_default_library", "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", + "//pkg/util/node:go_default_library", + "//pkg/util/procfs:go_default_library", "//pkg/util/version:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", ], ) @@ -36,10 +38,12 @@ go_test( srcs = [ "config_test.go", "dynamic_test.go", + "flags_test.go", ], embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", "//pkg/util/version:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", @@ -47,6 +51,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", "//vendor/k8s.io/client-go/testing: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 5503a16a7fc..2f09b5347be 100644 --- a/cmd/kubeadm/app/phases/kubelet/config.go +++ b/cmd/kubeadm/app/phases/kubelet/config.go @@ -19,16 +19,18 @@ package kubelet import ( "fmt" "io/ioutil" + "os" + "path/filepath" "k8s.io/api/core/v1" rbac "k8s.io/api/rbac/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" 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" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" - kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" rbachelper "k8s.io/kubernetes/pkg/apis/rbac/v1" kubeletconfigscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" @@ -37,18 +39,13 @@ import ( // WriteConfigToDisk writes the kubelet config object down to a file // Used at "kubeadm init" and "kubeadm upgrade" time -func WriteConfigToDisk(kubeletConfig *kubeletconfigv1beta1.KubeletConfiguration, kubeletVersion *version.Version) error { - - // If the kubelet version is v1.10.x, exit - if kubeletVersion.LessThan(kubeadmconstants.MinimumKubeletConfigVersion) { - return nil - } +func WriteConfigToDisk(kubeletConfig *kubeletconfigv1beta1.KubeletConfiguration, kubeletDir string) error { kubeletBytes, err := getConfigBytes(kubeletConfig) if err != nil { return err } - return writeConfigBytesToDisk(kubeletBytes) + return writeConfigBytesToDisk(kubeletBytes, kubeletDir) } // CreateConfigMap creates a ConfigMap with the generic kubelet configuration. @@ -60,11 +57,6 @@ func CreateConfigMap(cfg *kubeadmapi.MasterConfiguration, client clientset.Inter return err } - // If Kubernetes version is v1.10.x, exit - if k8sVersion.LessThan(kubeadmconstants.MinimumKubeletConfigVersion) { - return nil - } - configMapName := configMapName(k8sVersion) fmt.Printf("[kubelet] Creating a ConfigMap %q in namespace %s with the configuration for the kubelets in the cluster\n", configMapName, metav1.NamespaceSystem) @@ -130,12 +122,7 @@ func createConfigMapRBACRules(client clientset.Interface, k8sVersion *version.Ve // DownloadConfig downloads the kubelet configuration from a ConfigMap and writes it to disk. // Used at "kubeadm join" time -func DownloadConfig(kubeletKubeConfig string, kubeletVersion *version.Version) error { - - // If the kubelet version is v1.10.x, exit - if kubeletVersion.LessThan(kubeadmconstants.MinimumKubeletConfigVersion) { - return nil - } +func DownloadConfig(client clientset.Interface, kubeletVersion *version.Version, kubeletDir string) error { // Download the ConfigMap from the cluster based on what version the kubelet is configMapName := configMapName(kubeletVersion) @@ -143,17 +130,17 @@ func DownloadConfig(kubeletKubeConfig string, kubeletVersion *version.Version) e fmt.Printf("[kubelet] Downloading configuration for the kubelet from the %q ConfigMap in the %s namespace\n", configMapName, metav1.NamespaceSystem) - client, err := kubeconfigutil.ClientSetFromFile(kubeletKubeConfig) - if err != nil { - return fmt.Errorf("couldn't create client from kubeconfig file %q", kubeletKubeConfig) - } - kubeletCfg, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(configMapName, metav1.GetOptions{}) + // If the ConfigMap wasn't found and the kubelet version is v1.10.x, where we didn't support the config file yet + // just return, don't error out + if apierrors.IsNotFound(err) && kubeletVersion.Minor() == 10 { + return nil + } if err != nil { return err } - return writeConfigBytesToDisk([]byte(kubeletCfg.Data[kubeadmconstants.KubeletBaseConfigurationConfigMapKey])) + return writeConfigBytesToDisk([]byte(kubeletCfg.Data[kubeadmconstants.KubeletBaseConfigurationConfigMapKey]), kubeletDir) } // configMapName returns the right ConfigMap name for the right branch of k8s @@ -177,11 +164,17 @@ func getConfigBytes(kubeletConfig *kubeletconfigv1beta1.KubeletConfiguration) ([ } // writeConfigBytesToDisk writes a byte slice down to disk at the specific location of the kubelet config file -func writeConfigBytesToDisk(b []byte) error { - fmt.Printf("[kubelet] Writing kubelet configuration to file %q\n", kubeadmconstants.KubeletConfigurationFile) +func writeConfigBytesToDisk(b []byte, kubeletDir string) error { + configFile := filepath.Join(kubeletDir, kubeadmconstants.KubeletConfigurationFileName) + fmt.Printf("[kubelet] Writing kubelet configuration to file %q\n", configFile) - if err := ioutil.WriteFile(kubeadmconstants.KubeletConfigurationFile, b, 0644); err != nil { - return fmt.Errorf("failed to write kubelet configuration to the file %q: %v", kubeadmconstants.KubeletConfigurationFile, err) + // creates target folder if not already exists + if err := os.MkdirAll(kubeletDir, 0700); err != nil { + return fmt.Errorf("failed to create directory %q: %v", kubeletDir, err) + } + + if err := ioutil.WriteFile(configFile, b, 0644); err != nil { + return fmt.Errorf("failed to write kubelet configuration to the file %q: %v", configFile, err) } return nil } diff --git a/cmd/kubeadm/app/phases/kubelet/config_test.go b/cmd/kubeadm/app/phases/kubelet/config_test.go index 0e6d5b68c39..dc21da453d4 100644 --- a/cmd/kubeadm/app/phases/kubelet/config_test.go +++ b/cmd/kubeadm/app/phases/kubelet/config_test.go @@ -33,7 +33,7 @@ func TestCreateConfigMap(t *testing.T) { nodeName := "fake-node" client := fake.NewSimpleClientset() cfg := &kubeadmapi.MasterConfiguration{ - NodeName: nodeName, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: nodeName}, KubernetesVersion: "v1.11.0", KubeletConfiguration: kubeadmapi.KubeletConfiguration{ BaseConfig: &kubeletconfigv1beta1.KubeletConfiguration{}, diff --git a/cmd/kubeadm/app/phases/kubelet/dynamic.go b/cmd/kubeadm/app/phases/kubelet/dynamic.go index b65d7460370..696f591fbe4 100644 --- a/cmd/kubeadm/app/phases/kubelet/dynamic.go +++ b/cmd/kubeadm/app/phases/kubelet/dynamic.go @@ -17,20 +17,14 @@ limitations under the License. package kubelet import ( - "encoding/json" "fmt" - "os" - "path/filepath" "k8s.io/api/core/v1" - apierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/strategicpatch" - "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" + "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" "k8s.io/kubernetes/pkg/util/version" ) @@ -39,79 +33,29 @@ import ( // This func is ONLY run if the user enables the `DynamicKubeletConfig` feature gate, which is by default off func EnableDynamicConfigForNode(client clientset.Interface, nodeName string, kubeletVersion *version.Version) error { - // If the kubelet version is v1.10.x, exit - if kubeletVersion.LessThan(kubeadmconstants.MinimumKubeletConfigVersion) { - return nil - } - configMapName := configMapName(kubeletVersion) fmt.Printf("[kubelet] Enabling Dynamic Kubelet Config for Node %q; config sourced from ConfigMap %q in namespace %s\n", nodeName, configMapName, metav1.NamespaceSystem) fmt.Println("[kubelet] WARNING: The Dynamic Kubelet Config feature is alpha and off by default. It hasn't been well-tested yet at this stage, use with caution.") - // Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned. - return wait.Poll(kubeadmconstants.APICallRetryInterval, kubeadmconstants.UpdateNodeTimeout, func() (bool, error) { - node, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) - if err != nil { - return false, nil - } - - oldData, err := json.Marshal(node) - if err != nil { - return false, err - } - - kubeletCfg, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(configMapName, metav1.GetOptions{}) - if err != nil { - return false, nil - } - - node.Spec.ConfigSource = &v1.NodeConfigSource{ - ConfigMap: &v1.ConfigMapNodeConfigSource{ - Name: configMapName, - Namespace: metav1.NamespaceSystem, - UID: kubeletCfg.UID, - KubeletConfigKey: kubeadmconstants.KubeletBaseConfigurationConfigMapKey, - }, - } - - newData, err := json.Marshal(node) - if err != nil { - return false, err - } - - patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{}) - if err != nil { - return false, err - } - - if _, err := client.CoreV1().Nodes().Patch(node.Name, types.StrategicMergePatchType, patchBytes); err != nil { - if apierrs.IsConflict(err) { - fmt.Println("Temporarily unable to update node metadata due to conflict (will retry)") - return false, nil - } - return false, err - } - - return true, nil - }) -} - -// GetLocalNodeTLSBootstrappedClient waits for the kubelet to perform the TLS bootstrap -// and then creates a client from config file /etc/kubernetes/kubelet.conf -func GetLocalNodeTLSBootstrappedClient() (clientset.Interface, 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. - err := wait.PollImmediateInfinite(kubeadmconstants.APICallRetryInterval, func() (bool, error) { - _, err := os.Stat(kubeletKubeConfig) - return (err == nil), nil - }) + kubeletConfigMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(configMapName, metav1.GetOptions{}) if err != nil { - return nil, err + return fmt.Errorf("couldn't get the kubelet configuration ConfigMap: %v", err) } - return kubeconfigutil.ClientSetFromFile(kubeletKubeConfig) + // Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned. + return apiclient.PatchNode(client, nodeName, func(n *v1.Node) { + patchNodeForDynamicConfig(n, configMapName, kubeletConfigMap.UID) + }) +} + +func patchNodeForDynamicConfig(n *v1.Node, configMapName string, configMapUID types.UID) { + n.Spec.ConfigSource = &v1.NodeConfigSource{ + ConfigMap: &v1.ConfigMapNodeConfigSource{ + Name: configMapName, + Namespace: metav1.NamespaceSystem, + UID: configMapUID, + KubeletConfigKey: kubeadmconstants.KubeletBaseConfigurationConfigMapKey, + }, + } } diff --git a/cmd/kubeadm/app/phases/kubelet/dynamic_test.go b/cmd/kubeadm/app/phases/kubelet/dynamic_test.go index fe0ba35f41c..150eeda405b 100644 --- a/cmd/kubeadm/app/phases/kubelet/dynamic_test.go +++ b/cmd/kubeadm/app/phases/kubelet/dynamic_test.go @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" + kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/util/version" ) @@ -33,7 +34,8 @@ func TestEnableDynamicConfigForNode(t *testing.T) { client.PrependReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) { return true, &v1.Node{ ObjectMeta: metav1.ObjectMeta{ - Name: nodeName, + Name: nodeName, + Labels: map[string]string{kubeletapis.LabelHostname: nodeName}, }, Spec: v1.NodeSpec{ ConfigSource: &v1.NodeConfigSource{ diff --git a/cmd/kubeadm/app/phases/kubelet/flags.go b/cmd/kubeadm/app/phases/kubelet/flags.go index 167966793aa..51277b81e73 100644 --- a/cmd/kubeadm/app/phases/kubelet/flags.go +++ b/cmd/kubeadm/app/phases/kubelet/flags.go @@ -23,56 +23,108 @@ import ( "path/filepath" "strings" + "github.com/golang/glog" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + nodeutil "k8s.io/kubernetes/pkg/util/node" + "k8s.io/kubernetes/pkg/util/procfs" + utilsexec "k8s.io/utils/exec" ) +type kubeletFlagsOpts struct { + nodeRegOpts *kubeadmapi.NodeRegistrationOptions + featureGates map[string]bool + registerTaintsUsingFlags bool + execer utilsexec.Interface + pidOfFunc func(string) ([]int, error) + defaultHostname string +} + // WriteKubeletDynamicEnvFile writes a environment file with dynamic flags to the kubelet. // Used at "kubeadm init" and "kubeadm join" time. -func WriteKubeletDynamicEnvFile(cfg *kubeadmapi.MasterConfiguration) error { +func WriteKubeletDynamicEnvFile(nodeRegOpts *kubeadmapi.NodeRegistrationOptions, featureGates map[string]bool, registerTaintsUsingFlags bool, kubeletDir string) error { - // TODO: Pass through extra arguments from the config file here in the future - argList := kubeadmutil.BuildArgumentListFromMap(buildKubeletArgMap(cfg), map[string]string{}) + flagOpts := kubeletFlagsOpts{ + nodeRegOpts: nodeRegOpts, + featureGates: featureGates, + registerTaintsUsingFlags: registerTaintsUsingFlags, + execer: utilsexec.New(), + pidOfFunc: procfs.PidOf, + defaultHostname: nodeutil.GetHostname(""), + } + stringMap := buildKubeletArgMap(flagOpts) + argList := kubeadmutil.BuildArgumentListFromMap(stringMap, nodeRegOpts.KubeletExtraArgs) envFileContent := fmt.Sprintf("%s=%s\n", constants.KubeletEnvFileVariableName, strings.Join(argList, " ")) - return writeKubeletFlagBytesToDisk([]byte(envFileContent)) + return writeKubeletFlagBytesToDisk([]byte(envFileContent), kubeletDir) } // buildKubeletArgMap takes a MasterConfiguration object and builds based on that a string-string map with flags // that should be given to the local kubelet daemon. -func buildKubeletArgMap(cfg *kubeadmapi.MasterConfiguration) map[string]string { +func buildKubeletArgMap(opts kubeletFlagsOpts) map[string]string { kubeletFlags := map[string]string{} - if cfg.CRISocket == kubeadmapiv1alpha2.DefaultCRISocket { + if opts.nodeRegOpts.CRISocket == kubeadmapiv1alpha2.DefaultCRISocket { // These flags should only be set when running docker kubeletFlags["network-plugin"] = "cni" kubeletFlags["cni-conf-dir"] = "/etc/cni/net.d" kubeletFlags["cni-bin-dir"] = "/opt/cni/bin" + driver, err := kubeadmutil.GetCgroupDriverDocker(opts.execer) + if err != nil { + glog.Warningf("cannot automatically assign a '--cgroup-driver' value when starting the Kubelet: %v\n", err) + } else { + kubeletFlags["cgroup-driver"] = driver + } } else { kubeletFlags["container-runtime"] = "remote" - kubeletFlags["container-runtime-endpoint"] = cfg.CRISocket + kubeletFlags["container-runtime-endpoint"] = opts.nodeRegOpts.CRISocket } - // TODO: Add support for registering custom Taints and Labels - // TODO: Add support for overriding flags with ExtraArgs - // TODO: Pass through --hostname-override if a custom name is used? - // TODO: Check if `systemd-resolved` is running, and set `--resolv-conf` based on that - // TODO: Conditionally set `--cgroup-driver` to either `systemd` or `cgroupfs` + + if opts.registerTaintsUsingFlags && opts.nodeRegOpts.Taints != nil && len(opts.nodeRegOpts.Taints) > 0 { + taintStrs := []string{} + for _, taint := range opts.nodeRegOpts.Taints { + taintStrs = append(taintStrs, taint.ToString()) + } + + kubeletFlags["register-with-taints"] = strings.Join(taintStrs, ",") + } + + if pids, _ := opts.pidOfFunc("systemd-resolved"); len(pids) > 0 { + // procfs.PidOf only returns an error if the regex is empty or doesn't compile, so we can ignore it + kubeletFlags["resolv-conf"] = "/run/systemd/resolve/resolv.conf" + } + + // Make sure the node name we're passed will work with Kubelet + if opts.nodeRegOpts.Name != "" && opts.nodeRegOpts.Name != opts.defaultHostname { + glog.V(1).Info("setting kubelet hostname-override to %q", opts.nodeRegOpts.Name) + kubeletFlags["hostname-override"] = opts.nodeRegOpts.Name + } + + // If the user enabled Dynamic Kubelet Configuration (which is disabled by default), set the directory + // in the CLI flags so that the feature actually gets enabled + if features.Enabled(opts.featureGates, features.DynamicKubeletConfig) { + kubeletFlags["dynamic-config-dir"] = filepath.Join(constants.KubeletRunDirectory, constants.DynamicKubeletConfigurationDirectoryName) + } + + // TODO: Conditionally set `--cgroup-driver` to either `systemd` or `cgroupfs` for CRI other than Docker return kubeletFlags } // writeKubeletFlagBytesToDisk writes a byte slice down to disk at the specific location of the kubelet flag overrides file -func writeKubeletFlagBytesToDisk(b []byte) error { - fmt.Printf("[kubelet] Writing kubelet environment file with flags to file %q\n", constants.KubeletEnvFile) +func writeKubeletFlagBytesToDisk(b []byte, kubeletDir string) error { + kubeletEnvFilePath := filepath.Join(kubeletDir, constants.KubeletEnvFileName) + fmt.Printf("[kubelet] Writing kubelet environment file with flags to file %q\n", kubeletEnvFilePath) // creates target folder if not already exists - if err := os.MkdirAll(filepath.Dir(constants.KubeletEnvFile), 0700); err != nil { - return fmt.Errorf("failed to create directory %q: %v", filepath.Dir(constants.KubeletEnvFile), err) + if err := os.MkdirAll(kubeletDir, 0700); err != nil { + return fmt.Errorf("failed to create directory %q: %v", kubeletDir, err) } - if err := ioutil.WriteFile(constants.KubeletEnvFile, b, 0644); err != nil { - return fmt.Errorf("failed to write kubelet configuration to the file %q: %v", constants.KubeletEnvFile, err) + if err := ioutil.WriteFile(kubeletEnvFilePath, b, 0644); err != nil { + return fmt.Errorf("failed to write kubelet configuration to the file %q: %v", kubeletEnvFilePath, err) } return nil } diff --git a/cmd/kubeadm/app/phases/kubelet/flags_test.go b/cmd/kubeadm/app/phases/kubelet/flags_test.go new file mode 100644 index 00000000000..b50a658df53 --- /dev/null +++ b/cmd/kubeadm/app/phases/kubelet/flags_test.go @@ -0,0 +1,277 @@ +/* +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 ( + "context" + "errors" + "fmt" + "io" + "reflect" + "strings" + "testing" + + "k8s.io/api/core/v1" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/utils/exec" +) + +type fakeCmd struct { + b []byte + err error +} + +func (f fakeCmd) Run() error { return f.err } +func (f fakeCmd) CombinedOutput() ([]byte, error) { return f.b, f.err } +func (f fakeCmd) Output() ([]byte, error) { return f.b, f.err } +func (f fakeCmd) SetDir(dir string) {} +func (f fakeCmd) SetStdin(in io.Reader) {} +func (f fakeCmd) SetStdout(out io.Writer) {} +func (f fakeCmd) SetStderr(out io.Writer) {} +func (f fakeCmd) Stop() {} + +type fakeExecer struct { + ioMap map[string]fakeCmd +} + +func (f fakeExecer) Command(cmd string, args ...string) exec.Cmd { + cmds := []string{cmd} + cmds = append(cmds, args...) + return f.ioMap[strings.Join(cmds, " ")] +} +func (f fakeExecer) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd { + return f.Command(cmd, args...) +} +func (f fakeExecer) LookPath(file string) (string, error) { return "", errors.New("unknown binary") } + +var ( + systemdCgroupExecer = fakeExecer{ + ioMap: map[string]fakeCmd{ + "docker info": { + b: []byte(`Cgroup Driver: systemd`), + }, + }, + } + + cgroupfsCgroupExecer = fakeExecer{ + ioMap: map[string]fakeCmd{ + "docker info": { + b: []byte(`Cgroup Driver: cgroupfs`), + }, + }, + } + + errCgroupExecer = fakeExecer{ + ioMap: map[string]fakeCmd{ + "docker info": { + err: fmt.Errorf("no such binary: docker"), + }, + }, + } +) + +func binaryRunningPidOfFunc(_ string) ([]int, error) { + return []int{1, 2, 3}, nil +} + +func binaryNotRunningPidOfFunc(_ string) ([]int, error) { + return []int{}, nil +} + +func TestBuildKubeletArgMap(t *testing.T) { + + tests := []struct { + name string + opts kubeletFlagsOpts + expected map[string]string + }{ + { + name: "the simplest case", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/dockershim.sock", + Name: "foo", + Taints: []v1.Taint{ // This should be ignored as registerTaintsUsingFlags is false + { + Key: "foo", + Value: "bar", + Effect: "baz", + }, + }, + }, + execer: errCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "network-plugin": "cni", + "cni-conf-dir": "/etc/cni/net.d", + "cni-bin-dir": "/opt/cni/bin", + }, + }, + { + name: "nodeRegOpts.Name != default hostname", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/dockershim.sock", + Name: "override-name", + }, + execer: errCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "default", + }, + expected: map[string]string{ + "network-plugin": "cni", + "cni-conf-dir": "/etc/cni/net.d", + "cni-bin-dir": "/opt/cni/bin", + "hostname-override": "override-name", + }, + }, + { + name: "systemd cgroup driver", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/dockershim.sock", + Name: "foo", + }, + execer: systemdCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "network-plugin": "cni", + "cni-conf-dir": "/etc/cni/net.d", + "cni-bin-dir": "/opt/cni/bin", + "cgroup-driver": "systemd", + }, + }, + { + name: "cgroupfs cgroup driver", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/dockershim.sock", + Name: "foo", + }, + execer: cgroupfsCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "network-plugin": "cni", + "cni-conf-dir": "/etc/cni/net.d", + "cni-bin-dir": "/opt/cni/bin", + "cgroup-driver": "cgroupfs", + }, + }, + { + name: "external CRI runtime", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/containerd.sock", + Name: "foo", + }, + execer: cgroupfsCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "container-runtime": "remote", + "container-runtime-endpoint": "/var/run/containerd.sock", + }, + }, + { + name: "register with taints", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/containerd.sock", + Name: "foo", + Taints: []v1.Taint{ + { + Key: "foo", + Value: "bar", + Effect: "baz", + }, + { + Key: "key", + Value: "val", + Effect: "eff", + }, + }, + }, + registerTaintsUsingFlags: true, + execer: cgroupfsCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "container-runtime": "remote", + "container-runtime-endpoint": "/var/run/containerd.sock", + "register-with-taints": "foo=bar:baz,key=val:eff", + }, + }, + { + name: "systemd-resolved running", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/containerd.sock", + Name: "foo", + }, + execer: cgroupfsCgroupExecer, + pidOfFunc: binaryRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "container-runtime": "remote", + "container-runtime-endpoint": "/var/run/containerd.sock", + "resolv-conf": "/run/systemd/resolve/resolv.conf", + }, + }, + { + name: "dynamic kubelet config enabled", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/containerd.sock", + Name: "foo", + }, + featureGates: map[string]bool{ + "DynamicKubeletConfig": true, + }, + execer: cgroupfsCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "container-runtime": "remote", + "container-runtime-endpoint": "/var/run/containerd.sock", + "dynamic-config-dir": "/var/lib/kubelet/dynamic-config", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actual := buildKubeletArgMap(test.opts) + if !reflect.DeepEqual(actual, test.expected) { + t.Errorf( + "failed buildKubeletArgMap:\n\texpected: %v\n\t actual: %v", + test.expected, + actual, + ) + } + }) + } +} diff --git a/cmd/kubeadm/app/phases/markmaster/BUILD b/cmd/kubeadm/app/phases/markmaster/BUILD index efb2903f412..aceff8cf395 100644 --- a/cmd/kubeadm/app/phases/markmaster/BUILD +++ b/cmd/kubeadm/app/phases/markmaster/BUILD @@ -27,14 +27,8 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster", deps = [ "//cmd/kubeadm/app/constants:go_default_library", - "//pkg/kubelet/apis:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", + "//cmd/kubeadm/app/util/apiclient:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], ) diff --git a/cmd/kubeadm/app/phases/markmaster/markmaster.go b/cmd/kubeadm/app/phases/markmaster/markmaster.go index 9f8f52237d9..1119708403f 100644 --- a/cmd/kubeadm/app/phases/markmaster/markmaster.go +++ b/cmd/kubeadm/app/phases/markmaster/markmaster.go @@ -17,107 +17,50 @@ limitations under the License. package markmaster import ( - "encoding/json" "fmt" - "github.com/golang/glog" - "k8s.io/api/core/v1" - apierrs "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/strategicpatch" - "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" ) // MarkMaster taints the master and sets the master label -func MarkMaster(client clientset.Interface, masterName string, taint bool) error { +func MarkMaster(client clientset.Interface, masterName string, taints []v1.Taint) error { - if taint { - glog.Infof("[markmaster] will mark node %s as master by adding a label and a taint\n", masterName) - } else { - glog.Infof("[markmaster] will mark node %s as master by adding a label\n", masterName) + fmt.Printf("[markmaster] Marking the node %s as master by adding the label \"%s=''\"\n", masterName, constants.LabelNodeRoleMaster) + + if taints != nil && len(taints) > 0 { + taintStrs := []string{} + for _, taint := range taints { + taintStrs = append(taintStrs, taint.ToString()) + } + fmt.Printf("[markmaster] Marking the node %s as master by adding the taints %v\n", masterName, taintStrs) } - // Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned. - return wait.Poll(kubeadmconstants.APICallRetryInterval, kubeadmconstants.MarkMasterTimeout, func() (bool, error) { - // First get the node object - n, err := client.CoreV1().Nodes().Get(masterName, metav1.GetOptions{}) - if err != nil { - return false, nil - } - - // The node may appear to have no labels at first, - // so we wait for it to get hostname label. - if _, found := n.ObjectMeta.Labels[kubeletapis.LabelHostname]; !found { - return false, nil - } - - oldData, err := json.Marshal(n) - if err != nil { - return false, err - } - - // The master node should be tainted and labelled accordingly - markMasterNode(n, taint) - - newData, err := json.Marshal(n) - if err != nil { - return false, err - } - - patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{}) - if err != nil { - return false, err - } - - if _, err := client.CoreV1().Nodes().Patch(n.Name, types.StrategicMergePatchType, patchBytes); err != nil { - if apierrs.IsConflict(err) { - fmt.Println("[markmaster] Temporarily unable to update master node metadata due to conflict (will retry)") - return false, nil - } - return false, err - } - - if taint { - fmt.Printf("[markmaster] Master %s tainted and labelled with key/value: %s=%q\n", masterName, kubeadmconstants.LabelNodeRoleMaster, "") - } else { - fmt.Printf("[markmaster] Master %s labelled with key/value: %s=%q\n", masterName, kubeadmconstants.LabelNodeRoleMaster, "") - } - - return true, nil + return apiclient.PatchNode(client, masterName, func(n *v1.Node) { + markMasterNode(n, taints) }) } -func markMasterNode(n *v1.Node, taint bool) { - n.ObjectMeta.Labels[kubeadmconstants.LabelNodeRoleMaster] = "" - if taint { - addTaintIfNotExists(n, kubeadmconstants.MasterTaint) - } else { - delTaintIfExists(n, kubeadmconstants.MasterTaint) - } -} - -func addTaintIfNotExists(n *v1.Node, t v1.Taint) { - for _, taint := range n.Spec.Taints { - if taint == t { - return +func taintExists(taint v1.Taint, taints []v1.Taint) bool { + for _, t := range taints { + if t == taint { + return true } } - n.Spec.Taints = append(n.Spec.Taints, t) + return false } -func delTaintIfExists(n *v1.Node, t v1.Taint) { - var taints []v1.Taint - for _, taint := range n.Spec.Taints { - if taint == t { - continue +func markMasterNode(n *v1.Node, taints []v1.Taint) { + n.ObjectMeta.Labels[constants.LabelNodeRoleMaster] = "" + + for _, nt := range n.Spec.Taints { + if !taintExists(nt, taints) { + taints = append(taints, nt) } - taints = append(taints, t) } + n.Spec.Taints = taints } diff --git a/cmd/kubeadm/app/phases/markmaster/markmaster_test.go b/cmd/kubeadm/app/phases/markmaster/markmaster_test.go index d7d5a934501..c8f937abd56 100644 --- a/cmd/kubeadm/app/phases/markmaster/markmaster_test.go +++ b/cmd/kubeadm/app/phases/markmaster/markmaster_test.go @@ -40,53 +40,70 @@ func TestMarkMaster(t *testing.T) { // will need to change if strategicpatch's behavior changes in the // future. tests := []struct { - name string - existingLabel string - existingTaint *v1.Taint - wantTaint bool - expectedPatch string + name string + existingLabel string + existingTaints []v1.Taint + newTaints []v1.Taint + expectedPatch string }{ { "master label and taint missing", "", nil, - true, + []v1.Taint{kubeadmconstants.MasterTaint}, "{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}},\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"}]}}", }, { "master label and taint missing but taint not wanted", "", nil, - false, + nil, "{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}}}", }, { "master label missing", "", - &kubeadmconstants.MasterTaint, - true, + []v1.Taint{kubeadmconstants.MasterTaint}, + []v1.Taint{kubeadmconstants.MasterTaint}, "{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}}}", }, { "master taint missing", kubeadmconstants.LabelNodeRoleMaster, nil, - true, + []v1.Taint{kubeadmconstants.MasterTaint}, "{\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"}]}}", }, { "nothing missing", kubeadmconstants.LabelNodeRoleMaster, - &kubeadmconstants.MasterTaint, - true, + []v1.Taint{kubeadmconstants.MasterTaint}, + []v1.Taint{kubeadmconstants.MasterTaint}, "{}", }, { - "nothing missing but taint unwanted", + "has taint and no new taints wanted", kubeadmconstants.LabelNodeRoleMaster, - &kubeadmconstants.MasterTaint, - false, - "{\"spec\":{\"taints\":null}}", + []v1.Taint{ + { + Key: "node.cloudprovider.kubernetes.io/uninitialized", + Effect: v1.TaintEffectNoSchedule, + }, + }, + nil, + "{}", + }, + { + "has taint and should merge with wanted taint", + kubeadmconstants.LabelNodeRoleMaster, + []v1.Taint{ + { + Key: "node.cloudprovider.kubernetes.io/uninitialized", + Effect: v1.TaintEffectNoSchedule, + }, + }, + []v1.Taint{kubeadmconstants.MasterTaint}, + "{\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"},{\"effect\":\"NoSchedule\",\"key\":\"node.cloudprovider.kubernetes.io/uninitialized\"}]}}", }, } @@ -105,8 +122,8 @@ func TestMarkMaster(t *testing.T) { masterNode.ObjectMeta.Labels[tc.existingLabel] = "" } - if tc.existingTaint != nil { - masterNode.Spec.Taints = append(masterNode.Spec.Taints, *tc.existingTaint) + if tc.existingTaints != nil { + masterNode.Spec.Taints = tc.existingTaints } jsonNode, err := json.Marshal(masterNode) @@ -144,8 +161,7 @@ func TestMarkMaster(t *testing.T) { t.Fatalf("MarkMaster(%s): unexpected error building clientset: %v", tc.name, err) } - err = MarkMaster(cs, hostname, tc.wantTaint) - if err != nil { + if err := MarkMaster(cs, hostname, tc.newTaints); err != nil { t.Errorf("MarkMaster(%s) returned unexpected error: %v", tc.name, err) } diff --git a/cmd/kubeadm/app/phases/patchnode/BUILD b/cmd/kubeadm/app/phases/patchnode/BUILD new file mode 100644 index 00000000000..88c6fbd3419 --- /dev/null +++ b/cmd/kubeadm/app/phases/patchnode/BUILD @@ -0,0 +1,28 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["patchnode.go"], + importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode", + visibility = ["//visibility:public"], + deps = [ + "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/util/apiclient:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes: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/cmd/kubeadm/app/phases/patchnode/patchnode.go b/cmd/kubeadm/app/phases/patchnode/patchnode.go new file mode 100644 index 00000000000..1ebf9b8a9b0 --- /dev/null +++ b/cmd/kubeadm/app/phases/patchnode/patchnode.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 patchnode + +import ( + "fmt" + + "k8s.io/api/core/v1" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" +) + +// AnnotateCRISocket annotates the node with the given crisocket +func AnnotateCRISocket(client clientset.Interface, nodeName string, criSocket string) error { + + fmt.Printf("[patchnode] Uploading the CRI Socket information %q to the Node API object %q as an annotation\n", criSocket, nodeName) + + return apiclient.PatchNode(client, nodeName, func(n *v1.Node) { + annotateNodeWithCRISocket(n, criSocket) + }) +} + +func annotateNodeWithCRISocket(n *v1.Node, criSocket string) { + n.ObjectMeta.Annotations[constants.AnnotationKubeadmCRISocket] = criSocket +} diff --git a/cmd/kubeadm/app/phases/selfhosting/BUILD b/cmd/kubeadm/app/phases/selfhosting/BUILD index 8ca10bd1bb3..4503f0c71cc 100644 --- a/cmd/kubeadm/app/phases/selfhosting/BUILD +++ b/cmd/kubeadm/app/phases/selfhosting/BUILD @@ -17,7 +17,6 @@ go_test( deps = [ "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", - "//pkg/volume/util:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", ], @@ -37,12 +36,13 @@ go_library( "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//pkg/volume/util:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", ], ) diff --git a/cmd/kubeadm/app/phases/selfhosting/selfhosting.go b/cmd/kubeadm/app/phases/selfhosting/selfhosting.go index 4993ba0a74c..c5f2aa218fa 100644 --- a/cmd/kubeadm/app/phases/selfhosting/selfhosting.go +++ b/cmd/kubeadm/app/phases/selfhosting/selfhosting.go @@ -18,6 +18,7 @@ package selfhosting import ( "fmt" + "io/ioutil" "os" "time" @@ -26,12 +27,13 @@ import ( apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" clientset "k8s.io/client-go/kubernetes" + clientscheme "k8s.io/client-go/kubernetes/scheme" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" - volumeutil "k8s.io/kubernetes/pkg/volume/util" ) const ( @@ -85,12 +87,11 @@ func CreateSelfHostedControlPlane(manifestsDir, kubeConfigDir string, cfg *kubea continue } - // Load the Static Pod file in order to be able to create a self-hosted variant of that file - pod, err := volumeutil.LoadPodFromFile(manifestPath) + // Load the Static Pod spec in order to be able to create a self-hosted variant of that file + podSpec, err := loadPodSpecFromFile(manifestPath) if err != nil { return err } - podSpec := &pod.Spec // Build a DaemonSet object from the loaded PodSpec ds := BuildDaemonSet(componentName, podSpec, mutators) @@ -117,7 +118,7 @@ func CreateSelfHostedControlPlane(manifestsDir, kubeConfigDir string, cfg *kubea // Wait for the mirror Pod hash to be removed; otherwise we'll run into race conditions here when the kubelet hasn't had time to // remove the Static Pod (or the mirror Pod respectively). This implicitly also tests that the API server endpoint is healthy, // because this blocks until the API server returns a 404 Not Found when getting the Static Pod - staticPodName := fmt.Sprintf("%s-%s", componentName, cfg.NodeName) + staticPodName := fmt.Sprintf("%s-%s", componentName, cfg.NodeRegistration.Name) if err := waiter.WaitForPodToDisappear(staticPodName); err != nil { return err } @@ -127,7 +128,7 @@ func CreateSelfHostedControlPlane(manifestsDir, kubeConfigDir string, cfg *kubea return err } - glog.Infof("[self-hosted] self-hosted %s ready after %f seconds\n", componentName, time.Since(start).Seconds()) + fmt.Printf("[self-hosted] self-hosted %s ready after %f seconds\n", componentName, time.Since(start).Seconds()) } return nil } @@ -174,3 +175,23 @@ func BuildSelfhostedComponentLabels(component string) map[string]string { func BuildSelfHostedComponentLabelQuery(componentName string) string { return fmt.Sprintf("k8s-app=%s", kubeadmconstants.AddSelfHostedPrefix(componentName)) } + +func loadPodSpecFromFile(filePath string) (*v1.PodSpec, error) { + podDef, err := ioutil.ReadFile(filePath) + if err != nil { + return nil, fmt.Errorf("failed to read file path %s: %+v", filePath, err) + } + + if len(podDef) == 0 { + return nil, fmt.Errorf("file was empty: %s", filePath) + } + + codec := clientscheme.Codecs.UniversalDecoder() + pod := &v1.Pod{} + + if err = runtime.DecodeInto(codec, podDef, pod); err != nil { + return nil, fmt.Errorf("failed decoding pod: %v", err) + } + + return &pod.Spec, nil +} diff --git a/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go b/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go index 5b30899d77b..8d7e757f675 100644 --- a/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go +++ b/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go @@ -26,7 +26,6 @@ import ( apps "k8s.io/api/apps/v1" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/util" - volumeutil "k8s.io/kubernetes/pkg/volume/util" ) const ( @@ -494,11 +493,10 @@ func TestBuildDaemonSet(t *testing.T) { } defer os.Remove(tempFile) - pod, err := volumeutil.LoadPodFromFile(tempFile) + podSpec, err := loadPodSpecFromFile(tempFile) if err != nil { - t.Fatalf("couldn't load the specified Pod") + t.Fatalf("couldn't load the specified Pod Spec") } - podSpec := &pod.Spec ds := BuildDaemonSet(rt.component, podSpec, GetDefaultMutators()) dsBytes, err := util.MarshalToYaml(ds, apps.SchemeGroupVersion) @@ -517,6 +515,11 @@ func TestLoadPodSpecFromFile(t *testing.T) { content string expectError bool }{ + { + // No content + content: "", + expectError: true, + }, { // Good YAML content: ` @@ -570,11 +573,16 @@ spec: } defer os.Remove(tempFile) - _, err = volumeutil.LoadPodFromFile(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("") + 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/upgrade/BUILD b/cmd/kubeadm/app/phases/upgrade/BUILD index 7f8d4efac9e..81a36153a82 100644 --- a/cmd/kubeadm/app/phases/upgrade/BUILD +++ b/cmd/kubeadm/app/phases/upgrade/BUILD @@ -28,6 +28,7 @@ go_library( "//cmd/kubeadm/app/phases/controlplane:go_default_library", "//cmd/kubeadm/app/phases/etcd:go_default_library", "//cmd/kubeadm/app/phases/kubelet:go_default_library", + "//cmd/kubeadm/app/phases/patchnode:go_default_library", "//cmd/kubeadm/app/phases/selfhosting:go_default_library", "//cmd/kubeadm/app/phases/uploadconfig:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", diff --git a/cmd/kubeadm/app/phases/upgrade/compute.go b/cmd/kubeadm/app/phases/upgrade/compute.go index 96c9e2d4189..326951168fd 100644 --- a/cmd/kubeadm/app/phases/upgrade/compute.go +++ b/cmd/kubeadm/app/phases/upgrade/compute.go @@ -173,7 +173,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA After: ClusterState{ KubeVersion: patchVersionStr, DNSType: ActiveDNSAddon(featureGates), - DNSVersion: dns.GetDNSVersion(patchVersion, ActiveDNSAddon(featureGates)), + DNSVersion: kubeadmconstants.GetDNSVersion(ActiveDNSAddon(featureGates)), KubeadmVersion: newKubeadmVer, EtcdVersion: getSuggestedEtcdVersion(patchVersionStr), // KubeletVersions is unset here as it is not used anywhere in .After @@ -190,7 +190,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA After: ClusterState{ KubeVersion: stableVersionStr, DNSType: ActiveDNSAddon(featureGates), - DNSVersion: dns.GetDNSVersion(stableVersion, ActiveDNSAddon(featureGates)), + DNSVersion: kubeadmconstants.GetDNSVersion(ActiveDNSAddon(featureGates)), KubeadmVersion: stableVersionStr, EtcdVersion: getSuggestedEtcdVersion(stableVersionStr), // KubeletVersions is unset here as it is not used anywhere in .After @@ -236,7 +236,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA After: ClusterState{ KubeVersion: previousBranchLatestVersionStr, DNSType: ActiveDNSAddon(featureGates), - DNSVersion: dns.GetDNSVersion(previousBranchLatestVersion, ActiveDNSAddon(featureGates)), + DNSVersion: kubeadmconstants.GetDNSVersion(ActiveDNSAddon(featureGates)), KubeadmVersion: previousBranchLatestVersionStr, EtcdVersion: getSuggestedEtcdVersion(previousBranchLatestVersionStr), // KubeletVersions is unset here as it is not used anywhere in .After @@ -249,12 +249,12 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA // Default to assume that the experimental version to show is the unstable one unstableKubeVersion := latestVersionStr - unstableKubeDNSVersion := dns.GetDNSVersion(latestVersion, ActiveDNSAddon(featureGates)) + unstableKubeDNSVersion := kubeadmconstants.GetDNSVersion(ActiveDNSAddon(featureGates)) // Ẃe should not display alpha.0. The previous branch's beta/rc versions are more relevant due how the kube branching process works. if latestVersion.PreRelease() == "alpha.0" { unstableKubeVersion = previousBranchLatestVersionStr - unstableKubeDNSVersion = dns.GetDNSVersion(previousBranchLatestVersion, ActiveDNSAddon(featureGates)) + unstableKubeDNSVersion = kubeadmconstants.GetDNSVersion(ActiveDNSAddon(featureGates)) } upgrades = append(upgrades, Upgrade{ diff --git a/cmd/kubeadm/app/phases/upgrade/compute_test.go b/cmd/kubeadm/app/phases/upgrade/compute_test.go index 7050ed636af..ee17ee76a87 100644 --- a/cmd/kubeadm/app/phases/upgrade/compute_test.go +++ b/cmd/kubeadm/app/phases/upgrade/compute_test.go @@ -168,7 +168,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.10.3", KubeadmVersion: "v1.10.3", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.1.12", }, }, @@ -207,7 +207,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.10.3", KubeadmVersion: "v1.10.3", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.1.12", }, }, @@ -246,7 +246,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.11.0", KubeadmVersion: "v1.11.0", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.2.18", }, }, @@ -285,7 +285,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.10.5", KubeadmVersion: "v1.10.5", // Note: The kubeadm version mustn't be "downgraded" here DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.1.12", }, }, @@ -305,7 +305,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.11.1", KubeadmVersion: "v1.11.1", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.2.18", }, }, @@ -364,7 +364,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.11.0-alpha.2", KubeadmVersion: "v1.11.0-alpha.2", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.2.18", }, }, @@ -404,7 +404,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.11.0-alpha.2", KubeadmVersion: "v1.11.0-alpha.2", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.2.18", }, }, @@ -445,7 +445,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.11.0-beta.1", KubeadmVersion: "v1.11.0-beta.1", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.2.18", }, }, @@ -486,7 +486,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.11.0-rc.1", KubeadmVersion: "v1.11.0-rc.1", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.2.18", }, }, @@ -527,7 +527,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.11.6-rc.1", KubeadmVersion: "v1.11.6-rc.1", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.2.18", }, }, @@ -568,7 +568,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.11.0-rc.1", KubeadmVersion: "v1.11.0-rc.1", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.2.18", }, }, @@ -588,7 +588,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.12.0-alpha.2", KubeadmVersion: "v1.12.0-alpha.2", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.2.18", }, }, @@ -641,7 +641,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.12.1", KubeadmVersion: "v1.12.1", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.2.18", }, }, @@ -678,7 +678,7 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeVersion: "v1.12.0", KubeadmVersion: "v1.12.0", DNSType: "coredns", - DNSVersion: "1.0.6", + DNSVersion: "1.1.3", EtcdVersion: "3.2.18", }, }, diff --git a/cmd/kubeadm/app/phases/upgrade/policy.go b/cmd/kubeadm/app/phases/upgrade/policy.go index 807cd9dbeb7..25c5d4a2035 100644 --- a/cmd/kubeadm/app/phases/upgrade/policy.go +++ b/cmd/kubeadm/app/phases/upgrade/policy.go @@ -118,8 +118,7 @@ func EnforceVersionPolicies(versionGetter VersionGetter, newK8sVersionStr string if kubeadmVersion.Major() > newK8sVersion.Major() || kubeadmVersion.Minor() > newK8sVersion.Minor() { - skewErrors.Mandatory = append(skewErrors.Mandatory, fmt.Errorf("Kubeadm version %s can only be used to upgrade to Kubernetes versions %d.%d", kubeadmVersionStr, kubeadmVersion.Major(), kubeadmVersion.Minor())) - + skewErrors.Skippable = append(skewErrors.Skippable, fmt.Errorf("Kubeadm version %s can only be used to upgrade to Kubernetes version %d.%d", kubeadmVersionStr, kubeadmVersion.Major(), kubeadmVersion.Minor())) } // Detect if the version is unstable and the user didn't allow that diff --git a/cmd/kubeadm/app/phases/upgrade/policy_test.go b/cmd/kubeadm/app/phases/upgrade/policy_test.go index 870ec47045b..ccf2861273b 100644 --- a/cmd/kubeadm/app/phases/upgrade/policy_test.go +++ b/cmd/kubeadm/app/phases/upgrade/policy_test.go @@ -75,7 +75,8 @@ func TestEnforceVersionPolicies(t *testing.T) { kubeadmVersion: "v1.10.3", }, newK8sVersion: "v1.9.10", - expectedMandatoryErrs: 2, // version must be higher than v1.10.0, can't upgrade old k8s with newer kubeadm + expectedMandatoryErrs: 1, // version must be higher than v1.10.0 + expectedSkippableErrs: 1, // can't upgrade old k8s with newer kubeadm }, { name: "upgrading two minor versions in one go is not supported", @@ -96,7 +97,8 @@ func TestEnforceVersionPolicies(t *testing.T) { kubeadmVersion: "v1.12.0", }, newK8sVersion: "v1.10.3", - expectedMandatoryErrs: 2, // can't downgrade two minor versions, can't upgrade old k8s with newer kubeadm + 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", @@ -187,7 +189,7 @@ func TestEnforceVersionPolicies(t *testing.T) { kubeadmVersion: "v1.11.0", }, newK8sVersion: "v1.10.6", - expectedMandatoryErrs: 1, // can't upgrade old k8s with newer kubeadm + 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 47a20ef70cb..15a0b2f5ca6 100644 --- a/cmd/kubeadm/app/phases/upgrade/postupgrade.go +++ b/cmd/kubeadm/app/phases/upgrade/postupgrade.go @@ -18,6 +18,7 @@ package upgrade import ( "fmt" + "io/ioutil" "os" "path/filepath" "time" @@ -37,6 +38,7 @@ import ( nodebootstraptoken "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node" certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" + patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode" "k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting" "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" @@ -58,6 +60,23 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterC errs = append(errs, err) } + // Create the new, version-branched kubelet ComponentConfig ConfigMap + if err := kubeletphase.CreateConfigMap(cfg, client); err != nil { + errs = append(errs, fmt.Errorf("error creating kubelet configuration ConfigMap: %v", err)) + } + + // Write the new kubelet config down to disk and the env file if needed + if err := writeKubeletConfigFiles(client, cfg, newK8sVer, dryRun); err != nil { + errs = append(errs, err) + } + + // Annotate the node with the crisocket information, sourced either from the MasterConfiguration struct or + // --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, fmt.Errorf("error uploading crisocket: %v", err)) + } + // Create/update RBAC rules that makes the bootstrap tokens able to post CSRs if err := nodebootstraptoken.AllowBootstrapTokensToPostCSRs(client); err != nil { errs = append(errs, err) @@ -88,24 +107,9 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterC errs = append(errs, err) } - certAndKeyDir := kubeadmapiv1alpha2.DefaultCertificatesDir - shouldBackup, err := shouldBackupAPIServerCertAndKey(certAndKeyDir) - // Don't fail the upgrade phase if failing to determine to backup kube-apiserver cert and key. - if err != nil { - fmt.Printf("[postupgrade] WARNING: failed to determine to backup kube-apiserver cert and key: %v", err) - } else if shouldBackup { - // Don't fail the upgrade phase if failing to backup kube-apiserver cert and key. - if err := backupAPIServerCertAndKey(certAndKeyDir); err != nil { - fmt.Printf("[postupgrade] WARNING: failed to backup kube-apiserver cert and key: %v", err) - } - if err := certsphase.CreateAPIServerCertAndKeyFiles(cfg); err != nil { - errs = append(errs, err) - } - } - - // Create the new, version-branched kubelet ComponentConfig ConfigMap - if err := kubeletphase.CreateConfigMap(cfg, client); err != nil { - errs = append(errs, fmt.Errorf("error creating kubelet configuration ConfigMap: %v", err)) + // Rotate the kube-apiserver cert and key if needed + if err := backupAPIServerCertIfNeeded(cfg, dryRun); err != nil { + errs = append(errs, err) } // Upgrade kube-dns/CoreDNS and kube-proxy @@ -113,10 +117,8 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterC errs = append(errs, err) } // Remove the old DNS deployment if a new DNS service is now used (kube-dns to CoreDNS or vice versa) - if !dryRun { - if err := removeOldDNSDeploymentIfAnotherDNSIsUsed(cfg, client); err != nil { - errs = append(errs, err) - } + if err := removeOldDNSDeploymentIfAnotherDNSIsUsed(cfg, client, dryRun); err != nil { + errs = append(errs, err) } if err := proxy.EnsureProxyAddon(cfg, client); err != nil { @@ -125,7 +127,7 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterC return errors.NewAggregate(errs) } -func removeOldDNSDeploymentIfAnotherDNSIsUsed(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { +func removeOldDNSDeploymentIfAnotherDNSIsUsed(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface, dryRun bool) error { return apiclient.TryRunCommand(func() error { installedDeploymentName := kubeadmconstants.KubeDNS deploymentToDelete := kubeadmconstants.CoreDNS @@ -134,14 +136,21 @@ func removeOldDNSDeploymentIfAnotherDNSIsUsed(cfg *kubeadmapi.MasterConfiguratio installedDeploymentName = kubeadmconstants.CoreDNS deploymentToDelete = kubeadmconstants.KubeDNS } - dnsDeployment, err := client.AppsV1().Deployments(metav1.NamespaceSystem).Get(installedDeploymentName, metav1.GetOptions{}) - if err != nil { - return err + + // If we're dry-running, we don't need to wait for the new DNS addon to become ready + if !dryRun { + dnsDeployment, err := client.AppsV1().Deployments(metav1.NamespaceSystem).Get(installedDeploymentName, metav1.GetOptions{}) + if err != nil { + return err + } + if dnsDeployment.Status.ReadyReplicas == 0 { + return fmt.Errorf("the DNS deployment isn't ready yet") + } } - if dnsDeployment.Status.ReadyReplicas == 0 { - return fmt.Errorf("the DNS deployment isn't ready yet") - } - err = apiclient.DeleteDeploymentForeground(client, metav1.NamespaceSystem, deploymentToDelete) + + // We don't want to wait for the DNS deployment above to become ready when dryrunning (as it never will) + // but here we should execute the DELETE command against the dryrun clientset, as it will only be logged + err := apiclient.DeleteDeploymentForeground(client, metav1.NamespaceSystem, deploymentToDelete) if err != nil && !apierrors.IsNotFound(err) { return err } @@ -163,6 +172,69 @@ func upgradeToSelfHosting(client clientset.Interface, cfg *kubeadmapi.MasterConf return nil } +func backupAPIServerCertIfNeeded(cfg *kubeadmapi.MasterConfiguration, dryRun bool) error { + certAndKeyDir := kubeadmapiv1alpha2.DefaultCertificatesDir + 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 fmt.Errorf("[postupgrade] WARNING: failed to determine to backup kube-apiserver cert and key: %v", err) + } + + if !shouldBackup { + return nil + } + + // If dry-running, just say that this would happen to the user and exit + if dryRun { + fmt.Println("[postupgrade] Would rotate the API server certificate and key.") + return nil + } + + // Don't fail the upgrade phase if failing to backup kube-apiserver cert and key, just continue rotating the cert + // TODO: We might want to reconsider this choice. + if err := backupAPIServerCertAndKey(certAndKeyDir); err != nil { + fmt.Printf("[postupgrade] WARNING: failed to backup kube-apiserver cert and key: %v", err) + } + return certsphase.CreateAPIServerCertAndKeyFiles(cfg) +} + +func writeKubeletConfigFiles(client clientset.Interface, cfg *kubeadmapi.MasterConfiguration, newK8sVer *version.Version, dryRun bool) error { + kubeletDir, err := getKubeletDir(dryRun) + if err != nil { + // The error here should never occur in reality, would only be thrown if /tmp doesn't exist on the machine. + return err + } + errs := []error{} + // Write the configuration for the kubelet down to disk so the upgraded kubelet can start with fresh config + if err := kubeletphase.DownloadConfig(client, newK8sVer, kubeletDir); err != nil { + // Tolerate the error being NotFound when dryrunning, as there is a pretty common scenario: the dryrun process + // *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, fmt.Errorf("error downloading kubelet configuration from the ConfigMap: %v", err)) + } + } + + if dryRun { // Print what contents would be written + dryrunutil.PrintDryRunFile(kubeadmconstants.KubeletConfigurationFileName, kubeletDir, kubeadmconstants.KubeletRunDirectory, os.Stdout) + } + + envFilePath := filepath.Join(kubeadmconstants.KubeletRunDirectory, kubeadmconstants.KubeletEnvFileName) + if _, err := os.Stat(envFilePath); os.IsNotExist(err) { + // Write env file with flags for the kubelet to use. We do not need to write the --register-with-taints for the master, + // 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.NodeRegistration, cfg.FeatureGates, false, kubeletDir); err != nil { + errs = append(errs, fmt.Errorf("error writing a dynamic environment file for the kubelet: %v", err)) + } + + if dryRun { // Print what contents would be written + dryrunutil.PrintDryRunFile(kubeadmconstants.KubeletEnvFileName, kubeletDir, kubeadmconstants.KubeletRunDirectory, os.Stdout) + } + } + return errors.NewAggregate(errs) +} + // getWaiter gets the right waiter implementation for the right occasion // TODO: Consolidate this with what's in init.go? func getWaiter(dryRun bool, client clientset.Interface) apiclient.Waiter { @@ -172,6 +244,15 @@ func getWaiter(dryRun bool, client clientset.Interface) apiclient.Waiter { return apiclient.NewKubeWaiter(client, 30*time.Minute, os.Stdout) } +// getKubeletDir gets the kubelet directory based on whether the user is dry-running this command or not. +// TODO: Consolidate this with similar funcs? +func getKubeletDir(dryRun bool) (string, error) { + if dryRun { + return ioutil.TempDir("", "kubeadm-upgrade-dryrun") + } + return kubeadmconstants.KubeletRunDirectory, nil +} + // backupAPIServerCertAndKey backups the old cert and key of kube-apiserver to a specified directory. func backupAPIServerCertAndKey(certAndKeyDir string) error { subDir := filepath.Join(certAndKeyDir, "expired") diff --git a/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go b/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go index 652dee2e40b..c25387e8eca 100644 --- a/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go +++ b/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go @@ -131,9 +131,9 @@ func TestRollbackFiles(t *testing.T) { func TestShouldBackupAPIServerCertAndKey(t *testing.T) { cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "test-node", + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "test-node"}, } for desc, test := range map[string]struct { diff --git a/cmd/kubeadm/app/phases/upgrade/staticpods.go b/cmd/kubeadm/app/phases/upgrade/staticpods.go index a041c9669cf..33b1a0dae8a 100644 --- a/cmd/kubeadm/app/phases/upgrade/staticpods.go +++ b/cmd/kubeadm/app/phases/upgrade/staticpods.go @@ -51,6 +51,8 @@ type StaticPodPathManager interface { BackupManifestDir() string // BackupEtcdDir should point to the backup directory used for backuping manifests during the transition BackupEtcdDir() string + // CleanupDirs cleans up all temporary directories + CleanupDirs() error } // KubeStaticPodPathManager is a real implementation of StaticPodPathManager that is used when upgrading a static pod cluster @@ -59,34 +61,39 @@ type KubeStaticPodPathManager struct { tempManifestDir string backupManifestDir string backupEtcdDir string + + keepManifestDir bool + keepEtcdDir bool } // NewKubeStaticPodPathManager creates a new instance of KubeStaticPodPathManager -func NewKubeStaticPodPathManager(realDir, tempDir, backupDir, backupEtcdDir string) StaticPodPathManager { +func NewKubeStaticPodPathManager(realDir, tempDir, backupDir, backupEtcdDir string, keepManifestDir, keepEtcdDir bool) StaticPodPathManager { return &KubeStaticPodPathManager{ realManifestDir: realDir, tempManifestDir: tempDir, backupManifestDir: backupDir, backupEtcdDir: backupEtcdDir, + keepManifestDir: keepManifestDir, + keepEtcdDir: keepEtcdDir, } } // NewKubeStaticPodPathManagerUsingTempDirs creates a new instance of KubeStaticPodPathManager with temporary directories backing it -func NewKubeStaticPodPathManagerUsingTempDirs(realManifestDir string) (StaticPodPathManager, error) { +func NewKubeStaticPodPathManagerUsingTempDirs(realManifestDir string, saveManifestsDir, saveEtcdDir bool) (StaticPodPathManager, error) { upgradedManifestsDir, err := constants.CreateTempDirForKubeadm("kubeadm-upgraded-manifests") if err != nil { return nil, err } - backupManifestsDir, err := constants.CreateTempDirForKubeadm("kubeadm-backup-manifests") + backupManifestsDir, err := constants.CreateTimestampDirForKubeadm("kubeadm-backup-manifests") if err != nil { return nil, err } - backupEtcdDir, err := constants.CreateTempDirForKubeadm("kubeadm-backup-etcd") + backupEtcdDir, err := constants.CreateTimestampDirForKubeadm("kubeadm-backup-etcd") if err != nil { return nil, err } - return NewKubeStaticPodPathManager(realManifestDir, upgradedManifestsDir, backupManifestsDir, backupEtcdDir), nil + return NewKubeStaticPodPathManager(realManifestDir, upgradedManifestsDir, backupManifestsDir, backupEtcdDir, saveManifestsDir, saveEtcdDir), nil } // MoveFile should move a file from oldPath to newPath @@ -129,6 +136,26 @@ func (spm *KubeStaticPodPathManager) BackupEtcdDir() string { return spm.backupEtcdDir } +// CleanupDirs cleans up all temporary directories except those the user has requested to keep around +func (spm *KubeStaticPodPathManager) CleanupDirs() error { + if err := os.RemoveAll(spm.TempManifestDir()); err != nil { + return err + } + if !spm.keepManifestDir { + if err := os.RemoveAll(spm.BackupManifestDir()); err != nil { + return err + } + } + + if !spm.keepEtcdDir { + if err := os.RemoveAll(spm.BackupEtcdDir()); err != nil { + return err + } + } + + return nil +} + func upgradeComponent(component string, waiter apiclient.Waiter, pathMgr StaticPodPathManager, cfg *kubeadmapi.MasterConfiguration, beforePodHash string, recoverManifests map[string]string, isTLSUpgrade bool) error { // Special treatment is required for etcd case, when rollbackOldManifests should roll back etcd // manifests only for the case when component is Etcd @@ -206,7 +233,7 @@ func upgradeComponent(component string, waiter apiclient.Waiter, pathMgr StaticP // notice the removal of the Static Pod, leading to a false positive below where we check that the API endpoint is healthy // If we don't do this, there is a case where we remove the Static Pod manifest, kubelet is slow to react, kubeadm checks the // API endpoint below of the OLD Static Pod component and proceeds quickly enough, which might lead to unexpected results. - if err := waiter.WaitForStaticPodHashChange(cfg.NodeName, component, beforePodHash); err != nil { + if err := waiter.WaitForStaticPodHashChange(cfg.NodeRegistration.Name, component, beforePodHash); err != nil { return rollbackOldManifests(recoverManifests, err, pathMgr, recoverEtcd) } @@ -266,7 +293,7 @@ func performEtcdStaticPodUpgrade(waiter apiclient.Waiter, pathMgr StaticPodPathM return false, nil } - beforeEtcdPodHash, err := waiter.WaitForStaticPodSingleHash(cfg.NodeName, constants.Etcd) + beforeEtcdPodHash, err := waiter.WaitForStaticPodSingleHash(cfg.NodeRegistration.Name, constants.Etcd) if err != nil { return true, fmt.Errorf("failed to get etcd pod's hash: %v", err) } @@ -376,7 +403,7 @@ func StaticPodControlPlane(waiter apiclient.Waiter, pathMgr StaticPodPathManager var isTLSUpgrade bool var isExternalEtcd bool - beforePodHashMap, err := waiter.WaitForStaticPodControlPlaneHashes(cfg.NodeName) + beforePodHashMap, err := waiter.WaitForStaticPodControlPlaneHashes(cfg.NodeRegistration.Name) if err != nil { return err } @@ -449,11 +476,7 @@ func StaticPodControlPlane(waiter apiclient.Waiter, pathMgr StaticPodPathManager // Remove the temporary directories used on a best-effort (don't fail if the calls error out) // The calls are set here by design; we should _not_ use "defer" above as that would remove the directories // even in the "fail and rollback" case, where we want the directories preserved for the user. - os.RemoveAll(pathMgr.TempManifestDir()) - os.RemoveAll(pathMgr.BackupManifestDir()) - os.RemoveAll(pathMgr.BackupEtcdDir()) - - return nil + return pathMgr.CleanupDirs() } // rollbackOldManifests rolls back the backed-up manifests if something went wrong. diff --git a/cmd/kubeadm/app/phases/upgrade/staticpods_test.go b/cmd/kubeadm/app/phases/upgrade/staticpods_test.go index 44a299b5a3a..9a4fe92f9ae 100644 --- a/cmd/kubeadm/app/phases/upgrade/staticpods_test.go +++ b/cmd/kubeadm/app/phases/upgrade/staticpods_test.go @@ -66,7 +66,9 @@ networking: dnsDomain: cluster.local podSubnet: "" serviceSubnet: 10.96.0.0/12 -nodeName: thegopher +nodeRegistration: + name: foo + criSocket: "" schedulerExtraArgs: null token: ce3aa5.5ec8455bb76b379f tokenTTL: 24h @@ -201,6 +203,16 @@ func (spm *fakeStaticPodPathManager) BackupEtcdDir() string { return spm.backupEtcdDir } +func (spm *fakeStaticPodPathManager) CleanupDirs() error { + if err := os.RemoveAll(spm.TempManifestDir()); err != nil { + return err + } + if err := os.RemoveAll(spm.BackupManifestDir()); err != nil { + return err + } + return os.RemoveAll(spm.BackupEtcdDir()) +} + type fakeTLSEtcdClient struct{ TLS bool } func (c fakeTLSEtcdClient) HasTLS() bool { @@ -511,3 +523,81 @@ func getConfig(version, certsDir, etcdDataDir string) (*kubeadmapi.MasterConfigu kubeadmscheme.Scheme.Convert(externalcfg, internalcfg, nil) return internalcfg, nil } + +func getTempDir(t *testing.T, name string) (string, func()) { + dir, err := ioutil.TempDir(os.TempDir(), name) + if err != nil { + t.Fatalf("couldn't make temporary directory: %v", err) + } + + return dir, func() { + os.RemoveAll(dir) + } +} + +func TestCleanupDirs(t *testing.T) { + tests := []struct { + name string + keepManifest, keepEtcd bool + }{ + { + name: "save manifest backup", + keepManifest: true, + }, + { + name: "save both etcd and manifest", + keepManifest: true, + keepEtcd: true, + }, + { + name: "save nothing", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + realManifestDir, cleanup := getTempDir(t, "realManifestDir") + defer cleanup() + + tempManifestDir, cleanup := getTempDir(t, "tempManifestDir") + defer cleanup() + + backupManifestDir, cleanup := getTempDir(t, "backupManifestDir") + defer cleanup() + + backupEtcdDir, cleanup := getTempDir(t, "backupEtcdDir") + defer cleanup() + + mgr := NewKubeStaticPodPathManager(realManifestDir, tempManifestDir, backupManifestDir, backupEtcdDir, test.keepManifest, test.keepEtcd) + err := mgr.CleanupDirs() + if err != nil { + t.Errorf("unexpected error cleaning up: %v", err) + } + + if _, err := os.Stat(tempManifestDir); !os.IsNotExist(err) { + t.Errorf("%q should not have existed", tempManifestDir) + } + _, err = os.Stat(backupManifestDir) + if test.keepManifest { + if err != nil { + t.Errorf("unexpected error getting backup manifest dir") + } + } else { + if !os.IsNotExist(err) { + t.Error("expected backup manifest to not exist") + } + } + + _, err = os.Stat(backupEtcdDir) + if test.keepEtcd { + if err != nil { + t.Errorf("unexpected error getting backup etcd dir") + } + } else { + if !os.IsNotExist(err) { + t.Error("expected backup etcd dir to not exist") + } + } + }) + } +} diff --git a/cmd/kubeadm/app/phases/uploadconfig/BUILD b/cmd/kubeadm/app/phases/uploadconfig/BUILD index 18639345d91..faa9a5ae409 100644 --- a/cmd/kubeadm/app/phases/uploadconfig/BUILD +++ b/cmd/kubeadm/app/phases/uploadconfig/BUILD @@ -17,7 +17,6 @@ go_library( "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", diff --git a/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go b/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go index 68a9391c99c..7445b436167 100644 --- a/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go +++ b/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go @@ -17,7 +17,7 @@ limitations under the License. package uploadconfig import ( - "github.com/golang/glog" + "fmt" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -34,14 +34,16 @@ import ( // UploadConfiguration saves the MasterConfiguration used for later reference (when upgrading for instance) func UploadConfiguration(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { - glog.Infof("[uploadconfig] storing the configuration used in ConfigMap %q in the %q Namespace\n", kubeadmconstants.MasterConfigurationConfigMap, metav1.NamespaceSystem) + fmt.Printf("[uploadconfig] storing the configuration used in ConfigMap %q in the %q Namespace\n", kubeadmconstants.MasterConfigurationConfigMap, metav1.NamespaceSystem) // Convert cfg to the external version as that's the only version of the API that can be deserialized later externalcfg := &kubeadmapiv1alpha2.MasterConfiguration{} kubeadmscheme.Scheme.Convert(cfg, externalcfg, nil) // Removes sensitive info from the data that will be stored in the config map - externalcfg.Token = "" + externalcfg.BootstrapTokens = nil + // Clear the NodeRegistration object. + externalcfg.NodeRegistration = kubeadmapiv1alpha2.NodeRegistrationOptions{} cfgYaml, err := util.MarshalToYamlForCodecs(externalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, scheme.Codecs) if err != nil { diff --git a/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go b/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go index e683bf3bbe7..327f4f9e2b4 100644 --- a/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go +++ b/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go @@ -63,8 +63,19 @@ func TestUploadConfiguration(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cfg := &kubeadmapi.MasterConfiguration{ - KubernetesVersion: "1.7.3", - Token: "1234567", + KubernetesVersion: "v1.10.3", + BootstrapTokens: []kubeadmapi.BootstrapToken{ + { + Token: &kubeadmapi.BootstrapTokenString{ + ID: "abcdef", + Secret: "abcdef0123456789", + }, + }, + }, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{ + Name: "node-foo", + CRISocket: "/var/run/custom-cri.sock", + }, } client := clientsetfake.NewSimpleClientset() if tt.errOnCreate != nil { @@ -110,8 +121,14 @@ func TestUploadConfiguration(t *testing.T) { t.Errorf("Decoded value doesn't match, decoded = %#v, expected = %#v", decodedCfg.KubernetesVersion, cfg.KubernetesVersion) } - if decodedCfg.Token != "" { - t.Errorf("Decoded value contains token (sensitive info), decoded = %#v, expected = empty", decodedCfg.Token) + // If the decoded cfg has a BootstrapTokens array, verify the sensitive information we had isn't still there. + if len(decodedCfg.BootstrapTokens) > 0 && decodedCfg.BootstrapTokens[0].Token != nil && decodedCfg.BootstrapTokens[0].Token.String() == cfg.BootstrapTokens[0].Token.String() { + t.Errorf("Decoded value contains .BootstrapTokens (sensitive info), decoded = %#v, expected = empty", decodedCfg.BootstrapTokens) + } + + // Make sure no information from NodeRegistrationOptions was uploaded. + if decodedCfg.NodeRegistration.Name == cfg.NodeRegistration.Name || decodedCfg.NodeRegistration.CRISocket != kubeadmapiv1alpha2.DefaultCRISocket { + t.Errorf("Decoded value contains .NodeRegistration (node-specific info shouldn't be uploaded), decoded = %#v, expected = empty", decodedCfg.NodeRegistration) } if decodedExtCfg.Kind != "MasterConfiguration" { diff --git a/cmd/kubeadm/app/preflight/BUILD b/cmd/kubeadm/app/preflight/BUILD index d6b0d412cdf..aae4c5d45d0 100644 --- a/cmd/kubeadm/app/preflight/BUILD +++ b/cmd/kubeadm/app/preflight/BUILD @@ -52,11 +52,10 @@ go_library( "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", - "//pkg/apis/core/validation:go_default_library", + "//cmd/kubeadm/app/images:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", "//pkg/util/initsystem:go_default_library", "//pkg/util/ipvs:go_default_library", - "//pkg/util/procfs:go_default_library", "//pkg/util/version:go_default_library", "//pkg/version:go_default_library", "//test/e2e_node/system:go_default_library", diff --git a/cmd/kubeadm/app/preflight/checks.go b/cmd/kubeadm/app/preflight/checks.go index 8b3c5cb6a98..28d98e6ebbb 100644 --- a/cmd/kubeadm/app/preflight/checks.go +++ b/cmd/kubeadm/app/preflight/checks.go @@ -19,6 +19,8 @@ package preflight import ( "bufio" "bytes" + "crypto/tls" + "crypto/x509" "encoding/json" "errors" "fmt" @@ -26,31 +28,26 @@ import ( "io/ioutil" "net" "net/http" + "net/url" "os" "path/filepath" "runtime" "strings" "time" - "crypto/tls" - "crypto/x509" - "github.com/PuerkitoBio/purell" "github.com/blang/semver" "github.com/golang/glog" - "net/url" - netutil "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/sets" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmdefaults "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/pkg/apis/core/validation" + "k8s.io/kubernetes/cmd/kubeadm/app/images" "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" "k8s.io/kubernetes/pkg/util/initsystem" ipvsutil "k8s.io/kubernetes/pkg/util/ipvs" - "k8s.io/kubernetes/pkg/util/procfs" versionutil "k8s.io/kubernetes/pkg/util/version" kubeadmversion "k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/test/e2e_node/system" @@ -76,10 +73,16 @@ type Error struct { Msg string } +// Error implements the standard error interface func (e *Error) Error() string { return fmt.Sprintf("[preflight] Some fatal errors occurred:\n%s%s", e.Msg, "[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`") } +// Preflight identifies this error as a preflight error +func (e *Error) Preflight() bool { + return true +} + // Checker validates the state of the system to ensure kubeadm will be // successful as often as possible. type Checker interface { @@ -405,12 +408,9 @@ func (HostnameCheck) Name() string { // Check validates if hostname match dns sub domain regex. func (hc HostnameCheck) Check() (warnings, errors []error) { - glog.V(1).Infof("validating if hostname match dns sub domain") + glog.V(1).Infof("checking whether the given node name is reachable using net.LookupHost") errors = []error{} warnings = []error{} - for _, msg := range validation.ValidateNodeName(hc.nodeName, false) { - errors = append(errors, fmt.Errorf("hostname \"%s\" %s", hc.nodeName, msg)) - } addr, err := net.LookupHost(hc.nodeName) if addr == nil { warnings = append(warnings, fmt.Errorf("hostname \"%s\" could not be reached", hc.nodeName)) @@ -823,30 +823,28 @@ func getEtcdVersionResponse(client *http.Client, url string, target interface{}) return err } -// ResolveCheck tests for potential issues related to the system resolver configuration -type ResolveCheck struct{} - -// Name returns label for ResolveCheck -func (ResolveCheck) Name() string { - return "Resolve" +// ImagePullCheck will pull container images used by kubeadm +type ImagePullCheck struct { + Images images.Images + ImageList []string } -// Check validates the system resolver configuration -func (ResolveCheck) Check() (warnings, errors []error) { - glog.V(1).Infoln("validating the system resolver configuration") +// Name returns the label for ImagePullCheck +func (ImagePullCheck) Name() string { + return "ImagePull" +} - warnings = []error{} - - // procfs.PidOf only returns an error if the string passed is empty - // or there is an issue compiling the regex, so we can ignore it here - pids, _ := procfs.PidOf("systemd-resolved") - if len(pids) > 0 { - warnings = append(warnings, fmt.Errorf( - "systemd-resolved was detected, for cluster dns resolution to work "+ - "properly --resolv-conf=/run/systemd/resolve/resolv.conf must be set "+ - "for the kubelet. (/etc/systemd/system/kubelet.service.d/10-kubeadm.conf should be edited for this purpose)\n")) +// Check pulls images required by kubeadm. This is a mutating check +func (i ImagePullCheck) Check() (warnings, errors []error) { + for _, image := range i.ImageList { + glog.V(1).Infoln("pulling ", image) + if err := i.Images.Exists(image); err == nil { + continue + } + if err := i.Images.Pull(image); err != nil { + errors = append(errors, fmt.Errorf("failed to pull image [%s]: %v", image, err)) + } } - return warnings, errors } @@ -875,7 +873,7 @@ func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfi checks = addCommonChecks(execer, cfg, checks) // Check ipvs required kernel module once we use ipvs kube-proxy mode - if cfg.KubeProxy.Config.Mode == ipvsutil.IPVSProxyMode { + if cfg.KubeProxy.Config != nil && cfg.KubeProxy.Config.Mode == ipvsutil.IPVSProxyMode { checks = append(checks, ipvsutil.RequiredIPVSKernelModulesAvailableCheck{Executor: execer}, ) @@ -892,13 +890,13 @@ func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfi if cfg.Etcd.External != nil { // Only check etcd version when external endpoints are specified if cfg.Etcd.External.CAFile != "" { - checks = append(checks, FileExistingCheck{Path: cfg.Etcd.External.CAFile}) + checks = append(checks, FileExistingCheck{Path: cfg.Etcd.External.CAFile, Label: "ExternalEtcdClientCertificates"}) } if cfg.Etcd.External.CertFile != "" { - checks = append(checks, FileExistingCheck{Path: cfg.Etcd.External.CertFile}) + checks = append(checks, FileExistingCheck{Path: cfg.Etcd.External.CertFile, Label: "ExternalEtcdClientCertificates"}) } if cfg.Etcd.External.KeyFile != "" { - checks = append(checks, FileExistingCheck{Path: cfg.Etcd.External.KeyFile}) + checks = append(checks, FileExistingCheck{Path: cfg.Etcd.External.KeyFile, Label: "ExternalEtcdClientCertificates"}) } checks = append(checks, ExternalEtcdVersionCheck{Etcd: cfg.Etcd}) } @@ -959,15 +957,6 @@ func RunJoinNodeChecks(execer utilsexec.Interface, cfg *kubeadmapi.NodeConfigura // addCommonChecks is a helper function to deplicate checks that are common between both the // kubeadm init and join commands func addCommonChecks(execer utilsexec.Interface, cfg kubeadmapi.CommonConfiguration, checks []Checker) []Checker { - // check if we can use crictl to perform checks via the CRI - glog.V(1).Infoln("checking if we can use crictl to perform checks via the CRI") - criCtlChecker := InPathCheck{ - executable: "crictl", - mandatory: false, - exec: execer, - suggestion: fmt.Sprintf("go get %v", kubeadmconstants.CRICtlPackage), - } - // Check whether or not the CRI socket defined is the default if cfg.GetCRISocket() != kubeadmdefaults.DefaultCRISocket { checks = append(checks, CRICheck{socket: cfg.GetCRISocket(), exec: execer}) @@ -981,6 +970,7 @@ func addCommonChecks(execer utilsexec.Interface, cfg kubeadmapi.CommonConfigurat FileContentCheck{Path: bridgenf, Content: []byte{'1'}}, FileContentCheck{Path: ipv4Forward, Content: []byte{'1'}}, SwapCheck{}, + InPathCheck{executable: "crictl", mandatory: true, exec: execer}, InPathCheck{executable: "ip", mandatory: true, exec: execer}, InPathCheck{executable: "iptables", mandatory: true, exec: execer}, InPathCheck{executable: "mount", mandatory: true, exec: execer}, @@ -989,9 +979,7 @@ func addCommonChecks(execer utilsexec.Interface, cfg kubeadmapi.CommonConfigurat InPathCheck{executable: "ethtool", mandatory: false, exec: execer}, InPathCheck{executable: "socat", mandatory: false, exec: execer}, InPathCheck{executable: "tc", mandatory: false, exec: execer}, - InPathCheck{executable: "touch", mandatory: false, exec: execer}, - criCtlChecker, - ResolveCheck{}) + InPathCheck{executable: "touch", mandatory: false, exec: execer}) } checks = append(checks, SystemVerificationCheck{CRISocket: cfg.GetCRISocket()}, @@ -1012,6 +1000,19 @@ func RunRootCheckOnly(ignorePreflightErrors sets.String) error { return RunChecks(checks, os.Stderr, ignorePreflightErrors) } +// RunPullImagesCheck will pull images kubeadm needs if the are not found on the system +func RunPullImagesCheck(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfiguration, ignorePreflightErrors sets.String) error { + criInterfacer, err := images.NewCRInterfacer(execer, cfg.GetCRISocket()) + if err != nil { + return err + } + + checks := []Checker{ + ImagePullCheck{Images: criInterfacer, ImageList: images.GetAllImages(cfg)}, + } + return RunChecks(checks, os.Stderr, ignorePreflightErrors) +} + // RunChecks runs each check, displays it's warnings/errors, and once all // are processed will exit if any errors occurred. func RunChecks(checks []Checker, ww io.Writer, ignorePreflightErrors sets.String) error { @@ -1051,22 +1052,43 @@ func RunChecks(checks []Checker, ww io.Writer, ignorePreflightErrors sets.String } // TryStartKubelet attempts to bring up kubelet service -func TryStartKubelet(ignorePreflightErrors sets.String) { - if setHasItemOrAll(ignorePreflightErrors, "StartKubelet") { - return - } +// TODO: Move these kubelet start/stop functions to some other place, e.g. phases/kubelet +func TryStartKubelet() { // If we notice that the kubelet service is inactive, try to start it initSystem, err := initsystem.GetInitSystem() if err != nil { - glog.Infoln("[preflight] no supported init system detected, won't ensure kubelet is running.") - } else if initSystem.ServiceExists("kubelet") { + fmt.Println("[preflight] no supported init system detected, won't make sure the kubelet is running properly.") + return + } - glog.Infoln("[preflight] Activating the kubelet service") - // This runs "systemctl daemon-reload && systemctl restart kubelet" - if err := initSystem.ServiceRestart("kubelet"); err != nil { - glog.Warningf("[preflight] unable to start the kubelet service: [%v]\n", err) - glog.Warningf("[preflight] please ensure kubelet is running manually.") - } + if !initSystem.ServiceExists("kubelet") { + fmt.Println("[preflight] couldn't detect a kubelet service, can't make sure the kubelet is running properly.") + } + + fmt.Println("[preflight] Activating the kubelet service") + // This runs "systemctl daemon-reload && systemctl restart kubelet" + if err := initSystem.ServiceRestart("kubelet"); err != nil { + fmt.Printf("[preflight] WARNING: unable to start the kubelet service: [%v]\n", err) + fmt.Printf("[preflight] please ensure kubelet is reloaded and running manually.\n") + } +} + +// TryStopKubelet attempts to bring down the kubelet service momentarily +func TryStopKubelet() { + // If we notice that the kubelet service is inactive, try to start it + initSystem, err := initsystem.GetInitSystem() + if err != nil { + fmt.Println("[preflight] no supported init system detected, won't make sure the kubelet not running for a short period of time while setting up configuration for it.") + return + } + + if !initSystem.ServiceExists("kubelet") { + fmt.Println("[preflight] couldn't detect a kubelet service, can't make sure the kubelet not running for a short period of time while setting up configuration for it.") + } + + // This runs "systemctl daemon-reload && systemctl stop kubelet" + if err := initSystem.ServiceStop("kubelet"); err != nil { + fmt.Printf("[preflight] WARNING: unable to stop the kubelet service momentarily: [%v]\n", err) } } diff --git a/cmd/kubeadm/app/preflight/checks_test.go b/cmd/kubeadm/app/preflight/checks_test.go index cfea0abc450..f6908c7c3e0 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" + "errors" "fmt" "io/ioutil" "strings" @@ -696,3 +697,32 @@ func TestSetHasItemOrAll(t *testing.T) { } } } + +type imgs struct{} + +func (i *imgs) Pull(image string) error { + if image == "bad pull" { + return errors.New("pull error") + } + return nil +} +func (i *imgs) Exists(image string) error { + if image == "found" { + return nil + } + return errors.New("error") +} + +func TestImagePullCheck(t *testing.T) { + i := ImagePullCheck{ + Images: &imgs{}, + ImageList: []string{"found", "not found", "bad pull"}, + } + warnings, errors := i.Check() + if len(warnings) != 0 { + t.Fatalf("did not expect any warnings but got %q", warnings) + } + if len(errors) != 1 { + t.Fatalf("expected 1 errors but got %d: %q", len(errors), errors) + } +} diff --git a/cmd/kubeadm/app/util/BUILD b/cmd/kubeadm/app/util/BUILD index 3dfc790b59e..19057966524 100644 --- a/cmd/kubeadm/app/util/BUILD +++ b/cmd/kubeadm/app/util/BUILD @@ -10,6 +10,7 @@ go_library( name = "go_default_library", srcs = [ "arguments.go", + "cgroupdriver.go", "copy.go", "endpoint.go", "error.go", @@ -20,7 +21,7 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/preflight:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", "//vendor/gopkg.in/yaml.v2:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", @@ -29,6 +30,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", ], ) @@ -36,6 +38,7 @@ go_test( name = "go_default_test", srcs = [ "arguments_test.go", + "cgroupdriver_test.go", "endpoint_test.go", "error_test.go", "marshal_test.go", @@ -47,7 +50,6 @@ go_test( "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", - "//cmd/kubeadm/app/preflight:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", ], @@ -72,7 +74,6 @@ filegroup( "//cmd/kubeadm/app/util/kubeconfig:all-srcs", "//cmd/kubeadm/app/util/pubkeypin:all-srcs", "//cmd/kubeadm/app/util/staticpod:all-srcs", - "//cmd/kubeadm/app/util/token:all-srcs", ], tags = ["automanaged"], ) diff --git a/cmd/kubeadm/app/util/apiclient/BUILD b/cmd/kubeadm/app/util/apiclient/BUILD index 5704d1228a1..d702b7328c9 100644 --- a/cmd/kubeadm/app/util/apiclient/BUILD +++ b/cmd/kubeadm/app/util/apiclient/BUILD @@ -19,6 +19,7 @@ go_library( deps = [ "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", + "//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", @@ -28,8 +29,10 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", diff --git a/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go b/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go index 34b20dc38d9..3841a715fce 100644 --- a/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go +++ b/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go @@ -20,6 +20,7 @@ import ( "encoding/json" "fmt" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" @@ -72,6 +73,8 @@ func NewClientBackedDryRunGetterFromKubeconfig(file string) (*ClientBackedDryRun // HandleGetAction handles GET actions to the dryrun clientset this interface supports func (clg *ClientBackedDryRunGetter) HandleGetAction(action core.GetAction) (bool, runtime.Object, error) { unstructuredObj, err := clg.dynamicClient.Resource(action.GetResource()).Namespace(action.GetNamespace()).Get(action.GetName(), metav1.GetOptions{}) + // Inform the user that the requested object wasn't found. + printIfNotExists(err) if err != nil { return true, nil, err } @@ -120,3 +123,9 @@ func decodeUnstructuredIntoAPIObject(action core.Action, unstructuredObj runtime } return newObj, nil } + +func printIfNotExists(err error) { + if apierrors.IsNotFound(err) { + fmt.Println("[dryrun] The GET request didn't yield any result, the API Server returned a NotFound error.") + } +} diff --git a/cmd/kubeadm/app/util/apiclient/dryrunclient.go b/cmd/kubeadm/app/util/apiclient/dryrunclient.go index 6c0d796e6fa..4d4a52d706a 100644 --- a/cmd/kubeadm/app/util/apiclient/dryrunclient.go +++ b/cmd/kubeadm/app/util/apiclient/dryrunclient.go @@ -55,6 +55,18 @@ type DryRunClientOptions struct { PrintGETAndLIST bool } +// GetDefaultDryRunClientOptions returns the default DryRunClientOptions values +func GetDefaultDryRunClientOptions(drg DryRunGetter, w io.Writer) DryRunClientOptions { + return DryRunClientOptions{ + Writer: w, + Getter: drg, + PrependReactors: []core.Reactor{}, + AppendReactors: []core.Reactor{}, + MarshalFunc: DefaultMarshalFunc, + PrintGETAndLIST: false, + } +} + // actionWithName is the generic interface for an action that has a name associated with it // This just makes it easier to catch all actions that has a name; instead of hard-coding all request that has it associated type actionWithName interface { @@ -71,14 +83,7 @@ type actionWithObject interface { // NewDryRunClient is a wrapper for NewDryRunClientWithOpts using some default values func NewDryRunClient(drg DryRunGetter, w io.Writer) clientset.Interface { - return NewDryRunClientWithOpts(DryRunClientOptions{ - Writer: w, - Getter: drg, - PrependReactors: []core.Reactor{}, - AppendReactors: []core.Reactor{}, - MarshalFunc: DefaultMarshalFunc, - PrintGETAndLIST: false, - }) + return NewDryRunClientWithOpts(GetDefaultDryRunClientOptions(drg, w)) } // NewDryRunClientWithOpts returns a clientset.Interface that can be used normally for talking to the Kubernetes API. diff --git a/cmd/kubeadm/app/util/apiclient/idempotency.go b/cmd/kubeadm/app/util/apiclient/idempotency.go index ffe42df077a..bc36f65ebdd 100644 --- a/cmd/kubeadm/app/util/apiclient/idempotency.go +++ b/cmd/kubeadm/app/util/apiclient/idempotency.go @@ -17,6 +17,7 @@ limitations under the License. package apiclient import ( + "encoding/json" "fmt" apps "k8s.io/api/apps/v1" @@ -24,7 +25,12 @@ import ( rbac "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/strategicpatch" + "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" ) // TODO: We should invent a dynamic mechanism for this using the dynamic client instead of hard-coding these functions per-type @@ -186,3 +192,49 @@ func CreateOrUpdateClusterRoleBinding(client clientset.Interface, clusterRoleBin } return nil } + +// PatchNode tries to patch a node using the following client, executing patchFn for the actual mutating logic +func PatchNode(client clientset.Interface, nodeName string, patchFn func(*v1.Node)) error { + // Loop on every false return. Return with an error if raised. Exit successfully if true is returned. + return wait.Poll(constants.APICallRetryInterval, constants.PatchNodeTimeout, func() (bool, error) { + // First get the node object + n, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) + if err != nil { + return false, nil + } + + // The node may appear to have no labels at first, + // so we wait for it to get hostname label. + if _, found := n.ObjectMeta.Labels[kubeletapis.LabelHostname]; !found { + return false, nil + } + + oldData, err := json.Marshal(n) + if err != nil { + return false, err + } + + // Execute the mutating function + patchFn(n) + + newData, err := json.Marshal(n) + if err != nil { + return false, err + } + + patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{}) + if err != nil { + return false, err + } + + if _, err := client.CoreV1().Nodes().Patch(n.Name, types.StrategicMergePatchType, patchBytes); err != nil { + if apierrors.IsConflict(err) { + fmt.Println("[patchnode] Temporarily unable to update node metadata due to conflict (will retry)") + return false, nil + } + return false, err + } + + return true, nil + }) +} diff --git a/cmd/kubeadm/app/util/apiclient/init_dryrun.go b/cmd/kubeadm/app/util/apiclient/init_dryrun.go index b21ec7810d0..f4da31f8c3c 100644 --- a/cmd/kubeadm/app/util/apiclient/init_dryrun.go +++ b/cmd/kubeadm/app/util/apiclient/init_dryrun.go @@ -132,6 +132,7 @@ func (idr *InitDryRunGetter) handleGetNode(action core.GetAction) (bool, runtime Labels: map[string]string{ "kubernetes.io/hostname": idr.masterName, }, + Annotations: map[string]string{}, }, }, nil } diff --git a/cmd/kubeadm/app/util/audit/BUILD b/cmd/kubeadm/app/util/audit/BUILD index 7f5453fab3a..cd3098c00f2 100644 --- a/cmd/kubeadm/app/util/audit/BUILD +++ b/cmd/kubeadm/app/util/audit/BUILD @@ -8,8 +8,10 @@ go_library( deps = [ "//cmd/kubeadm/app/util:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/audit/install:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", ], ) @@ -18,8 +20,9 @@ go_test( srcs = ["utils_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/kubectl/scheme:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/audit/install:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit/v1beta1:go_default_library", ], ) diff --git a/cmd/kubeadm/app/util/audit/utils.go b/cmd/kubeadm/app/util/audit/utils.go index 688d8f0f614..8155d096b18 100644 --- a/cmd/kubeadm/app/util/audit/utils.go +++ b/cmd/kubeadm/app/util/audit/utils.go @@ -23,8 +23,10 @@ import ( "path/filepath" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apiserver/pkg/apis/audit/install" auditv1beta1 "k8s.io/apiserver/pkg/apis/audit/v1beta1" - "k8s.io/client-go/kubernetes/scheme" "k8s.io/kubernetes/cmd/kubeadm/app/util" ) @@ -32,7 +34,7 @@ import ( func CreateDefaultAuditLogPolicy(policyFile string) error { policy := auditv1beta1.Policy{ TypeMeta: metav1.TypeMeta{ - APIVersion: "audit.k8s.io/v1beta1", + APIVersion: auditv1beta1.SchemeGroupVersion.String(), Kind: "Policy", }, Rules: []auditv1beta1.PolicyRule{ @@ -50,11 +52,15 @@ func writePolicyToDisk(policyFile string, policy *auditv1beta1.Policy) error { return fmt.Errorf("failed to create directory %q: %v", filepath.Dir(policyFile), err) } - // Registers auditv1beta1 with the runtime Scheme - auditv1beta1.AddToScheme(scheme.Scheme) + scheme := runtime.NewScheme() + // Registers the API group with the scheme and adds types to a scheme + install.Install(scheme) + + codecs := serializer.NewCodecFactory(scheme) // writes the policy to disk - serialized, err := util.MarshalToYaml(policy, auditv1beta1.SchemeGroupVersion) + serialized, err := util.MarshalToYamlForCodecs(policy, auditv1beta1.SchemeGroupVersion, codecs) + if err != nil { return fmt.Errorf("failed to marshal audit policy to YAML: %v", err) } diff --git a/cmd/kubeadm/app/util/audit/utils_test.go b/cmd/kubeadm/app/util/audit/utils_test.go index 113488a752f..01fde9eb8de 100644 --- a/cmd/kubeadm/app/util/audit/utils_test.go +++ b/cmd/kubeadm/app/util/audit/utils_test.go @@ -23,8 +23,9 @@ import ( "testing" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apiserver/pkg/apis/audit/install" auditv1beta1 "k8s.io/apiserver/pkg/apis/audit/v1beta1" - "k8s.io/kubernetes/pkg/kubectl/scheme" ) func cleanup(t *testing.T, path string) { @@ -50,8 +51,11 @@ func TestCreateDefaultAuditLogPolicy(t *testing.T) { if err != nil { t.Fatalf("failed to read %v: %v", auditPolicyFile, err) } + scheme := runtime.NewScheme() + install.Install(scheme) + codecs := serializer.NewCodecFactory(scheme) policy := auditv1beta1.Policy{} - err = runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), policyBytes, &policy) + err = runtime.DecodeInto(codecs.UniversalDecoder(), policyBytes, &policy) if err != nil { t.Fatalf("failed to decode written policy: %v", err) } diff --git a/cmd/kubeadm/app/util/cgroupdriver.go b/cmd/kubeadm/app/util/cgroupdriver.go new file mode 100644 index 00000000000..b03a299126e --- /dev/null +++ b/cmd/kubeadm/app/util/cgroupdriver.go @@ -0,0 +1,75 @@ +/* +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" + "strings" + + utilsexec "k8s.io/utils/exec" +) + +// TODO: add support for detecting the cgroup driver for CRI other than +// Docker. Currently only Docker driver detection is supported: +// Discussion: +// https://github.com/kubernetes/kubeadm/issues/844 + +// GetCgroupDriverDocker runs 'docker info' to obtain the docker cgroup driver +func GetCgroupDriverDocker(execer utilsexec.Interface) (string, error) { + info, err := callDockerInfo(execer) + if err != nil { + return "", err + } + return getCgroupDriverFromDockerInfo(info) +} + +func validateCgroupDriver(driver string) error { + if driver != "cgroupfs" && driver != "systemd" { + return fmt.Errorf("unknown cgroup driver %q", driver) + } + return nil +} + +// TODO: Docker 1.13 has a new way to obatain the cgroup driver: +// docker info -f "{{.CgroupDriver}} +// If the minimum supported Docker version in K8s becomes 1.13, move to +// this syntax. +func callDockerInfo(execer utilsexec.Interface) (string, error) { + out, err := execer.Command("docker", "info").Output() + if err != nil { + return "", fmt.Errorf("cannot execute 'docker info': %v", err) + } + return string(out), nil +} + +func getCgroupDriverFromDockerInfo(info string) (string, error) { + lineSeparator := ": " + prefix := "Cgroup Driver" + for _, line := range strings.Split(info, "\n") { + if !strings.Contains(line, prefix+lineSeparator) { + continue + } + lineSplit := strings.Split(line, lineSeparator) + // At this point len(lineSplit) is always >= 2 + driver := lineSplit[1] + if err := validateCgroupDriver(driver); err != nil { + return "", err + } + return driver, nil + } + return "", fmt.Errorf("cgroup driver is not defined in 'docker info'") +} diff --git a/cmd/kubeadm/app/util/cgroupdriver_test.go b/cmd/kubeadm/app/util/cgroupdriver_test.go new file mode 100644 index 00000000000..ca1ba3a4545 --- /dev/null +++ b/cmd/kubeadm/app/util/cgroupdriver_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 util + +import ( + "testing" +) + +func TestGetCgroupDriverDocker(t *testing.T) { + testCases := []struct { + name string + info string + expectedError bool + }{ + { + name: "valid: value is 'cgroupfs'", + info: `Cgroup Driver: cgroupfs`, + expectedError: false, + }, + { + name: "valid: value is 'systemd'", + info: `Cgroup Driver: systemd`, + expectedError: false, + }, + { + name: "invalid: missing 'Cgroup Driver' key and value", + info: "", + expectedError: true, + }, + { + name: "invalid: only a 'Cgroup Driver' key is present", + info: `Cgroup Driver`, + expectedError: true, + }, + { + name: "invalid: empty 'Cgroup Driver' value", + info: `Cgroup Driver: `, + expectedError: true, + }, + { + name: "invalid: unknown 'Cgroup Driver' value", + info: `Cgroup Driver: invalid-value`, + expectedError: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if _, err := getCgroupDriverFromDockerInfo(tc.info); (err != nil) != tc.expectedError { + t.Fatalf("expected error: %v, saw: %v, error: %v", tc.expectedError, (err != nil), err) + } + }) + } +} diff --git a/cmd/kubeadm/app/util/config/BUILD b/cmd/kubeadm/app/util/config/BUILD index 02eacd1243f..b73f62f00e7 100644 --- a/cmd/kubeadm/app/util/config/BUILD +++ b/cmd/kubeadm/app/util/config/BUILD @@ -22,15 +22,16 @@ go_library( "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", - "//cmd/kubeadm/app/util/token:go_default_library", "//pkg/util/node:go_default_library", "//pkg/util/version:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", ], ) diff --git a/cmd/kubeadm/app/util/config/masterconfig.go b/cmd/kubeadm/app/util/config/masterconfig.go index ec2f84dec46..03ef0374372 100644 --- a/cmd/kubeadm/app/util/config/masterconfig.go +++ b/cmd/kubeadm/app/util/config/masterconfig.go @@ -20,11 +20,14 @@ import ( "fmt" "io/ioutil" "net" + "strings" "github.com/golang/glog" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" netutil "k8s.io/apimachinery/pkg/util/net" + bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" @@ -32,7 +35,6 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" - tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token" "k8s.io/kubernetes/pkg/util/node" "k8s.io/kubernetes/pkg/util/version" ) @@ -59,20 +61,40 @@ func SetInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error { cfg.KubeProxy.Config.BindAddress = kubeadmapiv1alpha2.DefaultProxyBindAddressv6 } // Resolve possible version labels and validate version string - err = NormalizeKubernetesVersion(cfg) - if err != nil { + if err := NormalizeKubernetesVersion(cfg); err != nil { return err } - if cfg.Token == "" { - var err error - cfg.Token, err = tokenutil.GenerateToken() + // Downcase SANs. Some domain names (like ELBs) have capitals in them. + LowercaseSANs(cfg.APIServerCertSANs) + + // Populate the .Token field with a random value if unset + // We do this at this layer, and not the API defaulting layer + // because of possible security concerns, and more practically + // because we can't return errors in the API object defaulting + // process but here we can. + for i, bt := range cfg.BootstrapTokens { + if bt.Token != nil && len(bt.Token.String()) > 0 { + continue + } + + tokenStr, err := bootstraputil.GenerateBootstrapToken() if err != nil { return fmt.Errorf("couldn't generate random token: %v", err) } + token, err := kubeadmapi.NewBootstrapTokenString(tokenStr) + if err != nil { + return err + } + cfg.BootstrapTokens[i].Token = token } - cfg.NodeName = node.GetHostname(cfg.NodeName) + cfg.NodeRegistration.Name = node.GetHostname(cfg.NodeRegistration.Name) + + // Only if the slice is nil, we should append the master taint. This allows the user to specify an empty slice for no default master taint + if cfg.NodeRegistration.Taints == nil { + cfg.NodeRegistration.Taints = []v1.Taint{kubeadmconstants.MasterTaint} + } return nil } @@ -197,3 +219,14 @@ func NormalizeKubernetesVersion(cfg *kubeadmapi.MasterConfiguration) error { } return nil } + +// LowercaseSANs can be used to force all SANs to be lowercase so it passes IsDNS1123Subdomain +func LowercaseSANs(sans []string) { + for i, san := range sans { + lowercase := strings.ToLower(san) + if lowercase != san { + glog.V(1).Infof("lowercasing SAN %q to %q", san, lowercase) + sans[i] = lowercase + } + } +} diff --git a/cmd/kubeadm/app/util/config/masterconfig_test.go b/cmd/kubeadm/app/util/config/masterconfig_test.go index 997b4bd9c07..a8a6115c7ad 100644 --- a/cmd/kubeadm/app/util/config/masterconfig_test.go +++ b/cmd/kubeadm/app/util/config/masterconfig_test.go @@ -176,3 +176,50 @@ func TestUpgrade(t *testing.T) { t.Errorf("v1alpha1 object after unmarshal, conversion and marshal didn't match expected value.\n\tdiff: \n%s\n", diff(afterExpected, afterActual)) } } + +func TestLowercaseSANs(t *testing.T) { + tests := []struct { + name string + in []string + out []string + }{ + { + name: "empty struct", + }, + { + name: "already lowercase", + in: []string{"example.k8s.io"}, + out: []string{"example.k8s.io"}, + }, + { + name: "ip addresses and uppercase", + in: []string{"EXAMPLE.k8s.io", "10.100.0.1"}, + out: []string{"example.k8s.io", "10.100.0.1"}, + }, + { + name: "punycode and uppercase", + in: []string{"xn--7gq663byk9a.xn--fiqz9s", "ANOTHEREXAMPLE.k8s.io"}, + out: []string{"xn--7gq663byk9a.xn--fiqz9s", "anotherexample.k8s.io"}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + cfg := &v1alpha2.MasterConfiguration{ + APIServerCertSANs: test.in, + } + + LowercaseSANs(cfg.APIServerCertSANs) + + if len(cfg.APIServerCertSANs) != len(test.out) { + t.Fatalf("expected %d elements, got %d", len(test.out), len(cfg.APIServerCertSANs)) + } + + for i, expected := range test.out { + if cfg.APIServerCertSANs[i] != expected { + t.Errorf("expected element %d to be %q, got %q", i, expected, cfg.APIServerCertSANs[i]) + } + } + }) + } +} diff --git a/cmd/kubeadm/app/util/config/nodeconfig.go b/cmd/kubeadm/app/util/config/nodeconfig.go index b8ffc64d932..77bcf8b32f6 100644 --- a/cmd/kubeadm/app/util/config/nodeconfig.go +++ b/cmd/kubeadm/app/util/config/nodeconfig.go @@ -33,7 +33,7 @@ import ( // SetJoinDynamicDefaults checks and sets configuration values for the NodeConfiguration object func SetJoinDynamicDefaults(cfg *kubeadmapi.NodeConfiguration) error { - cfg.NodeName = node.GetHostname(cfg.NodeName) + cfg.NodeRegistration.Name = node.GetHostname(cfg.NodeRegistration.Name) return nil } diff --git a/cmd/kubeadm/app/util/config/nodeconfig_test.go b/cmd/kubeadm/app/util/config/nodeconfig_test.go index dd26b79dd32..dcf679815a0 100644 --- a/cmd/kubeadm/app/util/config/nodeconfig_test.go +++ b/cmd/kubeadm/app/util/config/nodeconfig_test.go @@ -24,19 +24,17 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" - "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" ) const ( - node_v1alpha1YAML = "testdata/conversion/node/v1alpha1.yaml" - node_v1alpha2YAML = "testdata/conversion/node/v1alpha2.yaml" - node_internalYAML = "testdata/conversion/node/internal.yaml" - node_incompleteYAML = "testdata/defaulting/node/incomplete.yaml" - node_defaultedv1alpha1YAML = "testdata/defaulting/node/defaulted_v1alpha1.yaml" - node_defaultedv1alpha2YAML = "testdata/defaulting/node/defaulted_v1alpha2.yaml" - node_invalidYAML = "testdata/validation/invalid_nodecfg.yaml" + node_v1alpha1YAML = "testdata/conversion/node/v1alpha1.yaml" + node_v1alpha2YAML = "testdata/conversion/node/v1alpha2.yaml" + node_internalYAML = "testdata/conversion/node/internal.yaml" + node_incompleteYAML = "testdata/defaulting/node/incomplete.yaml" + node_defaultedYAML = "testdata/defaulting/node/defaulted.yaml" + node_invalidYAML = "testdata/validation/invalid_nodecfg.yaml" ) func TestNodeConfigFileAndDefaultsToInternalConfig(t *testing.T) { @@ -67,16 +65,10 @@ func TestNodeConfigFileAndDefaultsToInternalConfig(t *testing.T) { }, // These tests are reading one file that has only a subset of the fields populated, loading it using NodeConfigFileAndDefaultsToInternalConfig, // and then marshals the internal object to the expected groupVersion - { // v1alpha1 -> default -> validate -> internal -> v1alpha1 - name: "incompleteYAMLToDefaulted", - in: node_incompleteYAML, - out: node_defaultedv1alpha1YAML, - groupVersion: v1alpha1.SchemeGroupVersion, - }, { // v1alpha1 -> default -> validate -> internal -> v1alpha2 name: "incompleteYAMLToDefaulted", in: node_incompleteYAML, - out: node_defaultedv1alpha2YAML, + out: node_defaultedYAML, groupVersion: v1alpha2.SchemeGroupVersion, }, { // v1alpha1 (faulty) -> validation should fail diff --git a/cmd/kubeadm/app/util/config/testdata/conversion/master/internal.yaml b/cmd/kubeadm/app/util/config/testdata/conversion/master/internal.yaml index e6bcefe3baa..3364c14fd6e 100644 --- a/cmd/kubeadm/app/util/config/testdata/conversion/master/internal.yaml +++ b/cmd/kubeadm/app/util/config/testdata/conversion/master/internal.yaml @@ -10,8 +10,17 @@ AuditPolicyConfiguration: LogDir: /var/log/kubernetes/audit LogMaxAge: 2 Path: "" +BootstrapTokens: +- Description: "" + Expires: null + Groups: + - system:bootstrappers:kubeadm:default-node-token + TTL: 24h0m0s + Token: s73ybu.6tw6wnqgp5z0wb77 + Usages: + - signing + - authentication CIImageRepository: "" -CRISocket: /var/run/dockershim.sock CertificatesDir: /etc/kubernetes/pki ClusterName: kubernetes ControllerManagerExtraArgs: null @@ -55,7 +64,7 @@ KubeProxy: minSyncPeriod: 0s syncPeriod: 30s ipvs: - ExcludeCIDRs: null + excludeCIDRs: null minSyncPeriod: 0s scheduler: "" syncPeriod: 30s @@ -140,15 +149,13 @@ Networking: DNSDomain: cluster.local PodSubnet: "" ServiceSubnet: 10.96.0.0/12 -NoTaintMaster: false -NodeName: master-1 +NodeRegistration: + CRISocket: /var/run/dockershim.sock + KubeletExtraArgs: null + Name: master-1 + Taints: + - effect: NoSchedule + key: node-role.kubernetes.io/master SchedulerExtraArgs: null SchedulerExtraVolumes: null -Token: s73ybu.6tw6wnqgp5z0wb77 -TokenGroups: -- system:bootstrappers:kubeadm:default-node-token -TokenTTL: 24h0m0s -TokenUsages: -- signing -- authentication UnifiedControlPlaneImage: "" diff --git a/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1.yaml b/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1.yaml index 75f36c4279f..1ad3415af1d 100644 --- a/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1.yaml +++ b/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1.yaml @@ -53,7 +53,7 @@ kubeProxy: minSyncPeriod: 0s syncPeriod: 30s ipvs: - ExcludeCIDRs: null + excludeCIDRs: null minSyncPeriod: 0s scheduler: "" syncPeriod: 30s diff --git a/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1_without_TypeMeta.yaml b/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1_without_TypeMeta.yaml index e8065236cae..dfaccd79534 100644 --- a/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1_without_TypeMeta.yaml +++ b/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1_without_TypeMeta.yaml @@ -50,7 +50,7 @@ kubeProxy: minSyncPeriod: 0s syncPeriod: 30s ipvs: - ExcludeCIDRs: null + excludeCIDRs: null minSyncPeriod: 0s scheduler: "" syncPeriod: 30s diff --git a/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha2.yaml b/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha2.yaml index d5f30a60566..f8af262b3fb 100644 --- a/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha2.yaml +++ b/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha2.yaml @@ -9,9 +9,16 @@ auditPolicy: logDir: /var/log/kubernetes/audit logMaxAge: 2 path: "" +bootstrapTokens: +- groups: + - system:bootstrappers:kubeadm:default-node-token + token: s73ybu.6tw6wnqgp5z0wb77 + ttl: 24h0m0s + usages: + - signing + - authentication certificatesDir: /etc/kubernetes/pki clusterName: kubernetes -criSocket: /var/run/dockershim.sock etcd: local: dataDir: /var/lib/etcd @@ -47,7 +54,7 @@ kubeProxy: minSyncPeriod: 0s syncPeriod: 30s ipvs: - ExcludeCIDRs: null + excludeCIDRs: null minSyncPeriod: 0s scheduler: "" syncPeriod: 30s @@ -132,12 +139,10 @@ networking: dnsDomain: cluster.local podSubnet: "" serviceSubnet: 10.96.0.0/12 -nodeName: master-1 -token: s73ybu.6tw6wnqgp5z0wb77 -tokenGroups: -- system:bootstrappers:kubeadm:default-node-token -tokenTTL: 24h0m0s -tokenUsages: -- signing -- authentication +nodeRegistration: + criSocket: /var/run/dockershim.sock + name: master-1 + taints: + - effect: NoSchedule + key: node-role.kubernetes.io/master unifiedControlPlaneImage: "" diff --git a/cmd/kubeadm/app/util/config/testdata/conversion/node/internal.yaml b/cmd/kubeadm/app/util/config/testdata/conversion/node/internal.yaml index dce87719dd4..cd820682b78 100644 --- a/cmd/kubeadm/app/util/config/testdata/conversion/node/internal.yaml +++ b/cmd/kubeadm/app/util/config/testdata/conversion/node/internal.yaml @@ -1,5 +1,4 @@ CACertPath: /etc/kubernetes/pki/ca.crt -CRISocket: /var/run/dockershim.sock ClusterName: kubernetes DiscoveryFile: "" DiscoveryTimeout: 5m0s @@ -9,6 +8,10 @@ DiscoveryTokenAPIServers: DiscoveryTokenCACertHashes: null DiscoveryTokenUnsafeSkipCAVerification: true FeatureGates: null -NodeName: master-1 +NodeRegistration: + CRISocket: /var/run/dockershim.sock + KubeletExtraArgs: null + Name: master-1 + Taints: null TLSBootstrapToken: abcdef.0123456789abcdef Token: abcdef.0123456789abcdef diff --git a/cmd/kubeadm/app/util/config/testdata/conversion/node/v1alpha2.yaml b/cmd/kubeadm/app/util/config/testdata/conversion/node/v1alpha2.yaml index 8cf55e5da27..40754a5888b 100644 --- a/cmd/kubeadm/app/util/config/testdata/conversion/node/v1alpha2.yaml +++ b/cmd/kubeadm/app/util/config/testdata/conversion/node/v1alpha2.yaml @@ -1,7 +1,6 @@ apiVersion: kubeadm.k8s.io/v1alpha2 caCertPath: /etc/kubernetes/pki/ca.crt clusterName: kubernetes -criSocket: /var/run/dockershim.sock discoveryFile: "" discoveryTimeout: 5m0s discoveryToken: abcdef.0123456789abcdef @@ -9,6 +8,8 @@ discoveryTokenAPIServers: - kube-apiserver:6443 discoveryTokenUnsafeSkipCAVerification: true kind: NodeConfiguration -nodeName: master-1 +nodeRegistration: + criSocket: /var/run/dockershim.sock + name: master-1 tlsBootstrapToken: abcdef.0123456789abcdef token: abcdef.0123456789abcdef diff --git a/cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml b/cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml index 6cea70575d7..70ea5986e11 100644 --- a/cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml +++ b/cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml @@ -7,9 +7,16 @@ auditPolicy: logDir: /var/log/kubernetes/audit logMaxAge: 2 path: "" +bootstrapTokens: +- groups: + - system:bootstrappers:kubeadm:default-node-token + token: s73ybu.6tw6wnqgp5z0wb77 + ttl: 24h0m0s + usages: + - signing + - authentication certificatesDir: /var/lib/kubernetes/pki clusterName: kubernetes -criSocket: /var/run/criruntime.sock etcd: local: dataDir: /var/lib/etcd @@ -42,7 +49,7 @@ kubeProxy: minSyncPeriod: 0s syncPeriod: 30s ipvs: - ExcludeCIDRs: null + excludeCIDRs: null minSyncPeriod: 0s scheduler: "" syncPeriod: 30s @@ -127,12 +134,10 @@ networking: dnsDomain: cluster.global podSubnet: "" serviceSubnet: 10.196.0.0/12 -nodeName: master-1 -token: s73ybu.6tw6wnqgp5z0wb77 -tokenGroups: -- system:bootstrappers:kubeadm:default-node-token -tokenTTL: 24h0m0s -tokenUsages: -- signing -- authentication +nodeRegistration: + criSocket: /var/run/criruntime.sock + name: master-1 + taints: + - effect: NoSchedule + key: node-role.kubernetes.io/master unifiedControlPlaneImage: "" diff --git a/cmd/kubeadm/app/util/config/testdata/defaulting/master/incomplete.yaml b/cmd/kubeadm/app/util/config/testdata/defaulting/master/incomplete.yaml index 405046ee5d3..e2d6be82bbc 100644 --- a/cmd/kubeadm/app/util/config/testdata/defaulting/master/incomplete.yaml +++ b/cmd/kubeadm/app/util/config/testdata/defaulting/master/incomplete.yaml @@ -1,3 +1,5 @@ +# This file _should_ set TypeMeta, but at some point earlier we supported deserializing MasterConfigurations without TypeMeta, so we need to support that as long as we +# support the v1alpha1 API. In the meantime kubeadm will treat this as v1alpha1 automatically when unmarshalling. api: advertiseAddress: 192.168.2.2 bindPort: 6443 diff --git a/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted_v1alpha2.yaml b/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted.yaml similarity index 83% rename from cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted_v1alpha2.yaml rename to cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted.yaml index 4be5386539d..85c6b9b481c 100644 --- a/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted_v1alpha2.yaml +++ b/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted.yaml @@ -1,7 +1,6 @@ apiVersion: kubeadm.k8s.io/v1alpha2 caCertPath: /etc/kubernetes/pki/ca.crt clusterName: kubernetes -criSocket: /var/run/dockershim.sock discoveryFile: "" discoveryTimeout: 5m0s discoveryToken: abcdef.0123456789abcdef @@ -9,6 +8,8 @@ discoveryTokenAPIServers: - kube-apiserver:6443 discoveryTokenUnsafeSkipCAVerification: true kind: NodeConfiguration -nodeName: thegopher +nodeRegistration: + criSocket: /var/run/dockershim.sock + name: thegopher tlsBootstrapToken: abcdef.0123456789abcdef token: abcdef.0123456789abcdef diff --git a/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted_v1alpha1.yaml b/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted_v1alpha1.yaml deleted file mode 100644 index 5ffc2205fdf..00000000000 --- a/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted_v1alpha1.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: kubeadm.k8s.io/v1alpha1 -caCertPath: /etc/kubernetes/pki/ca.crt -clusterName: kubernetes -criSocket: /var/run/dockershim.sock -discoveryFile: "" -discoveryTimeout: 5m0s -discoveryToken: abcdef.0123456789abcdef -discoveryTokenAPIServers: -- kube-apiserver:6443 -discoveryTokenUnsafeSkipCAVerification: true -kind: NodeConfiguration -nodeName: thegopher -tlsBootstrapToken: abcdef.0123456789abcdef -token: abcdef.0123456789abcdef diff --git a/cmd/kubeadm/app/util/config/testdata/v1alpha1_upgrade/after.yaml b/cmd/kubeadm/app/util/config/testdata/v1alpha1_upgrade/after.yaml index 045df0ad360..a08a94a5402 100644 --- a/cmd/kubeadm/app/util/config/testdata/v1alpha1_upgrade/after.yaml +++ b/cmd/kubeadm/app/util/config/testdata/v1alpha1_upgrade/after.yaml @@ -49,7 +49,7 @@ kubeProxy: minSyncPeriod: 0s syncPeriod: 30s ipvs: - ExcludeCIDRs: null + excludeCIDRs: null minSyncPeriod: 0s scheduler: "" syncPeriod: 30s diff --git a/cmd/kubeadm/app/util/dryrun/dryrun.go b/cmd/kubeadm/app/util/dryrun/dryrun.go index 0dcdb6ccb55..7c18df0672a 100644 --- a/cmd/kubeadm/app/util/dryrun/dryrun.go +++ b/cmd/kubeadm/app/util/dryrun/dryrun.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "io/ioutil" + "path/filepath" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -43,6 +44,13 @@ func NewFileToPrint(realPath, printPath string) FileToPrint { } } +// PrintDryRunFile is a helper method around PrintDryRunFiles +func PrintDryRunFile(fileName, realDir, printDir string, w io.Writer) error { + return PrintDryRunFiles([]FileToPrint{ + NewFileToPrint(filepath.Join(realDir, fileName), filepath.Join(printDir, fileName)), + }, w) +} + // PrintDryRunFiles prints the contents of the FileToPrints given to it to the writer w func PrintDryRunFiles(files []FileToPrint, w io.Writer) error { errs := []error{} diff --git a/cmd/kubeadm/app/util/error.go b/cmd/kubeadm/app/util/error.go index 61327cf5608..4eaf984fd4e 100644 --- a/cmd/kubeadm/app/util/error.go +++ b/cmd/kubeadm/app/util/error.go @@ -22,7 +22,6 @@ import ( "strings" utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/kubernetes/cmd/kubeadm/app/preflight" ) const ( @@ -34,10 +33,6 @@ const ( ValidationExitCode = 3 ) -type debugError interface { - DebugError() (msg string, args []interface{}) -} - // fatal prints the message if set and then exits. func fatal(msg string, code int) { if len(msg) > 0 { @@ -57,16 +52,22 @@ func fatal(msg string, code int) { // This method is generic to the command in use and may be used by non-Kubectl // commands. func CheckErr(err error) { - checkErr("", err, fatal) + checkErr(err, fatal) +} + +// preflightError allows us to know if the error is a preflight error or not +// defining the interface here avoids an import cycle of pulling in preflight into the util package +type preflightError interface { + Preflight() bool } // checkErr formats a given error as a string and calls the passed handleErr -// func with that string and an kubectl exit code. -func checkErr(prefix string, err error, handleErr func(string, int)) { +// func with that string and an exit code. +func checkErr(err error, handleErr func(string, int)) { switch err.(type) { case nil: return - case *preflight.Error: + case preflightError: handleErr(err.Error(), PreFlightExitCode) case utilerrors.Aggregate: handleErr(err.Error(), ValidationExitCode) diff --git a/cmd/kubeadm/app/util/error_test.go b/cmd/kubeadm/app/util/error_test.go index c28a6cc0566..20c4fdb8fb3 100644 --- a/cmd/kubeadm/app/util/error_test.go +++ b/cmd/kubeadm/app/util/error_test.go @@ -19,10 +19,12 @@ package util import ( "fmt" "testing" - - "k8s.io/kubernetes/cmd/kubeadm/app/preflight" ) +type pferror struct{} + +func (p *pferror) Preflight() bool { return true } +func (p *pferror) Error() string { return "" } func TestCheckErr(t *testing.T) { var codeReturned int errHandle := func(err string, code int) { @@ -35,12 +37,12 @@ func TestCheckErr(t *testing.T) { }{ {nil, 0}, {fmt.Errorf(""), DefaultErrorExitCode}, - {&preflight.Error{}, PreFlightExitCode}, + {&pferror{}, PreFlightExitCode}, } for _, rt := range tokenTest { codeReturned = 0 - checkErr("", rt.e, errHandle) + checkErr(rt.e, errHandle) if codeReturned != rt.expected { t.Errorf( "failed checkErr:\n\texpected: %d\n\t actual: %d", diff --git a/cmd/kubeadm/app/util/etcd/BUILD b/cmd/kubeadm/app/util/etcd/BUILD index 8a439c27352..852e914f87f 100644 --- a/cmd/kubeadm/app/util/etcd/BUILD +++ b/cmd/kubeadm/app/util/etcd/BUILD @@ -6,6 +6,7 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd", visibility = ["//visibility:public"], deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util/staticpod:go_default_library", "//vendor/github.com/coreos/etcd/clientv3:go_default_library", @@ -17,7 +18,10 @@ go_test( name = "go_default_test", srcs = ["etcd_test.go"], embed = [":go_default_library"], - deps = ["//cmd/kubeadm/test:go_default_library"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/test:go_default_library", + ], ) filegroup( diff --git a/cmd/kubeadm/app/util/etcd/etcd.go b/cmd/kubeadm/app/util/etcd/etcd.go index a390d670640..3470da6b5c9 100644 --- a/cmd/kubeadm/app/util/etcd/etcd.go +++ b/cmd/kubeadm/app/util/etcd/etcd.go @@ -26,6 +26,7 @@ import ( "github.com/coreos/etcd/clientv3" "github.com/coreos/etcd/pkg/transport" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod" ) @@ -216,3 +217,8 @@ func (c Client) WaitForClusterAvailable(delay time.Duration, retries int, retryI } return false, fmt.Errorf("timeout waiting for etcd cluster to be available") } + +// CheckConfigurationIsHA returns true if the given MasterConfiguration etcd block appears to be an HA configuration. +func CheckConfigurationIsHA(cfg *kubeadmapi.Etcd) bool { + return cfg.External != nil && len(cfg.External.Endpoints) > 1 +} diff --git a/cmd/kubeadm/app/util/etcd/etcd_test.go b/cmd/kubeadm/app/util/etcd/etcd_test.go index 1003f6cf262..58e133eca03 100644 --- a/cmd/kubeadm/app/util/etcd/etcd_test.go +++ b/cmd/kubeadm/app/util/etcd/etcd_test.go @@ -22,6 +22,7 @@ import ( "path/filepath" "testing" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" testutil "k8s.io/kubernetes/cmd/kubeadm/test" ) @@ -83,6 +84,64 @@ spec: 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 @@ -144,6 +203,13 @@ func TestPodManifestHasTLS(t *testing.T) { 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, @@ -195,3 +261,50 @@ func TestPodManifestHasTLS(t *testing.T) { } } } + +func TestCheckConfigurationIsHA(t *testing.T) { + var tests = []struct { + name string + cfg *kubeadmapi.Etcd + expected bool + }{ + { + name: "HA etcd", + cfg: &kubeadmapi.Etcd{ + External: &kubeadmapi.ExternalEtcd{ + Endpoints: []string{"10.100.0.1:2379", "10.100.0.2:2379", "10.100.0.3:2379"}, + }, + }, + expected: true, + }, + { + name: "single External etcd", + cfg: &kubeadmapi.Etcd{ + External: &kubeadmapi.ExternalEtcd{ + Endpoints: []string{"10.100.0.1:2379"}, + }, + }, + expected: false, + }, + { + name: "local etcd", + cfg: &kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{}, + }, + expected: false, + }, + { + name: "empty etcd struct", + cfg: &kubeadmapi.Etcd{}, + expected: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if isHA := CheckConfigurationIsHA(test.cfg); isHA != test.expected { + t.Errorf("expected isHA to be %v, got %v", test.expected, isHA) + } + }) + } +} diff --git a/cmd/kubeadm/app/util/marshal.go b/cmd/kubeadm/app/util/marshal.go index 76bd2ea7f62..aa201cabb7b 100644 --- a/cmd/kubeadm/app/util/marshal.go +++ b/cmd/kubeadm/app/util/marshal.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" clientsetscheme "k8s.io/client-go/kubernetes/scheme" + kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" ) // MarshalToYaml marshals an object into yaml. @@ -34,6 +35,8 @@ func MarshalToYaml(obj runtime.Object, gv schema.GroupVersion) ([]byte, error) { } // MarshalToYamlForCodecs marshals an object into yaml using the specified codec +// TODO: Is specifying the gv really needed here? +// TODO: Can we support json out of the box easily here? func MarshalToYamlForCodecs(obj runtime.Object, gv schema.GroupVersion, codecs serializer.CodecFactory) ([]byte, error) { mediaType := "application/yaml" info, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), mediaType) @@ -51,6 +54,8 @@ func UnmarshalFromYaml(buffer []byte, gv schema.GroupVersion) (runtime.Object, e } // UnmarshalFromYamlForCodecs unmarshals yaml into an object using the specified codec +// TODO: Is specifying the gv really needed here? +// TODO: Can we support json out of the box easily here? func UnmarshalFromYamlForCodecs(buffer []byte, gv schema.GroupVersion, codecs serializer.CodecFactory) (runtime.Object, error) { mediaType := "application/yaml" info, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), mediaType) @@ -62,6 +67,40 @@ func UnmarshalFromYamlForCodecs(buffer []byte, gv schema.GroupVersion, codecs se return runtime.Decode(decoder, buffer) } +// GroupVersionKindFromBytes parses the bytes and returns the gvk +func GroupVersionKindFromBytes(buffer []byte, codecs serializer.CodecFactory) (schema.GroupVersionKind, error) { + + decoded, err := LoadYAML(buffer) + if err != nil { + return schema.EmptyObjectKind.GroupVersionKind(), fmt.Errorf("unable to decode config from bytes: %v", err) + } + kindStr, apiVersionStr := "", "" + + // As there was a bug in kubeadm v1.10 and earlier that made the YAML uploaded to the cluster configmap NOT have metav1.TypeMeta information + // we need to populate this here manually. If kind or apiVersion is empty, we know the apiVersion is v1alpha1, as by the time kubeadm had this bug, + // it could only write + // TODO: Remove this "hack" in v1.12 when we know the ConfigMap always contains v1alpha2 content written by kubeadm v1.11. Also, we will drop support for + // v1alpha1 in v1.12 + kind := decoded["kind"] + apiVersion := decoded["apiVersion"] + if kind == nil || len(kind.(string)) == 0 { + kindStr = "MasterConfiguration" + } else { + kindStr = kind.(string) + } + if apiVersion == nil || len(apiVersion.(string)) == 0 { + apiVersionStr = kubeadmapiv1alpha1.SchemeGroupVersion.String() + } else { + apiVersionStr = apiVersion.(string) + } + gv, err := schema.ParseGroupVersion(apiVersionStr) + if err != nil { + return schema.EmptyObjectKind.GroupVersionKind(), fmt.Errorf("unable to parse apiVersion: %v", err) + } + + return gv.WithKind(kindStr), nil +} + // LoadYAML is a small wrapper around go-yaml that ensures all nested structs are map[string]interface{} instead of map[interface{}]interface{}. func LoadYAML(bytes []byte) (map[string]interface{}, error) { var decoded map[interface{}]interface{} diff --git a/cmd/kubeadm/app/util/staticpod/utils.go b/cmd/kubeadm/app/util/staticpod/utils.go index d09518e11ab..76d2ecb326d 100644 --- a/cmd/kubeadm/app/util/staticpod/utils.go +++ b/cmd/kubeadm/app/util/staticpod/utils.go @@ -102,7 +102,7 @@ func ComponentProbe(cfg *kubeadmapi.MasterConfiguration, componentName string, p func EtcdProbe(cfg *kubeadmapi.MasterConfiguration, componentName string, port int, certsDir string, CACertName string, CertName string, KeyName string) *v1.Probe { tlsFlags := fmt.Sprintf("--cacert=%[1]s/%[2]s --cert=%[1]s/%[3]s --key=%[1]s/%[4]s", certsDir, CACertName, CertName, KeyName) // etcd pod is alive if a linearizable get succeeds. - cmd := fmt.Sprintf("ETCDCTL_API=3 etcdctl --endpoints=%s:%d %s get foo", GetProbeAddress(cfg, componentName), port, tlsFlags) + cmd := fmt.Sprintf("ETCDCTL_API=3 etcdctl --endpoints=https://[%s]:%d %s get foo", GetProbeAddress(cfg, componentName), port, tlsFlags) return &v1.Probe{ Handler: v1.Handler{ @@ -254,6 +254,13 @@ func GetProbeAddress(cfg *kubeadmapi.MasterConfiguration, componentName string) } // Return the IP if the URL contains an address instead of a name. if ip := net.ParseIP(parsedURL.Hostname()); ip != nil { + // etcdctl doesn't support auto-converting zero addresses into loopback addresses + if ip.Equal(net.IPv4zero) { + return "127.0.0.1" + } + if ip.Equal(net.IPv6zero) { + return net.IPv6loopback.String() + } return ip.String() } // Use the local resolver to try resolving the name within the URL. diff --git a/cmd/kubeadm/app/util/staticpod/utils_test.go b/cmd/kubeadm/app/util/staticpod/utils_test.go index 96c3d8dc419..815e8434d89 100644 --- a/cmd/kubeadm/app/util/staticpod/utils_test.go +++ b/cmd/kubeadm/app/util/staticpod/utils_test.go @@ -219,7 +219,79 @@ func TestEtcdProbe(t *testing.T) { cacert: "ca1", cert: "cert1", key: "key1", - expected: "ETCDCTL_API=3 etcdctl --endpoints=1.2.3.4:1 --cacert=secretsA/ca1 --cert=secretsA/cert1 --key=secretsA/key1 get foo", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[1.2.3.4]:1 --cacert=secretsA/ca1 --cert=secretsA/cert1 --key=secretsA/key1 get foo", + }, + { + name: "valid etcd probe using listen-client-urls unspecified IPv6 address", + cfg: &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + ExtraArgs: map[string]string{ + "listen-client-urls": "http://[0:0:0:0:0:0:0:0]:2379"}, + }, + }, + }, + component: kubeadmconstants.Etcd, + port: 1, + certsDir: "secretsB", + cacert: "ca2", + cert: "cert2", + key: "key2", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[::1]:1 --cacert=secretsB/ca2 --cert=secretsB/cert2 --key=secretsB/key2 get foo", + }, + { + name: "valid etcd probe using listen-client-urls unspecified IPv6 address 2", + cfg: &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + ExtraArgs: map[string]string{ + "listen-client-urls": "http://[::0:0]:2379"}, + }, + }, + }, + component: kubeadmconstants.Etcd, + port: 1, + certsDir: "secretsB", + cacert: "ca2", + cert: "cert2", + key: "key2", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[::1]:1 --cacert=secretsB/ca2 --cert=secretsB/cert2 --key=secretsB/key2 get foo", + }, + { + name: "valid etcd probe using listen-client-urls unspecified IPv6 address 3", + cfg: &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + ExtraArgs: map[string]string{ + "listen-client-urls": "http://[::]:2379"}, + }, + }, + }, + component: kubeadmconstants.Etcd, + port: 1, + certsDir: "secretsB", + cacert: "ca2", + cert: "cert2", + key: "key2", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[::1]:1 --cacert=secretsB/ca2 --cert=secretsB/cert2 --key=secretsB/key2 get foo", + }, + { + name: "valid etcd probe using listen-client-urls unspecified IPv4 address", + cfg: &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + ExtraArgs: map[string]string{ + "listen-client-urls": "http://1.2.3.4:2379,http://4.3.2.1:2379"}, + }, + }, + }, + component: kubeadmconstants.Etcd, + port: 1, + certsDir: "secretsA", + cacert: "ca1", + cert: "cert1", + key: "key1", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[1.2.3.4]:1 --cacert=secretsA/ca1 --cert=secretsA/cert1 --key=secretsA/key1 get foo", }, { name: "valid etcd probe using listen-client-urls IPv6 addresses", @@ -237,7 +309,7 @@ func TestEtcdProbe(t *testing.T) { cacert: "ca2", cert: "cert2", key: "key2", - expected: "ETCDCTL_API=3 etcdctl --endpoints=2001:db8::1:1 --cacert=secretsB/ca2 --cert=secretsB/cert2 --key=secretsB/key2 get foo", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[2001:db8::1]:1 --cacert=secretsB/ca2 --cert=secretsB/cert2 --key=secretsB/key2 get foo", }, { name: "valid IPv4 etcd probe using hostname for listen-client-urls", @@ -255,7 +327,7 @@ func TestEtcdProbe(t *testing.T) { cacert: "ca3", cert: "cert3", key: "key3", - expected: "ETCDCTL_API=3 etcdctl --endpoints=127.0.0.1:1 --cacert=secretsC/ca3 --cert=secretsC/cert3 --key=secretsC/key3 get foo", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[127.0.0.1]:1 --cacert=secretsC/ca3 --cert=secretsC/cert3 --key=secretsC/key3 get foo", }, } for _, rt := range tests { diff --git a/cmd/kubeadm/app/util/token/BUILD b/cmd/kubeadm/app/util/token/BUILD deleted file mode 100644 index d16eb5018d5..00000000000 --- a/cmd/kubeadm/app/util/token/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["tokens_test.go"], - embed = [":go_default_library"], - deps = ["//cmd/kubeadm/app/apis/kubeadm:go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["tokens.go"], - importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util/token", - deps = ["//cmd/kubeadm/app/apis/kubeadm:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/cmd/kubeadm/app/util/token/tokens.go b/cmd/kubeadm/app/util/token/tokens.go deleted file mode 100644 index 6be9260005e..00000000000 --- a/cmd/kubeadm/app/util/token/tokens.go +++ /dev/null @@ -1,125 +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 token - -import ( - "bufio" - "crypto/rand" - "fmt" - "regexp" - - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" -) - -const ( - // TokenIDBytes defines a number of bytes used for a token id - TokenIDBytes = 6 - // TokenSecretBytes defines a number of bytes used for a secret - TokenSecretBytes = 16 -) - -var ( - // TokenIDRegexpString defines token's id regular expression pattern - TokenIDRegexpString = "^([a-z0-9]{6})$" - // TokenIDRegexp is a compiled regular expression of TokenIDRegexpString - TokenIDRegexp = regexp.MustCompile(TokenIDRegexpString) - // TokenRegexpString defines id.secret regular expression pattern - TokenRegexpString = "^([a-z0-9]{6})\\.([a-z0-9]{16})$" - // TokenRegexp is a compiled regular expression of TokenRegexpString - TokenRegexp = regexp.MustCompile(TokenRegexpString) -) - -const validBootstrapTokenChars = "0123456789abcdefghijklmnopqrstuvwxyz" - -func randBytes(length int) (string, error) { - // len("0123456789abcdefghijklmnopqrstuvwxyz") = 36 which doesn't evenly divide - // the possible values of a byte: 256 mod 36 = 4. Discard any random bytes we - // read that are >= 252 so the bytes we evenly divide the character set. - const maxByteValue = 252 - - var ( - b byte - err error - token = make([]byte, length) - ) - - reader := bufio.NewReaderSize(rand.Reader, length*2) - for i := range token { - for { - if b, err = reader.ReadByte(); err != nil { - return "", err - } - if b < maxByteValue { - break - } - } - - token[i] = validBootstrapTokenChars[int(b)%len(validBootstrapTokenChars)] - } - - return string(token), nil -} - -// GenerateToken generates a new token with a token ID that is valid as a -// Kubernetes DNS label. -// For more info, see kubernetes/pkg/util/validation/validation.go. -func GenerateToken() (string, error) { - tokenID, err := randBytes(TokenIDBytes) - if err != nil { - return "", err - } - - tokenSecret, err := randBytes(TokenSecretBytes) - if err != nil { - return "", err - } - - return fmt.Sprintf("%s.%s", tokenID, tokenSecret), nil -} - -// ParseTokenID tries and parse a valid token ID from a string. -// An error is returned in case of failure. -func ParseTokenID(s string) error { - if !TokenIDRegexp.MatchString(s) { - return fmt.Errorf("token ID [%q] was not of form [%q]", s, TokenIDRegexpString) - } - return nil -} - -// ParseToken tries and parse a valid token from a string. -// A token ID and token secret are returned in case of success, an error otherwise. -func ParseToken(s string) (string, string, error) { - split := TokenRegexp.FindStringSubmatch(s) - if len(split) != 3 { - return "", "", fmt.Errorf("token [%q] was not of form [%q]", s, TokenRegexpString) - } - return split[1], split[2], nil -} - -// BearerToken returns a string representation of the passed token. -func BearerToken(d *kubeadmapi.TokenDiscovery) string { - return fmt.Sprintf("%s.%s", d.ID, d.Secret) -} - -// ValidateToken validates whether a token is well-formed. -// In case it's not, the corresponding error is returned as well. -func ValidateToken(d *kubeadmapi.TokenDiscovery) (bool, error) { - if _, _, err := ParseToken(d.ID + "." + d.Secret); err != nil { - return false, err - } - return true, nil -} diff --git a/cmd/kubeadm/app/util/token/tokens_test.go b/cmd/kubeadm/app/util/token/tokens_test.go deleted file mode 100644 index 4146a027036..00000000000 --- a/cmd/kubeadm/app/util/token/tokens_test.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 token - -import ( - "testing" - - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" -) - -func TestTokenParse(t *testing.T) { - var tests = []struct { - token string - expected bool - }{ - {token: "1234567890123456789012", expected: false}, // invalid parcel size - {token: "12345.1234567890123456", expected: false}, // invalid parcel size - {token: ".1234567890123456", expected: false}, // invalid parcel size - {token: "123456:1234567890.123456", expected: false}, // invalid separation - {token: "abcdef:1234567890123456", expected: false}, // invalid separation - {token: "Abcdef.1234567890123456", expected: false}, // invalid token id - {token: "123456.AABBCCDDEEFFGGHH", expected: false}, // invalid token secret - {token: "abcdef.1234567890123456", expected: true}, - {token: "123456.aabbccddeeffgghh", expected: true}, - } - - for _, rt := range tests { - _, _, actual := ParseToken(rt.token) - if (actual == nil) != rt.expected { - t.Errorf( - "failed ParseToken for this token: [%s]\n\texpected: %t\n\t actual: %t", - rt.token, - rt.expected, - (actual == nil), - ) - } - } - -} - -func TestParseTokenID(t *testing.T) { - var tests = []struct { - tokenID string - expected bool - }{ - {tokenID: "", expected: false}, - {tokenID: "1234567890123456789012", expected: false}, - {tokenID: "12345", expected: false}, - {tokenID: "Abcdef", expected: false}, - {tokenID: "abcdef", expected: true}, - {tokenID: "123456", expected: true}, - } - for _, rt := range tests { - actual := ParseTokenID(rt.tokenID) - if (actual == nil) != rt.expected { - t.Errorf( - "failed ParseTokenID for this token ID: [%s]\n\texpected: %t\n\t actual: %t", - rt.tokenID, - rt.expected, - (actual == nil), - ) - } - } -} - -func TestValidateToken(t *testing.T) { - var tests = []struct { - token *kubeadmapi.TokenDiscovery - expected bool - }{ - {token: &kubeadmapi.TokenDiscovery{ID: "", Secret: ""}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "1234567890123456789012", Secret: ""}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "", Secret: "1234567890123456789012"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "12345", Secret: "1234567890123456"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "Abcdef", Secret: "1234567890123456"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "123456", Secret: "AABBCCDDEEFFGGHH"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "abc*ef", Secret: "1234567890123456"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "abcdef", Secret: "123456789*123456"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "abcdef", Secret: "1234567890123456"}, expected: true}, - {token: &kubeadmapi.TokenDiscovery{ID: "123456", Secret: "aabbccddeeffgghh"}, expected: true}, - {token: &kubeadmapi.TokenDiscovery{ID: "abc456", Secret: "1234567890123456"}, expected: true}, - {token: &kubeadmapi.TokenDiscovery{ID: "abcdef", Secret: "123456ddeeffgghh"}, expected: true}, - } - for _, rt := range tests { - valid, actual := ValidateToken(rt.token) - if (actual == nil) != rt.expected { - t.Errorf( - "failed ValidateToken for this token ID: [%s]\n\texpected: %t\n\t actual: %t", - rt.token, - rt.expected, - (actual == nil), - ) - } - if (valid == true) != rt.expected { - t.Errorf( - "failed ValidateToken for this token ID: [%s]\n\texpected: %t\n\t actual: %t", - rt.token, - rt.expected, - (actual == nil), - ) - } - } -} - -func TestGenerateToken(t *testing.T) { - token, err := GenerateToken() - if err != nil { - t.Fatalf("GenerateToken returned an unexpected error: %+v", err) - } - tokenID, tokenSecret, err := ParseToken(token) - if err != nil { - t.Fatalf("GenerateToken returned an unexpected error: %+v", err) - } - if len(tokenID) != 6 { - t.Errorf("failed GenerateToken first part length:\n\texpected: 6\n\t actual: %d", len(tokenID)) - } - if len(tokenSecret) != 16 { - t.Errorf("failed GenerateToken second part length:\n\texpected: 16\n\t actual: %d", len(tokenSecret)) - } -} - -func TestRandBytes(t *testing.T) { - var randTest = []int{ - 0, - 1, - 2, - 3, - 100, - } - - for _, rt := range randTest { - actual, err := randBytes(rt) - if err != nil { - t.Errorf("failed randBytes: %v", err) - } - if len(actual) != rt { - t.Errorf("failed randBytes:\n\texpected: %d\n\t actual: %d\n", rt, len(actual)) - } - } -} - -func TestBearerToken(t *testing.T) { - var tests = []struct { - token *kubeadmapi.TokenDiscovery - expected string - }{ - {token: &kubeadmapi.TokenDiscovery{ID: "foo", Secret: "bar"}, expected: "foo.bar"}, // should use default - } - for _, rt := range tests { - actual := BearerToken(rt.token) - if actual != rt.expected { - t.Errorf( - "failed BearerToken:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual, - ) - } - } -} diff --git a/cmd/kubeadm/test/util.go b/cmd/kubeadm/test/util.go index fdfdae5592b..afe20702cd0 100644 --- a/cmd/kubeadm/test/util.go +++ b/cmd/kubeadm/test/util.go @@ -57,9 +57,11 @@ func SetupMasterConfigurationFile(t *testing.T, tmpdir string, cfg *kubeadmapi.M kind: MasterConfiguration certificatesDir: {{.CertificatesDir}} api: - advertiseAddress: {{.API.AdvertiseAddress}} - bindPort: {{.API.BindPort}} - nodeName: {{.NodeName}} + advertiseAddress: {{.API.AdvertiseAddress}} + bindPort: {{.API.BindPort}} + nodeRegistration: + name: {{.NodeRegistration.Name}} + kubernetesVersion: v1.10.0 `))) f, err := os.Create(cfgPath) diff --git a/cmd/kubelet/app/BUILD b/cmd/kubelet/app/BUILD index af2fcc09ad5..b2f3efbc793 100644 --- a/cmd/kubelet/app/BUILD +++ b/cmd/kubelet/app/BUILD @@ -110,6 +110,7 @@ go_library( "//pkg/util/io:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/node:go_default_library", + "//pkg/util/nsenter:go_default_library", "//pkg/util/oom:go_default_library", "//pkg/util/rlimit:go_default_library", "//pkg/version:go_default_library", @@ -170,6 +171,7 @@ go_library( "//vendor/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/client-go/util/cert:go_default_library", "//vendor/k8s.io/client-go/util/certificate:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", ] + select({ "@io_bazel_rules_go//go/platform:linux": [ "//vendor/golang.org/x/exp/inotify:go_default_library", diff --git a/cmd/kubelet/app/options/container_runtime.go b/cmd/kubelet/app/options/container_runtime.go index 2f04036bffb..d07cfb699f4 100644 --- a/cmd/kubelet/app/options/container_runtime.go +++ b/cmd/kubelet/app/options/container_runtime.go @@ -45,12 +45,13 @@ func NewContainerRuntimeOptions() *config.ContainerRuntimeOptions { } return &config.ContainerRuntimeOptions{ - ContainerRuntime: kubetypes.DockerContainerRuntime, - DockerEndpoint: dockerEndpoint, - DockershimRootDirectory: "/var/lib/dockershim", - DockerDisableSharedPID: true, - PodSandboxImage: defaultPodSandboxImage, - ImagePullProgressDeadline: metav1.Duration{Duration: 1 * time.Minute}, - ExperimentalDockershim: false, + ContainerRuntime: kubetypes.DockerContainerRuntime, + RedirectContainerStreaming: false, + DockerEndpoint: dockerEndpoint, + DockershimRootDirectory: "/var/lib/dockershim", + DockerDisableSharedPID: true, + PodSandboxImage: defaultPodSandboxImage, + ImagePullProgressDeadline: metav1.Duration{Duration: 1 * time.Minute}, + ExperimentalDockershim: false, } } diff --git a/cmd/kubelet/app/options/options.go b/cmd/kubelet/app/options/options.go index 82d319e21d1..048637bdac2 100644 --- a/cmd/kubelet/app/options/options.go +++ b/cmd/kubelet/app/options/options.go @@ -169,6 +169,9 @@ type KubeletFlags struct { // bootstrapCheckpointPath is the path to the directory containing pod checkpoints to // run on restore BootstrapCheckpointPath string + // NodeStatusMaxImages caps the number of images reported in Node.Status.Images. + // This is an experimental, short-term flag to help with node scalability. + NodeStatusMaxImages int32 // DEPRECATED FLAGS // minimumGCAge is the minimum age for a finished container before it is @@ -192,8 +195,6 @@ type KubeletFlags struct { // This flag, if set, instructs the kubelet to keep volumes from terminated pods mounted to the node. // This can be useful for debugging volume related issues. KeepTerminatedPodVolumes bool - // enable gathering custom metrics. - EnableCustomMetrics bool // allowPrivileged enables containers to request privileged mode. // Defaults to true. AllowPrivileged bool @@ -231,19 +232,19 @@ func NewKubeletFlags() *KubeletFlags { RegisterSchedulable: true, ExperimentalKernelMemcgNotification: false, RemoteRuntimeEndpoint: remoteRuntimeEndpoint, - // TODO(#54161:v1.11.0): Remove --enable-custom-metrics flag, it is deprecated. - EnableCustomMetrics: false, - NodeLabels: make(map[string]string), - VolumePluginDir: "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/", - RegisterNode: true, - SeccompProfileRoot: filepath.Join(defaultRootDir, "seccomp"), - HostNetworkSources: []string{kubetypes.AllSource}, - HostPIDSources: []string{kubetypes.AllSource}, - HostIPCSources: []string{kubetypes.AllSource}, + NodeLabels: make(map[string]string), + VolumePluginDir: "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/", + RegisterNode: true, + SeccompProfileRoot: filepath.Join(defaultRootDir, "seccomp"), + HostNetworkSources: []string{kubetypes.AllSource}, + HostPIDSources: []string{kubetypes.AllSource}, + HostIPCSources: []string{kubetypes.AllSource}, // TODO(#56523:v1.12.0): Remove --cadvisor-port, it has been deprecated since v1.10 CAdvisorPort: 0, // TODO(#58010:v1.13.0): Remove --allow-privileged, it is deprecated AllowPrivileged: true, + // prior to the introduction of this flag, there was a hardcoded cap of 50 images + NodeStatusMaxImages: 50, } } @@ -255,6 +256,9 @@ func ValidateKubeletFlags(f *KubeletFlags) error { if f.CAdvisorPort != 0 && utilvalidation.IsValidPortNum(int(f.CAdvisorPort)) != nil { return fmt.Errorf("invalid configuration: CAdvisorPort (--cadvisor-port) %v must be between 0 and 65535, inclusive", f.CAdvisorPort) } + if f.NodeStatusMaxImages < -1 { + return fmt.Errorf("invalid configuration: NodeStatusMaxImages (--node-status-max-images) must be -1 or greater") + } return nil } @@ -357,7 +361,7 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { fs.BoolVar(&f.RunOnce, "runonce", f.RunOnce, "If true, exit after spawning pods from static pod files or remote urls. Exclusive with --enable-server") fs.BoolVar(&f.EnableServer, "enable-server", f.EnableServer, "Enable the Kubelet's server") - fs.StringVar(&f.HostnameOverride, "hostname-override", f.HostnameOverride, "If non-empty, will use this string as identification instead of the actual hostname.") + fs.StringVar(&f.HostnameOverride, "hostname-override", f.HostnameOverride, "If non-empty, will use this string as identification instead of the actual hostname. If --cloud-provider is set, the cloud provider determines the name of the node (consult cloud provider documentation to determine if and how the hostname is used).") fs.StringVar(&f.NodeIP, "node-ip", f.NodeIP, "IP address of the node. If set, kubelet will use this IP address for the node") @@ -366,7 +370,7 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { fs.StringVar(&f.CertDirectory, "cert-dir", f.CertDirectory, "The directory where the TLS certs are located. "+ "If --tls-cert-file and --tls-private-key-file are provided, this flag will be ignored.") - fs.StringVar(&f.CloudProvider, "cloud-provider", f.CloudProvider, "The provider for cloud services. Specify empty string for running with no cloud provider.") + fs.StringVar(&f.CloudProvider, "cloud-provider", f.CloudProvider, "The provider for cloud services. Specify empty string for running with no cloud provider. If set, the cloud provider determines the name of the node (consult cloud provider documentation to determine if and how the hostname is used).") fs.StringVar(&f.CloudConfigFile, "cloud-config", f.CloudConfigFile, "The path to the cloud provider configuration file. Empty string for no configuration file.") fs.StringVar(&f.RootDirectory, "root-dir", f.RootDirectory, "Directory path for managing kubelet files (volume mounts,etc).") @@ -379,7 +383,7 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { // EXPERIMENTAL FLAGS fs.StringVar(&f.ExperimentalMounterPath, "experimental-mounter-path", f.ExperimentalMounterPath, "[Experimental] Path of mounter binary. Leave empty to use the default mount.") - fs.StringSliceVar(&f.AllowedUnsafeSysctls, "experimental-allowed-unsafe-sysctls", f.AllowedUnsafeSysctls, "Comma-separated whitelist of unsafe sysctls or unsafe sysctl patterns (ending in *). Use these at your own risk.") + fs.StringSliceVar(&f.AllowedUnsafeSysctls, "allowed-unsafe-sysctls", f.AllowedUnsafeSysctls, "Comma-separated whitelist of unsafe sysctls or unsafe sysctl patterns (ending in *). Use these at your own risk. Sysctls feature gate is enabled by default.") fs.BoolVar(&f.ExperimentalKernelMemcgNotification, "experimental-kernel-memcg-notification", f.ExperimentalKernelMemcgNotification, "If enabled, the kubelet will integrate with the kernel memcg notification to determine if memory eviction thresholds are crossed rather than polling.") fs.StringVar(&f.RemoteRuntimeEndpoint, "container-runtime-endpoint", f.RemoteRuntimeEndpoint, "[Experimental] The endpoint of remote runtime service. Currently unix socket is supported on Linux, and tcp is supported on windows. Examples:'unix:///var/run/dockershim.sock', 'tcp://localhost:3735'") fs.StringVar(&f.RemoteImageEndpoint, "image-service-endpoint", f.RemoteImageEndpoint, "[Experimental] The endpoint of remote image service. If not specified, it will be the same with container-runtime-endpoint by default. Currently unix socket is supported on Linux, and tcp is supported on windows. Examples:'unix:///var/run/dockershim.sock', 'tcp://localhost:3735'") @@ -392,6 +396,7 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { fs.BoolVar(&f.ExitOnLockContention, "exit-on-lock-contention", f.ExitOnLockContention, "Whether kubelet should exit upon lock-file contention.") fs.StringVar(&f.SeccompProfileRoot, "seccomp-profile-root", f.SeccompProfileRoot, " Directory path for seccomp profiles.") fs.StringVar(&f.BootstrapCheckpointPath, "bootstrap-checkpoint-path", f.BootstrapCheckpointPath, " Path to to the directory where the checkpoints are stored") + fs.Int32Var(&f.NodeStatusMaxImages, "node-status-max-images", f.NodeStatusMaxImages, " The maximum number of images to report in Node.Status.Images. If -1 is specified, no cap will be applied. Default: 50") // DEPRECATED FLAGS fs.StringVar(&f.BootstrapKubeconfig, "experimental-bootstrap-kubeconfig", f.BootstrapKubeconfig, "") @@ -412,9 +417,6 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { fs.MarkDeprecated("non-masquerade-cidr", "will be removed in a future version") fs.BoolVar(&f.KeepTerminatedPodVolumes, "keep-terminated-pod-volumes", f.KeepTerminatedPodVolumes, "Keep terminated pod volumes mounted to the node after the pod terminates. Can be useful for debugging volume related issues.") fs.MarkDeprecated("keep-terminated-pod-volumes", "will be removed in a future version") - // TODO(#54161:v1.11.0): Remove --enable-custom-metrics flag, it is deprecated. - fs.BoolVar(&f.EnableCustomMetrics, "enable-custom-metrics", f.EnableCustomMetrics, "Support for gathering custom metrics.") - fs.MarkDeprecated("enable-custom-metrics", "will be removed in a future version") // TODO(#58010:v1.13.0): Remove --allow-privileged, it is deprecated fs.BoolVar(&f.AllowPrivileged, "allow-privileged", f.AllowPrivileged, "If true, allow containers to request privileged mode. Default: true") fs.MarkDeprecated("allow-privileged", "will be removed in a future version") @@ -487,13 +489,16 @@ func AddKubeletConfigFlags(mainfs *pflag.FlagSet, c *kubeletconfig.KubeletConfig "If --tls-cert-file and --tls-private-key-file are not provided, a self-signed certificate and key "+ "are generated for the public address and saved to the directory passed to --cert-dir.") fs.StringVar(&c.TLSPrivateKeyFile, "tls-private-key-file", c.TLSPrivateKeyFile, "File containing x509 private key matching --tls-cert-file.") + + tlsCipherPossibleValues := flag.TLSCipherPossibleValues() fs.StringSliceVar(&c.TLSCipherSuites, "tls-cipher-suites", c.TLSCipherSuites, "Comma-separated list of cipher suites for the server. "+ - "Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). "+ - "If omitted, the default Go cipher suites will be used") + "If omitted, the default Go cipher suites will be used. "+ + "Possible values: "+strings.Join(tlsCipherPossibleValues, ",")) + tlsPossibleVersions := flag.TLSPossibleVersions() fs.StringVar(&c.TLSMinVersion, "tls-min-version", c.TLSMinVersion, "Minimum TLS version supported. "+ - "Value must match version names from https://golang.org/pkg/crypto/tls/#pkg-constants.") + "Possible values: "+strings.Join(tlsPossibleVersions, ", ")) fs.BoolVar(&c.RotateCertificates, "rotate-certificates", c.RotateCertificates, " Auto rotate the kubelet client certificates by requesting new certificates from the kube-apiserver when the certificate expiration approaches.") fs.Int32Var(&c.RegistryPullQPS, "registry-qps", c.RegistryPullQPS, "If > 0, limit registry pull QPS to this value. If 0, unlimited.") diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index ca13dc51d30..bcd5ea562ae 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -91,10 +91,12 @@ import ( kubeio "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" nodeutil "k8s.io/kubernetes/pkg/util/node" + "k8s.io/kubernetes/pkg/util/nsenter" "k8s.io/kubernetes/pkg/util/oom" "k8s.io/kubernetes/pkg/util/rlimit" "k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/pkg/version/verflag" + "k8s.io/utils/exec" ) const ( @@ -361,11 +363,12 @@ func UnsecuredDependencies(s *options.KubeletServer) (*kubelet.Dependencies, err var writer kubeio.Writer = &kubeio.StdWriter{} if s.Containerized { glog.V(2).Info("Running kubelet in containerized mode") - mounter, err = mount.NewNsenterMounter() + ne, err := nsenter.NewNsenter(nsenter.DefaultHostRootFsPath, exec.New()) if err != nil { return nil, err } - writer = &kubeio.NsenterWriter{} + mounter = mount.NewNsenterMounter(s.RootDirectory, ne) + writer = kubeio.NewNsenterWriter(ne) } var dockerClientConfig *dockershim.ClientConfig @@ -718,7 +721,7 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan glog.Warning(err) } - if err := RunKubelet(&s.KubeletFlags, &s.KubeletConfiguration, kubeDeps, s.RunOnce, stopCh); err != nil { + if err := RunKubelet(&s.KubeletFlags, &s.KubeletConfiguration, kubeDeps, s.RunOnce); err != nil { return err } @@ -884,7 +887,7 @@ func addChaosToClientConfig(s *options.KubeletServer, config *restclient.Config) // 2 Kubelet binary // 3 Standalone 'kubernetes' binary // Eventually, #2 will be replaced with instances of #3 -func RunKubelet(kubeFlags *options.KubeletFlags, kubeCfg *kubeletconfiginternal.KubeletConfiguration, kubeDeps *kubelet.Dependencies, runOnce bool, stopCh <-chan struct{}) error { +func RunKubelet(kubeFlags *options.KubeletFlags, kubeCfg *kubeletconfiginternal.KubeletConfiguration, kubeDeps *kubelet.Dependencies, runOnce bool) error { hostname := nodeutil.GetHostname(kubeFlags.HostnameOverride) // Query the cloud provider for our node name, default to hostname if kubeDeps.Cloud == nil nodeName, err := getNodeName(kubeDeps.Cloud, hostname) @@ -958,7 +961,7 @@ func RunKubelet(kubeFlags *options.KubeletFlags, kubeCfg *kubeletconfiginternal. kubeFlags.NodeLabels, kubeFlags.SeccompProfileRoot, kubeFlags.BootstrapCheckpointPath, - stopCh) + kubeFlags.NodeStatusMaxImages) if err != nil { return fmt.Errorf("failed to create kubelet: %v", err) } @@ -1043,7 +1046,7 @@ func CreateAndInitKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, nodeLabels map[string]string, seccompProfileRoot string, bootstrapCheckpointPath string, - stopCh <-chan struct{}) (k kubelet.Bootstrap, err error) { + nodeStatusMaxImages int32) (k kubelet.Bootstrap, err error) { // TODO: block until all sources have delivered at least one update to the channel, or break the sync loop // up into "per source" synchronizations @@ -1077,7 +1080,7 @@ func CreateAndInitKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, nodeLabels, seccompProfileRoot, bootstrapCheckpointPath, - stopCh) + nodeStatusMaxImages) if err != nil { return nil, err } @@ -1170,30 +1173,17 @@ func RunDockershim(f *options.KubeletFlags, c *kubeletconfiginternal.KubeletConf SupportedPortForwardProtocols: streaming.DefaultConfig.SupportedPortForwardProtocols, } + // Standalone dockershim will always start the local streaming server. ds, err := dockershim.NewDockerService(dockerClientConfig, r.PodSandboxImage, streamingConfig, &pluginSettings, - f.RuntimeCgroups, c.CgroupDriver, r.DockershimRootDirectory, r.DockerDisableSharedPID) + f.RuntimeCgroups, c.CgroupDriver, r.DockershimRootDirectory, r.DockerDisableSharedPID, true /*startLocalStreamingServer*/) if err != nil { return err } glog.V(2).Infof("Starting the GRPC server for the docker CRI shim.") server := dockerremote.NewDockerServer(f.RemoteRuntimeEndpoint, ds) - if err := server.Start(stopCh); err != nil { - return err - } - - streamingServer := &http.Server{ - Addr: net.JoinHostPort(c.Address, strconv.Itoa(int(c.Port))), - Handler: ds, - } - - go func() { - <-stopCh - streamingServer.Shutdown(context.Background()) - }() - - // Start the streaming server - if err := streamingServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { + if err := server.Start(); err != nil { return err } + <-stopCh return nil } diff --git a/docs/.generated_docs b/docs/.generated_docs index 4cbec27e77f..0fd748bcfc2 100644 --- a/docs/.generated_docs +++ b/docs/.generated_docs @@ -9,7 +9,7 @@ docs/admin/kubeadm_alpha.md docs/admin/kubeadm_alpha_phase.md docs/admin/kubeadm_alpha_phase_addon.md docs/admin/kubeadm_alpha_phase_addon_all.md -docs/admin/kubeadm_alpha_phase_addon_kube-dns.md +docs/admin/kubeadm_alpha_phase_addon_coredns.md docs/admin/kubeadm_alpha_phase_addon_kube-proxy.md docs/admin/kubeadm_alpha_phase_bootstrap-token.md docs/admin/kubeadm_alpha_phase_bootstrap-token_all.md @@ -46,9 +46,12 @@ docs/admin/kubeadm_alpha_phase_kubeconfig_kubelet.md docs/admin/kubeadm_alpha_phase_kubeconfig_scheduler.md docs/admin/kubeadm_alpha_phase_kubeconfig_user.md docs/admin/kubeadm_alpha_phase_kubelet.md -docs/admin/kubeadm_alpha_phase_kubelet_enable-dynamic-config.md -docs/admin/kubeadm_alpha_phase_kubelet_upload-config.md -docs/admin/kubeadm_alpha_phase_kubelet_write-config-to-disk.md +docs/admin/kubeadm_alpha_phase_kubelet_config.md +docs/admin/kubeadm_alpha_phase_kubelet_config_download.md +docs/admin/kubeadm_alpha_phase_kubelet_config_enable-dynamic.md +docs/admin/kubeadm_alpha_phase_kubelet_config_upload.md +docs/admin/kubeadm_alpha_phase_kubelet_config_write-to-disk.md +docs/admin/kubeadm_alpha_phase_kubelet_write-env-file.md docs/admin/kubeadm_alpha_phase_mark-master.md docs/admin/kubeadm_alpha_phase_preflight.md docs/admin/kubeadm_alpha_phase_preflight_master.md @@ -61,6 +64,7 @@ docs/admin/kubeadm_config.md docs/admin/kubeadm_config_images.md docs/admin/kubeadm_config_images_list.md docs/admin/kubeadm_config_images_pull.md +docs/admin/kubeadm_config_migrate.md docs/admin/kubeadm_config_print-default.md docs/admin/kubeadm_config_upload.md docs/admin/kubeadm_config_upload_from-file.md @@ -77,6 +81,8 @@ docs/admin/kubeadm_token_list.md docs/admin/kubeadm_upgrade.md docs/admin/kubeadm_upgrade_apply.md docs/admin/kubeadm_upgrade_diff.md +docs/admin/kubeadm_upgrade_node.md +docs/admin/kubeadm_upgrade_node_config.md docs/admin/kubeadm_upgrade_plan.md docs/admin/kubeadm_version.md docs/admin/kubelet.md @@ -86,7 +92,7 @@ docs/man/man1/kube-controller-manager.1 docs/man/man1/kube-proxy.1 docs/man/man1/kube-scheduler.1 docs/man/man1/kubeadm-alpha-phase-addon-all.1 -docs/man/man1/kubeadm-alpha-phase-addon-kube-dns.1 +docs/man/man1/kubeadm-alpha-phase-addon-coredns.1 docs/man/man1/kubeadm-alpha-phase-addon-kube-proxy.1 docs/man/man1/kubeadm-alpha-phase-addon.1 docs/man/man1/kubeadm-alpha-phase-bootstrap-token-all.1 @@ -123,9 +129,12 @@ docs/man/man1/kubeadm-alpha-phase-kubeconfig-kubelet.1 docs/man/man1/kubeadm-alpha-phase-kubeconfig-scheduler.1 docs/man/man1/kubeadm-alpha-phase-kubeconfig-user.1 docs/man/man1/kubeadm-alpha-phase-kubeconfig.1 -docs/man/man1/kubeadm-alpha-phase-kubelet-enable-dynamic-config.1 -docs/man/man1/kubeadm-alpha-phase-kubelet-upload-config.1 -docs/man/man1/kubeadm-alpha-phase-kubelet-write-config-to-disk.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-config-download.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-config-enable-dynamic.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-config-upload.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-config-write-to-disk.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-config.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-write-env-file.1 docs/man/man1/kubeadm-alpha-phase-kubelet.1 docs/man/man1/kubeadm-alpha-phase-mark-master.1 docs/man/man1/kubeadm-alpha-phase-preflight-master.1 @@ -140,6 +149,7 @@ docs/man/man1/kubeadm-completion.1 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-upload-from-file.1 docs/man/man1/kubeadm-config-upload-from-flags.1 @@ -156,6 +166,8 @@ docs/man/man1/kubeadm-token-list.1 docs/man/man1/kubeadm-token.1 docs/man/man1/kubeadm-upgrade-apply.1 docs/man/man1/kubeadm-upgrade-diff.1 +docs/man/man1/kubeadm-upgrade-node-config.1 +docs/man/man1/kubeadm-upgrade-node.1 docs/man/man1/kubeadm-upgrade-plan.1 docs/man/man1/kubeadm-upgrade.1 docs/man/man1/kubeadm-version.1 diff --git a/docs/admin/kubeadm_alpha_phase_addon_kube-dns.md b/docs/admin/kubeadm_alpha_phase_addon_coredns.md similarity index 100% rename from docs/admin/kubeadm_alpha_phase_addon_kube-dns.md rename to docs/admin/kubeadm_alpha_phase_addon_coredns.md diff --git a/docs/admin/kubeadm_alpha_phase_kubelet_enable-dynamic-config.md b/docs/admin/kubeadm_alpha_phase_kubelet_config.md similarity index 100% rename from docs/admin/kubeadm_alpha_phase_kubelet_enable-dynamic-config.md rename to docs/admin/kubeadm_alpha_phase_kubelet_config.md diff --git a/docs/admin/kubeadm_alpha_phase_kubelet_upload-config.md b/docs/admin/kubeadm_alpha_phase_kubelet_config_download.md similarity index 100% rename from docs/admin/kubeadm_alpha_phase_kubelet_upload-config.md rename to docs/admin/kubeadm_alpha_phase_kubelet_config_download.md diff --git a/docs/admin/kubeadm_alpha_phase_kubelet_write-config-to-disk.md b/docs/admin/kubeadm_alpha_phase_kubelet_config_enable-dynamic.md similarity index 100% rename from docs/admin/kubeadm_alpha_phase_kubelet_write-config-to-disk.md rename to docs/admin/kubeadm_alpha_phase_kubelet_config_enable-dynamic.md diff --git a/docs/man/man1/kubeadm-alpha-phase-addon-kube-dns.1 b/docs/admin/kubeadm_alpha_phase_kubelet_config_upload.md similarity index 100% rename from docs/man/man1/kubeadm-alpha-phase-addon-kube-dns.1 rename to docs/admin/kubeadm_alpha_phase_kubelet_config_upload.md diff --git a/docs/man/man1/kubeadm-alpha-phase-kubelet-enable-dynamic-config.1 b/docs/admin/kubeadm_alpha_phase_kubelet_config_write-to-disk.md similarity index 100% rename from docs/man/man1/kubeadm-alpha-phase-kubelet-enable-dynamic-config.1 rename to docs/admin/kubeadm_alpha_phase_kubelet_config_write-to-disk.md diff --git a/docs/man/man1/kubeadm-alpha-phase-kubelet-upload-config.1 b/docs/admin/kubeadm_alpha_phase_kubelet_write-env-file.md similarity index 100% rename from docs/man/man1/kubeadm-alpha-phase-kubelet-upload-config.1 rename to docs/admin/kubeadm_alpha_phase_kubelet_write-env-file.md diff --git a/docs/man/man1/kubeadm-alpha-phase-kubelet-write-config-to-disk.1 b/docs/admin/kubeadm_config_migrate.md similarity index 100% rename from docs/man/man1/kubeadm-alpha-phase-kubelet-write-config-to-disk.1 rename to docs/admin/kubeadm_config_migrate.md diff --git a/docs/admin/kubeadm_upgrade_node.md b/docs/admin/kubeadm_upgrade_node.md new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/admin/kubeadm_upgrade_node.md @@ -0,0 +1,3 @@ +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/docs/admin/kubeadm_upgrade_node_config.md b/docs/admin/kubeadm_upgrade_node_config.md new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/admin/kubeadm_upgrade_node_config.md @@ -0,0 +1,3 @@ +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/docs/api-reference/apps/v1/definitions.html b/docs/api-reference/apps/v1/definitions.html index 68d17e7a575..6d9be73be9a 100755 --- a/docs/api-reference/apps/v1/definitions.html +++ b/docs/api-reference/apps/v1/definitions.html @@ -512,7 +512,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects. The requirements of them are ANDed.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -1341,6 +1341,9 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+
@@ -1557,6 +1560,54 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

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

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -3220,7 +3271,7 @@ When an object is created, the system will populate this list with the current s

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -3475,6 +3526,13 @@ When an object is created, the system will populate this list with the current s

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -3956,6 +4014,13 @@ When an object is created, the system will populate this list with the current s

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -5723,6 +5788,13 @@ Examples:

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + @@ -5788,6 +5860,40 @@ Examples:
+
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

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

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

+

v1.OwnerReference

@@ -6427,6 +6533,13 @@ Examples:

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -7385,6 +7498,47 @@ The StatefulSet guarantees that a given network identity will always map to the +
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

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

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.DeploymentSpec

diff --git a/docs/api-reference/apps/v1beta1/definitions.html b/docs/api-reference/apps/v1beta1/definitions.html index 04d3a39f6d6..4ecd2527dee 100755 --- a/docs/api-reference/apps/v1beta1/definitions.html +++ b/docs/api-reference/apps/v1beta1/definitions.html @@ -623,7 +623,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects. The requirements of them are ANDed.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -1273,6 +1273,9 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+
@@ -1448,6 +1451,54 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

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

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -3217,7 +3268,7 @@ The StatefulSet guarantees that a given network identity will always map to the

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -3472,6 +3523,13 @@ The StatefulSet guarantees that a given network identity will always map to the

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -4009,6 +4067,13 @@ The StatefulSet guarantees that a given network identity will always map to the

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -5858,6 +5923,47 @@ Examples:

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + + + + +
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

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

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

@@ -6342,6 +6448,13 @@ Examples:

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -6843,6 +6956,47 @@ Examples:
+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

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

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.Patch

diff --git a/docs/api-reference/apps/v1beta2/definitions.html b/docs/api-reference/apps/v1beta2/definitions.html index 2221a7e1464..e2ee3536fd9 100755 --- a/docs/api-reference/apps/v1beta2/definitions.html +++ b/docs/api-reference/apps/v1beta2/definitions.html @@ -515,7 +515,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects. The requirements of them are ANDed.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -1454,6 +1454,9 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+
@@ -1629,6 +1632,54 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

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

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -3923,7 +3974,7 @@ The StatefulSet guarantees that a given network identity will always map to the

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -4178,6 +4229,13 @@ The StatefulSet guarantees that a given network identity will always map to the

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -4625,6 +4683,13 @@ The StatefulSet guarantees that a given network identity will always map to the

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -6192,6 +6257,47 @@ Examples:

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + + + + +
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

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

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

@@ -6621,6 +6727,13 @@ Examples:

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -7376,6 +7489,47 @@ Examples:
+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

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

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.Patch

diff --git a/docs/api-reference/batch/v1/definitions.html b/docs/api-reference/batch/v1/definitions.html index 4e96f025f6a..54bd21255c3 100755 --- a/docs/api-reference/batch/v1/definitions.html +++ b/docs/api-reference/batch/v1/definitions.html @@ -488,7 +488,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects. The requirements of them are ANDed.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -1028,6 +1028,9 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+
@@ -1203,6 +1206,54 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

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

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -2587,7 +2638,7 @@ When an object is created, the system will populate this list with the current s

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -2842,6 +2893,13 @@ When an object is created, the system will populate this list with the current s

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -3289,6 +3347,13 @@ When an object is created, the system will populate this list with the current s

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -4663,6 +4728,13 @@ Examples:

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + @@ -4735,6 +4807,40 @@ Examples:
+
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

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

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

+

v1.OwnerReference

@@ -5161,6 +5267,13 @@ Examples:

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -5775,6 +5888,47 @@ Examples:
+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

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

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.Patch

diff --git a/docs/api-reference/batch/v1beta1/definitions.html b/docs/api-reference/batch/v1beta1/definitions.html index c8ce2f1f2f7..c390d9875d1 100755 --- a/docs/api-reference/batch/v1beta1/definitions.html +++ b/docs/api-reference/batch/v1beta1/definitions.html @@ -488,7 +488,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects. The requirements of them are ANDed.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -1069,6 +1069,9 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+
@@ -1244,6 +1247,54 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

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

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -2621,7 +2672,7 @@ When an object is created, the system will populate this list with the current s

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -2876,6 +2927,13 @@ When an object is created, the system will populate this list with the current s

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -3323,6 +3381,13 @@ When an object is created, the system will populate this list with the current s

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -4032,6 +4097,54 @@ Examples:
+
+
+

v1.PodDNSConfig

+
+

PodDNSConfig defines the DNS parameters of a pod in addition to those generated from DNSPolicy.

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

nameservers

A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. Duplicated nameservers will be removed.

false

string array

searches

A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. Duplicated search paths will be removed.

false

string array

options

A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. Duplicated entries will be removed. Resolution options given in Options will override those that appear in the base DNSPolicy.

false

v1.PodDNSConfigOption array

+

v1.Status

@@ -4115,54 +4228,6 @@ Examples:
-
-
-

v1.PodDNSConfig

-
-

PodDNSConfig defines the DNS parameters of a pod in addition to those generated from DNSPolicy.

-
- ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionRequiredSchemaDefault

nameservers

A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. Duplicated nameservers will be removed.

false

string array

searches

A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. Duplicated search paths will be removed.

false

string array

options

A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. Duplicated entries will be removed. Resolution options given in Options will override those that appear in the base DNSPolicy.

false

v1.PodDNSConfigOption array

-

v1.NFSVolumeSource

@@ -4814,6 +4879,47 @@ Examples:

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + + + + +
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

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

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

@@ -5106,6 +5212,47 @@ Examples:
+
+
+

v1.PodDNSConfigOption

+
+

PodDNSConfigOption defines DNS resolver options of a pod.

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

name

Required.

false

string

value

false

string

+

v1.SecretProjection

@@ -5157,47 +5304,6 @@ Examples:
-
-
-

v1.PodDNSConfigOption

-
-

PodDNSConfigOption defines DNS resolver options of a pod.

-
- ------- - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionRequiredSchemaDefault

name

Required.

false

string

value

false

string

-

v1beta1.CronJobList

@@ -5298,6 +5404,13 @@ Examples:

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -5795,6 +5908,47 @@ Examples:
+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

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

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.Patch

diff --git a/docs/api-reference/batch/v2alpha1/definitions.html b/docs/api-reference/batch/v2alpha1/definitions.html index 5926d49603a..b8326c03dcf 100755 --- a/docs/api-reference/batch/v2alpha1/definitions.html +++ b/docs/api-reference/batch/v2alpha1/definitions.html @@ -488,7 +488,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects. The requirements of them are ANDed.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -1028,6 +1028,9 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+
@@ -1203,6 +1206,54 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

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

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -2594,7 +2645,7 @@ When an object is created, the system will populate this list with the current s

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -2849,6 +2900,13 @@ When an object is created, the system will populate this list with the current s

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -3296,6 +3354,13 @@ When an object is created, the system will populate this list with the current s

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -3929,6 +3994,54 @@ Examples:
+
+
+

v1.PodDNSConfig

+
+

PodDNSConfig defines the DNS parameters of a pod in addition to those generated from DNSPolicy.

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

nameservers

A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. Duplicated nameservers will be removed.

false

string array

searches

A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. Duplicated search paths will be removed.

false

string array

options

A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. Duplicated entries will be removed. Resolution options given in Options will override those that appear in the base DNSPolicy.

false

v1.PodDNSConfigOption array

+

v1.Status

@@ -4012,54 +4125,6 @@ Examples:
-
-
-

v1.PodDNSConfig

-
-

PodDNSConfig defines the DNS parameters of a pod in addition to those generated from DNSPolicy.

-
- ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionRequiredSchemaDefault

nameservers

A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. Duplicated nameservers will be removed.

false

string array

searches

A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. Duplicated search paths will be removed.

false

string array

options

A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. Duplicated entries will be removed. Resolution options given in Options will override those that appear in the base DNSPolicy.

false

v1.PodDNSConfigOption array

-

v1.NFSVolumeSource

@@ -4670,6 +4735,47 @@ Examples:

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + + + + +
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

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

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

@@ -4962,6 +5068,47 @@ Examples:
+
+
+

v1.PodDNSConfigOption

+
+

PodDNSConfigOption defines DNS resolver options of a pod.

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

name

Required.

false

string

value

false

string

+

v1.SecretProjection

@@ -5013,47 +5160,6 @@ Examples:
-
-
-

v1.PodDNSConfigOption

-
-

PodDNSConfigOption defines DNS resolver options of a pod.

-
- ------- - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionRequiredSchemaDefault

name

Required.

false

string

value

false

string

-

v1.CinderVolumeSource

@@ -5099,6 +5205,13 @@ Examples:

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -5678,6 +5791,47 @@ Examples:
+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

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

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.Patch

diff --git a/docs/api-reference/extensions/v1beta1/definitions.html b/docs/api-reference/extensions/v1beta1/definitions.html index d2969deece6..7f7616f4cc8 100755 --- a/docs/api-reference/extensions/v1beta1/definitions.html +++ b/docs/api-reference/extensions/v1beta1/definitions.html @@ -450,6 +450,13 @@ Examples: /foo would allow /foo, /foo/ an

string

+ +

readOnly

+

when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.

+

false

+

boolean

+

false

+ @@ -740,7 +747,7 @@ Examples: /foo would allow /foo, /foo/ an

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects. The requirements of them are ANDed.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -1746,6 +1753,9 @@ Examples: /foo would allow /foo, /foo/ an

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+
@@ -1921,6 +1931,54 @@ Examples: /foo would allow /foo, /foo/ an
+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

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

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -3406,6 +3464,44 @@ When an object is created, the system will populate this list with the current s +
+
+

v1beta1.DaemonSetUpdateStrategy

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

type

Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is OnDelete.

false

string

rollingUpdate

Rolling update config params. Present only if type = "RollingUpdate".

false

v1beta1.RollingUpdateDaemonSet

+

v1.AzureDiskVolumeSource

@@ -3523,44 +3619,6 @@ When an object is created, the system will populate this list with the current s -
-
-

v1beta1.DaemonSetUpdateStrategy

- ------- - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionRequiredSchemaDefault

type

Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is OnDelete.

false

string

rollingUpdate

Rolling update config params. Present only if type = "RollingUpdate".

false

v1beta1.RollingUpdateDaemonSet

-

v1.VsphereVirtualDiskVolumeSource

@@ -3801,7 +3859,7 @@ When an object is created, the system will populate this list with the current s

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -4056,6 +4114,13 @@ When an object is created, the system will populate this list with the current s

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -4648,6 +4713,13 @@ When an object is created, the system will populate this list with the current s

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -6577,6 +6649,13 @@ If PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Po

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + @@ -6621,6 +6700,40 @@ If PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Po +
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

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

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

+

v1.OwnerReference

@@ -7315,6 +7428,13 @@ If PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Po

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -7857,6 +7977,47 @@ If PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Po +
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

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

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1beta1.NetworkPolicyPort

@@ -8054,6 +8215,24 @@ If PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Po

v1beta1.AllowedFlexVolume array

+ +

allowedUnsafeSysctls

+

allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in "" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.
+
+Examples: e.g. "foo/
" allows "foo/bar", "foo/baz", etc. e.g. "foo.*" allows "foo.bar", "foo.baz", etc.

+

false

+

string array

+ + + +

forbiddenSysctls

+

forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in "" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.
+
+Examples: e.g. "foo/
" forbids "foo/bar", "foo/baz", etc. e.g. "foo.*" forbids "foo.bar", "foo.baz", etc.

+

false

+

string array

+ + diff --git a/docs/api-reference/policy/v1beta1/definitions.html b/docs/api-reference/policy/v1beta1/definitions.html index 0e05aef6978..69c98d7a631 100755 --- a/docs/api-reference/policy/v1beta1/definitions.html +++ b/docs/api-reference/policy/v1beta1/definitions.html @@ -420,6 +420,13 @@ Examples: /foo would allow /foo, /foo/ an

string

+ +

readOnly

+

when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.

+

false

+

boolean

+

false

+ @@ -1476,6 +1483,24 @@ Examples: /foo would allow /foo, /foo/ an

v1beta1.AllowedFlexVolume array

+ +

allowedUnsafeSysctls

+

allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in "" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.
+
+Examples: e.g. "foo/
" allows "foo/bar", "foo/baz", etc. e.g. "foo.*" allows "foo.bar", "foo.baz", etc.

+

false

+

string array

+ + + +

forbiddenSysctls

+

forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in "" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.
+
+Examples: e.g. "foo/
" forbids "foo/bar", "foo/baz", etc. e.g. "foo.*" forbids "foo.bar", "foo.baz", etc.

+

false

+

string array

+ + diff --git a/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html b/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html index e048b45f835..57c45025da3 100755 --- a/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html +++ b/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html @@ -1370,6 +1370,9 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+
@@ -1573,6 +1576,54 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

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

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -2378,6 +2429,13 @@ When an object is created, the system will populate this list with the current s

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -3365,7 +3423,7 @@ When an object is created, the system will populate this list with the current s

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -3726,6 +3784,13 @@ When an object is created, the system will populate this list with the current s

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + diff --git a/docs/api-reference/storage.k8s.io/v1/definitions.html b/docs/api-reference/storage.k8s.io/v1/definitions.html index a8b980f1f74..6d6bed86b24 100755 --- a/docs/api-reference/storage.k8s.io/v1/definitions.html +++ b/docs/api-reference/storage.k8s.io/v1/definitions.html @@ -559,6 +559,47 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } +
+
+

v1.TopologySelectorLabelRequirement

+
+

A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.

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

key

The label key that the selector applies to.

true

string

values

An array of string values. One value must match the label to be selected. Each entry in Values is ORed.

true

string array

+

v1.StatusDetails

@@ -1003,6 +1044,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

v1.VolumeBindingMode

+ +

allowedTopologies

+

Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.

+

false

+

v1.TopologySelectorTerm array

+ + @@ -1230,6 +1278,40 @@ When an object is created, the system will populate this list with the current s +
+
+

v1.TopologySelectorTerm

+
+

A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.

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

matchLabelExpressions

A list of topology selector requirements by labels.

false

v1.TopologySelectorLabelRequirement array

+

v1.PersistentVolumeReclaimPolicy

diff --git a/docs/api-reference/storage.k8s.io/v1beta1/definitions.html b/docs/api-reference/storage.k8s.io/v1beta1/definitions.html index 1e36a24524d..77fec9d25d9 100755 --- a/docs/api-reference/storage.k8s.io/v1beta1/definitions.html +++ b/docs/api-reference/storage.k8s.io/v1beta1/definitions.html @@ -779,6 +779,40 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

v1.PersistentVolumeReclaimPolicy

+
+
+

v1.TopologySelectorTerm

+
+

A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.

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

matchLabelExpressions

A list of topology selector requirements by labels.

false

v1.TopologySelectorLabelRequirement array

+

v1beta1.VolumeAttachmentList

@@ -1041,6 +1075,47 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } +
+
+

v1.TopologySelectorLabelRequirement

+
+

A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.

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

key

The label key that the selector applies to.

true

string

values

An array of string values. One value must match the label to be selected. Each entry in Values is ORed.

true

string array

+

v1.Initializer

@@ -1075,6 +1150,47 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } +
+
+

v1beta1.VolumeError

+
+

VolumeError captures an error encountered during a volume operation.

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

time

Time the error was encountered.

false

string

message

String detailing the error encountered during Attach or Detach operation. This string maybe logged, so it should not contain sensitive information.

false

string

+

v1beta1.StorageClass

@@ -1165,45 +1281,11 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

v1beta1.VolumeBindingMode

- - - -
-
-

v1beta1.VolumeError

-
-

VolumeError captures an error encountered during a volume operation.

-
- ------- - - - - - - - - - - - - + + - - - - - - - - + diff --git a/docs/api-reference/v1/definitions.html b/docs/api-reference/v1/definitions.html index ac244a75f50..be6ea3dd077 100755 --- a/docs/api-reference/v1/definitions.html +++ b/docs/api-reference/v1/definitions.html @@ -967,6 +967,9 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+
NameDescriptionRequiredSchemaDefault

time

Time the error was encountered.

allowedTopologies

Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.

false

string

message

String detailing the error encountered during Attach or Detach operation. This string maybe logged, so it should not contain sensitive information.

false

string

v1.TopologySelectorTerm array

@@ -4134,7 +4137,7 @@ Examples:
- + @@ -4355,6 +4358,13 @@ Examples:
+ + + + + + +

cinder

Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md

false

v1.CinderVolumeSource

v1.CinderPersistentVolumeSource

integer (int64)

sysctls

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

false

v1.Sysctl array

@@ -4973,6 +4983,13 @@ Examples:

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -5717,6 +5734,47 @@ Examples:
+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

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

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.Patch

@@ -5953,6 +6011,40 @@ Examples:
+
+
+

v1.ScopeSelector

+
+

A scope selector represents the AND of the selectors represented by the scoped-resource selector requirements.

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

matchExpressions

A list of scope selector requirements by scope of the resources.

false

v1.ScopedResourceSelectorRequirement array

+

v1.NodeSystemInfo

@@ -6543,7 +6635,7 @@ Examples:

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects. The requirements of them are ANDed.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -6860,7 +6952,7 @@ Examples:
- + @@ -6872,6 +6964,13 @@ Examples:
+ + + + + + +

hard

Hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/

hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/

false

object

v1.ResourceQuotaScope array

scopeSelector

scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota but expressed using ScopeSelectorOperator in combination with possible values. For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched.

false

v1.ScopeSelector

@@ -7300,6 +7399,54 @@ Examples:
+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

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

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.LocalObjectReference

@@ -7899,6 +8046,61 @@ Examples:

v1.UniqueVolumeName

+
+
+

v1.CinderPersistentVolumeSource

+
+

Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.

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

volumeID

volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md

true

string

fsType

Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md

false

string

readOnly

Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md

false

boolean

false

secretRef

Optional: points to a secret object containing parameters used to connect to OpenStack.

false

v1.SecretReference

+

v1.NodeConfigStatus

@@ -8264,61 +8466,6 @@ Examples:
-
-
-

v1.LimitRangeList

-
-

LimitRangeList is a list of LimitRange items.

-
- ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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

items

Items is a list of LimitRange objects. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

true

v1.LimitRange array

-

v1.ServiceAccountList

@@ -8374,6 +8521,61 @@ Examples:
+
+
+

v1.LimitRangeList

+
+

LimitRangeList is a list of LimitRange items.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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

items

Items is a list of LimitRange objects. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

true

v1.LimitRange array

+

v1.Endpoints

@@ -8570,7 +8772,7 @@ Examples:

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -8777,6 +8979,13 @@ Examples:

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -9160,7 +9369,7 @@ Examples:

v1.PodStatus

-

PodStatus represents information about the status of a pod. Status may trail the actual state of a system.

+

PodStatus represents information about the status of a pod. Status may trail the actual state of a system, especially if the node that hosts the pod cannot contact the control plane.

@@ -9182,7 +9391,11 @@ Examples:
- + @@ -9473,6 +9686,61 @@ Examples:
+ + + + + + + + +

phase

Current condition of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase

The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. The conditions array, the reason and message fields, and the individual container status arrays contain more detail about the pod’s status. There are five possible phase values:
+
+Pending: The pod has been accepted by the Kubernetes system, but one or more of the container images has not been created. This includes time before being scheduled as well as time spent downloading images over the network, which could take a while. Running: The pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting. Succeeded: All containers in the pod have terminated in success, and will not be restarted. Failed: All containers in the pod have terminated, and at least one container has terminated in failure. The container either exited with non-zero status or was terminated by the system. Unknown: For some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod.
+
+More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase

false

string

v1.PodDNSConfig

readinessGates

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

false

v1.PodReadinessGate array

+ +
+
+

v1.ScopedResourceSelectorRequirement

+
+

A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator that relates the scope name and values.

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

scopeName

The name of the scope that the selector applies to.

true

string

operator

Represents a scope’s relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist.

true

string

values

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.

false

string array

@@ -9639,7 +9907,7 @@ Examples:

type

-

Type is the type of the condition. Currently only Ready. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions

+

Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions

true

string

@@ -10325,6 +10593,40 @@ Examples:
+
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

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

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

+

v1.ComponentCondition

@@ -10697,44 +10999,6 @@ Examples:
-
-
-

v1.WatchEvent

- ------- - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionRequiredSchemaDefault

type

true

string

object

true

string

-

v1.Secret

@@ -10804,6 +11068,44 @@ Examples:
+
+
+

v1.WatchEvent

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

type

true

string

object

true

string

+

v1.LabelSelectorRequirement

diff --git a/docs/man/man1/kubeadm-alpha-phase-addon-coredns.1 b/docs/man/man1/kubeadm-alpha-phase-addon-coredns.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/kubeadm-alpha-phase-addon-coredns.1 @@ -0,0 +1,3 @@ +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/docs/man/man1/kubeadm-alpha-phase-kubelet-config-download.1 b/docs/man/man1/kubeadm-alpha-phase-kubelet-config-download.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/kubeadm-alpha-phase-kubelet-config-download.1 @@ -0,0 +1,3 @@ +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/docs/man/man1/kubeadm-alpha-phase-kubelet-config-enable-dynamic.1 b/docs/man/man1/kubeadm-alpha-phase-kubelet-config-enable-dynamic.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/kubeadm-alpha-phase-kubelet-config-enable-dynamic.1 @@ -0,0 +1,3 @@ +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/docs/man/man1/kubeadm-alpha-phase-kubelet-config-upload.1 b/docs/man/man1/kubeadm-alpha-phase-kubelet-config-upload.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/kubeadm-alpha-phase-kubelet-config-upload.1 @@ -0,0 +1,3 @@ +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/docs/man/man1/kubeadm-alpha-phase-kubelet-config-write-to-disk.1 b/docs/man/man1/kubeadm-alpha-phase-kubelet-config-write-to-disk.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/kubeadm-alpha-phase-kubelet-config-write-to-disk.1 @@ -0,0 +1,3 @@ +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/docs/man/man1/kubeadm-alpha-phase-kubelet-config.1 b/docs/man/man1/kubeadm-alpha-phase-kubelet-config.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/kubeadm-alpha-phase-kubelet-config.1 @@ -0,0 +1,3 @@ +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/docs/man/man1/kubeadm-alpha-phase-kubelet-write-env-file.1 b/docs/man/man1/kubeadm-alpha-phase-kubelet-write-env-file.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/kubeadm-alpha-phase-kubelet-write-env-file.1 @@ -0,0 +1,3 @@ +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/docs/man/man1/kubeadm-config-migrate.1 b/docs/man/man1/kubeadm-config-migrate.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/kubeadm-config-migrate.1 @@ -0,0 +1,3 @@ +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/docs/man/man1/kubeadm-upgrade-node-config.1 b/docs/man/man1/kubeadm-upgrade-node-config.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/kubeadm-upgrade-node-config.1 @@ -0,0 +1,3 @@ +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/docs/man/man1/kubeadm-upgrade-node.1 b/docs/man/man1/kubeadm-upgrade-node.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/kubeadm-upgrade-node.1 @@ -0,0 +1,3 @@ +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 2b2798e46a7..0a5ba6fea10 100644 --- a/hack/.golint_failures +++ b/hack/.golint_failures @@ -6,7 +6,6 @@ cmd/kube-controller-manager/app cmd/kube-proxy/app cmd/kube-scheduler/app cmd/kubeadm/app -cmd/kubeadm/app/apis/kubeadm/v1alpha1 cmd/kubeadm/app/apis/kubeadm/v1alpha2 cmd/kubeadm/app/util/config cmd/kubelet/app @@ -148,7 +147,6 @@ pkg/kubectl/cmd/templates pkg/kubectl/cmd/testing pkg/kubectl/cmd/util pkg/kubectl/cmd/util/editor -pkg/kubectl/cmd/util/jsonmerge pkg/kubectl/cmd/util/sanity pkg/kubectl/cmd/wait pkg/kubectl/genericclioptions @@ -156,7 +154,6 @@ pkg/kubectl/genericclioptions/printers pkg/kubectl/genericclioptions/resource pkg/kubectl/metricsutil pkg/kubectl/util -pkg/kubectl/util/crlf pkg/kubectl/util/slice pkg/kubelet pkg/kubelet/apis @@ -166,6 +163,7 @@ pkg/kubelet/apis/deviceplugin/v1alpha pkg/kubelet/apis/deviceplugin/v1beta1 pkg/kubelet/apis/kubeletconfig pkg/kubelet/apis/kubeletconfig/v1beta1 +pkg/kubelet/apis/pluginregistration/v1alpha1 pkg/kubelet/cadvisor pkg/kubelet/cadvisor/testing pkg/kubelet/checkpoint @@ -217,6 +215,9 @@ pkg/kubelet/sysctl pkg/kubelet/types pkg/kubelet/util pkg/kubelet/util/cache +pkg/kubelet/util/pluginwatcher +pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1 +pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2 pkg/kubelet/util/queue pkg/kubelet/util/sliceutils pkg/kubemark @@ -380,7 +381,9 @@ pkg/volume/azure_dd pkg/volume/azure_file pkg/volume/cephfs pkg/volume/configmap +pkg/volume/csi pkg/volume/csi/fake +pkg/volume/csi/labelmanager pkg/volume/empty_dir pkg/volume/fc pkg/volume/flexvolume diff --git a/hack/import-restrictions.yaml b/hack/import-restrictions.yaml index c053eb45251..19e12ac1e94 100644 --- a/hack/import-restrictions.yaml +++ b/hack/import-restrictions.yaml @@ -24,6 +24,7 @@ # TODO this one should be tightened. We depend on it for testing, but we should instead create our own scheme - k8s.io/api/core/v1 - k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers + - k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource - baseImportPath: "./vendor/k8s.io/apimachinery/" allowedImports: diff --git a/hack/lib/golang.sh b/hack/lib/golang.sh index 9f229168a8a..c5d463483bf 100755 --- a/hack/lib/golang.sh +++ b/hack/lib/golang.sh @@ -213,12 +213,27 @@ readonly KUBE_STATIC_LIBRARIES=( kubectl ) +# KUBE_CGO_OVERRIDES is a space-separated list of binaries which should be built +# with CGO enabled, assuming CGO is supported on the target platform. +# This overrides any entry in KUBE_STATIC_LIBRARIES. +IFS=" " read -ra KUBE_CGO_OVERRIDES <<< "${KUBE_CGO_OVERRIDES:-}" +readonly KUBE_CGO_OVERRIDES +# KUBE_STATIC_OVERRIDES is a space-separated list of binaries which should be +# built with CGO disabled. This is in addition to the list in +# KUBE_STATIC_LIBRARIES. +IFS=" " read -ra KUBE_STATIC_OVERRIDES <<< "${KUBE_STATIC_OVERRIDES:-}" +readonly KUBE_STATIC_OVERRIDES + kube::golang::is_statically_linked_library() { local e + # Explicitly enable cgo when building kubectl for darwin from darwin. + [[ "$(go env GOHOSTOS)" == "darwin" && "$(go env GOOS)" == "darwin" && + "$1" == *"/kubectl" ]] && return 1 + if [[ -n "${KUBE_CGO_OVERRIDES:+x}" ]]; then + for e in "${KUBE_CGO_OVERRIDES[@]}"; do [[ "$1" == *"/$e" ]] && return 1; done; + fi for e in "${KUBE_STATIC_LIBRARIES[@]}"; do [[ "$1" == *"/$e" ]] && return 0; done; - # Allow individual overrides--e.g., so that you can get a static build of - # kubectl for inclusion in a container. - if [ -n "${KUBE_STATIC_OVERRIDES:+x}" ]; then + if [[ -n "${KUBE_STATIC_OVERRIDES:+x}" ]]; then for e in "${KUBE_STATIC_OVERRIDES[@]}"; do [[ "$1" == *"/$e" ]] && return 0; done; fi return 1; diff --git a/hack/local-up-cluster.sh b/hack/local-up-cluster.sh index 9abcbc22d91..c12b2660402 100755 --- a/hack/local-up-cluster.sh +++ b/hack/local-up-cluster.sh @@ -126,13 +126,11 @@ if [ "${CLOUD_PROVIDER}" == "openstack" ]; then fi fi -# set feature gates if using ipvs mode +# load required kernel modules if proxy mode is set to "ipvs". if [ "${KUBE_PROXY_MODE}" == "ipvs" ]; then # If required kernel modules are not available, fall back to iptables. sudo modprobe -a ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack_ipv4 - if [[ $? -eq 0 ]]; then - FEATURE_GATES="${FEATURE_GATES},SupportIPVSProxyMode=true" - else + if [[ $? -ne 0 ]]; then echo "Required kernel modules for ipvs not found. Falling back to iptables mode." KUBE_PROXY_MODE=iptables fi @@ -239,7 +237,6 @@ CPU_CFS_QUOTA=${CPU_CFS_QUOTA:-true} ENABLE_HOSTPATH_PROVISIONER=${ENABLE_HOSTPATH_PROVISIONER:-"false"} CLAIM_BINDER_SYNC_PERIOD=${CLAIM_BINDER_SYNC_PERIOD:-"15s"} # current k8s default ENABLE_CONTROLLER_ATTACH_DETACH=${ENABLE_CONTROLLER_ATTACH_DETACH:-"true"} # current default -KEEP_TERMINATED_POD_VOLUMES=${KEEP_TERMINATED_POD_VOLUMES:-"true"} # This is the default dir and filename where the apiserver will generate a self-signed cert # which should be able to be used as the CA to verify itself CERT_DIR=${CERT_DIR:-"/var/run/kubernetes"} @@ -772,7 +769,6 @@ function start_kubelet { --enable-controller-attach-detach="${ENABLE_CONTROLLER_ATTACH_DETACH}" --cgroups-per-qos="${CGROUPS_PER_QOS}" --cgroup-driver="${CGROUP_DRIVER}" - --keep-terminated-pod-volumes="${KEEP_TERMINATED_POD_VOLUMES}" --eviction-hard="${EVICTION_HARD}" --eviction-soft="${EVICTION_SOFT}" --eviction-pressure-transition-period="${EVICTION_PRESSURE_TRANSITION_PERIOD}" @@ -905,7 +901,7 @@ EOF function start_kubedns { if [[ "${ENABLE_CLUSTER_DNS}" = true ]]; then - cp "${KUBE_ROOT}/cluster/addons/dns/kube-dns.yaml.in" kube-dns.yaml + cp "${KUBE_ROOT}/cluster/addons/dns/kube-dns/kube-dns.yaml.in" kube-dns.yaml sed -i -e "s/{{ pillar\['dns_domain'\] }}/${DNS_DOMAIN}/g" kube-dns.yaml sed -i -e "s/{{ pillar\['dns_server'\] }}/${DNS_SERVER_IP}/g" kube-dns.yaml diff --git a/hack/make-rules/BUILD b/hack/make-rules/BUILD index d05b2a98ba1..2ff9bb3bfac 100644 --- a/hack/make-rules/BUILD +++ b/hack/make-rules/BUILD @@ -106,7 +106,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//hack/make-rules/helpers/go2make:all-srcs", + ], tags = ["automanaged"], visibility = ["//visibility:public"], ) diff --git a/hack/make-rules/helpers/cache_go_dirs.sh b/hack/make-rules/helpers/cache_go_dirs.sh index 390f8a21bc0..6587fecf371 100755 --- a/hack/make-rules/helpers/cache_go_dirs.sh +++ b/hack/make-rules/helpers/cache_go_dirs.sh @@ -36,22 +36,23 @@ trap "rm -f '${CACHE}'" HUP INT TERM ERR # Example: # kfind -type f -name foobar.go function kfind() { - # include the "special" vendor directories which are actually part - # of the Kubernetes source tree - generators will use these for - # including certain core API concepts. - find -H . ./vendor/k8s.io/apimachinery ./vendor/k8s.io/apiserver ./vendor/k8s.io/kube-aggregator ./vendor/k8s.io/apiextensions-apiserver ./vendor/k8s.io/metrics ./vendor/k8s.io/sample-apiserver ./vendor/k8s.io/api ./vendor/k8s.io/client-go ./vendor/k8s.io/code-generator ./vendor/k8s.io/sample-controller \ + # We want to include the "special" vendor directories which are actually + # part of the Kubernetes source tree (./staging/*) but we need them to be + # named as their ./vendor/* equivalents. Also, we do not want all of + # ./vendor or even all of ./vendor/k8s.io. + find -H . \ \( \ -not \( \ \( \ -path ./vendor -o \ - -path ./staging -o \ -path ./_\* -o \ -path ./.\* -o \ -path ./docs \ \) -prune \ \) \ \) \ - "$@" + "$@" \ + | sed 's|^./staging/src|vendor|' } NEED_FIND=true diff --git a/hack/make-rules/helpers/go2make/BUILD b/hack/make-rules/helpers/go2make/BUILD new file mode 100644 index 00000000000..ab5678ffd32 --- /dev/null +++ b/hack/make-rules/helpers/go2make/BUILD @@ -0,0 +1,41 @@ +# gazelle:exclude testdata + +load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "go2make.go", + "pkgwalk.go", + ], + importpath = "k8s.io/kubernetes/hack/make-rules/helpers/go2make", + visibility = ["//visibility:private"], + deps = ["//vendor/github.com/spf13/pflag:go_default_library"], +) + +go_binary( + name = "go2make", + embed = [":go_default_library"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["pkgwalk_test.go"], + data = glob(["testdata/**"]), + embed = [":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/hack/make-rules/helpers/go2make/go2make.go b/hack/make-rules/helpers/go2make/go2make.go new file mode 100644 index 00000000000..0ffa585bc71 --- /dev/null +++ b/hack/make-rules/helpers/go2make/go2make.go @@ -0,0 +1,215 @@ +/* +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 main + +import ( + "bytes" + goflag "flag" + "fmt" + "go/build" + "io" + "os" + "sort" + "strings" + + "github.com/spf13/pflag" +) + +var flPrune = pflag.StringSlice("prune", nil, "sub-packages to prune (recursive, may be specified multiple times)") +var flDebug = pflag.BoolP("debug", "d", false, "enable debugging output") +var flHelp = pflag.BoolP("help", "h", false, "print help and exit") + +func main() { + pflag.CommandLine.AddGoFlagSet(goflag.CommandLine) + pflag.Usage = func() { help(os.Stderr) } + pflag.Parse() + + debug("PWD", getwd()) + + build.Default.BuildTags = []string{"ignore_autogenerated"} + build.Default.UseAllFiles = false + + if *flHelp { + help(os.Stdout) + os.Exit(0) + } + if len(pflag.Args()) == 0 { + help(os.Stderr) + os.Exit(1) + } + for _, in := range pflag.Args() { + if strings.HasSuffix(in, "/...") { + // Recurse. + debug("starting", in) + pkgName := strings.TrimSuffix(in, "/...") + if err := WalkPkg(pkgName, visitPkg); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + } else { + // Import one package. + if err := saveImport(in); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } + } + } +} + +func help(out io.Writer) { + fmt.Fprintf(out, "Usage: %s [FLAG...] \n", os.Args[0]) + fmt.Fprintf(out, "\n") + fmt.Fprintf(out, "go2make calculates all of the dependencies of a set of Go packages and prints\n") + fmt.Fprintf(out, "them as variable definitions suitable for use as a Makefile.\n") + fmt.Fprintf(out, "\n") + fmt.Fprintf(out, "Package specifications may be simple (e.g. 'example.com/txt/color') or\n") + fmt.Fprintf(out, "recursive (e.g. 'example.com/txt/...')\n") + fmt.Fprintf(out, " Example:\n") + fmt.Fprintf(out, " $ %s ./example.com/pretty\n", os.Args[0]) + fmt.Fprintf(out, " example.com/txt/split := \\\n") + fmt.Fprintf(out, " /go/src/example.com/txt/split/ \\\n") + fmt.Fprintf(out, " /go/src/example.com/txt/split/split.go \\\n") + fmt.Fprintf(out, " ./example.com/pretty := \\\n") + fmt.Fprintf(out, " /go/src/example.com/pretty/ \\\n") + fmt.Fprintf(out, " /go/src/example.com/pretty/print.go \\\n") + fmt.Fprintf(out, " /go/src/example.com/txt/split/ \\\n") + fmt.Fprintf(out, " /go/src/example.com/txt/split/split.go\n") + fmt.Fprintf(out, "\n") + fmt.Fprintf(out, " Flags:\n") + + pflag.PrintDefaults() +} + +func debug(items ...interface{}) { + if *flDebug { + x := []interface{}{"DBG:"} + x = append(x, items...) + fmt.Println(x...) + } +} + +func visitPkg(importPath, absPath string) error { + debug("visit", importPath) + return saveImport(importPath) +} + +func prune(pkgName string) bool { + for _, pr := range *flPrune { + if pr == pkgName { + return true + } + } + return false +} + +// cache keeps track of which packages we have already loaded. +var cache = map[string]*build.Package{} + +func saveImport(pkgName string) error { + if cache[pkgName] != nil { + return nil + } + if prune(pkgName) { + debug("prune", pkgName) + return ErrSkipPkg + } + pkg, err := loadPackage(pkgName) + if err != nil { + return err + } + debug("save", pkgName) + cache[pkgName] = pkg + + debug("recurse", pkgName) + defer func() { debug("done ", pkgName) }() + if !pkg.Goroot && (len(pkg.GoFiles)+len(pkg.Imports) > 0) { + // Process deps of this package before the package itself. + for _, impName := range pkg.Imports { + if impName == "C" { + continue + } + debug("depends on", impName) + saveImport(impName) + } + + // Emit a variable for each package. + var buf bytes.Buffer + buf.WriteString(pkgName) + buf.WriteString(" := ") + + // Packages depend on their own directories, their own files, and + // transitive list of all deps' directories and files. + all := map[string]struct{}{} + all[pkg.Dir+"/"] = struct{}{} + filesForPkg(pkg, all) + for _, imp := range pkg.Imports { + pkg := cache[imp] + if pkg == nil || pkg.Goroot { + continue + } + all[pkg.Dir+"/"] = struct{}{} + filesForPkg(pkg, all) + } + // Sort and de-dup them. + files := flatten(all) + for _, f := range files { + buf.WriteString(" \\\n ") + buf.WriteString(f) + } + + fmt.Println(buf.String()) + } + return nil +} + +func filesForPkg(pkg *build.Package, all map[string]struct{}) { + for _, file := range pkg.GoFiles { + if pkg.Dir != "." { + file = pkg.Dir + "/" + file + } + all[file] = struct{}{} + } +} + +func flatten(all map[string]struct{}) []string { + list := make([]string, 0, len(all)) + for k := range all { + list = append(list, k) + } + sort.Strings(list) + return list +} + +func loadPackage(pkgName string) (*build.Package, error) { + debug("load", pkgName) + pkg, err := build.Import(pkgName, getwd(), 0) + if err != nil { + // We can ignore NoGoError. Anything else is real. + if _, ok := err.(*build.NoGoError); !ok { + return nil, err + } + } + return pkg, nil +} + +func getwd() string { + pwd, err := os.Getwd() + if err != nil { + panic(fmt.Sprintf("can't get working directory: %v", err)) + } + return pwd +} diff --git a/hack/make-rules/helpers/go2make/pkgwalk.go b/hack/make-rules/helpers/go2make/pkgwalk.go new file mode 100644 index 00000000000..6d8dfdb0f7a --- /dev/null +++ b/hack/make-rules/helpers/go2make/pkgwalk.go @@ -0,0 +1,117 @@ +/* +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 main + +import ( + "fmt" + "go/build" + "os" + "path" + "sort" +) + +// VisitFunc is a function called by WalkPkg to examine a single package. +type VisitFunc func(importPath string, absPath string) error + +// ErrSkipPkg can be returned by a VisitFunc to indicate that the package in +// question should not be walked any further. +var ErrSkipPkg = fmt.Errorf("package skipped") + +// WalkPkg recursively visits all packages under pkgName. This is similar +// to filepath.Walk, except that it follows symlinks. A package is always +// visited before the children of that package. If visit returns ErrSkipPkg, +// pkgName will not be walked. +func WalkPkg(pkgName string, visit VisitFunc) error { + // Visit the package itself. + pkg, err := findPackage(pkgName) + if err != nil { + return err + } + if err := visit(pkg.ImportPath, pkg.Dir); err == ErrSkipPkg { + return nil + } else if err != nil { + return err + } + + // Read all of the child dirents and find sub-packages. + infos, err := readDirInfos(pkg.Dir) + if err != nil { + return err + } + for _, info := range infos { + if !info.IsDir() { + continue + } + name := info.Name() + if name[0] == '_' || (len(name) > 1 && name[0] == '.') || name == "testdata" { + continue + } + // Don't use path.Join() because it drops leading `./` via path.Clean(). + err := WalkPkg(pkgName+"/"+name, visit) + if err != nil { + return err + } + } + return nil +} + +// findPackage finds a Go package. +func findPackage(pkgName string) (*build.Package, error) { + debug("find", pkgName) + pkg, err := build.Import(pkgName, getwd(), build.FindOnly) + if err != nil { + return nil, err + } + return pkg, nil +} + +// readDirInfos returns a list of os.FileInfo structures for the dirents under +// dirPath. The result list is sorted by name. This is very similar to +// ioutil.ReadDir, except that it follows symlinks. +func readDirInfos(dirPath string) ([]os.FileInfo, error) { + names, err := readDirNames(dirPath) + if err != nil { + return nil, err + } + sort.Strings(names) + + infos := make([]os.FileInfo, 0, len(names)) + for _, n := range names { + info, err := os.Stat(path.Join(dirPath, n)) + if err != nil { + return nil, err + } + infos = append(infos, info) + } + return infos, nil +} + +// readDirNames returns a list of all dirents in dirPath. The result list is +// not sorted or filtered. +func readDirNames(dirPath string) ([]string, error) { + d, err := os.Open(dirPath) + if err != nil { + return nil, err + } + defer d.Close() + + names, err := d.Readdirnames(-1) + if err != nil { + return nil, err + } + return names, nil +} diff --git a/hack/make-rules/helpers/go2make/pkgwalk_test.go b/hack/make-rules/helpers/go2make/pkgwalk_test.go new file mode 100644 index 00000000000..140f5121558 --- /dev/null +++ b/hack/make-rules/helpers/go2make/pkgwalk_test.go @@ -0,0 +1,222 @@ +/* +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 main + +import ( + "path" + "reflect" + "sort" + "testing" +) + +func Test_WalkPkg(t *testing.T) { + testCases := []struct { + pkg string + fail bool + expected []string + }{ + { + pkg: "./testdata/nonexistent-dir", + fail: true, + }, + { + pkg: "./testdata/dir-without-gofiles", + expected: []string{"./testdata/dir-without-gofiles"}, + }, + { + pkg: "./testdata/dir-with-gofiles", + expected: []string{"./testdata/dir-with-gofiles", "./testdata/dir-with-gofiles/subdir"}, + }, + } + + for i, tc := range testCases { + visited := []string{} + err := WalkPkg(tc.pkg, func(imp, abs string) error { + if _, base := path.Split(imp); base == "skipme" { + return ErrSkipPkg + } + visited = append(visited, imp) + return nil + }) + if err != nil && tc.fail { + continue + } + if err != nil { + t.Errorf("[%d] unexpected error: %v", i, err) + continue + } + if tc.fail { + t.Errorf("[%d] expected error", i) + continue + } + if !reflect.DeepEqual(visited, tc.expected) { + t.Errorf("[%d] unexpected results: %v", i, visited) + } + } +} +func Test_findPackage(t *testing.T) { + testCases := []struct { + pkg string + fail bool + }{ + { + pkg: "./testdata/nonexistent-dir", + fail: true, + }, + { + pkg: "./testdata/dir-without-gofiles", + }, + { + pkg: "./testdata/dir-with-gofiles", + }, + } + + for i, tc := range testCases { + _, err := findPackage(tc.pkg) + if err != nil && tc.fail { + continue + } + if err != nil { + t.Errorf("[%d] unexpected error: %v", i, err) + continue + } + if tc.fail { + t.Errorf("[%d] expected error", i) + continue + } + } +} + +func Test_readDirInfos(t *testing.T) { + testCases := []struct { + dir string + fail bool + expected map[string]bool + }{ + { + dir: "./testdata/nonexistent-dir", + fail: true, + }, + { + dir: "./testdata/dir-without-gofiles", + expected: map[string]bool{"README": true}, + }, + { + dir: "./testdata/dir-with-gofiles", + expected: map[string]bool{ + "README": true, + "foo.go": true, + "bar.go": true, + "subdir": true, + "testdata": true, + "_underscore": true, + ".dot": true, + "skipme": true, + }, + }, + } + + for i, tc := range testCases { + infos, err := readDirInfos(tc.dir) + if err != nil && tc.fail { + continue + } + if err != nil { + t.Errorf("[%d] unexpected error: %v", i, err) + continue + } + if tc.fail { + t.Errorf("[%d] expected error", i) + continue + } + result := make([]string, len(infos)) + sorted := make([]string, len(infos)) + for i, inf := range infos { + result[i] = inf.Name() + sorted[i] = inf.Name() + } + sort.Strings(sorted) + if !reflect.DeepEqual(result, sorted) { + t.Errorf("[%d] result was not sorted: %v", i, result) + } + for _, r := range result { + if !tc.expected[r] { + t.Errorf("[%d] got unexpected result: %s", i, r) + } else { + delete(tc.expected, r) + } + } + for r := range tc.expected { + t.Errorf("[%d] missing expected result: %s", i, r) + } + } +} + +func Test_readDirNames(t *testing.T) { + testCases := []struct { + dir string + fail bool + expected map[string]bool + }{ + { + dir: "./testdata/nonexistent-dir", + fail: true, + }, + { + dir: "./testdata/dir-without-gofiles", + expected: map[string]bool{"README": true}, + }, + { + dir: "./testdata/dir-with-gofiles", + expected: map[string]bool{ + "README": true, + "foo.go": true, + "bar.go": true, + "subdir": true, + "testdata": true, + "_underscore": true, + ".dot": true, + "skipme": true, + }, + }, + } + + for i, tc := range testCases { + result, err := readDirNames(tc.dir) + if err != nil && tc.fail { + continue + } + if err != nil { + t.Errorf("[%d] unexpected error: %v", i, err) + continue + } + if tc.fail { + t.Errorf("[%d] expected error", i) + continue + } + for _, r := range result { + if !tc.expected[r] { + t.Errorf("[%d] got unexpected result: %s", i, r) + } else { + delete(tc.expected, r) + } + } + for r := range tc.expected { + t.Errorf("[%d] missing expected result: %s", i, r) + } + } +} diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/.dot/README b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/.dot/README new file mode 100644 index 00000000000..e845566c06f --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/.dot/README @@ -0,0 +1 @@ +README diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/.dot/subsubdir/README b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/.dot/subsubdir/README new file mode 100644 index 00000000000..e845566c06f --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/.dot/subsubdir/README @@ -0,0 +1 @@ +README diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/README b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/README new file mode 100644 index 00000000000..e845566c06f --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/README @@ -0,0 +1 @@ +README diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/_underscore/README b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/_underscore/README new file mode 100644 index 00000000000..e845566c06f --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/_underscore/README @@ -0,0 +1 @@ +README diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/_underscore/subsubdir/README b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/_underscore/subsubdir/README new file mode 100644 index 00000000000..e845566c06f --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/_underscore/subsubdir/README @@ -0,0 +1 @@ +README diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/bar.go b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/bar.go new file mode 100644 index 00000000000..ce91c95ae93 --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/bar.go @@ -0,0 +1,20 @@ +/* +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 gofiles + +func bar() { +} diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/foo.go b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/foo.go new file mode 100644 index 00000000000..57690637d17 --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/foo.go @@ -0,0 +1,20 @@ +/* +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 gofiles + +func foo() { +} diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/skipme/README b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/skipme/README new file mode 100644 index 00000000000..e845566c06f --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/skipme/README @@ -0,0 +1 @@ +README diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/skipme/subsubdir/README b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/skipme/subsubdir/README new file mode 100644 index 00000000000..e845566c06f --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/skipme/subsubdir/README @@ -0,0 +1 @@ +README diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/subdir/README b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/subdir/README new file mode 100644 index 00000000000..e845566c06f --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/subdir/README @@ -0,0 +1 @@ +README diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/testdata/README b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/testdata/README new file mode 100644 index 00000000000..e845566c06f --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/testdata/README @@ -0,0 +1 @@ +README diff --git a/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/testdata/subsubdir/README b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/testdata/subsubdir/README new file mode 100644 index 00000000000..e845566c06f --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/testdata/subsubdir/README @@ -0,0 +1 @@ +README diff --git a/hack/make-rules/helpers/go2make/testdata/dir-without-gofiles/README b/hack/make-rules/helpers/go2make/testdata/dir-without-gofiles/README new file mode 100644 index 00000000000..e845566c06f --- /dev/null +++ b/hack/make-rules/helpers/go2make/testdata/dir-without-gofiles/README @@ -0,0 +1 @@ +README diff --git a/hack/make-rules/test-cmd-util.sh b/hack/make-rules/test-cmd-util.sh index 492297477f7..c210418c20d 100755 --- a/hack/make-rules/test-cmd-util.sh +++ b/hack/make-rules/test-cmd-util.sh @@ -5278,6 +5278,12 @@ runTests() { output_message=$(kubectl auth can-i list jobs.batch/bar -n foo --quiet 2>&1 "${kube_flags[@]}") kube::test::if_empty_string "${output_message}" + + output_message=$(kubectl auth can-i get pods --subresource=log 2>&1 "${kube_flags[@]}"; echo $?) + kube::test::if_has_string "${output_message}" '0' + + output_message=$(kubectl auth can-i get pods --subresource=log --quiet 2>&1 "${kube_flags[@]}"; echo $?) + kube::test::if_has_string "${output_message}" '0' fi # kubectl auth reconcile diff --git a/hack/update-generated-kubelet-plugin-registration-dockerized.sh b/hack/update-generated-kubelet-plugin-registration-dockerized.sh new file mode 100755 index 00000000000..daf5abbd36a --- /dev/null +++ b/hack/update-generated-kubelet-plugin-registration-dockerized.sh @@ -0,0 +1,29 @@ +#!/bin/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="$(cd "$(dirname "${BASH_SOURCE}")/../" && pwd -P)" +KUBELET_PLUGIN_REGISTRATION_ROOT="${KUBE_ROOT}/pkg/kubelet/apis/pluginregistration/v1alpha1/" +KUBELET_EXAMPLE_PLUGIN_V1BETA1="${KUBE_ROOT}/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/" +KUBELET_EXAMPLE_PLUGIN_V1BETA2="${KUBE_ROOT}/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/" + +source "${KUBE_ROOT}/hack/lib/protoc.sh" +kube::protoc::generate_proto ${KUBELET_PLUGIN_REGISTRATION_ROOT} +kube::protoc::generate_proto ${KUBELET_EXAMPLE_PLUGIN_V1BETA1} +kube::protoc::generate_proto ${KUBELET_EXAMPLE_PLUGIN_V1BETA2} diff --git a/hack/update-generated-kubelet-plugin-registration.sh b/hack/update-generated-kubelet-plugin-registration.sh new file mode 100755 index 00000000000..308733c0246 --- /dev/null +++ b/hack/update-generated-kubelet-plugin-registration.sh @@ -0,0 +1,27 @@ +#!/bin/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}")/.. + +# NOTE: All output from this script needs to be copied back to the calling +# source tree. This is managed in kube::build::copy_output in build/common.sh. +# If the output set is changed update that function. + +${KUBE_ROOT}/build/run.sh hack/update-generated-kubelet-plugin-registration-dockerized.sh "$@" diff --git a/hack/verify-generated-files-remake.sh b/hack/verify-generated-files-remake.sh old mode 100644 new mode 100755 index 9c80a6bc013..5cc44616a26 --- a/hack/verify-generated-files-remake.sh +++ b/hack/verify-generated-files-remake.sh @@ -21,10 +21,303 @@ set -o pipefail KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. source "${KUBE_ROOT}/hack/lib/init.sh" -make generated_files -X=$(make generated_files DBG_CODEGEN=1) -if [[ -n "${X}" ]]; then - echo "Back-to-back 'make' runs are not clean for codegen" - echo "${X}" +# $1 = filename pattern as in "zz_generated.$1.go" +function find_genfiles() { + find . \ + \( \ + -not \( \ + \( \ + -path ./_\* -o \ + -path ./.\* \ + \) -prune \ + \) \ + \) -name "zz_generated.$1.go" +} + +# $1 = filename pattern as in "zz_generated.$1.go" +# $2 timestamp file +function newer() { + find_genfiles "$1" | while read F; do + if [[ "${F}" -nt "$2" ]]; then + echo "${F}" + fi + done +} + +# $1 = filename pattern as in "zz_generated.$1.go" +# $2 timestamp file +function older() { + find_genfiles "$1" | while read F; do + if [[ "$2" -nt "${F}" ]]; then + echo "${F}" + fi + done +} + +function assert_clean() { + make generated_files >/dev/null + touch "${STAMP}" + make generated_files >/dev/null + X=($(newer deepcopy "${STAMP}")) + if [[ "${#X[*]}" != 0 ]]; then + echo "Generated files changed on back-to-back 'make' runs:" + echo " ${X[@]:-(none)}" + return 1 + fi + true +} + +STAMP=/tmp/stamp.$RANDOM + +# +# Test when we touch a file in a package that needs codegen. +# + +assert_clean + +DIR=staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1 +touch "$DIR/types.go" +touch "${STAMP}" +make generated_files >/dev/null +X=($(newer deepcopy "${STAMP}")) +if [[ "${#X[*]}" != 1 || ! ( "${X[0]}" =~ "${DIR}/zz_generated.deepcopy.go" ) ]]; then + echo "Wrong generated deepcopy files changed after touching src file:" + echo " ${X[@]:-(none)}" + exit 1 +fi +X=($(newer defaults "${STAMP}")) +if [[ "${#X[*]}" != 1 || ! ( "${X[0]}" =~ "${DIR}/zz_generated.defaults.go" ) ]]; then + echo "Wrong generated defaults files changed after touching src file:" + echo " ${X[@]:-(none)}" + exit 1 +fi +X=($(newer conversion "${STAMP}")) +if [[ "${#X[*]}" != 1 || ! ( "${X[0]}" =~ "${DIR}/zz_generated.conversion.go" ) ]]; then + echo "Wrong generated conversion files changed after touching src file:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +# +# Test when the codegen tool itself changes: deepcopy +# + +assert_clean + +touch staging/src/k8s.io/code-generator/cmd/deepcopy-gen/main.go +touch "${STAMP}" +make generated_files >/dev/null +X=($(older deepcopy "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated deepcopy files did not change after touching code-generator file:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch staging/src/k8s.io/code-generator/cmd/deepcopy-gen/ +touch "${STAMP}" +make generated_files >/dev/null +X=($(older deepcopy "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated deepcopy files did not change after touching code-generator dir:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch vendor/k8s.io/gengo/examples/deepcopy-gen/generators/deepcopy.go +touch "${STAMP}" +make generated_files >/dev/null +X=($(older deepcopy "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated deepcopy files did not change after touching code-generator dep file:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch vendor/k8s.io/gengo/examples/deepcopy-gen/generators/ +touch "${STAMP}" +make generated_files >/dev/null +X=($(older deepcopy "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated deepcopy files did not change after touching code-generator dep dir:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +# +# Test when the codegen tool itself changes: defaults +# + +assert_clean + +touch staging/src/k8s.io/code-generator/cmd/defaulter-gen/main.go +touch "${STAMP}" +make generated_files >/dev/null +X=($(older defaults "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated defaults files did not change after touching code-generator file:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch staging/src/k8s.io/code-generator/cmd/defaulter-gen/ +touch "${STAMP}" +make generated_files >/dev/null +X=($(older defaults "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated defaults files did not change after touching code-generator dir:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch vendor/k8s.io/gengo/examples/defaulter-gen/generators/defaulter.go +touch "${STAMP}" +make generated_files >/dev/null +X=($(older defaults "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated defaults files did not change after touching code-generator dep file:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch vendor/k8s.io/gengo/examples/defaulter-gen/generators/ +touch "${STAMP}" +make generated_files >/dev/null +X=($(older defaults "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated defaults files did not change after touching code-generator dep dir:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +# +# Test when the codegen tool itself changes: conversion +# + +assert_clean + +touch staging/src/k8s.io/code-generator/cmd/conversion-gen/main.go +touch "${STAMP}" +make generated_files >/dev/null +X=($(older conversion "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated conversion files did not change after touching code-generator file:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch staging/src/k8s.io/code-generator/cmd/conversion-gen/ +touch "${STAMP}" +make generated_files >/dev/null +X=($(older conversion "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated conversion files did not change after touching code-generator dir:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch vendor/k8s.io/code-generator/cmd/conversion-gen/generators/conversion.go +touch "${STAMP}" +make generated_files >/dev/null +X=($(older conversion "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated conversion files did not change after touching code-generator dep file:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch vendor/k8s.io/code-generator/cmd/conversion-gen/generators/ +touch "${STAMP}" +make generated_files >/dev/null +X=($(older conversion "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated conversion files did not change after touching code-generator dep dir:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +# +# Test when we touch a file in a package that needs codegen. +# + +assert_clean + +touch "staging/src/k8s.io/api/core/v1/types.go" +touch "${STAMP}" +make generated_files >/dev/null +X=($(newer openapi "${STAMP}")) +if [[ "${#X[*]}" != 1 || ! ( "${X[0]}" =~ "pkg/generated/openapi/zz_generated.openapi.go" ) ]]; then + echo "Wrong generated openapi files changed after touching src file:" + echo "${X[@]:-(none)}" + exit 1 +fi + +# +# Test when the codegen tool itself changes: openapi +# + +assert_clean + +touch staging/src/k8s.io/code-generator/cmd/openapi-gen/main.go +touch "${STAMP}" +make generated_files >/dev/null +X=($(older openapi "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated openapi files did not change after touching code-generator file:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch staging/src/k8s.io/code-generator/cmd/openapi-gen/ +touch "${STAMP}" +make generated_files >/dev/null +X=($(older openapi "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated openapi files did not change after touching code-generator dir:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch vendor/k8s.io/kube-openapi/pkg/generators/openapi.go +touch "${STAMP}" +make generated_files >/dev/null +X=($(older openapi "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated openapi files did not change after touching code-generator dep file:" + echo " ${X[@]:-(none)}" + exit 1 +fi + +assert_clean + +touch vendor/k8s.io/kube-openapi/pkg/generators +touch "${STAMP}" +make generated_files >/dev/null +X=($(older openapi "${STAMP}")) +if [[ "${#X[*]}" != 0 ]]; then + echo "Generated openapi files did not change after touching code-generator dep dir:" + echo " ${X[@]:-(none)}" exit 1 fi diff --git a/hack/verify-generated-kubelet-plugin-registration.sh b/hack/verify-generated-kubelet-plugin-registration.sh new file mode 100755 index 00000000000..3dfffa8dcc0 --- /dev/null +++ b/hack/verify-generated-kubelet-plugin-registration.sh @@ -0,0 +1,39 @@ +#!/bin/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}")/.. +ERROR="Kubelet Plugin Registration api is out of date. Please run hack/update-generated-kubelet-plugin-registration.sh" +KUBELET_PLUGIN_REGISTRATION_ROOT="${KUBE_ROOT}/pkg/kubelet/apis/pluginregistration/v1alpha1/" + +source "${KUBE_ROOT}/hack/lib/protoc.sh" +kube::golang::setup_env + +function cleanup { + rm -rf ${KUBELET_PLUGIN_REGISTRATION_ROOT}/_tmp/ +} + +trap cleanup EXIT + +mkdir -p ${KUBELET_PLUGIN_REGISTRATION_ROOT}/_tmp +cp ${KUBELET_PLUGIN_REGISTRATION_ROOT}/api.pb.go ${KUBELET_PLUGIN_REGISTRATION_ROOT}/_tmp/ + +KUBE_VERBOSE=3 "${KUBE_ROOT}/hack/update-generated-kubelet-plugin-registration.sh" +kube::protoc::diff "${KUBELET_PLUGIN_REGISTRATION_ROOT}/api.pb.go" "${KUBELET_PLUGIN_REGISTRATION_ROOT}/_tmp/api.pb.go" ${ERROR} +echo "Generated Kubelet Plugin Registration api is up to date." diff --git a/pkg/api/persistentvolume/util.go b/pkg/api/persistentvolume/util.go index d36f7c0cddb..d5a93667aa9 100644 --- a/pkg/api/persistentvolume/util.go +++ b/pkg/api/persistentvolume/util.go @@ -61,6 +61,10 @@ func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool { return false } } + case source.Cinder != nil: + if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Namespace, source.Cinder.SecretRef.Name, true /* kubeletVisible */) { + return false + } case source.FlexVolume != nil: if source.FlexVolume.SecretRef != nil { // previously persisted PV objects use claimRef namespace diff --git a/pkg/api/persistentvolume/util_test.go b/pkg/api/persistentvolume/util_test.go index e2d5a15278f..ffa361cc93d 100644 --- a/pkg/api/persistentvolume/util_test.go +++ b/pkg/api/persistentvolume/util_test.go @@ -58,6 +58,12 @@ func TestPVSecrets(t *testing.T) { CephFS: &api.CephFSPersistentVolumeSource{ SecretRef: &api.SecretReference{ Name: "Spec.PersistentVolumeSource.CephFS.SecretRef"}}}}}, + {Spec: api.PersistentVolumeSpec{ + PersistentVolumeSource: api.PersistentVolumeSource{ + Cinder: &api.CinderPersistentVolumeSource{ + SecretRef: &api.SecretReference{ + Name: "Spec.PersistentVolumeSource.Cinder.SecretRef", + Namespace: "cinder"}}}}}, {Spec: api.PersistentVolumeSpec{ ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"}, PersistentVolumeSource: api.PersistentVolumeSource{ @@ -159,6 +165,7 @@ func TestPVSecrets(t *testing.T) { expectedSecretPaths := sets.NewString( "Spec.PersistentVolumeSource.AzureFile.SecretName", "Spec.PersistentVolumeSource.CephFS.SecretRef", + "Spec.PersistentVolumeSource.Cinder.SecretRef", "Spec.PersistentVolumeSource.FlexVolume.SecretRef", "Spec.PersistentVolumeSource.RBD.SecretRef", "Spec.PersistentVolumeSource.ScaleIO.SecretRef", @@ -195,6 +202,8 @@ func TestPVSecrets(t *testing.T) { "claimrefns/Spec.PersistentVolumeSource.CephFS.SecretRef", "cephfs/Spec.PersistentVolumeSource.CephFS.SecretRef", + "cinder/Spec.PersistentVolumeSource.Cinder.SecretRef", + "claimrefns/Spec.PersistentVolumeSource.FlexVolume.SecretRef", "flexns/Spec.PersistentVolumeSource.FlexVolume.SecretRef", diff --git a/pkg/api/pod/util.go b/pkg/api/pod/util.go index 0d17feef33a..c462855420e 100644 --- a/pkg/api/pod/util.go +++ b/pkg/api/pod/util.go @@ -58,6 +58,10 @@ func VisitPodSecretNames(pod *api.Pod, visitor Visitor) bool { if source.CephFS.SecretRef != nil && !visitor(source.CephFS.SecretRef.Name) { return false } + case source.Cinder != nil: + if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Name) { + return false + } case source.FlexVolume != nil: if source.FlexVolume.SecretRef != nil && !visitor(source.FlexVolume.SecretRef.Name) { return false diff --git a/pkg/api/pod/util_test.go b/pkg/api/pod/util_test.go index 43ddf8aff8a..b29f822013a 100644 --- a/pkg/api/pod/util_test.go +++ b/pkg/api/pod/util_test.go @@ -64,6 +64,10 @@ func TestPodSecrets(t *testing.T) { CephFS: &api.CephFSVolumeSource{ SecretRef: &api.LocalObjectReference{ Name: "Spec.Volumes[*].VolumeSource.CephFS.SecretRef"}}}}, { + VolumeSource: api.VolumeSource{ + Cinder: &api.CinderVolumeSource{ + SecretRef: &api.LocalObjectReference{ + Name: "Spec.Volumes[*].VolumeSource.Cinder.SecretRef"}}}}, { VolumeSource: api.VolumeSource{ FlexVolume: &api.FlexVolumeSource{ SecretRef: &api.LocalObjectReference{ @@ -118,6 +122,7 @@ func TestPodSecrets(t *testing.T) { "Spec.InitContainers[*].Env[*].ValueFrom.SecretKeyRef", "Spec.Volumes[*].VolumeSource.AzureFile.SecretName", "Spec.Volumes[*].VolumeSource.CephFS.SecretRef", + "Spec.Volumes[*].VolumeSource.Cinder.SecretRef", "Spec.Volumes[*].VolumeSource.FlexVolume.SecretRef", "Spec.Volumes[*].VolumeSource.Projected.Sources[*].Secret", "Spec.Volumes[*].VolumeSource.RBD.SecretRef", diff --git a/pkg/api/testing/BUILD b/pkg/api/testing/BUILD index 5b7ba9b52a3..677c51b6df8 100644 --- a/pkg/api/testing/BUILD +++ b/pkg/api/testing/BUILD @@ -96,6 +96,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", diff --git a/pkg/api/testing/serialization_test.go b/pkg/api/testing/serialization_test.go index 39f60d2992f..cccccedb8c0 100644 --- a/pkg/api/testing/serialization_test.go +++ b/pkg/api/testing/serialization_test.go @@ -37,6 +37,7 @@ import ( "k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json" "k8s.io/apimachinery/pkg/runtime/serializer/streaming" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/sets" @@ -299,6 +300,9 @@ func TestObjectWatchFraming(t *testing.T) { f := fuzzer.FuzzerFor(FuzzerFuncs, rand.NewSource(benchmarkSeed), legacyscheme.Codecs) secret := &api.Secret{} f.Fuzz(secret) + if secret.Data == nil { + secret.Data = map[string][]byte{} + } secret.Data["binary"] = []byte{0x00, 0x10, 0x30, 0x55, 0xff, 0x00} secret.Data["utf8"] = []byte("a string with \u0345 characters") secret.Data["long"] = bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x00}, 1000) @@ -557,9 +561,10 @@ func BenchmarkDecodeIntoJSONCodecGenConfigFast(b *testing.B) { b.StopTimer() } -// BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary -// provides a baseline for JSON decode performance -// with jsoniter.ConfigCompatibleWithStandardLibrary +// BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary provides a +// baseline for JSON decode performance with +// jsoniter.ConfigCompatibleWithStandardLibrary, but with case sensitivity set +// to true func BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary(b *testing.B) { kcodec := testapi.Default.Codec() items := benchmarkItems(b) @@ -574,9 +579,10 @@ func BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary(b *testi } b.ResetTimer() + iter := k8s_json.CaseSensitiveJsonIterator() for i := 0; i < b.N; i++ { obj := v1.Pod{} - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(encoded[i%width], &obj); err != nil { + if err := iter.Unmarshal(encoded[i%width], &obj); err != nil { b.Fatal(err) } } diff --git a/pkg/api/v1/pod/util.go b/pkg/api/v1/pod/util.go index aa79c7250db..e84295092e4 100644 --- a/pkg/api/v1/pod/util.go +++ b/pkg/api/v1/pod/util.go @@ -84,6 +84,10 @@ func VisitPodSecretNames(pod *v1.Pod, visitor Visitor) bool { if source.CephFS.SecretRef != nil && !visitor(source.CephFS.SecretRef.Name) { return false } + case source.Cinder != nil: + if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Name) { + return false + } case source.FlexVolume != nil: if source.FlexVolume.SecretRef != nil && !visitor(source.FlexVolume.SecretRef.Name) { return false @@ -257,9 +261,18 @@ func GetPodCondition(status *v1.PodStatus, conditionType v1.PodConditionType) (i if status == nil { return -1, nil } - for i := range status.Conditions { - if status.Conditions[i].Type == conditionType { - return i, &status.Conditions[i] + return GetPodConditionFromList(status.Conditions, conditionType) +} + +// GetPodConditionFromList extracts the provided condition from the given list of condition and +// returns the index of the condition and the condition. Returns -1 and nil if the condition is not present. +func GetPodConditionFromList(conditions []v1.PodCondition, conditionType v1.PodConditionType) (int, *v1.PodCondition) { + if conditions == nil { + return -1, nil + } + for i := range conditions { + if conditions[i].Type == conditionType { + return i, &conditions[i] } } return -1, nil diff --git a/pkg/api/v1/pod/util_test.go b/pkg/api/v1/pod/util_test.go index 5310bc32859..aad3a258bbf 100644 --- a/pkg/api/v1/pod/util_test.go +++ b/pkg/api/v1/pod/util_test.go @@ -233,6 +233,10 @@ func TestPodSecrets(t *testing.T) { CephFS: &v1.CephFSVolumeSource{ SecretRef: &v1.LocalObjectReference{ Name: "Spec.Volumes[*].VolumeSource.CephFS.SecretRef"}}}}, { + VolumeSource: v1.VolumeSource{ + Cinder: &v1.CinderVolumeSource{ + SecretRef: &v1.LocalObjectReference{ + Name: "Spec.Volumes[*].VolumeSource.Cinder.SecretRef"}}}}, { VolumeSource: v1.VolumeSource{ FlexVolume: &v1.FlexVolumeSource{ SecretRef: &v1.LocalObjectReference{ @@ -287,6 +291,7 @@ func TestPodSecrets(t *testing.T) { "Spec.InitContainers[*].Env[*].ValueFrom.SecretKeyRef", "Spec.Volumes[*].VolumeSource.AzureFile.SecretName", "Spec.Volumes[*].VolumeSource.CephFS.SecretRef", + "Spec.Volumes[*].VolumeSource.Cinder.SecretRef", "Spec.Volumes[*].VolumeSource.FlexVolume.SecretRef", "Spec.Volumes[*].VolumeSource.Projected.Sources[*].Secret", "Spec.Volumes[*].VolumeSource.RBD.SecretRef", diff --git a/pkg/apis/apps/fuzzer/BUILD b/pkg/apis/apps/fuzzer/BUILD index 80ee7db3234..3e37df54cda 100644 --- a/pkg/apis/apps/fuzzer/BUILD +++ b/pkg/apis/apps/fuzzer/BUILD @@ -12,6 +12,7 @@ go_library( deps = [ "//pkg/apis/apps:go_default_library", "//vendor/github.com/google/gofuzz:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", ], ) diff --git a/pkg/apis/apps/fuzzer/fuzzer.go b/pkg/apis/apps/fuzzer/fuzzer.go index 8013a273b01..edd83be2508 100644 --- a/pkg/apis/apps/fuzzer/fuzzer.go +++ b/pkg/apis/apps/fuzzer/fuzzer.go @@ -19,6 +19,7 @@ package fuzzer import ( fuzz "github.com/google/gofuzz" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/kubernetes/pkg/apis/apps" ) @@ -46,6 +47,12 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { if s.Status.CollisionCount == nil { s.Status.CollisionCount = new(int32) } + if s.Spec.Selector == nil { + s.Spec.Selector = &metav1.LabelSelector{MatchLabels: s.Spec.Template.Labels} + } + if len(s.Labels) == 0 { + s.Labels = s.Spec.Template.Labels + } }, } } diff --git a/pkg/apis/apps/v1/conversion.go b/pkg/apis/apps/v1/conversion.go index 0908f7fc2bb..565430b0e96 100644 --- a/pkg/apis/apps/v1/conversion.go +++ b/pkg/apis/apps/v1/conversion.go @@ -182,6 +182,7 @@ func Convert_v1_Deployment_To_extensions_Deployment(in *appsv1.Deployment, out * out.Spec.RollbackTo = new(extensions.RollbackConfig) out.Spec.RollbackTo.Revision = revision64 } + out.Annotations = deepCopyStringMap(out.Annotations) delete(out.Annotations, appsv1.DeprecatedRollbackTo) } else { out.Spec.RollbackTo = nil @@ -195,6 +196,8 @@ func Convert_v1_Deployment_To_extensions_Deployment(in *appsv1.Deployment, out * func Convert_extensions_Deployment_To_v1_Deployment(in *extensions.Deployment, out *appsv1.Deployment, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta + out.Annotations = deepCopyStringMap(out.Annotations) // deep copy because we modify it below + if err := Convert_extensions_DeploymentSpec_To_v1_DeploymentSpec(&in.Spec, &out.Spec, s); err != nil { return err } @@ -235,9 +238,8 @@ func Convert_v1_RollingUpdateDaemonSet_To_extensions_RollingUpdateDaemonSet(in * func Convert_extensions_DaemonSet_To_v1_DaemonSet(in *extensions.DaemonSet, out *appsv1.DaemonSet, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if out.Annotations == nil { - out.Annotations = make(map[string]string) - } + out.Annotations = deepCopyStringMap(out.Annotations) // deep copy annotations because we change them below + out.Annotations[appsv1.DeprecatedTemplateGeneration] = strconv.FormatInt(in.Spec.TemplateGeneration, 10) if err := Convert_extensions_DaemonSetSpec_To_v1_DaemonSetSpec(&in.Spec, &out.Spec, s); err != nil { return err @@ -287,6 +289,7 @@ func Convert_v1_DaemonSet_To_extensions_DaemonSet(in *appsv1.DaemonSet, out *ext return err } else { out.Spec.TemplateGeneration = value64 + out.Annotations = deepCopyStringMap(out.Annotations) delete(out.Annotations, appsv1.DeprecatedTemplateGeneration) } } @@ -496,3 +499,11 @@ func Convert_apps_StatefulSetStatus_To_v1_StatefulSetStatus(in *apps.StatefulSet } return nil } + +func deepCopyStringMap(m map[string]string) map[string]string { + ret := make(map[string]string, len(m)) + for k, v := range m { + ret[k] = v + } + return ret +} diff --git a/pkg/apis/apps/v1/zz_generated.defaults.go b/pkg/apis/apps/v1/zz_generated.defaults.go index 257bac9e8e6..8a4a0a5d724 100644 --- a/pkg/apis/apps/v1/zz_generated.defaults.go +++ b/pkg/apis/apps/v1/zz_generated.defaults.go @@ -86,6 +86,9 @@ func SetObjectDefaults_DaemonSet(in *v1.DaemonSet) { } } } + if b.ServiceAccountToken != nil { + core_v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -230,6 +233,9 @@ func SetObjectDefaults_Deployment(in *v1.Deployment) { } } } + if b.ServiceAccountToken != nil { + core_v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -374,6 +380,9 @@ func SetObjectDefaults_ReplicaSet(in *v1.ReplicaSet) { } } } + if b.ServiceAccountToken != nil { + core_v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -518,6 +527,9 @@ func SetObjectDefaults_StatefulSet(in *v1.StatefulSet) { } } } + if b.ServiceAccountToken != nil { + core_v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/pkg/apis/apps/v1beta1/zz_generated.defaults.go b/pkg/apis/apps/v1beta1/zz_generated.defaults.go index 17f2fda2ea9..656f61edc99 100644 --- a/pkg/apis/apps/v1beta1/zz_generated.defaults.go +++ b/pkg/apis/apps/v1beta1/zz_generated.defaults.go @@ -82,6 +82,9 @@ func SetObjectDefaults_Deployment(in *v1beta1.Deployment) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -226,6 +229,9 @@ func SetObjectDefaults_StatefulSet(in *v1beta1.StatefulSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/pkg/apis/apps/v1beta2/conversion.go b/pkg/apis/apps/v1beta2/conversion.go index f71de4f28e7..a3671668fcb 100644 --- a/pkg/apis/apps/v1beta2/conversion.go +++ b/pkg/apis/apps/v1beta2/conversion.go @@ -415,6 +415,7 @@ func Convert_v1beta2_Deployment_To_extensions_Deployment(in *appsv1beta2.Deploym out.Spec.RollbackTo = new(extensions.RollbackConfig) out.Spec.RollbackTo.Revision = revision64 } + out.Annotations = deepCopyStringMap(out.Annotations) delete(out.Annotations, appsv1beta2.DeprecatedRollbackTo) } else { out.Spec.RollbackTo = nil @@ -440,6 +441,8 @@ func Convert_v1beta2_ReplicaSetSpec_To_extensions_ReplicaSetSpec(in *appsv1beta2 func Convert_extensions_Deployment_To_v1beta2_Deployment(in *extensions.Deployment, out *appsv1beta2.Deployment, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta + out.Annotations = deepCopyStringMap(out.Annotations) // deep copy because we modify annotations below + if err := Convert_extensions_DeploymentSpec_To_v1beta2_DeploymentSpec(&in.Spec, &out.Spec, s); err != nil { return err } @@ -463,9 +466,7 @@ func Convert_extensions_Deployment_To_v1beta2_Deployment(in *extensions.Deployme func Convert_extensions_DaemonSet_To_v1beta2_DaemonSet(in *extensions.DaemonSet, out *appsv1beta2.DaemonSet, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if out.Annotations == nil { - out.Annotations = make(map[string]string) - } + out.Annotations = deepCopyStringMap(out.Annotations) out.Annotations[appsv1beta2.DeprecatedTemplateGeneration] = strconv.FormatInt(in.Spec.TemplateGeneration, 10) if err := Convert_extensions_DaemonSetSpec_To_v1beta2_DaemonSetSpec(&in.Spec, &out.Spec, s); err != nil { return err @@ -515,6 +516,7 @@ func Convert_v1beta2_DaemonSet_To_extensions_DaemonSet(in *appsv1beta2.DaemonSet return err } else { out.Spec.TemplateGeneration = value64 + out.Annotations = deepCopyStringMap(out.Annotations) delete(out.Annotations, appsv1beta2.DeprecatedTemplateGeneration) } } @@ -552,3 +554,11 @@ func Convert_v1beta2_DaemonSetUpdateStrategy_To_extensions_DaemonSetUpdateStrate } return nil } + +func deepCopyStringMap(m map[string]string) map[string]string { + ret := make(map[string]string, len(m)) + for k, v := range m { + ret[k] = v + } + return ret +} diff --git a/pkg/apis/apps/v1beta2/zz_generated.defaults.go b/pkg/apis/apps/v1beta2/zz_generated.defaults.go index 8415f3a614f..713bcaa7819 100644 --- a/pkg/apis/apps/v1beta2/zz_generated.defaults.go +++ b/pkg/apis/apps/v1beta2/zz_generated.defaults.go @@ -86,6 +86,9 @@ func SetObjectDefaults_DaemonSet(in *v1beta2.DaemonSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -230,6 +233,9 @@ func SetObjectDefaults_Deployment(in *v1beta2.Deployment) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -374,6 +380,9 @@ func SetObjectDefaults_ReplicaSet(in *v1beta2.ReplicaSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -518,6 +527,9 @@ func SetObjectDefaults_StatefulSet(in *v1beta2.StatefulSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/pkg/apis/authentication/BUILD b/pkg/apis/authentication/BUILD index 1d09c7766db..1781f634232 100644 --- a/pkg/apis/authentication/BUILD +++ b/pkg/apis/authentication/BUILD @@ -37,6 +37,7 @@ filegroup( "//pkg/apis/authentication/install:all-srcs", "//pkg/apis/authentication/v1:all-srcs", "//pkg/apis/authentication/v1beta1:all-srcs", + "//pkg/apis/authentication/validation:all-srcs", ], tags = ["automanaged"], ) diff --git a/vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/BUILD b/pkg/apis/authentication/validation/BUILD similarity index 57% rename from vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/BUILD rename to pkg/apis/authentication/validation/BUILD index 35716e585b4..3192543f9c7 100644 --- a/vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/BUILD +++ b/pkg/apis/authentication/validation/BUILD @@ -2,9 +2,13 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", - srcs = ["doc.go"], - importpath = "google.golang.org/grpc/grpclb/grpc_lb_v1", + srcs = ["validation.go"], + importpath = "k8s.io/kubernetes/pkg/apis/authentication/validation", visibility = ["//visibility:public"], + deps = [ + "//pkg/apis/authentication:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + ], ) filegroup( @@ -16,10 +20,7 @@ filegroup( filegroup( name = "all-srcs", - srcs = [ - ":package-srcs", - "//vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/messages:all-srcs", - ], + srcs = [":package-srcs"], tags = ["automanaged"], visibility = ["//visibility:public"], ) diff --git a/pkg/apis/authentication/validation/validation.go b/pkg/apis/authentication/validation/validation.go new file mode 100644 index 00000000000..b174ddfc1e9 --- /dev/null +++ b/pkg/apis/authentication/validation/validation.go @@ -0,0 +1,41 @@ +/* +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 validation contains methods to validate kinds in the +// authentication.k8s.io API group. +package validation + +import ( + "time" + + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/kubernetes/pkg/apis/authentication" +) + +// ValidateTokenRequest validates a TokenRequest. +func ValidateTokenRequest(tr *authentication.TokenRequest) field.ErrorList { + allErrs := field.ErrorList{} + specPath := field.NewPath("spec") + + const min = 10 * time.Minute + if tr.Spec.ExpirationSeconds < int64(min.Seconds()) { + allErrs = append(allErrs, field.Invalid(specPath.Child("expirationSeconds"), tr.Spec.ExpirationSeconds, "may not specify a duration less than 10 minutes")) + } + if tr.Spec.ExpirationSeconds > 1<<32 { + allErrs = append(allErrs, field.Invalid(specPath.Child("expirationSeconds"), tr.Spec.ExpirationSeconds, "may not specify a duration larger than 2^32 seconds")) + } + return allErrs +} diff --git a/pkg/apis/batch/fuzzer/fuzzer.go b/pkg/apis/batch/fuzzer/fuzzer.go index 4b0a8b9064d..b6f82a2b1e3 100644 --- a/pkg/apis/batch/fuzzer/fuzzer.go +++ b/pkg/apis/batch/fuzzer/fuzzer.go @@ -32,6 +32,14 @@ func newBool(val bool) *bool { // Funcs returns the fuzzer functions for the batch api group. var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ + func(j *batch.Job, c fuzz.Continue) { + c.FuzzNoCustom(j) // fuzz self without calling this function again + + // match defaulting + if len(j.Labels) == 0 { + j.Labels = j.Spec.Template.Labels + } + }, func(j *batch.JobSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // fuzz self without calling this function again completions := int32(c.Rand.Int31()) diff --git a/pkg/apis/batch/v1/zz_generated.defaults.go b/pkg/apis/batch/v1/zz_generated.defaults.go index 985b58211f0..859d17b768c 100644 --- a/pkg/apis/batch/v1/zz_generated.defaults.go +++ b/pkg/apis/batch/v1/zz_generated.defaults.go @@ -80,6 +80,9 @@ func SetObjectDefaults_Job(in *v1.Job) { } } } + if b.ServiceAccountToken != nil { + core_v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/pkg/apis/batch/v1beta1/zz_generated.defaults.go b/pkg/apis/batch/v1beta1/zz_generated.defaults.go index c18e8ec10a9..d90031c32aa 100644 --- a/pkg/apis/batch/v1beta1/zz_generated.defaults.go +++ b/pkg/apis/batch/v1beta1/zz_generated.defaults.go @@ -81,6 +81,9 @@ func SetObjectDefaults_CronJob(in *v1beta1.CronJob) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -224,6 +227,9 @@ func SetObjectDefaults_JobTemplate(in *v1beta1.JobTemplate) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/pkg/apis/batch/v2alpha1/zz_generated.defaults.go b/pkg/apis/batch/v2alpha1/zz_generated.defaults.go index ea224b1024d..367c56b15ed 100644 --- a/pkg/apis/batch/v2alpha1/zz_generated.defaults.go +++ b/pkg/apis/batch/v2alpha1/zz_generated.defaults.go @@ -81,6 +81,9 @@ func SetObjectDefaults_CronJob(in *v2alpha1.CronJob) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -224,6 +227,9 @@ func SetObjectDefaults_JobTemplate(in *v2alpha1.JobTemplate) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/pkg/apis/componentconfig/types.go b/pkg/apis/componentconfig/types.go index 7ca6a224445..51f79b1513e 100644 --- a/pkg/apis/componentconfig/types.go +++ b/pkg/apis/componentconfig/types.go @@ -323,9 +323,6 @@ type KubeCloudSharedConfiguration struct { // configureCloudRoutes enables CIDRs allocated with allocateNodeCIDRs // to be configured on the cloud provider. ConfigureCloudRoutes bool - // serviceAccountKeyFile is the filename containing a PEM-encoded private RSA key - // used to sign service account tokens. - ServiceAccountKeyFile string // nodeSyncPeriod is the period for syncing nodes from cloudprovider. Longer // periods will result in fewer calls to cloud provider, but may delay addition // of new nodes to cluster. @@ -506,6 +503,9 @@ type ResourceQuotaControllerConfiguration struct { } type SAControllerConfiguration struct { + // serviceAccountKeyFile is the filename containing a PEM-encoded private RSA key + // used to sign service account tokens. + ServiceAccountKeyFile string // concurrentSATokenSyncs is the number of service account token syncing operations // that will be done concurrently. ConcurrentSATokenSyncs int32 diff --git a/pkg/apis/componentconfig/v1alpha1/types.go b/pkg/apis/componentconfig/v1alpha1/types.go index 129f5d650c5..55b10a11519 100644 --- a/pkg/apis/componentconfig/v1alpha1/types.go +++ b/pkg/apis/componentconfig/v1alpha1/types.go @@ -366,9 +366,6 @@ type KubeCloudSharedConfiguration struct { // configureCloudRoutes enables CIDRs allocated with allocateNodeCIDRs // to be configured on the cloud provider. ConfigureCloudRoutes *bool `json:"configureCloudRoutes"` - // serviceAccountKeyFile is the filename containing a PEM-encoded private RSA key - // used to sign service account tokens. - ServiceAccountKeyFile string `json:"serviceAccountKeyFile"` // nodeSyncPeriod is the period for syncing nodes from cloudprovider. Longer // periods will result in fewer calls to cloud provider, but may delay addition // of new nodes to cluster. @@ -549,6 +546,9 @@ type ResourceQuotaControllerConfiguration struct { } type SAControllerConfiguration struct { + // serviceAccountKeyFile is the filename containing a PEM-encoded private RSA key + // used to sign service account tokens. + ServiceAccountKeyFile string `json:"serviceAccountKeyFile"` // concurrentSATokenSyncs is the number of service account token syncing operations // that will be done concurrently. ConcurrentSATokenSyncs int32 `json:"concurrentSATokenSyncs"` diff --git a/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go b/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go index 9e6cc33cb32..3412cc7c004 100644 --- a/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go @@ -516,7 +516,6 @@ func autoConvert_v1alpha1_KubeCloudSharedConfiguration_To_componentconfig_KubeCl if err := v1.Convert_Pointer_bool_To_bool(&in.ConfigureCloudRoutes, &out.ConfigureCloudRoutes, s); err != nil { return err } - out.ServiceAccountKeyFile = in.ServiceAccountKeyFile out.NodeSyncPeriod = in.NodeSyncPeriod return nil } @@ -540,7 +539,6 @@ func autoConvert_componentconfig_KubeCloudSharedConfiguration_To_v1alpha1_KubeCl if err := v1.Convert_bool_To_Pointer_bool(&in.ConfigureCloudRoutes, &out.ConfigureCloudRoutes, s); err != nil { return err } - out.ServiceAccountKeyFile = in.ServiceAccountKeyFile out.NodeSyncPeriod = in.NodeSyncPeriod return nil } @@ -1045,6 +1043,7 @@ func Convert_componentconfig_ResourceQuotaControllerConfiguration_To_v1alpha1_Re } func autoConvert_v1alpha1_SAControllerConfiguration_To_componentconfig_SAControllerConfiguration(in *SAControllerConfiguration, out *componentconfig.SAControllerConfiguration, s conversion.Scope) error { + out.ServiceAccountKeyFile = in.ServiceAccountKeyFile out.ConcurrentSATokenSyncs = in.ConcurrentSATokenSyncs out.RootCAFile = in.RootCAFile return nil @@ -1056,6 +1055,7 @@ func Convert_v1alpha1_SAControllerConfiguration_To_componentconfig_SAControllerC } func autoConvert_componentconfig_SAControllerConfiguration_To_v1alpha1_SAControllerConfiguration(in *componentconfig.SAControllerConfiguration, out *SAControllerConfiguration, s conversion.Scope) error { + out.ServiceAccountKeyFile = in.ServiceAccountKeyFile out.ConcurrentSATokenSyncs = in.ConcurrentSATokenSyncs out.RootCAFile = in.RootCAFile return nil diff --git a/pkg/apis/core/annotation_key_constants.go b/pkg/apis/core/annotation_key_constants.go index cfebd86a4b1..a1e6daae496 100644 --- a/pkg/apis/core/annotation_key_constants.go +++ b/pkg/apis/core/annotation_key_constants.go @@ -56,20 +56,6 @@ const ( // in the Annotations of a Node. PreferAvoidPodsAnnotationKey string = "scheduler.alpha.kubernetes.io/preferAvoidPods" - // SysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Only a limited set of whitelisted and isolated sysctls is supported by - // the kubelet. Pods with other sysctls will fail to launch. - SysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/sysctls" - - // UnsafeSysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Unsafe sysctls must be explicitly enabled for a kubelet. They are properly - // namespaced to a pod or a container, but their isolation is usually unclear or weak. Their use - // is at-your-own-risk. Pods that attempt to set an unsafe sysctl that is not enabled for a kubelet - // will fail to launch. - UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls" - // ObjectTTLAnnotations represents a suggestion for kubelet for how long it can cache // an object (e.g. secret, config map) before fetching it again from apiserver. // This annotation can be attached to node. diff --git a/pkg/apis/core/fuzzer/fuzzer.go b/pkg/apis/core/fuzzer/fuzzer.go index 73ddd36d094..dede9ceb690 100644 --- a/pkg/apis/core/fuzzer/fuzzer.go +++ b/pkg/apis/core/fuzzer/fuzzer.go @@ -93,6 +93,19 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { c.Fuzz(&j.ObjectMeta) j.Target.Name = c.RandString() }, + func(j *core.ReplicationController, c fuzz.Continue) { + c.FuzzNoCustom(j) + + // match defaulting + if j.Spec.Template != nil { + if len(j.Labels) == 0 { + j.Labels = j.Spec.Template.Labels + } + if len(j.Spec.Selector) == 0 { + j.Spec.Selector = j.Spec.Template.Labels + } + } + }, func(j *core.ReplicationControllerSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // fuzz self without calling this function again //j.TemplateRef = nil // this is required for round trip diff --git a/pkg/apis/core/helper/helpers.go b/pkg/apis/core/helper/helpers.go index 7f0523579ef..7be34a8578b 100644 --- a/pkg/apis/core/helper/helpers.go +++ b/pkg/apis/core/helper/helpers.go @@ -103,6 +103,7 @@ var standardResourceQuotaScopes = sets.NewString( string(core.ResourceQuotaScopeNotTerminating), string(core.ResourceQuotaScopeBestEffort), string(core.ResourceQuotaScopeNotBestEffort), + string(core.ResourceQuotaScopePriorityClass), ) // IsStandardResourceQuotaScope returns true if the scope is a standard value @@ -126,7 +127,7 @@ var podComputeQuotaResources = sets.NewString( // IsResourceQuotaScopeValidForResource returns true if the resource applies to the specified scope func IsResourceQuotaScopeValidForResource(scope core.ResourceQuotaScope, resource string) bool { switch scope { - case core.ResourceQuotaScopeTerminating, core.ResourceQuotaScopeNotTerminating, core.ResourceQuotaScopeNotBestEffort: + case core.ResourceQuotaScopeTerminating, core.ResourceQuotaScopeNotTerminating, core.ResourceQuotaScopeNotBestEffort, core.ResourceQuotaScopePriorityClass: return podObjectCountQuotaResources.Has(resource) || podComputeQuotaResources.Has(resource) case core.ResourceQuotaScopeBestEffort: return podObjectCountQuotaResources.Has(resource) @@ -498,54 +499,6 @@ func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]core.Taint, return taints, nil } -// SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls -// and a slice of unsafe Sysctls. This is only a convenience wrapper around -// SysctlsFromPodAnnotation. -func SysctlsFromPodAnnotations(a map[string]string) ([]core.Sysctl, []core.Sysctl, error) { - safe, err := SysctlsFromPodAnnotation(a[core.SysctlsPodAnnotationKey]) - if err != nil { - return nil, nil, err - } - unsafe, err := SysctlsFromPodAnnotation(a[core.UnsafeSysctlsPodAnnotationKey]) - if err != nil { - return nil, nil, err - } - - return safe, unsafe, nil -} - -// SysctlsFromPodAnnotation parses an annotation value into a slice of Sysctls. -func SysctlsFromPodAnnotation(annotation string) ([]core.Sysctl, error) { - if len(annotation) == 0 { - return nil, nil - } - - kvs := strings.Split(annotation, ",") - sysctls := make([]core.Sysctl, len(kvs)) - for i, kv := range kvs { - cs := strings.Split(kv, "=") - if len(cs) != 2 || len(cs[0]) == 0 { - return nil, fmt.Errorf("sysctl %q not of the format sysctl_name=value", kv) - } - sysctls[i].Name = cs[0] - sysctls[i].Value = cs[1] - } - return sysctls, nil -} - -// PodAnnotationsFromSysctls creates an annotation value for a slice of Sysctls. -func PodAnnotationsFromSysctls(sysctls []core.Sysctl) string { - if len(sysctls) == 0 { - return "" - } - - kvs := make([]string, len(sysctls)) - for i := range sysctls { - kvs[i] = fmt.Sprintf("%s=%s", sysctls[i].Name, sysctls[i].Value) - } - return strings.Join(kvs, ",") -} - // GetPersistentVolumeClass returns StorageClassName. func GetPersistentVolumeClass(volume *core.PersistentVolume) string { // Use beta annotation first @@ -584,3 +537,28 @@ func PersistentVolumeClaimHasClass(claim *core.PersistentVolumeClaim) bool { return false } + +// ScopedResourceSelectorRequirementsAsSelector converts the ScopedResourceSelectorRequirement api type into a struct that implements +// labels.Selector. +func ScopedResourceSelectorRequirementsAsSelector(ssr core.ScopedResourceSelectorRequirement) (labels.Selector, error) { + selector := labels.NewSelector() + var op selection.Operator + switch ssr.Operator { + case core.ScopeSelectorOpIn: + op = selection.In + case core.ScopeSelectorOpNotIn: + op = selection.NotIn + case core.ScopeSelectorOpExists: + op = selection.Exists + case core.ScopeSelectorOpDoesNotExist: + op = selection.DoesNotExist + default: + return nil, fmt.Errorf("%q is not a valid scope selector operator", ssr.Operator) + } + r, err := labels.NewRequirement(string(ssr.ScopeName), op, ssr.Values) + if err != nil { + return nil, err + } + selector = selector.Add(*r) + return selector, nil +} diff --git a/pkg/apis/core/helper/helpers_test.go b/pkg/apis/core/helper/helpers_test.go index c63ba46c295..2d1700b155c 100644 --- a/pkg/apis/core/helper/helpers_test.go +++ b/pkg/apis/core/helper/helpers_test.go @@ -239,53 +239,6 @@ func TestNodeSelectorRequirementsAsSelector(t *testing.T) { } } -func TestSysctlsFromPodAnnotation(t *testing.T) { - type Test struct { - annotation string - expectValue []core.Sysctl - expectErr bool - } - for i, test := range []Test{ - { - annotation: "", - expectValue: nil, - }, - { - annotation: "foo.bar", - expectErr: true, - }, - { - annotation: "=123", - expectErr: true, - }, - { - annotation: "foo.bar=", - expectValue: []core.Sysctl{{Name: "foo.bar", Value: ""}}, - }, - { - annotation: "foo.bar=42", - expectValue: []core.Sysctl{{Name: "foo.bar", Value: "42"}}, - }, - { - annotation: "foo.bar=42,", - expectErr: true, - }, - { - annotation: "foo.bar=42,abc.def=1", - expectValue: []core.Sysctl{{Name: "foo.bar", Value: "42"}, {Name: "abc.def", Value: "1"}}, - }, - } { - sysctls, err := SysctlsFromPodAnnotation(test.annotation) - if test.expectErr && err == nil { - t.Errorf("[%v]expected error but got none", i) - } else if !test.expectErr && err != nil { - t.Errorf("[%v]did not expect error but got: %v", i, err) - } else if !reflect.DeepEqual(sysctls, test.expectValue) { - t.Errorf("[%v]expect value %v but got %v", i, test.expectValue, sysctls) - } - } -} - func TestIsHugePageResourceName(t *testing.T) { testCases := []struct { name core.ResourceName diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index 54c23ab7194..cd1235b6c3e 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -75,6 +75,9 @@ type VolumeSource struct { // +optional AWSElasticBlockStore *AWSElasticBlockStoreVolumeSource // GitRepo represents a git repository at a particular revision. + // DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an + // EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir + // into the Pod's container. // +optional GitRepo *GitRepoVolumeSource // Secret represents a secret that should populate this volume. @@ -190,7 +193,7 @@ type PersistentVolumeSource struct { FlexVolume *FlexPersistentVolumeSource // Cinder represents a cinder volume attached and mounted on kubelets host machine // +optional - Cinder *CinderVolumeSource + Cinder *CinderPersistentVolumeSource // CephFS represents a Ceph FS mount on the host that shares a pod's lifetime // +optional CephFS *CephFSPersistentVolumeSource @@ -790,6 +793,10 @@ type AWSElasticBlockStoreVolumeSource struct { // Represents a volume that is populated with the contents of a git repository. // Git repo volumes do not support ownership management. // Git repo volumes support SELinux relabeling. +// +// DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an +// EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir +// into the Pod's container. type GitRepoVolumeSource struct { // Repository URL Repository string @@ -992,6 +999,32 @@ type CinderVolumeSource struct { // the ReadOnly setting in VolumeMounts. // +optional ReadOnly bool + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + SecretRef *LocalObjectReference +} + +// Represents a cinder volume resource in Openstack. A Cinder volume +// must exist before mounting to a container. The volume must also be +// in the same region as the kubelet. Cinder volumes support ownership +// management and SELinux relabeling. +type CinderPersistentVolumeSource struct { + // Unique id of the volume used to identify the cinder volume + VolumeID string + // Filesystem type to mount. + // Must be a filesystem type supported by the host operating system. + // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // +optional + FSType string + // Optional: Defaults to false (read/write). ReadOnly here will force + // the ReadOnly setting in VolumeMounts. + // +optional + ReadOnly bool + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + SecretRef *SecretReference } // Represents a Ceph Filesystem mount that lasts the lifetime of a pod @@ -1391,6 +1424,28 @@ type ConfigMapProjection struct { Optional *bool } +// ServiceAccountTokenProjection represents a projected service account token +// volume. This projection can be used to insert a service account token into +// the pods runtime filesystem for use against APIs (Kubernetes API Server or +// otherwise). +type ServiceAccountTokenProjection struct { + // Audience is the intended audience of the token. A recipient of a token + // must identify itself with an identifier specified in the audience of the + // token, and otherwise should reject the token. The audience defaults to the + // identifier of the apiserver. + Audience string + // ExpirationSeconds is the requested duration of validity of the service + // account token. As the token approaches expiration, the kubelet volume + // plugin will proactively rotate the service account token. The kubelet will + // start trying to rotate the token if the token is older than 80 percent of + // its time to live or if the token is older than 24 hours.Defaults to 1 hour + // and must be at least 10 minutes. + ExpirationSeconds int64 + // Path is the path relative to the mount point of the file to project the + // token into. + Path string +} + // Represents a projected volume source type ProjectedVolumeSource struct { // list of volume projections @@ -1414,6 +1469,8 @@ type VolumeProjection struct { DownwardAPI *DownwardAPIProjection // information about the configMap data to project ConfigMap *ConfigMapProjection + // information about the serviceAccountToken data to project + ServiceAccountToken *ServiceAccountTokenProjection } // Maps a string key to a path within a volume. @@ -2037,6 +2094,8 @@ const ( // PodReasonUnschedulable reason in PodScheduled PodCondition means that the scheduler // can't schedule the pod right now, for example due to insufficient resources in the cluster. PodReasonUnschedulable = "Unschedulable" + // ContainersReady indicates whether all containers in the pod are ready. + ContainersReady PodConditionType = "ContainersReady" ) type PodCondition struct { @@ -2109,6 +2168,7 @@ type NodeSelector struct { // A null or empty node selector term matches no objects. The requirements of // them are ANDed. +// The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. type NodeSelectorTerm struct { // A list of node selector requirements by node's labels. MatchExpressions []NodeSelectorRequirement @@ -2146,6 +2206,27 @@ const ( NodeSelectorOpLt NodeSelectorOperator = "Lt" ) +// A topology selector term represents the result of label queries. +// A null or empty topology selector term matches no objects. +// The requirements of them are ANDed. +// It provides a subset of functionality as NodeSelectorTerm. +// This is an alpha feature and may change in the future. +type TopologySelectorTerm struct { + // A list of topology selector requirements by labels. + // +optional + MatchLabelExpressions []TopologySelectorLabelRequirement +} + +// A topology selector requirement is a selector that matches given label. +// This is an alpha feature and may change in the future. +type TopologySelectorLabelRequirement struct { + // The label key that the selector applies to. + Key string + // An array of string values. One value must match the label to be selected. + // Each entry in Values is ORed. + Values []string +} + // Affinity is a group of affinity scheduling rules. type Affinity struct { // Describes node affinity scheduling rules for the pod. @@ -2378,6 +2459,12 @@ const ( TolerationOpEqual TolerationOperator = "Equal" ) +// PodReadinessGate contains the reference to a pod condition +type PodReadinessGate struct { + // ConditionType refers to a condition in the pod's condition list with matching type. + ConditionType PodConditionType +} + // PodSpec is a description of a pod type PodSpec struct { Volumes []Volume @@ -2474,6 +2561,12 @@ type PodSpec struct { // configuration based on DNSPolicy. // +optional DNSConfig *PodDNSConfig + // If specified, all readiness gates will be evaluated for pod readiness. + // A pod is ready when all its containers are ready AND + // all conditions specified in the readiness gates have status equal to "True" + // More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md + // +optional + ReadinessGates []PodReadinessGate } // HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the @@ -2566,6 +2659,10 @@ type PodSecurityContext struct { // If unset, the Kubelet will not modify the ownership and permissions of any volume. // +optional FSGroup *int64 + // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + // sysctls (by the container runtime) might fail to launch. + // +optional + Sysctls []Sysctl } // PodQOSClass defines the supported qos classes of Pods. @@ -3559,6 +3656,8 @@ const ( ResourceDefaultNamespacePrefix = "kubernetes.io/" // Name prefix for huge page resources (alpha). ResourceHugePagesPrefix = "hugepages-" + // Name prefix for storage resource limits + ResourceAttachableVolumesPrefix = "attachable-volumes-" ) // ResourceList is a set of (resource name, quantity) pairs. @@ -4097,6 +4196,8 @@ const ( ResourceQuotaScopeBestEffort ResourceQuotaScope = "BestEffort" // Match all pod objects that do not have best effort quality of service ResourceQuotaScopeNotBestEffort ResourceQuotaScope = "NotBestEffort" + // Match all pod objects that have priority class mentioned + ResourceQuotaScopePriorityClass ResourceQuotaScope = "PriorityClass" ) // ResourceQuotaSpec defines the desired hard limits to enforce for Quota @@ -4108,8 +4209,47 @@ type ResourceQuotaSpec struct { // If not specified, the quota matches all objects. // +optional Scopes []ResourceQuotaScope + // ScopeSelector is also a collection of filters like Scopes that must match each object tracked by a quota + // but expressed using ScopeSelectorOperator in combination with possible values. + // +optional + ScopeSelector *ScopeSelector } +// A scope selector represents the AND of the selectors represented +// by the scoped-resource selector terms. +type ScopeSelector struct { + // A list of scope selector requirements by scope of the resources. + // +optional + MatchExpressions []ScopedResourceSelectorRequirement +} + +// A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator +// that relates the scope name and values. +type ScopedResourceSelectorRequirement struct { + // The name of the scope that the selector applies to. + ScopeName ResourceQuotaScope + // Represents a scope's relationship to a set of values. + // Valid operators are In, NotIn, Exists, DoesNotExist. + Operator ScopeSelectorOperator + // 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. + // +optional + Values []string +} + +// A scope selector operator is the set of operators that can be used in +// a scope selector requirement. +type ScopeSelectorOperator string + +const ( + ScopeSelectorOpIn ScopeSelectorOperator = "In" + ScopeSelectorOpNotIn ScopeSelectorOperator = "NotIn" + ScopeSelectorOpExists ScopeSelectorOperator = "Exists" + ScopeSelectorOpDoesNotExist ScopeSelectorOperator = "DoesNotExist" +) + // ResourceQuotaStatus defines the enforced hard limits and observed use type ResourceQuotaStatus struct { // Hard is the set of enforced hard limits for each named resource diff --git a/pkg/apis/core/v1/conversion.go b/pkg/apis/core/v1/conversion.go index d5bce756c71..bc431d1478d 100644 --- a/pkg/apis/core/v1/conversion.go +++ b/pkg/apis/core/v1/conversion.go @@ -495,6 +495,14 @@ func Convert_core_PodSecurityContext_To_v1_PodSecurityContext(in *core.PodSecuri out.RunAsGroup = in.RunAsGroup out.RunAsNonRoot = in.RunAsNonRoot out.FSGroup = in.FSGroup + if in.Sysctls != nil { + out.Sysctls = make([]v1.Sysctl, len(in.Sysctls)) + for i, sysctl := range in.Sysctls { + if err := Convert_core_Sysctl_To_v1_Sysctl(&sysctl, &out.Sysctls[i], s); err != nil { + return err + } + } + } return nil } @@ -512,6 +520,15 @@ func Convert_v1_PodSecurityContext_To_core_PodSecurityContext(in *v1.PodSecurity out.RunAsGroup = in.RunAsGroup out.RunAsNonRoot = in.RunAsNonRoot out.FSGroup = in.FSGroup + if in.Sysctls != nil { + out.Sysctls = make([]core.Sysctl, len(in.Sysctls)) + for i, sysctl := range in.Sysctls { + if err := Convert_v1_Sysctl_To_core_Sysctl(&sysctl, &out.Sysctls[i], s); err != nil { + return err + } + } + } + return nil } diff --git a/pkg/apis/core/v1/defaults.go b/pkg/apis/core/v1/defaults.go index 09ee8f3feb1..110ef54df10 100644 --- a/pkg/apis/core/v1/defaults.go +++ b/pkg/apis/core/v1/defaults.go @@ -17,6 +17,8 @@ limitations under the License. package v1 import ( + "time" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" @@ -223,6 +225,12 @@ func SetDefaults_ProjectedVolumeSource(obj *v1.ProjectedVolumeSource) { obj.DefaultMode = &perm } } +func SetDefaults_ServiceAccountTokenProjection(obj *v1.ServiceAccountTokenProjection) { + hour := int64(time.Hour.Seconds()) + if obj.ExpirationSeconds == nil { + obj.ExpirationSeconds = &hour + } +} func SetDefaults_PersistentVolume(obj *v1.PersistentVolume) { if obj.Status.Phase == "" { obj.Status.Phase = v1.VolumePending diff --git a/pkg/apis/core/v1/helper/helpers.go b/pkg/apis/core/v1/helper/helpers.go index c7e2c2d0c7a..c8dbbdce92b 100644 --- a/pkg/apis/core/v1/helper/helpers.go +++ b/pkg/apis/core/v1/helper/helpers.go @@ -92,10 +92,14 @@ func IsOvercommitAllowed(name v1.ResourceName) bool { !IsHugePageResourceName(name) } +func IsAttachableVolumeResourceName(name v1.ResourceName) bool { + return strings.HasPrefix(string(name), v1.ResourceAttachableVolumesPrefix) +} + // Extended and Hugepages resources func IsScalarResourceName(name v1.ResourceName) bool { return IsExtendedResourceName(name) || IsHugePageResourceName(name) || - IsPrefixedNativeResource(name) + IsPrefixedNativeResource(name) || IsAttachableVolumeResourceName(name) } // this function aims to check if the service's ClusterIP is set or not @@ -312,6 +316,50 @@ func MatchNodeSelectorTerms( return false } +// TopologySelectorRequirementsAsSelector converts the []TopologySelectorLabelRequirement api type into a struct +// that implements labels.Selector. +func TopologySelectorRequirementsAsSelector(tsm []v1.TopologySelectorLabelRequirement) (labels.Selector, error) { + if len(tsm) == 0 { + return labels.Nothing(), nil + } + + selector := labels.NewSelector() + for _, expr := range tsm { + r, err := labels.NewRequirement(expr.Key, selection.In, expr.Values) + if err != nil { + return nil, err + } + selector = selector.Add(*r) + } + + return selector, nil +} + +// MatchTopologySelectorTerms checks whether given labels match topology selector terms in ORed; +// nil or empty term matches no objects; while empty term list matches all objects. +func MatchTopologySelectorTerms(topologySelectorTerms []v1.TopologySelectorTerm, lbls labels.Set) bool { + if len(topologySelectorTerms) == 0 { + // empty term list matches all objects + return true + } + + for _, req := range topologySelectorTerms { + // nil or empty term selects no objects + if len(req.MatchLabelExpressions) == 0 { + continue + } + + labelSelector, err := TopologySelectorRequirementsAsSelector(req.MatchLabelExpressions) + if err != nil || !labelSelector.Matches(lbls) { + continue + } + + return true + } + + return false +} + // AddOrUpdateTolerationInPodSpec tries to add a toleration to the toleration list in PodSpec. // Returns true if something was updated, false otherwise. func AddOrUpdateTolerationInPodSpec(spec *v1.PodSpec, toleration *v1.Toleration) bool { @@ -414,54 +462,6 @@ func GetAvoidPodsFromNodeAnnotations(annotations map[string]string) (v1.AvoidPod return avoidPods, nil } -// SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls -// and a slice of unsafe Sysctls. This is only a convenience wrapper around -// SysctlsFromPodAnnotation. -func SysctlsFromPodAnnotations(a map[string]string) ([]v1.Sysctl, []v1.Sysctl, error) { - safe, err := SysctlsFromPodAnnotation(a[v1.SysctlsPodAnnotationKey]) - if err != nil { - return nil, nil, err - } - unsafe, err := SysctlsFromPodAnnotation(a[v1.UnsafeSysctlsPodAnnotationKey]) - if err != nil { - return nil, nil, err - } - - return safe, unsafe, nil -} - -// SysctlsFromPodAnnotation parses an annotation value into a slice of Sysctls. -func SysctlsFromPodAnnotation(annotation string) ([]v1.Sysctl, error) { - if len(annotation) == 0 { - return nil, nil - } - - kvs := strings.Split(annotation, ",") - sysctls := make([]v1.Sysctl, len(kvs)) - for i, kv := range kvs { - cs := strings.Split(kv, "=") - if len(cs) != 2 || len(cs[0]) == 0 { - return nil, fmt.Errorf("sysctl %q not of the format sysctl_name=value", kv) - } - sysctls[i].Name = cs[0] - sysctls[i].Value = cs[1] - } - return sysctls, nil -} - -// PodAnnotationsFromSysctls creates an annotation value for a slice of Sysctls. -func PodAnnotationsFromSysctls(sysctls []v1.Sysctl) string { - if len(sysctls) == 0 { - return "" - } - - kvs := make([]string, len(sysctls)) - for i := range sysctls { - kvs[i] = fmt.Sprintf("%s=%s", sysctls[i].Name, sysctls[i].Value) - } - return strings.Join(kvs, ",") -} - // GetPersistentVolumeClass returns StorageClassName. func GetPersistentVolumeClass(volume *v1.PersistentVolume) string { // Use beta annotation first diff --git a/pkg/apis/core/v1/helper/helpers_test.go b/pkg/apis/core/v1/helper/helpers_test.go index 682c96dc09c..58992ab0a04 100644 --- a/pkg/apis/core/v1/helper/helpers_test.go +++ b/pkg/apis/core/v1/helper/helpers_test.go @@ -301,6 +301,71 @@ func TestNodeSelectorRequirementsAsSelector(t *testing.T) { } } +func TestTopologySelectorRequirementsAsSelector(t *testing.T) { + mustParse := func(s string) labels.Selector { + out, e := labels.Parse(s) + if e != nil { + panic(e) + } + return out + } + tc := []struct { + in []v1.TopologySelectorLabelRequirement + out labels.Selector + expectErr bool + }{ + {in: nil, out: labels.Nothing()}, + {in: []v1.TopologySelectorLabelRequirement{}, out: labels.Nothing()}, + { + in: []v1.TopologySelectorLabelRequirement{{ + Key: "foo", + Values: []string{"bar", "baz"}, + }}, + out: mustParse("foo in (baz,bar)"), + }, + { + in: []v1.TopologySelectorLabelRequirement{{ + Key: "foo", + Values: []string{}, + }}, + expectErr: true, + }, + { + in: []v1.TopologySelectorLabelRequirement{ + { + Key: "foo", + Values: []string{"bar", "baz"}, + }, + { + Key: "invalid", + Values: []string{}, + }, + }, + expectErr: true, + }, + { + in: []v1.TopologySelectorLabelRequirement{{ + Key: "/invalidkey", + Values: []string{"bar", "baz"}, + }}, + expectErr: true, + }, + } + + for i, tc := range tc { + out, err := TopologySelectorRequirementsAsSelector(tc.in) + if err == nil && tc.expectErr { + t.Errorf("[%v]expected error but got none.", i) + } + if err != nil && !tc.expectErr { + t.Errorf("[%v]did not expect error but got: %v", i, err) + } + if !reflect.DeepEqual(out, tc.out) { + t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out) + } + } +} + func TestTolerationsTolerateTaintsWithFilter(t *testing.T) { testCases := []struct { description string @@ -517,53 +582,6 @@ func TestGetAvoidPodsFromNode(t *testing.T) { } } -func TestSysctlsFromPodAnnotation(t *testing.T) { - type Test struct { - annotation string - expectValue []v1.Sysctl - expectErr bool - } - for i, test := range []Test{ - { - annotation: "", - expectValue: nil, - }, - { - annotation: "foo.bar", - expectErr: true, - }, - { - annotation: "=123", - expectErr: true, - }, - { - annotation: "foo.bar=", - expectValue: []v1.Sysctl{{Name: "foo.bar", Value: ""}}, - }, - { - annotation: "foo.bar=42", - expectValue: []v1.Sysctl{{Name: "foo.bar", Value: "42"}}, - }, - { - annotation: "foo.bar=42,", - expectErr: true, - }, - { - annotation: "foo.bar=42,abc.def=1", - expectValue: []v1.Sysctl{{Name: "foo.bar", Value: "42"}, {Name: "abc.def", Value: "1"}}, - }, - } { - sysctls, err := SysctlsFromPodAnnotation(test.annotation) - if test.expectErr && err == nil { - t.Errorf("[%v]expected error but got none", i) - } else if !test.expectErr && err != nil { - t.Errorf("[%v]did not expect error but got: %v", i, err) - } else if !reflect.DeepEqual(sysctls, test.expectValue) { - t.Errorf("[%v]expect value %v but got %v", i, test.expectValue, sysctls) - } - } -} - func TestMatchNodeSelectorTerms(t *testing.T) { type args struct { nodeSelectorTerms []v1.NodeSelectorTerm @@ -792,3 +810,161 @@ func TestMatchNodeSelectorTerms(t *testing.T) { }) } } + +func TestMatchTopologySelectorTerms(t *testing.T) { + type args struct { + topologySelectorTerms []v1.TopologySelectorTerm + labels labels.Set + } + + tests := []struct { + name string + args args + want bool + }{ + { + name: "nil term list", + args: args{ + topologySelectorTerms: nil, + labels: nil, + }, + want: true, + }, + { + name: "nil term", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{}, + }, + }, + labels: nil, + }, + want: false, + }, + { + name: "label matches MatchLabelExpressions terms", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{{ + Key: "label_1", + Values: []string{"label_1_val"}, + }}, + }, + }, + labels: map[string]string{"label_1": "label_1_val"}, + }, + want: true, + }, + { + name: "label does not match MatchLabelExpressions terms", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{{ + Key: "label_1", + Values: []string{"label_1_val"}, + }}, + }, + }, + labels: map[string]string{"label_1": "label_1_val-failed"}, + }, + want: false, + }, + { + name: "multi-values in one requirement, one matched", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{{ + Key: "label_1", + Values: []string{"label_1_val1", "label_1_val2"}, + }}, + }, + }, + labels: map[string]string{"label_1": "label_1_val2"}, + }, + want: true, + }, + { + name: "multi-terms was set, one matched", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{{ + Key: "label_1", + Values: []string{"label_1_val"}, + }}, + }, + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{{ + Key: "label_2", + Values: []string{"label_2_val"}, + }}, + }, + }, + labels: map[string]string{ + "label_2": "label_2_val", + }, + }, + want: true, + }, + { + name: "multi-requirement in one term, fully matched", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ + { + Key: "label_1", + Values: []string{"label_1_val"}, + }, + { + Key: "label_2", + Values: []string{"label_2_val"}, + }, + }, + }, + }, + labels: map[string]string{ + "label_1": "label_1_val", + "label_2": "label_2_val", + }, + }, + want: true, + }, + { + name: "multi-requirement in one term, partial matched", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ + { + Key: "label_1", + Values: []string{"label_1_val"}, + }, + { + Key: "label_2", + Values: []string{"label_2_val"}, + }, + }, + }, + }, + labels: map[string]string{ + "label_1": "label_1_val-failed", + "label_2": "label_2_val", + }, + }, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := MatchTopologySelectorTerms(tt.args.topologySelectorTerms, tt.args.labels); got != tt.want { + t.Errorf("MatchTopologySelectorTermsORed() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/apis/core/v1/zz_generated.conversion.go b/pkg/apis/core/v1/zz_generated.conversion.go index 3106ad1770f..6ef20a5f7f5 100644 --- a/pkg/apis/core/v1/zz_generated.conversion.go +++ b/pkg/apis/core/v1/zz_generated.conversion.go @@ -64,6 +64,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource, Convert_v1_CephFSVolumeSource_To_core_CephFSVolumeSource, Convert_core_CephFSVolumeSource_To_v1_CephFSVolumeSource, + Convert_v1_CinderPersistentVolumeSource_To_core_CinderPersistentVolumeSource, + Convert_core_CinderPersistentVolumeSource_To_v1_CinderPersistentVolumeSource, Convert_v1_CinderVolumeSource_To_core_CinderVolumeSource, Convert_core_CinderVolumeSource_To_v1_CinderVolumeSource, Convert_v1_ClientIPConfig_To_core_ClientIPConfig, @@ -286,6 +288,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_PodPortForwardOptions_To_v1_PodPortForwardOptions, Convert_v1_PodProxyOptions_To_core_PodProxyOptions, Convert_core_PodProxyOptions_To_v1_PodProxyOptions, + Convert_v1_PodReadinessGate_To_core_PodReadinessGate, + Convert_core_PodReadinessGate_To_v1_PodReadinessGate, Convert_v1_PodSecurityContext_To_core_PodSecurityContext, Convert_core_PodSecurityContext_To_v1_PodSecurityContext, Convert_v1_PodSignature_To_core_PodSignature, @@ -350,6 +354,10 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_ScaleIOPersistentVolumeSource_To_v1_ScaleIOPersistentVolumeSource, Convert_v1_ScaleIOVolumeSource_To_core_ScaleIOVolumeSource, Convert_core_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource, + Convert_v1_ScopeSelector_To_core_ScopeSelector, + Convert_core_ScopeSelector_To_v1_ScopeSelector, + Convert_v1_ScopedResourceSelectorRequirement_To_core_ScopedResourceSelectorRequirement, + Convert_core_ScopedResourceSelectorRequirement_To_v1_ScopedResourceSelectorRequirement, Convert_v1_Secret_To_core_Secret, Convert_core_Secret_To_v1_Secret, Convert_v1_SecretEnvSource_To_core_SecretEnvSource, @@ -374,6 +382,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_ServiceAccount_To_v1_ServiceAccount, Convert_v1_ServiceAccountList_To_core_ServiceAccountList, Convert_core_ServiceAccountList_To_v1_ServiceAccountList, + Convert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection, + Convert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection, Convert_v1_ServiceList_To_core_ServiceList, Convert_core_ServiceList_To_v1_ServiceList, Convert_v1_ServicePort_To_core_ServicePort, @@ -398,6 +408,10 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_Taint_To_v1_Taint, Convert_v1_Toleration_To_core_Toleration, Convert_core_Toleration_To_v1_Toleration, + Convert_v1_TopologySelectorLabelRequirement_To_core_TopologySelectorLabelRequirement, + Convert_core_TopologySelectorLabelRequirement_To_v1_TopologySelectorLabelRequirement, + Convert_v1_TopologySelectorTerm_To_core_TopologySelectorTerm, + Convert_core_TopologySelectorTerm_To_v1_TopologySelectorTerm, Convert_v1_Volume_To_core_Volume, Convert_core_Volume_To_v1_Volume, Convert_v1_VolumeDevice_To_core_VolumeDevice, @@ -731,10 +745,37 @@ func Convert_core_CephFSVolumeSource_To_v1_CephFSVolumeSource(in *core.CephFSVol return autoConvert_core_CephFSVolumeSource_To_v1_CephFSVolumeSource(in, out, s) } +func autoConvert_v1_CinderPersistentVolumeSource_To_core_CinderPersistentVolumeSource(in *v1.CinderPersistentVolumeSource, out *core.CinderPersistentVolumeSource, s conversion.Scope) error { + out.VolumeID = in.VolumeID + out.FSType = in.FSType + out.ReadOnly = in.ReadOnly + out.SecretRef = (*core.SecretReference)(unsafe.Pointer(in.SecretRef)) + return nil +} + +// Convert_v1_CinderPersistentVolumeSource_To_core_CinderPersistentVolumeSource is an autogenerated conversion function. +func Convert_v1_CinderPersistentVolumeSource_To_core_CinderPersistentVolumeSource(in *v1.CinderPersistentVolumeSource, out *core.CinderPersistentVolumeSource, s conversion.Scope) error { + return autoConvert_v1_CinderPersistentVolumeSource_To_core_CinderPersistentVolumeSource(in, out, s) +} + +func autoConvert_core_CinderPersistentVolumeSource_To_v1_CinderPersistentVolumeSource(in *core.CinderPersistentVolumeSource, out *v1.CinderPersistentVolumeSource, s conversion.Scope) error { + out.VolumeID = in.VolumeID + out.FSType = in.FSType + out.ReadOnly = in.ReadOnly + out.SecretRef = (*v1.SecretReference)(unsafe.Pointer(in.SecretRef)) + return nil +} + +// Convert_core_CinderPersistentVolumeSource_To_v1_CinderPersistentVolumeSource is an autogenerated conversion function. +func Convert_core_CinderPersistentVolumeSource_To_v1_CinderPersistentVolumeSource(in *core.CinderPersistentVolumeSource, out *v1.CinderPersistentVolumeSource, s conversion.Scope) error { + return autoConvert_core_CinderPersistentVolumeSource_To_v1_CinderPersistentVolumeSource(in, out, s) +} + func autoConvert_v1_CinderVolumeSource_To_core_CinderVolumeSource(in *v1.CinderVolumeSource, out *core.CinderVolumeSource, s conversion.Scope) error { out.VolumeID = in.VolumeID out.FSType = in.FSType out.ReadOnly = in.ReadOnly + out.SecretRef = (*core.LocalObjectReference)(unsafe.Pointer(in.SecretRef)) return nil } @@ -747,6 +788,7 @@ func autoConvert_core_CinderVolumeSource_To_v1_CinderVolumeSource(in *core.Cinde out.VolumeID = in.VolumeID out.FSType = in.FSType out.ReadOnly = in.ReadOnly + out.SecretRef = (*v1.LocalObjectReference)(unsafe.Pointer(in.SecretRef)) return nil } @@ -3233,7 +3275,7 @@ func autoConvert_v1_PersistentVolumeSource_To_core_PersistentVolumeSource(in *v1 out.NFS = (*core.NFSVolumeSource)(unsafe.Pointer(in.NFS)) out.RBD = (*core.RBDPersistentVolumeSource)(unsafe.Pointer(in.RBD)) out.ISCSI = (*core.ISCSIPersistentVolumeSource)(unsafe.Pointer(in.ISCSI)) - out.Cinder = (*core.CinderVolumeSource)(unsafe.Pointer(in.Cinder)) + out.Cinder = (*core.CinderPersistentVolumeSource)(unsafe.Pointer(in.Cinder)) out.CephFS = (*core.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS)) out.FC = (*core.FCVolumeSource)(unsafe.Pointer(in.FC)) out.Flocker = (*core.FlockerVolumeSource)(unsafe.Pointer(in.Flocker)) @@ -3266,7 +3308,7 @@ func autoConvert_core_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *co out.Quobyte = (*v1.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte)) out.ISCSI = (*v1.ISCSIPersistentVolumeSource)(unsafe.Pointer(in.ISCSI)) out.FlexVolume = (*v1.FlexPersistentVolumeSource)(unsafe.Pointer(in.FlexVolume)) - out.Cinder = (*v1.CinderVolumeSource)(unsafe.Pointer(in.Cinder)) + out.Cinder = (*v1.CinderPersistentVolumeSource)(unsafe.Pointer(in.Cinder)) out.CephFS = (*v1.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS)) out.FC = (*v1.FCVolumeSource)(unsafe.Pointer(in.FC)) out.Flocker = (*v1.FlockerVolumeSource)(unsafe.Pointer(in.Flocker)) @@ -3713,6 +3755,26 @@ func Convert_core_PodProxyOptions_To_v1_PodProxyOptions(in *core.PodProxyOptions return autoConvert_core_PodProxyOptions_To_v1_PodProxyOptions(in, out, s) } +func autoConvert_v1_PodReadinessGate_To_core_PodReadinessGate(in *v1.PodReadinessGate, out *core.PodReadinessGate, s conversion.Scope) error { + out.ConditionType = core.PodConditionType(in.ConditionType) + return nil +} + +// Convert_v1_PodReadinessGate_To_core_PodReadinessGate is an autogenerated conversion function. +func Convert_v1_PodReadinessGate_To_core_PodReadinessGate(in *v1.PodReadinessGate, out *core.PodReadinessGate, s conversion.Scope) error { + return autoConvert_v1_PodReadinessGate_To_core_PodReadinessGate(in, out, s) +} + +func autoConvert_core_PodReadinessGate_To_v1_PodReadinessGate(in *core.PodReadinessGate, out *v1.PodReadinessGate, s conversion.Scope) error { + out.ConditionType = v1.PodConditionType(in.ConditionType) + return nil +} + +// Convert_core_PodReadinessGate_To_v1_PodReadinessGate is an autogenerated conversion function. +func Convert_core_PodReadinessGate_To_v1_PodReadinessGate(in *core.PodReadinessGate, out *v1.PodReadinessGate, s conversion.Scope) error { + return autoConvert_core_PodReadinessGate_To_v1_PodReadinessGate(in, out, s) +} + func autoConvert_v1_PodSecurityContext_To_core_PodSecurityContext(in *v1.PodSecurityContext, out *core.PodSecurityContext, s conversion.Scope) error { out.SELinuxOptions = (*core.SELinuxOptions)(unsafe.Pointer(in.SELinuxOptions)) out.RunAsUser = (*int64)(unsafe.Pointer(in.RunAsUser)) @@ -3720,6 +3782,7 @@ func autoConvert_v1_PodSecurityContext_To_core_PodSecurityContext(in *v1.PodSecu out.RunAsNonRoot = (*bool)(unsafe.Pointer(in.RunAsNonRoot)) out.SupplementalGroups = *(*[]int64)(unsafe.Pointer(&in.SupplementalGroups)) out.FSGroup = (*int64)(unsafe.Pointer(in.FSGroup)) + out.Sysctls = *(*[]core.Sysctl)(unsafe.Pointer(&in.Sysctls)) return nil } @@ -3734,6 +3797,7 @@ func autoConvert_core_PodSecurityContext_To_v1_PodSecurityContext(in *core.PodSe out.RunAsNonRoot = (*bool)(unsafe.Pointer(in.RunAsNonRoot)) out.SupplementalGroups = *(*[]int64)(unsafe.Pointer(&in.SupplementalGroups)) out.FSGroup = (*int64)(unsafe.Pointer(in.FSGroup)) + out.Sysctls = *(*[]v1.Sysctl)(unsafe.Pointer(&in.Sysctls)) return nil } @@ -3823,6 +3887,7 @@ func autoConvert_v1_PodSpec_To_core_PodSpec(in *v1.PodSpec, out *core.PodSpec, s out.PriorityClassName = in.PriorityClassName out.Priority = (*int32)(unsafe.Pointer(in.Priority)) out.DNSConfig = (*core.PodDNSConfig)(unsafe.Pointer(in.DNSConfig)) + out.ReadinessGates = *(*[]core.PodReadinessGate)(unsafe.Pointer(&in.ReadinessGates)) return nil } @@ -3887,6 +3952,7 @@ func autoConvert_core_PodSpec_To_v1_PodSpec(in *core.PodSpec, out *v1.PodSpec, s out.PriorityClassName = in.PriorityClassName out.Priority = (*int32)(unsafe.Pointer(in.Priority)) out.DNSConfig = (*v1.PodDNSConfig)(unsafe.Pointer(in.DNSConfig)) + out.ReadinessGates = *(*[]v1.PodReadinessGate)(unsafe.Pointer(&in.ReadinessGates)) return nil } @@ -4175,7 +4241,17 @@ func Convert_core_Probe_To_v1_Probe(in *core.Probe, out *v1.Probe, s conversion. } func autoConvert_v1_ProjectedVolumeSource_To_core_ProjectedVolumeSource(in *v1.ProjectedVolumeSource, out *core.ProjectedVolumeSource, s conversion.Scope) error { - out.Sources = *(*[]core.VolumeProjection)(unsafe.Pointer(&in.Sources)) + if in.Sources != nil { + in, out := &in.Sources, &out.Sources + *out = make([]core.VolumeProjection, len(*in)) + for i := range *in { + if err := Convert_v1_VolumeProjection_To_core_VolumeProjection(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Sources = nil + } out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode)) return nil } @@ -4186,7 +4262,17 @@ func Convert_v1_ProjectedVolumeSource_To_core_ProjectedVolumeSource(in *v1.Proje } func autoConvert_core_ProjectedVolumeSource_To_v1_ProjectedVolumeSource(in *core.ProjectedVolumeSource, out *v1.ProjectedVolumeSource, s conversion.Scope) error { - out.Sources = *(*[]v1.VolumeProjection)(unsafe.Pointer(&in.Sources)) + if in.Sources != nil { + in, out := &in.Sources, &out.Sources + *out = make([]v1.VolumeProjection, len(*in)) + for i := range *in { + if err := Convert_core_VolumeProjection_To_v1_VolumeProjection(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Sources = nil + } out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode)) return nil } @@ -4565,6 +4651,7 @@ func Convert_core_ResourceQuotaList_To_v1_ResourceQuotaList(in *core.ResourceQuo func autoConvert_v1_ResourceQuotaSpec_To_core_ResourceQuotaSpec(in *v1.ResourceQuotaSpec, out *core.ResourceQuotaSpec, s conversion.Scope) error { out.Hard = *(*core.ResourceList)(unsafe.Pointer(&in.Hard)) out.Scopes = *(*[]core.ResourceQuotaScope)(unsafe.Pointer(&in.Scopes)) + out.ScopeSelector = (*core.ScopeSelector)(unsafe.Pointer(in.ScopeSelector)) return nil } @@ -4576,6 +4663,7 @@ func Convert_v1_ResourceQuotaSpec_To_core_ResourceQuotaSpec(in *v1.ResourceQuota func autoConvert_core_ResourceQuotaSpec_To_v1_ResourceQuotaSpec(in *core.ResourceQuotaSpec, out *v1.ResourceQuotaSpec, s conversion.Scope) error { out.Hard = *(*v1.ResourceList)(unsafe.Pointer(&in.Hard)) out.Scopes = *(*[]v1.ResourceQuotaScope)(unsafe.Pointer(&in.Scopes)) + out.ScopeSelector = (*v1.ScopeSelector)(unsafe.Pointer(in.ScopeSelector)) return nil } @@ -4730,6 +4818,50 @@ func Convert_core_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource(in *core.ScaleIO return autoConvert_core_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource(in, out, s) } +func autoConvert_v1_ScopeSelector_To_core_ScopeSelector(in *v1.ScopeSelector, out *core.ScopeSelector, s conversion.Scope) error { + out.MatchExpressions = *(*[]core.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions)) + return nil +} + +// Convert_v1_ScopeSelector_To_core_ScopeSelector is an autogenerated conversion function. +func Convert_v1_ScopeSelector_To_core_ScopeSelector(in *v1.ScopeSelector, out *core.ScopeSelector, s conversion.Scope) error { + return autoConvert_v1_ScopeSelector_To_core_ScopeSelector(in, out, s) +} + +func autoConvert_core_ScopeSelector_To_v1_ScopeSelector(in *core.ScopeSelector, out *v1.ScopeSelector, s conversion.Scope) error { + out.MatchExpressions = *(*[]v1.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions)) + return nil +} + +// Convert_core_ScopeSelector_To_v1_ScopeSelector is an autogenerated conversion function. +func Convert_core_ScopeSelector_To_v1_ScopeSelector(in *core.ScopeSelector, out *v1.ScopeSelector, s conversion.Scope) error { + return autoConvert_core_ScopeSelector_To_v1_ScopeSelector(in, out, s) +} + +func autoConvert_v1_ScopedResourceSelectorRequirement_To_core_ScopedResourceSelectorRequirement(in *v1.ScopedResourceSelectorRequirement, out *core.ScopedResourceSelectorRequirement, s conversion.Scope) error { + out.ScopeName = core.ResourceQuotaScope(in.ScopeName) + out.Operator = core.ScopeSelectorOperator(in.Operator) + out.Values = *(*[]string)(unsafe.Pointer(&in.Values)) + return nil +} + +// Convert_v1_ScopedResourceSelectorRequirement_To_core_ScopedResourceSelectorRequirement is an autogenerated conversion function. +func Convert_v1_ScopedResourceSelectorRequirement_To_core_ScopedResourceSelectorRequirement(in *v1.ScopedResourceSelectorRequirement, out *core.ScopedResourceSelectorRequirement, s conversion.Scope) error { + return autoConvert_v1_ScopedResourceSelectorRequirement_To_core_ScopedResourceSelectorRequirement(in, out, s) +} + +func autoConvert_core_ScopedResourceSelectorRequirement_To_v1_ScopedResourceSelectorRequirement(in *core.ScopedResourceSelectorRequirement, out *v1.ScopedResourceSelectorRequirement, s conversion.Scope) error { + out.ScopeName = v1.ResourceQuotaScope(in.ScopeName) + out.Operator = v1.ScopeSelectorOperator(in.Operator) + out.Values = *(*[]string)(unsafe.Pointer(&in.Values)) + return nil +} + +// Convert_core_ScopedResourceSelectorRequirement_To_v1_ScopedResourceSelectorRequirement is an autogenerated conversion function. +func Convert_core_ScopedResourceSelectorRequirement_To_v1_ScopedResourceSelectorRequirement(in *core.ScopedResourceSelectorRequirement, out *v1.ScopedResourceSelectorRequirement, s conversion.Scope) error { + return autoConvert_core_ScopedResourceSelectorRequirement_To_v1_ScopedResourceSelectorRequirement(in, out, s) +} + func autoConvert_v1_Secret_To_core_Secret(in *v1.Secret, out *core.Secret, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta out.Data = *(*map[string][]byte)(unsafe.Pointer(&in.Data)) @@ -5055,6 +5187,34 @@ func Convert_core_ServiceAccountList_To_v1_ServiceAccountList(in *core.ServiceAc return autoConvert_core_ServiceAccountList_To_v1_ServiceAccountList(in, out, s) } +func autoConvert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection(in *v1.ServiceAccountTokenProjection, out *core.ServiceAccountTokenProjection, s conversion.Scope) error { + out.Audience = in.Audience + if err := meta_v1.Convert_Pointer_int64_To_int64(&in.ExpirationSeconds, &out.ExpirationSeconds, s); err != nil { + return err + } + out.Path = in.Path + return nil +} + +// Convert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection is an autogenerated conversion function. +func Convert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection(in *v1.ServiceAccountTokenProjection, out *core.ServiceAccountTokenProjection, s conversion.Scope) error { + return autoConvert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection(in, out, s) +} + +func autoConvert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection(in *core.ServiceAccountTokenProjection, out *v1.ServiceAccountTokenProjection, s conversion.Scope) error { + out.Audience = in.Audience + if err := meta_v1.Convert_int64_To_Pointer_int64(&in.ExpirationSeconds, &out.ExpirationSeconds, s); err != nil { + return err + } + out.Path = in.Path + return nil +} + +// Convert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection is an autogenerated conversion function. +func Convert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection(in *core.ServiceAccountTokenProjection, out *v1.ServiceAccountTokenProjection, s conversion.Scope) error { + return autoConvert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection(in, out, s) +} + func autoConvert_v1_ServiceList_To_core_ServiceList(in *v1.ServiceList, out *core.ServiceList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { @@ -5387,6 +5547,48 @@ func Convert_core_Toleration_To_v1_Toleration(in *core.Toleration, out *v1.Toler return autoConvert_core_Toleration_To_v1_Toleration(in, out, s) } +func autoConvert_v1_TopologySelectorLabelRequirement_To_core_TopologySelectorLabelRequirement(in *v1.TopologySelectorLabelRequirement, out *core.TopologySelectorLabelRequirement, s conversion.Scope) error { + out.Key = in.Key + out.Values = *(*[]string)(unsafe.Pointer(&in.Values)) + return nil +} + +// Convert_v1_TopologySelectorLabelRequirement_To_core_TopologySelectorLabelRequirement is an autogenerated conversion function. +func Convert_v1_TopologySelectorLabelRequirement_To_core_TopologySelectorLabelRequirement(in *v1.TopologySelectorLabelRequirement, out *core.TopologySelectorLabelRequirement, s conversion.Scope) error { + return autoConvert_v1_TopologySelectorLabelRequirement_To_core_TopologySelectorLabelRequirement(in, out, s) +} + +func autoConvert_core_TopologySelectorLabelRequirement_To_v1_TopologySelectorLabelRequirement(in *core.TopologySelectorLabelRequirement, out *v1.TopologySelectorLabelRequirement, s conversion.Scope) error { + out.Key = in.Key + out.Values = *(*[]string)(unsafe.Pointer(&in.Values)) + return nil +} + +// Convert_core_TopologySelectorLabelRequirement_To_v1_TopologySelectorLabelRequirement is an autogenerated conversion function. +func Convert_core_TopologySelectorLabelRequirement_To_v1_TopologySelectorLabelRequirement(in *core.TopologySelectorLabelRequirement, out *v1.TopologySelectorLabelRequirement, s conversion.Scope) error { + return autoConvert_core_TopologySelectorLabelRequirement_To_v1_TopologySelectorLabelRequirement(in, out, s) +} + +func autoConvert_v1_TopologySelectorTerm_To_core_TopologySelectorTerm(in *v1.TopologySelectorTerm, out *core.TopologySelectorTerm, s conversion.Scope) error { + out.MatchLabelExpressions = *(*[]core.TopologySelectorLabelRequirement)(unsafe.Pointer(&in.MatchLabelExpressions)) + return nil +} + +// Convert_v1_TopologySelectorTerm_To_core_TopologySelectorTerm is an autogenerated conversion function. +func Convert_v1_TopologySelectorTerm_To_core_TopologySelectorTerm(in *v1.TopologySelectorTerm, out *core.TopologySelectorTerm, s conversion.Scope) error { + return autoConvert_v1_TopologySelectorTerm_To_core_TopologySelectorTerm(in, out, s) +} + +func autoConvert_core_TopologySelectorTerm_To_v1_TopologySelectorTerm(in *core.TopologySelectorTerm, out *v1.TopologySelectorTerm, s conversion.Scope) error { + out.MatchLabelExpressions = *(*[]v1.TopologySelectorLabelRequirement)(unsafe.Pointer(&in.MatchLabelExpressions)) + return nil +} + +// Convert_core_TopologySelectorTerm_To_v1_TopologySelectorTerm is an autogenerated conversion function. +func Convert_core_TopologySelectorTerm_To_v1_TopologySelectorTerm(in *core.TopologySelectorTerm, out *v1.TopologySelectorTerm, s conversion.Scope) error { + return autoConvert_core_TopologySelectorTerm_To_v1_TopologySelectorTerm(in, out, s) +} + func autoConvert_v1_Volume_To_core_Volume(in *v1.Volume, out *core.Volume, s conversion.Scope) error { out.Name = in.Name if err := Convert_v1_VolumeSource_To_core_VolumeSource(&in.VolumeSource, &out.VolumeSource, s); err != nil { @@ -5487,6 +5689,15 @@ func autoConvert_v1_VolumeProjection_To_core_VolumeProjection(in *v1.VolumeProje out.Secret = (*core.SecretProjection)(unsafe.Pointer(in.Secret)) out.DownwardAPI = (*core.DownwardAPIProjection)(unsafe.Pointer(in.DownwardAPI)) out.ConfigMap = (*core.ConfigMapProjection)(unsafe.Pointer(in.ConfigMap)) + if in.ServiceAccountToken != nil { + in, out := &in.ServiceAccountToken, &out.ServiceAccountToken + *out = new(core.ServiceAccountTokenProjection) + if err := Convert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection(*in, *out, s); err != nil { + return err + } + } else { + out.ServiceAccountToken = nil + } return nil } @@ -5499,6 +5710,15 @@ func autoConvert_core_VolumeProjection_To_v1_VolumeProjection(in *core.VolumePro out.Secret = (*v1.SecretProjection)(unsafe.Pointer(in.Secret)) out.DownwardAPI = (*v1.DownwardAPIProjection)(unsafe.Pointer(in.DownwardAPI)) out.ConfigMap = (*v1.ConfigMapProjection)(unsafe.Pointer(in.ConfigMap)) + if in.ServiceAccountToken != nil { + in, out := &in.ServiceAccountToken, &out.ServiceAccountToken + *out = new(v1.ServiceAccountTokenProjection) + if err := Convert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection(*in, *out, s); err != nil { + return err + } + } else { + out.ServiceAccountToken = nil + } return nil } @@ -5531,7 +5751,15 @@ func autoConvert_v1_VolumeSource_To_core_VolumeSource(in *v1.VolumeSource, out * out.Quobyte = (*core.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte)) out.AzureDisk = (*core.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk)) out.PhotonPersistentDisk = (*core.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) - out.Projected = (*core.ProjectedVolumeSource)(unsafe.Pointer(in.Projected)) + if in.Projected != nil { + in, out := &in.Projected, &out.Projected + *out = new(core.ProjectedVolumeSource) + if err := Convert_v1_ProjectedVolumeSource_To_core_ProjectedVolumeSource(*in, *out, s); err != nil { + return err + } + } else { + out.Projected = nil + } out.PortworxVolume = (*core.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.ScaleIO = (*core.ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO)) out.StorageOS = (*core.StorageOSVolumeSource)(unsafe.Pointer(in.StorageOS)) @@ -5567,7 +5795,15 @@ func autoConvert_core_VolumeSource_To_v1_VolumeSource(in *core.VolumeSource, out out.VsphereVolume = (*v1.VsphereVirtualDiskVolumeSource)(unsafe.Pointer(in.VsphereVolume)) out.AzureDisk = (*v1.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk)) out.PhotonPersistentDisk = (*v1.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) - out.Projected = (*v1.ProjectedVolumeSource)(unsafe.Pointer(in.Projected)) + if in.Projected != nil { + in, out := &in.Projected, &out.Projected + *out = new(v1.ProjectedVolumeSource) + if err := Convert_core_ProjectedVolumeSource_To_v1_ProjectedVolumeSource(*in, *out, s); err != nil { + return err + } + } else { + out.Projected = nil + } out.PortworxVolume = (*v1.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.ScaleIO = (*v1.ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO)) out.StorageOS = (*v1.StorageOSVolumeSource)(unsafe.Pointer(in.StorageOS)) diff --git a/pkg/apis/core/v1/zz_generated.defaults.go b/pkg/apis/core/v1/zz_generated.defaults.go index 3c4dc5e17c5..00e0b384aa8 100644 --- a/pkg/apis/core/v1/zz_generated.defaults.go +++ b/pkg/apis/core/v1/zz_generated.defaults.go @@ -213,6 +213,9 @@ func SetObjectDefaults_Pod(in *v1.Pod) { } } } + if b.ServiceAccountToken != nil { + SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -356,6 +359,9 @@ func SetObjectDefaults_PodTemplate(in *v1.PodTemplate) { } } } + if b.ServiceAccountToken != nil { + SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -501,6 +507,9 @@ func SetObjectDefaults_ReplicationController(in *v1.ReplicationController) { } } } + if b.ServiceAccountToken != nil { + SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index 6a01b7f6254..7050c604e5c 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -129,23 +129,6 @@ func ValidatePodSpecificAnnotations(annotations map[string]string, spec *core.Po allErrs = append(allErrs, ValidateSeccompPodAnnotations(annotations, fldPath)...) allErrs = append(allErrs, ValidateAppArmorPodAnnotations(annotations, spec, fldPath)...) - sysctls, err := helper.SysctlsFromPodAnnotation(annotations[core.SysctlsPodAnnotationKey]) - if err != nil { - allErrs = append(allErrs, field.Invalid(fldPath.Key(core.SysctlsPodAnnotationKey), annotations[core.SysctlsPodAnnotationKey], err.Error())) - } else { - allErrs = append(allErrs, validateSysctls(sysctls, fldPath.Key(core.SysctlsPodAnnotationKey))...) - } - unsafeSysctls, err := helper.SysctlsFromPodAnnotation(annotations[core.UnsafeSysctlsPodAnnotationKey]) - if err != nil { - allErrs = append(allErrs, field.Invalid(fldPath.Key(core.UnsafeSysctlsPodAnnotationKey), annotations[core.UnsafeSysctlsPodAnnotationKey], err.Error())) - } else { - allErrs = append(allErrs, validateSysctls(unsafeSysctls, fldPath.Key(core.UnsafeSysctlsPodAnnotationKey))...) - } - inBoth := sysctlIntersection(sysctls, unsafeSysctls) - if len(inBoth) > 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Key(core.UnsafeSysctlsPodAnnotationKey), strings.Join(inBoth, ", "), "can not be safe and unsafe")) - } - return allErrs } @@ -1039,6 +1022,21 @@ func validateProjectionSources(projection *core.ProjectedVolumeSource, projectio } } } + if projPath := fldPath.Child("serviceAccountToken"); source.ServiceAccountToken != nil { + numSources++ + if !utilfeature.DefaultFeatureGate.Enabled(features.TokenRequestProjection) { + allErrs = append(allErrs, field.Forbidden(projPath, "TokenRequestProjection feature is not enabled")) + } + if source.ServiceAccountToken.ExpirationSeconds < 10*60 { + allErrs = append(allErrs, field.Invalid(projPath.Child("expirationSeconds"), source.ServiceAccountToken.ExpirationSeconds, "may not specify a duration less than 10 minutes")) + } + if source.ServiceAccountToken.ExpirationSeconds > 1<<32 { + allErrs = append(allErrs, field.Invalid(projPath.Child("expirationSeconds"), source.ServiceAccountToken.ExpirationSeconds, "may not specify a duration larger than 2^32 seconds")) + } + if source.ServiceAccountToken.Path == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("path"), "")) + } + } if numSources > 1 { allErrs = append(allErrs, field.Forbidden(srcPath, "may not specify more than 1 volume type")) } @@ -1181,6 +1179,27 @@ func validateCinderVolumeSource(cd *core.CinderVolumeSource, fldPath *field.Path if len(cd.VolumeID) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("volumeID"), "")) } + if cd.SecretRef != nil { + if len(cd.SecretRef.Name) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("secretRef", "name"), "")) + } + } + return allErrs +} + +func validateCinderPersistentVolumeSource(cd *core.CinderPersistentVolumeSource, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if len(cd.VolumeID) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("volumeID"), "")) + } + if cd.SecretRef != nil { + if len(cd.SecretRef.Name) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("secretRef", "name"), "")) + } + if len(cd.SecretRef.Namespace) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("secretRef", "namespace"), "")) + } + } return allErrs } @@ -1607,7 +1626,7 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList { allErrs = append(allErrs, field.Forbidden(specPath.Child("cinder"), "may not specify more than 1 volume type")) } else { numVolumes++ - allErrs = append(allErrs, validateCinderVolumeSource(pv.Spec.Cinder, specPath.Child("cinder"))...) + allErrs = append(allErrs, validateCinderPersistentVolumeSource(pv.Spec.Cinder, specPath.Child("cinder"))...) } } if pv.Spec.FC != nil { @@ -2632,6 +2651,19 @@ const ( MaxDNSSearchListChars = 256 ) +func validateReadinessGates(readinessGates []core.PodReadinessGate, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if !utilfeature.DefaultFeatureGate.Enabled(features.PodReadinessGates) && len(readinessGates) > 0 { + return append(allErrs, field.Forbidden(fldPath, "PodReadinessGates is disabled by feature gate")) + } + for i, value := range readinessGates { + for _, msg := range validation.IsQualifiedName(string(value.ConditionType)) { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("conditionType"), string(value.ConditionType), msg)) + } + } + return allErrs +} + func validatePodDNSConfig(dnsConfig *core.PodDNSConfig, dnsPolicy *core.DNSPolicy, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} @@ -2749,7 +2781,7 @@ func validateTaintEffect(effect *core.TaintEffect, allowEmpty bool, fldPath *fie // TODO: Uncomment this block when implement TaintEffectNoScheduleNoAdmit. // string(core.TaintEffectNoScheduleNoAdmit), } - allErrors = append(allErrors, field.NotSupported(fldPath, effect, validValues)) + allErrors = append(allErrors, field.NotSupported(fldPath, *effect, validValues)) } return allErrors } @@ -2920,6 +2952,7 @@ func ValidatePodSpec(spec *core.PodSpec, fldPath *field.Path) field.ErrorList { allErrs = append(allErrs, validateImagePullSecrets(spec.ImagePullSecrets, fldPath.Child("imagePullSecrets"))...) allErrs = append(allErrs, validateAffinity(spec.Affinity, fldPath.Child("affinity"))...) allErrs = append(allErrs, validatePodDNSConfig(spec.DNSConfig, &spec.DNSPolicy, fldPath.Child("dnsConfig"))...) + allErrs = append(allErrs, validateReadinessGates(spec.ReadinessGates, fldPath.Child("readinessGates"))...) if len(spec.ServiceAccountName) > 0 { for _, msg := range ValidateServiceAccountName(spec.ServiceAccountName, false) { allErrs = append(allErrs, field.Invalid(fldPath.Child("serviceAccountName"), spec.ServiceAccountName, msg)) @@ -3054,6 +3087,32 @@ func ValidateNodeSelector(nodeSelector *core.NodeSelector, fldPath *field.Path) return allErrs } +// validateTopologySelectorLabelRequirement tests that the specified TopologySelectorLabelRequirement fields has valid data +func validateTopologySelectorLabelRequirement(rq core.TopologySelectorLabelRequirement, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if len(rq.Values) == 0 { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("values"), "must specify as least one value")) + } + allErrs = append(allErrs, unversionedvalidation.ValidateLabelName(rq.Key, fldPath.Child("key"))...) + + return allErrs +} + +// ValidateTopologySelectorTerm tests that the specified topology selector term has valid data +func ValidateTopologySelectorTerm(term core.TopologySelectorTerm, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + for i, req := range term.MatchLabelExpressions { + allErrs = append(allErrs, validateTopologySelectorLabelRequirement(req, fldPath.Child("matchLabelExpressions").Index(i))...) + } + } else if len(term.MatchLabelExpressions) != 0 { + allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate DynamicProvisioningScheduling")) + } + + return allErrs +} + // ValidateAvoidPodsInNodeAnnotations tests that the serialized AvoidPods in Node.Annotations has valid data func ValidateAvoidPodsInNodeAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} @@ -3288,12 +3347,16 @@ func IsValidSysctlName(name string) bool { func validateSysctls(sysctls []core.Sysctl, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} + names := make(map[string]struct{}) for i, s := range sysctls { if len(s.Name) == 0 { allErrs = append(allErrs, field.Required(fldPath.Index(i).Child("name"), "")) } else if !IsValidSysctlName(s.Name) { allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("name"), s.Name, fmt.Sprintf("must have at most %d characters and match regex %s", SysctlMaxLength, SysctlFmt))) + } else if _, ok := names[s.Name]; ok { + allErrs = append(allErrs, field.Duplicate(fldPath.Index(i).Child("name"), s.Name)) } + names[s.Name] = struct{}{} } return allErrs } @@ -3332,6 +3395,14 @@ func ValidatePodSecurityContext(securityContext *core.PodSecurityContext, spec * allErrs = append(allErrs, field.Invalid(fldPath.Child("shareProcessNamespace"), *securityContext.ShareProcessNamespace, "ShareProcessNamespace and HostPID cannot both be enabled")) } } + + if len(securityContext.Sysctls) != 0 { + if utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) { + allErrs = append(allErrs, validateSysctls(securityContext.Sysctls, fldPath.Child("sysctls"))...) + } else { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("sysctls"), "Sysctls are disabled by Sysctls feature-gate")) + } + } } return allErrs @@ -3470,6 +3541,7 @@ func ValidatePodStatusUpdate(newPod, oldPod *core.Pod) field.ErrorList { fldPath := field.NewPath("metadata") allErrs := ValidateObjectMetaUpdate(&newPod.ObjectMeta, &oldPod.ObjectMeta, fldPath) allErrs = append(allErrs, ValidatePodSpecificAnnotationUpdates(newPod, oldPod, fldPath.Child("annotations"))...) + allErrs = append(allErrs, validatePodConditions(newPod.Status.Conditions, fldPath.Child("conditions"))...) fldPath = field.NewPath("status") if newPod.Spec.NodeName != oldPod.Spec.NodeName { @@ -3493,6 +3565,21 @@ func ValidatePodStatusUpdate(newPod, oldPod *core.Pod) field.ErrorList { return allErrs } +// validatePodConditions tests if the custom pod conditions are valid. +func validatePodConditions(conditions []core.PodCondition, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + systemConditions := sets.NewString(string(core.PodScheduled), string(core.PodReady), string(core.PodInitialized)) + for i, condition := range conditions { + if systemConditions.Has(string(condition.Type)) { + continue + } + for _, msg := range validation.IsQualifiedName(string(condition.Type)) { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("Type"), string(condition.Type), msg)) + } + } + return allErrs +} + // ValidatePodBinding tests if required fields in the pod binding are legal. func ValidatePodBinding(binding *core.Binding) field.ErrorList { allErrs := field.ErrorList{} @@ -4720,6 +4807,74 @@ func validateResourceQuotaScopes(resourceQuotaSpec *core.ResourceQuotaSpec, fld return allErrs } +// validateScopedResourceSelectorRequirement tests that the match expressions has valid data +func validateScopedResourceSelectorRequirement(resourceQuotaSpec *core.ResourceQuotaSpec, fld *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + hardLimits := sets.NewString() + for k := range resourceQuotaSpec.Hard { + hardLimits.Insert(string(k)) + } + fldPath := fld.Child("matchExpressions") + scopeSet := sets.NewString() + for _, req := range resourceQuotaSpec.ScopeSelector.MatchExpressions { + if !helper.IsStandardResourceQuotaScope(string(req.ScopeName)) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("scopeName"), req.ScopeName, "unsupported scope")) + } + for _, k := range hardLimits.List() { + if helper.IsStandardQuotaResourceName(k) && !helper.IsResourceQuotaScopeValidForResource(req.ScopeName, k) { + allErrs = append(allErrs, field.Invalid(fldPath, resourceQuotaSpec.ScopeSelector, "unsupported scope applied to resource")) + } + } + switch req.ScopeName { + case core.ResourceQuotaScopeBestEffort, core.ResourceQuotaScopeNotBestEffort, core.ResourceQuotaScopeTerminating, core.ResourceQuotaScopeNotTerminating: + if req.Operator != core.ScopeSelectorOpExists { + allErrs = append(allErrs, field.Invalid(fldPath.Child("operator"), req.Operator, + "must be 'Exist' only operator when scope is any of ResourceQuotaScopeTerminating, ResourceQuotaScopeNotTerminating, ResourceQuotaScopeBestEffort and ResourceQuotaScopeNotBestEffort")) + } + } + + switch req.Operator { + case core.ScopeSelectorOpIn, core.ScopeSelectorOpNotIn: + if len(req.Values) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("values"), + "must be atleast one value when `operator` is 'In' or 'NotIn' for scope selector")) + } + case core.ScopeSelectorOpExists, core.ScopeSelectorOpDoesNotExist: + if len(req.Values) != 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("values"), req.Values, + "must be no value when `operator` is 'Exist' or 'DoesNotExist' for scope selector")) + } + default: + allErrs = append(allErrs, field.Invalid(fldPath.Child("operator"), req.Operator, "not a valid selector operator")) + } + scopeSet.Insert(string(req.ScopeName)) + } + invalidScopePairs := []sets.String{ + sets.NewString(string(core.ResourceQuotaScopeBestEffort), string(core.ResourceQuotaScopeNotBestEffort)), + sets.NewString(string(core.ResourceQuotaScopeTerminating), string(core.ResourceQuotaScopeNotTerminating)), + } + for _, invalidScopePair := range invalidScopePairs { + if scopeSet.HasAll(invalidScopePair.List()...) { + allErrs = append(allErrs, field.Invalid(fldPath, resourceQuotaSpec.Scopes, "conflicting scopes")) + } + } + + return allErrs +} + +// validateScopeSelector tests that the specified scope selector has valid data +func validateScopeSelector(resourceQuotaSpec *core.ResourceQuotaSpec, fld *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if resourceQuotaSpec.ScopeSelector == nil { + return allErrs + } + if !utilfeature.DefaultFeatureGate.Enabled(features.ResourceQuotaScopeSelectors) && resourceQuotaSpec.ScopeSelector != nil { + allErrs = append(allErrs, field.Forbidden(fld.Child("scopeSelector"), "ResourceQuotaScopeSelectors feature-gate is disabled")) + } + allErrs = append(allErrs, validateScopedResourceSelectorRequirement(resourceQuotaSpec, fld.Child("scopeSelector"))...) + return allErrs +} + // ValidateResourceQuota tests if required fields in the ResourceQuota are set. func ValidateResourceQuota(resourceQuota *core.ResourceQuota) field.ErrorList { allErrs := ValidateObjectMeta(&resourceQuota.ObjectMeta, true, ValidateResourceQuotaName, field.NewPath("metadata")) @@ -4759,6 +4914,7 @@ func ValidateResourceQuotaSpec(resourceQuotaSpec *core.ResourceQuotaSpec, fld *f allErrs = append(allErrs, ValidateResourceQuantityValue(string(k), v, resPath)...) } allErrs = append(allErrs, validateResourceQuotaScopes(resourceQuotaSpec, fld)...) + allErrs = append(allErrs, validateScopeSelector(resourceQuotaSpec, fld)...) return allErrs } @@ -5118,20 +5274,6 @@ func ValidateLoadBalancerStatus(status *core.LoadBalancerStatus, fldPath *field. return allErrs } -func sysctlIntersection(a []core.Sysctl, b []core.Sysctl) []string { - lookup := make(map[string]struct{}, len(a)) - result := []string{} - for i := range a { - lookup[a[i].Name] = struct{}{} - } - for i := range b { - if _, found := lookup[b[i].Name]; found { - result = append(result, b[i].Name) - } - } - return result -} - // validateVolumeNodeAffinity tests that the PersistentVolume.NodeAffinity has valid data // returns: // - true if volumeNodeAffinity is set diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index 416f4cd4890..6929ff2e519 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -5549,6 +5549,19 @@ func TestValidateContainers(t *testing.T) { TerminationMessagePolicy: "File", }, }, + "Invalid storage limit request": { + { + Name: "abc-123", + Image: "image", + Resources: core.ResourceRequirements{ + Limits: core.ResourceList{ + core.ResourceName("attachable-volumes-aws-ebs"): *resource.NewQuantity(10, resource.DecimalSI), + }, + }, + ImagePullPolicy: "IfNotPresent", + TerminationMessagePolicy: "File", + }, + }, "Request limit multiple invalid": { { Name: "abc-123", @@ -5865,6 +5878,149 @@ func TestValidatePodDNSConfig(t *testing.T) { } } +func TestValidatePodReadinessGates(t *testing.T) { + podReadinessGatesEnabled := utilfeature.DefaultFeatureGate.Enabled(features.PodReadinessGates) + defer func() { + // Restoring the old value. + if err := utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=%v", features.PodReadinessGates, podReadinessGatesEnabled)); err != nil { + t.Errorf("Failed to restore PodReadinessGates feature gate: %v", err) + } + }() + if err := utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.PodReadinessGates)); err != nil { + t.Errorf("Failed to enable PodReadinessGates feature gate: %v", err) + } + + successCases := []struct { + desc string + readinessGates []core.PodReadinessGate + }{ + { + "no gate", + []core.PodReadinessGate{}, + }, + { + "one readiness gate", + []core.PodReadinessGate{ + { + ConditionType: core.PodConditionType("example.com/condition"), + }, + }, + }, + { + "two readiness gates", + []core.PodReadinessGate{ + { + ConditionType: core.PodConditionType("example.com/condition1"), + }, + { + ConditionType: core.PodConditionType("example.com/condition2"), + }, + }, + }, + } + for _, tc := range successCases { + if errs := validateReadinessGates(tc.readinessGates, field.NewPath("field")); len(errs) != 0 { + t.Errorf("expect tc %q to success: %v", tc.desc, errs) + } + } + + errorCases := []struct { + desc string + readinessGates []core.PodReadinessGate + }{ + { + "invalid condition type", + []core.PodReadinessGate{ + { + ConditionType: core.PodConditionType("invalid/condition/type"), + }, + }, + }, + } + for _, tc := range errorCases { + if errs := validateReadinessGates(tc.readinessGates, field.NewPath("field")); len(errs) == 0 { + t.Errorf("expected tc %q to fail", tc.desc) + } + } +} + +func TestValidatePodConditions(t *testing.T) { + successCases := []struct { + desc string + podConditions []core.PodCondition + }{ + { + "no condition", + []core.PodCondition{}, + }, + { + "one system condition", + []core.PodCondition{ + { + Type: core.PodReady, + Status: core.ConditionTrue, + }, + }, + }, + { + "one system condition and one custom condition", + []core.PodCondition{ + { + Type: core.PodReady, + Status: core.ConditionTrue, + }, + { + Type: core.PodConditionType("example.com/condition"), + Status: core.ConditionFalse, + }, + }, + }, + { + "two custom condition", + []core.PodCondition{ + { + Type: core.PodConditionType("foobar"), + Status: core.ConditionTrue, + }, + { + Type: core.PodConditionType("example.com/condition"), + Status: core.ConditionFalse, + }, + }, + }, + } + + for _, tc := range successCases { + if errs := validatePodConditions(tc.podConditions, field.NewPath("field")); len(errs) != 0 { + t.Errorf("expected tc %q to success, but got: %v", tc.desc, errs) + } + } + + errorCases := []struct { + desc string + podConditions []core.PodCondition + }{ + { + "one system condition and a invalid custom condition", + []core.PodCondition{ + { + Type: core.PodReady, + Status: core.ConditionStatus("True"), + }, + { + Type: core.PodConditionType("invalid/custom/condition"), + Status: core.ConditionStatus("True"), + }, + }, + }, + } + for _, tc := range errorCases { + if errs := validatePodConditions(tc.podConditions, field.NewPath("field")); len(errs) == 0 { + t.Errorf("expected tc %q to fail", tc.desc) + } + } +} + func TestValidatePodSpec(t *testing.T) { activeDeadlineSeconds := int64(30) activeDeadlineSecondsMax := int64(math.MaxInt32) @@ -6622,12 +6778,28 @@ func TestValidatePod(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "123", Namespace: "ns", - Annotations: map[string]string{ - core.SysctlsPodAnnotationKey: "kernel.shmmni=32768,kernel.shmmax=1000000000", - core.UnsafeSysctlsPodAnnotationKey: "knet.ipv4.route.min_pmtu=1000", + }, + Spec: core.PodSpec{ + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + SecurityContext: &core.PodSecurityContext{ + Sysctls: []core.Sysctl{ + { + Name: "kernel.shmmni", + Value: "32768", + }, + { + Name: "kernel.shmmax", + Value: "1000000000", + }, + { + Name: "knet.ipv4.route.min_pmtu", + Value: "1000", + }, + }, }, }, - Spec: validPodSpec(nil), }, { // valid extended resources for init container ObjectMeta: metav1.ObjectMeta{Name: "valid-extended", Namespace: "ns"}, @@ -7308,59 +7480,6 @@ func TestValidatePod(t *testing.T) { Spec: validPodSpec(nil), }, }, - "invalid sysctl annotation": { - expectedError: "metadata.annotations[security.alpha.kubernetes.io/sysctls]", - spec: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - core.SysctlsPodAnnotationKey: "foo:", - }, - }, - Spec: validPodSpec(nil), - }, - }, - "invalid comma-separated sysctl annotation": { - expectedError: "not of the format sysctl_name=value", - spec: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - core.SysctlsPodAnnotationKey: "kernel.msgmax,", - }, - }, - Spec: validPodSpec(nil), - }, - }, - "invalid unsafe sysctl annotation": { - expectedError: "metadata.annotations[security.alpha.kubernetes.io/sysctls]", - spec: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - core.SysctlsPodAnnotationKey: "foo:", - }, - }, - Spec: validPodSpec(nil), - }, - }, - "intersecting safe sysctls and unsafe sysctls annotations": { - expectedError: "can not be safe and unsafe", - spec: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - core.SysctlsPodAnnotationKey: "kernel.shmmax=10000000", - core.UnsafeSysctlsPodAnnotationKey: "kernel.shmmax=10000000", - }, - }, - Spec: validPodSpec(nil), - }, - }, "invalid extended resource requirement: request must be == limit": { expectedError: "must be equal to example.com/a", spec: core.Pod{ @@ -11352,6 +11471,18 @@ func TestValidateResourceQuota(t *testing.T) { Scopes: []core.ResourceQuotaScope{core.ResourceQuotaScopeNotBestEffort}, } + scopeSelectorSpec := core.ResourceQuotaSpec{ + ScopeSelector: &core.ScopeSelector{ + MatchExpressions: []core.ScopedResourceSelectorRequirement{ + { + ScopeName: core.ResourceQuotaScopePriorityClass, + Operator: core.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + } + // storage is not yet supported as a quota tracked resource invalidQuotaResourceSpec := core.ResourceQuotaSpec{ Hard: core.ResourceList{ @@ -11444,6 +11575,13 @@ func TestValidateResourceQuota(t *testing.T) { }, Spec: bestEffortSpec, }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "abc", + Namespace: "foo", + }, + Spec: scopeSelectorSpec, + }, { ObjectMeta: metav1.ObjectMeta{ Name: "abc", @@ -11452,12 +11590,13 @@ func TestValidateResourceQuota(t *testing.T) { Spec: nonBestEffortSpec, }, } - + utilfeature.DefaultFeatureGate.Set("ResourceQuotaScopeSelectors=true") for _, successCase := range successCases { if errs := ValidateResourceQuota(&successCase); len(errs) != 0 { t.Errorf("expected success: %v", errs) } } + utilfeature.DefaultFeatureGate.Set("ResourceQuotaScopeSelectors=false") errorCases := map[string]struct { R core.ResourceQuota @@ -11503,6 +11642,10 @@ func TestValidateResourceQuota(t *testing.T) { core.ResourceQuota{ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: invalidScopeNameSpec}, "unsupported scope", }, + "forbidden-quota-scope-selector": { + core.ResourceQuota{ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: scopeSelectorSpec}, + "feature-gate is disabled", + }, } for k, v := range errorCases { errs := ValidateResourceQuota(&v.R) @@ -12625,6 +12768,11 @@ func TestValidateSysctls(t *testing.T) { "_invalid", } + duplicates := []string{ + "kernel.shmmax", + "kernel.shmmax", + } + sysctls := make([]core.Sysctl, len(valid)) for i, sysctl := range valid { sysctls[i].Name = sysctl @@ -12649,6 +12797,17 @@ func TestValidateSysctls(t *testing.T) { t.Errorf("unexpected errors: expected=%q, got=%q", expected, got) } } + + sysctls = make([]core.Sysctl, len(duplicates)) + for i, sysctl := range duplicates { + sysctls[i].Name = sysctl + } + errs = validateSysctls(sysctls, field.NewPath("foo")) + if len(errs) != 1 { + t.Errorf("unexpected validation errors: %v", errs) + } else if errs[0].Type != field.ErrorTypeDuplicate { + t.Errorf("expected error type %v, got %v", field.ErrorTypeDuplicate, errs[0].Type) + } } func newNodeNameEndpoint(nodeName string) *core.Endpoints { diff --git a/pkg/apis/core/zz_generated.deepcopy.go b/pkg/apis/core/zz_generated.deepcopy.go index f4e79ce13bd..3331f6e1fa9 100644 --- a/pkg/apis/core/zz_generated.deepcopy.go +++ b/pkg/apis/core/zz_generated.deepcopy.go @@ -380,9 +380,43 @@ func (in *CephFSVolumeSource) DeepCopy() *CephFSVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CinderPersistentVolumeSource) DeepCopyInto(out *CinderPersistentVolumeSource) { + *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + if *in == nil { + *out = nil + } else { + *out = new(SecretReference) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CinderPersistentVolumeSource. +func (in *CinderPersistentVolumeSource) DeepCopy() *CinderPersistentVolumeSource { + if in == nil { + return nil + } + out := new(CinderPersistentVolumeSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CinderVolumeSource) DeepCopyInto(out *CinderVolumeSource) { *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + if *in == nil { + *out = nil + } else { + *out = new(LocalObjectReference) + **out = **in + } + } return } @@ -3104,8 +3138,8 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) { if *in == nil { *out = nil } else { - *out = new(CinderVolumeSource) - **out = **in + *out = new(CinderPersistentVolumeSource) + (*in).DeepCopyInto(*out) } } if in.CephFS != nil { @@ -3719,6 +3753,22 @@ func (in *PodProxyOptions) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodReadinessGate) DeepCopyInto(out *PodReadinessGate) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodReadinessGate. +func (in *PodReadinessGate) DeepCopy() *PodReadinessGate { + if in == nil { + return nil + } + out := new(PodReadinessGate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) { *out = *in @@ -3781,6 +3831,11 @@ func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) { **out = **in } } + if in.Sysctls != nil { + in, out := &in.Sysctls, &out.Sysctls + *out = make([]Sysctl, len(*in)) + copy(*out, *in) + } return } @@ -3932,6 +3987,11 @@ func (in *PodSpec) DeepCopyInto(out *PodSpec) { (*in).DeepCopyInto(*out) } } + if in.ReadinessGates != nil { + in, out := &in.ReadinessGates, &out.ReadinessGates + *out = make([]PodReadinessGate, len(*in)) + copy(*out, *in) + } return } @@ -4575,6 +4635,15 @@ func (in *ResourceQuotaSpec) DeepCopyInto(out *ResourceQuotaSpec) { *out = make([]ResourceQuotaScope, len(*in)) copy(*out, *in) } + if in.ScopeSelector != nil { + in, out := &in.ScopeSelector, &out.ScopeSelector + if *in == nil { + *out = nil + } else { + *out = new(ScopeSelector) + (*in).DeepCopyInto(*out) + } + } return } @@ -4714,6 +4783,50 @@ func (in *ScaleIOVolumeSource) DeepCopy() *ScaleIOVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopeSelector) DeepCopyInto(out *ScopeSelector) { + *out = *in + if in.MatchExpressions != nil { + in, out := &in.MatchExpressions, &out.MatchExpressions + *out = make([]ScopedResourceSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopeSelector. +func (in *ScopeSelector) DeepCopy() *ScopeSelector { + if in == nil { + return nil + } + out := new(ScopeSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopedResourceSelectorRequirement) DeepCopyInto(out *ScopedResourceSelectorRequirement) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopedResourceSelectorRequirement. +func (in *ScopedResourceSelectorRequirement) DeepCopy() *ScopedResourceSelectorRequirement { + if in == nil { + return nil + } + out := new(ScopedResourceSelectorRequirement) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Secret) DeepCopyInto(out *Secret) { *out = *in @@ -5147,6 +5260,22 @@ func (in *ServiceAccountList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceAccountTokenProjection) DeepCopyInto(out *ServiceAccountTokenProjection) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccountTokenProjection. +func (in *ServiceAccountTokenProjection) DeepCopy() *ServiceAccountTokenProjection { + if in == nil { + return nil + } + out := new(ServiceAccountTokenProjection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceList) DeepCopyInto(out *ServiceList) { *out = *in @@ -5443,6 +5572,50 @@ func (in *Toleration) DeepCopy() *Toleration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TopologySelectorLabelRequirement) DeepCopyInto(out *TopologySelectorLabelRequirement) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologySelectorLabelRequirement. +func (in *TopologySelectorLabelRequirement) DeepCopy() *TopologySelectorLabelRequirement { + if in == nil { + return nil + } + out := new(TopologySelectorLabelRequirement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TopologySelectorTerm) DeepCopyInto(out *TopologySelectorTerm) { + *out = *in + if in.MatchLabelExpressions != nil { + in, out := &in.MatchLabelExpressions, &out.MatchLabelExpressions + *out = make([]TopologySelectorLabelRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologySelectorTerm. +func (in *TopologySelectorTerm) DeepCopy() *TopologySelectorTerm { + if in == nil { + return nil + } + out := new(TopologySelectorTerm) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Volume) DeepCopyInto(out *Volume) { *out = *in @@ -5556,6 +5729,15 @@ func (in *VolumeProjection) DeepCopyInto(out *VolumeProjection) { (*in).DeepCopyInto(*out) } } + if in.ServiceAccountToken != nil { + in, out := &in.ServiceAccountToken, &out.ServiceAccountToken + if *in == nil { + *out = nil + } else { + *out = new(ServiceAccountTokenProjection) + **out = **in + } + } return } @@ -5695,7 +5877,7 @@ func (in *VolumeSource) DeepCopyInto(out *VolumeSource) { *out = nil } else { *out = new(CinderVolumeSource) - **out = **in + (*in).DeepCopyInto(*out) } } if in.CephFS != nil { diff --git a/pkg/apis/extensions/fuzzer/BUILD b/pkg/apis/extensions/fuzzer/BUILD index 712d0f4e681..4f4bf9cce0f 100644 --- a/pkg/apis/extensions/fuzzer/BUILD +++ b/pkg/apis/extensions/fuzzer/BUILD @@ -12,6 +12,7 @@ go_library( deps = [ "//pkg/apis/extensions:go_default_library", "//vendor/github.com/google/gofuzz:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", ], diff --git a/pkg/apis/extensions/fuzzer/fuzzer.go b/pkg/apis/extensions/fuzzer/fuzzer.go index fb40167542e..277a327c944 100644 --- a/pkg/apis/extensions/fuzzer/fuzzer.go +++ b/pkg/apis/extensions/fuzzer/fuzzer.go @@ -21,6 +21,7 @@ import ( fuzz "github.com/google/gofuzz" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/kubernetes/pkg/apis/extensions" @@ -29,6 +30,17 @@ import ( // Funcs returns the fuzzer functions for the extensions api group. var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ + func(j *extensions.Deployment, c fuzz.Continue) { + c.FuzzNoCustom(j) + + // match defaulting + if j.Spec.Selector == nil { + j.Spec.Selector = &metav1.LabelSelector{MatchLabels: j.Spec.Template.Labels} + } + if len(j.Labels) == 0 { + j.Labels = j.Spec.Template.Labels + } + }, func(j *extensions.DeploymentSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // fuzz self without calling this function again rhl := int32(c.Rand.Int31()) @@ -54,6 +66,15 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { j.RollingUpdate = &rollingUpdate } }, + func(j *extensions.DaemonSet, c fuzz.Continue) { + c.FuzzNoCustom(j) + + // match defaulter + j.Spec.Template.Generation = 0 + if len(j.ObjectMeta.Labels) == 0 { + j.ObjectMeta.Labels = j.Spec.Template.ObjectMeta.Labels + } + }, func(j *extensions.DaemonSetSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // fuzz self without calling this function again rhl := int32(c.Rand.Int31()) @@ -78,5 +99,16 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { j.RollingUpdate = &rollingUpdate } }, + func(j *extensions.ReplicaSet, c fuzz.Continue) { + c.FuzzNoCustom(j) + + // match defaulter + if j.Spec.Selector == nil { + j.Spec.Selector = &metav1.LabelSelector{MatchLabels: j.Spec.Template.Labels} + } + if len(j.Labels) == 0 { + j.Labels = j.Spec.Template.Labels + } + }, } } diff --git a/pkg/apis/extensions/v1beta1/zz_generated.conversion.go b/pkg/apis/extensions/v1beta1/zz_generated.conversion.go index c6b51c84e88..2eb34cb40f9 100644 --- a/pkg/apis/extensions/v1beta1/zz_generated.conversion.go +++ b/pkg/apis/extensions/v1beta1/zz_generated.conversion.go @@ -168,6 +168,7 @@ func Convert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in *policy.Al func autoConvert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath(in *v1beta1.AllowedHostPath, out *policy.AllowedHostPath, s conversion.Scope) error { out.PathPrefix = in.PathPrefix + out.ReadOnly = in.ReadOnly return nil } @@ -178,6 +179,7 @@ func Convert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath(in *v1beta1.Allow func autoConvert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath(in *policy.AllowedHostPath, out *v1beta1.AllowedHostPath, s conversion.Scope) error { out.PathPrefix = in.PathPrefix + out.ReadOnly = in.ReadOnly return nil } @@ -1121,6 +1123,8 @@ func autoConvert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec(i } out.AllowedHostPaths = *(*[]policy.AllowedHostPath)(unsafe.Pointer(&in.AllowedHostPaths)) out.AllowedFlexVolumes = *(*[]policy.AllowedFlexVolume)(unsafe.Pointer(&in.AllowedFlexVolumes)) + out.AllowedUnsafeSysctls = *(*[]string)(unsafe.Pointer(&in.AllowedUnsafeSysctls)) + out.ForbiddenSysctls = *(*[]string)(unsafe.Pointer(&in.ForbiddenSysctls)) return nil } @@ -1158,6 +1162,8 @@ func autoConvert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(i } out.AllowedHostPaths = *(*[]v1beta1.AllowedHostPath)(unsafe.Pointer(&in.AllowedHostPaths)) out.AllowedFlexVolumes = *(*[]v1beta1.AllowedFlexVolume)(unsafe.Pointer(&in.AllowedFlexVolumes)) + out.AllowedUnsafeSysctls = *(*[]string)(unsafe.Pointer(&in.AllowedUnsafeSysctls)) + out.ForbiddenSysctls = *(*[]string)(unsafe.Pointer(&in.ForbiddenSysctls)) return nil } diff --git a/pkg/apis/extensions/v1beta1/zz_generated.defaults.go b/pkg/apis/extensions/v1beta1/zz_generated.defaults.go index 14df117c3ec..0fa4c321c29 100644 --- a/pkg/apis/extensions/v1beta1/zz_generated.defaults.go +++ b/pkg/apis/extensions/v1beta1/zz_generated.defaults.go @@ -88,6 +88,9 @@ func SetObjectDefaults_DaemonSet(in *v1beta1.DaemonSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -232,6 +235,9 @@ func SetObjectDefaults_Deployment(in *v1beta1.Deployment) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -398,6 +404,9 @@ func SetObjectDefaults_ReplicaSet(in *v1beta1.ReplicaSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/pkg/apis/policy/BUILD b/pkg/apis/policy/BUILD index 03daa629177..2b429bb086f 100644 --- a/pkg/apis/policy/BUILD +++ b/pkg/apis/policy/BUILD @@ -3,14 +3,12 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", - "go_test", ) go_library( name = "go_default_library", srcs = [ "doc.go", - "helpers.go", "register.go", "types.go", "zz_generated.deepcopy.go", @@ -43,9 +41,3 @@ filegroup( ], tags = ["automanaged"], ) - -go_test( - name = "go_default_test", - srcs = ["helpers_test.go"], - embed = [":go_default_library"], -) diff --git a/pkg/apis/policy/helpers.go b/pkg/apis/policy/helpers.go deleted file mode 100644 index 9c1ebd15235..00000000000 --- a/pkg/apis/policy/helpers.go +++ /dev/null @@ -1,37 +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 policy - -import ( - "strings" -) - -// SysctlsFromPodSecurityPolicyAnnotation parses an annotation value of the key -// SysctlsSecurityPolicyAnnotationKey into a slice of sysctls. An empty slice -// is returned if annotation is the empty string. -func SysctlsFromPodSecurityPolicyAnnotation(annotation string) ([]string, error) { - if len(annotation) == 0 { - return []string{}, nil - } - - return strings.Split(annotation, ","), nil -} - -// PodAnnotationsFromSysctls creates an annotation value for a slice of Sysctls. -func PodAnnotationsFromSysctls(sysctls []string) string { - return strings.Join(sysctls, ",") -} diff --git a/pkg/apis/policy/helpers_test.go b/pkg/apis/policy/helpers_test.go deleted file mode 100644 index b07c8e30f58..00000000000 --- a/pkg/apis/policy/helpers_test.go +++ /dev/null @@ -1,62 +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 policy - -import ( - "reflect" - "testing" -) - -func TestPodAnnotationsFromSysctls(t *testing.T) { - type Test struct { - sysctls []string - expectedValue string - } - for _, test := range []Test{ - {sysctls: []string{"a.b"}, expectedValue: "a.b"}, - {sysctls: []string{"a.b", "c.d"}, expectedValue: "a.b,c.d"}, - {sysctls: []string{"a.b", "a.b"}, expectedValue: "a.b,a.b"}, - {sysctls: []string{}, expectedValue: ""}, - {sysctls: nil, expectedValue: ""}, - } { - a := PodAnnotationsFromSysctls(test.sysctls) - if a != test.expectedValue { - t.Errorf("wrong value for %v: got=%q wanted=%q", test.sysctls, a, test.expectedValue) - } - } -} - -func TestSysctlsFromPodSecurityPolicyAnnotation(t *testing.T) { - type Test struct { - expectedValue []string - annotation string - } - for _, test := range []Test{ - {annotation: "a.b", expectedValue: []string{"a.b"}}, - {annotation: "a.b,c.d", expectedValue: []string{"a.b", "c.d"}}, - {annotation: "a.b,a.b", expectedValue: []string{"a.b", "a.b"}}, - {annotation: "", expectedValue: []string{}}, - } { - sysctls, err := SysctlsFromPodSecurityPolicyAnnotation(test.annotation) - if err != nil { - t.Errorf("error for %q: %v", test.annotation, err) - } - if !reflect.DeepEqual(sysctls, test.expectedValue) { - t.Errorf("wrong value for %q: got=%v wanted=%v", test.annotation, sysctls, test.expectedValue) - } - } -} diff --git a/pkg/apis/policy/types.go b/pkg/apis/policy/types.go index 4d138ec1044..298fcd0e4df 100644 --- a/pkg/apis/policy/types.go +++ b/pkg/apis/policy/types.go @@ -22,13 +22,6 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" ) -const ( - // SysctlsPodSecurityPolicyAnnotationKey represents the key of a whitelist of - // allowed safe and unsafe sysctls in a pod spec. It's a comma-separated list of plain sysctl - // names or sysctl patterns (which end in *). The string "*" matches all sysctls. - SysctlsPodSecurityPolicyAnnotationKey string = "security.alpha.kubernetes.io/sysctls" -) - // PodDisruptionBudgetSpec is a description of a PodDisruptionBudget. type PodDisruptionBudgetSpec struct { // An eviction is allowed if at least "minAvailable" pods selected by @@ -215,6 +208,25 @@ type PodSecurityPolicySpec struct { // is allowed in the "Volumes" field. // +optional AllowedFlexVolumes []AllowedFlexVolume + // AllowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + AllowedUnsafeSysctls []string + // ForbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + ForbiddenSysctls []string } // AllowedHostPath defines the host volume conditions that will be enabled by a policy @@ -228,6 +240,9 @@ type AllowedHostPath struct { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` PathPrefix string + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + ReadOnly bool } // HostPortRange defines a range of host ports that will be enabled by a policy diff --git a/pkg/apis/policy/v1beta1/zz_generated.conversion.go b/pkg/apis/policy/v1beta1/zz_generated.conversion.go index 9ac64398fc0..4e4e3cb1bcb 100644 --- a/pkg/apis/policy/v1beta1/zz_generated.conversion.go +++ b/pkg/apis/policy/v1beta1/zz_generated.conversion.go @@ -98,6 +98,7 @@ func Convert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in *policy.Al func autoConvert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath(in *v1beta1.AllowedHostPath, out *policy.AllowedHostPath, s conversion.Scope) error { out.PathPrefix = in.PathPrefix + out.ReadOnly = in.ReadOnly return nil } @@ -108,6 +109,7 @@ func Convert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath(in *v1beta1.Allow func autoConvert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath(in *policy.AllowedHostPath, out *v1beta1.AllowedHostPath, s conversion.Scope) error { out.PathPrefix = in.PathPrefix + out.ReadOnly = in.ReadOnly return nil } @@ -409,6 +411,8 @@ func autoConvert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec(i } out.AllowedHostPaths = *(*[]policy.AllowedHostPath)(unsafe.Pointer(&in.AllowedHostPaths)) out.AllowedFlexVolumes = *(*[]policy.AllowedFlexVolume)(unsafe.Pointer(&in.AllowedFlexVolumes)) + out.AllowedUnsafeSysctls = *(*[]string)(unsafe.Pointer(&in.AllowedUnsafeSysctls)) + out.ForbiddenSysctls = *(*[]string)(unsafe.Pointer(&in.ForbiddenSysctls)) return nil } @@ -446,6 +450,8 @@ func autoConvert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(i } out.AllowedHostPaths = *(*[]v1beta1.AllowedHostPath)(unsafe.Pointer(&in.AllowedHostPaths)) out.AllowedFlexVolumes = *(*[]v1beta1.AllowedFlexVolume)(unsafe.Pointer(&in.AllowedFlexVolumes)) + out.AllowedUnsafeSysctls = *(*[]string)(unsafe.Pointer(&in.AllowedUnsafeSysctls)) + out.ForbiddenSysctls = *(*[]string)(unsafe.Pointer(&in.ForbiddenSysctls)) return nil } diff --git a/pkg/apis/policy/validation/BUILD b/pkg/apis/policy/validation/BUILD index d4895156c42..14fcee1d6ef 100644 --- a/pkg/apis/policy/validation/BUILD +++ b/pkg/apis/policy/validation/BUILD @@ -15,12 +15,14 @@ go_library( "//pkg/apis/core/validation:go_default_library", "//pkg/apis/extensions/validation:go_default_library", "//pkg/apis/policy:go_default_library", + "//pkg/features:go_default_library", "//pkg/security/apparmor:go_default_library", "//pkg/security/podsecuritypolicy/seccomp:go_default_library", "//pkg/security/podsecuritypolicy/util:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/pkg/apis/policy/validation/validation.go b/pkg/apis/policy/validation/validation.go index c1b592a858f..aa898ad8fdd 100644 --- a/pkg/apis/policy/validation/validation.go +++ b/pkg/apis/policy/validation/validation.go @@ -30,9 +30,12 @@ import ( apivalidation "k8s.io/kubernetes/pkg/apis/core/validation" extensionsvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation" "k8s.io/kubernetes/pkg/apis/policy" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/security/apparmor" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" + + utilfeature "k8s.io/apiserver/pkg/util/feature" ) func ValidatePodDisruptionBudget(pdb *policy.PodDisruptionBudget) field.ErrorList { @@ -118,6 +121,9 @@ func ValidatePodSecurityPolicySpec(spec *policy.PodSecurityPolicySpec, fldPath * allErrs = append(allErrs, validatePSPDefaultAllowPrivilegeEscalation(fldPath.Child("defaultAllowPrivilegeEscalation"), spec.DefaultAllowPrivilegeEscalation, spec.AllowPrivilegeEscalation)...) 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)...) + allErrs = append(allErrs, validatePodSecurityPolicySysctls(fldPath.Child("forbiddenSysctls"), spec.ForbiddenSysctls)...) + allErrs = append(allErrs, validatePodSecurityPolicySysctlListsDoNotOverlap(fldPath.Child("allowedUnsafeSysctls"), fldPath.Child("forbiddenSysctls"), spec.AllowedUnsafeSysctls, spec.ForbiddenSysctls)...) return allErrs } @@ -138,15 +144,6 @@ func ValidatePodSecurityPolicySpecificAnnotations(annotations map[string]string, } } - sysctlAnnotation := annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] - sysctlFldPath := fldPath.Key(policy.SysctlsPodSecurityPolicyAnnotationKey) - sysctls, err := policy.SysctlsFromPodSecurityPolicyAnnotation(sysctlAnnotation) - if err != nil { - allErrs = append(allErrs, field.Invalid(sysctlFldPath, sysctlAnnotation, err.Error())) - } else { - allErrs = append(allErrs, validatePodSecurityPolicySysctls(sysctlFldPath, sysctls)...) - } - if p := annotations[seccomp.DefaultProfileAnnotationKey]; p != "" { allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.DefaultProfileAnnotationKey))...) } @@ -307,11 +304,64 @@ func IsValidSysctlPattern(name string) bool { return sysctlPatternRegexp.MatchString(name) } +func validatePodSecurityPolicySysctlListsDoNotOverlap(allowedSysctlsFldPath, forbiddenSysctlsFldPath *field.Path, allowedUnsafeSysctls, forbiddenSysctls []string) field.ErrorList { + allErrs := field.ErrorList{} + for i, allowedSysctl := range allowedUnsafeSysctls { + isAllowedSysctlPattern := false + allowedSysctlPrefix := "" + if strings.HasSuffix(allowedSysctl, "*") { + isAllowedSysctlPattern = true + allowedSysctlPrefix = strings.TrimSuffix(allowedSysctl, "*") + } + for j, forbiddenSysctl := range forbiddenSysctls { + isForbiddenSysctlPattern := false + forbiddenSysctlPrefix := "" + if strings.HasSuffix(forbiddenSysctl, "*") { + isForbiddenSysctlPattern = true + forbiddenSysctlPrefix = strings.TrimSuffix(forbiddenSysctl, "*") + } + switch { + case isAllowedSysctlPattern && isForbiddenSysctlPattern: + if strings.HasPrefix(allowedSysctlPrefix, forbiddenSysctlPrefix) { + allErrs = append(allErrs, field.Invalid(allowedSysctlsFldPath.Index(i), allowedUnsafeSysctls[i], fmt.Sprintf("sysctl overlaps with %v", forbiddenSysctl))) + } else if strings.HasPrefix(forbiddenSysctlPrefix, allowedSysctlPrefix) { + allErrs = append(allErrs, field.Invalid(forbiddenSysctlsFldPath.Index(j), forbiddenSysctls[j], fmt.Sprintf("sysctl overlaps with %v", allowedSysctl))) + } + case isAllowedSysctlPattern: + if strings.HasPrefix(forbiddenSysctl, allowedSysctlPrefix) { + allErrs = append(allErrs, field.Invalid(forbiddenSysctlsFldPath.Index(j), forbiddenSysctls[j], fmt.Sprintf("sysctl overlaps with %v", allowedSysctl))) + } + case isForbiddenSysctlPattern: + if strings.HasPrefix(allowedSysctl, forbiddenSysctlPrefix) { + allErrs = append(allErrs, field.Invalid(allowedSysctlsFldPath.Index(i), allowedUnsafeSysctls[i], fmt.Sprintf("sysctl overlaps with %v", forbiddenSysctl))) + } + default: + if allowedSysctl == forbiddenSysctl { + allErrs = append(allErrs, field.Invalid(allowedSysctlsFldPath.Index(i), allowedUnsafeSysctls[i], fmt.Sprintf("sysctl overlaps with %v", forbiddenSysctl))) + } + } + } + } + return allErrs +} + // validatePodSecurityPolicySysctls validates the sysctls fields of PodSecurityPolicy. func validatePodSecurityPolicySysctls(fldPath *field.Path, sysctls []string) field.ErrorList { allErrs := field.ErrorList{} + + if len(sysctls) == 0 { + return allErrs + } + + if !utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) { + return append(allErrs, field.Forbidden(fldPath, "Sysctls are disabled by Sysctls feature-gate")) + } + + coversAll := false for i, s := range sysctls { - if !IsValidSysctlPattern(string(s)) { + if len(s) == 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i), sysctls[i], fmt.Sprintf("empty sysctl not allowed"))) + } else if !IsValidSysctlPattern(string(s)) { allErrs = append( allErrs, field.Invalid(fldPath.Index(i), sysctls[i], fmt.Sprintf("must have at most %d characters and match regex %s", @@ -319,9 +369,15 @@ func validatePodSecurityPolicySysctls(fldPath *field.Path, sysctls []string) fie SysctlPatternFmt, )), ) + } else if s[0] == '*' { + coversAll = true } } + if coversAll && len(sysctls) > 1 { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("items"), fmt.Sprintf("if '*' is present, must not specify other sysctls"))) + } + return allErrs } diff --git a/pkg/apis/policy/validation/validation_test.go b/pkg/apis/policy/validation/validation_test.go index 681812a63cc..552fd8cecab 100644 --- a/pkg/apis/policy/validation/validation_test.go +++ b/pkg/apis/policy/validation/validation_test.go @@ -323,8 +323,19 @@ func TestValidatePodSecurityPolicy(t *testing.T) { apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + ",not-good", } - invalidSysctlPattern := validPSP() - invalidSysctlPattern.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "a.*.b" + invalidAllowedUnsafeSysctlPattern := validPSP() + invalidAllowedUnsafeSysctlPattern.Spec.AllowedUnsafeSysctls = []string{"a.*.b"} + + invalidForbiddenSysctlPattern := validPSP() + invalidForbiddenSysctlPattern.Spec.ForbiddenSysctls = []string{"a.*.b"} + + invalidOverlappingSysctls := validPSP() + invalidOverlappingSysctls.Spec.ForbiddenSysctls = []string{"kernel.*", "net.ipv4.ip_local_port_range"} + invalidOverlappingSysctls.Spec.AllowedUnsafeSysctls = []string{"kernel.shmmax", "net.ipv4.ip_local_port_range"} + + invalidDuplicatedSysctls := validPSP() + invalidDuplicatedSysctls.Spec.ForbiddenSysctls = []string{"net.ipv4.ip_local_port_range"} + invalidDuplicatedSysctls.Spec.AllowedUnsafeSysctls = []string{"net.ipv4.ip_local_port_range"} invalidSeccompDefault := validPSP() invalidSeccompDefault.Annotations = map[string]string{ @@ -456,11 +467,26 @@ func TestValidatePodSecurityPolicy(t *testing.T) { errorType: field.ErrorTypeInvalid, errorDetail: "invalid AppArmor profile name: \"not-good\"", }, - "invalid sysctl pattern": { - psp: invalidSysctlPattern, + "invalid allowed unsafe sysctl pattern": { + psp: invalidAllowedUnsafeSysctlPattern, errorType: field.ErrorTypeInvalid, errorDetail: fmt.Sprintf("must have at most 253 characters and match regex %s", SysctlPatternFmt), }, + "invalid forbidden sysctl pattern": { + psp: invalidForbiddenSysctlPattern, + errorType: field.ErrorTypeInvalid, + errorDetail: fmt.Sprintf("must have at most 253 characters and match regex %s", SysctlPatternFmt), + }, + "invalid overlapping sysctl pattern": { + psp: invalidOverlappingSysctls, + errorType: field.ErrorTypeInvalid, + errorDetail: fmt.Sprintf("sysctl overlaps with %s", invalidOverlappingSysctls.Spec.ForbiddenSysctls[0]), + }, + "invalid duplicated sysctls": { + psp: invalidDuplicatedSysctls, + errorType: field.ErrorTypeInvalid, + errorDetail: fmt.Sprintf("sysctl overlaps with %s", invalidDuplicatedSysctls.Spec.AllowedUnsafeSysctls[0]), + }, "invalid seccomp default profile": { psp: invalidSeccompDefault, errorType: field.ErrorTypeInvalid, @@ -561,8 +587,11 @@ func TestValidatePodSecurityPolicy(t *testing.T) { apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + "," + apparmor.ProfileNamePrefix + "foo", } - withSysctl := validPSP() - withSysctl.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "net.*" + withForbiddenSysctl := validPSP() + withForbiddenSysctl.Spec.ForbiddenSysctls = []string{"net.*"} + + withAllowedUnsafeSysctl := validPSP() + withAllowedUnsafeSysctl.Spec.AllowedUnsafeSysctls = []string{"net.ipv4.tcp_max_syn_backlog"} validSeccomp := validPSP() validSeccomp.Annotations = map[string]string{ @@ -607,8 +636,11 @@ func TestValidatePodSecurityPolicy(t *testing.T) { "valid AppArmor annotations": { psp: validAppArmor, }, - "with network sysctls": { - psp: withSysctl, + "with network sysctls forbidden": { + psp: withForbiddenSysctl, + }, + "with unsafe net.ipv4.tcp_max_syn_backlog sysctl allowed": { + psp: withAllowedUnsafeSysctl, }, "valid seccomp annotations": { psp: validSeccomp, diff --git a/pkg/apis/policy/zz_generated.deepcopy.go b/pkg/apis/policy/zz_generated.deepcopy.go index 25147ba6c2a..3bb51ae48eb 100644 --- a/pkg/apis/policy/zz_generated.deepcopy.go +++ b/pkg/apis/policy/zz_generated.deepcopy.go @@ -385,6 +385,16 @@ func (in *PodSecurityPolicySpec) DeepCopyInto(out *PodSecurityPolicySpec) { *out = make([]AllowedFlexVolume, len(*in)) copy(*out, *in) } + if in.AllowedUnsafeSysctls != nil { + in, out := &in.AllowedUnsafeSysctls, &out.AllowedUnsafeSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ForbiddenSysctls != nil { + in, out := &in.ForbiddenSysctls, &out.ForbiddenSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/pkg/apis/settings/v1alpha1/zz_generated.defaults.go b/pkg/apis/settings/v1alpha1/zz_generated.defaults.go index a02bfefecad..b8559cf3ef3 100644 --- a/pkg/apis/settings/v1alpha1/zz_generated.defaults.go +++ b/pkg/apis/settings/v1alpha1/zz_generated.defaults.go @@ -86,6 +86,9 @@ func SetObjectDefaults_PodPreset(in *v1alpha1.PodPreset) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/pkg/apis/storage/types.go b/pkg/apis/storage/types.go index e44b327d381..cd86b02f281 100644 --- a/pkg/apis/storage/types.go +++ b/pkg/apis/storage/types.go @@ -72,6 +72,14 @@ type StorageClass struct { // the VolumeScheduling feature. // +optional VolumeBindingMode *VolumeBindingMode + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + AllowedTopologies []api.TopologySelectorTerm } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/apis/storage/util/BUILD b/pkg/apis/storage/util/BUILD index 7a5a5fd334c..c095396fb11 100644 --- a/pkg/apis/storage/util/BUILD +++ b/pkg/apis/storage/util/BUILD @@ -39,6 +39,7 @@ go_test( srcs = ["util_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/apis/core:go_default_library", "//pkg/apis/storage:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], diff --git a/pkg/apis/storage/util/util.go b/pkg/apis/storage/util/util.go index 9d134043563..c81a95b8165 100644 --- a/pkg/apis/storage/util/util.go +++ b/pkg/apis/storage/util/util.go @@ -27,4 +27,7 @@ func DropDisabledAlphaFields(class *storage.StorageClass) { if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { class.VolumeBindingMode = nil } + if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + class.AllowedTopologies = nil + } } diff --git a/pkg/apis/storage/util/util_test.go b/pkg/apis/storage/util/util_test.go index 1a0ef70b0b5..f783c2ee422 100644 --- a/pkg/apis/storage/util/util_test.go +++ b/pkg/apis/storage/util/util_test.go @@ -17,39 +17,60 @@ limitations under the License. package util import ( + "reflect" "testing" utilfeature "k8s.io/apiserver/pkg/util/feature" + api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/storage" ) func TestDropAlphaFields(t *testing.T) { bindingMode := storage.VolumeBindingWaitForFirstConsumer + allowedTopologies := []api.TopologySelectorTerm{ + { + MatchLabelExpressions: []api.TopologySelectorLabelRequirement{ + { + Key: "kubernetes.io/hostname", + Values: []string{"node1"}, + }, + }, + }, + } // Test that field gets dropped when feature gate is not set - if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false"); err != nil { - t.Fatalf("Failed to set feature gate for VolumeScheduling: %v", err) + if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false,DynamicProvisioningScheduling=false"); err != nil { + t.Fatalf("Failed to set feature gate for VolumeScheduling or DynamicProvisioningScheduling: %v", err) } 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) + } // Test that field does not get dropped when feature gate is set class = &storage.StorageClass{ VolumeBindingMode: &bindingMode, + AllowedTopologies: allowedTopologies, } - if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=true"); err != nil { - t.Fatalf("Failed to set feature gate for VolumeScheduling: %v", err) + if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=true,DynamicProvisioningScheduling=true"); err != nil { + t.Fatalf("Failed to set feature gate for VolumeScheduling or DynamicProvisioningScheduling: %v", err) } DropDisabledAlphaFields(class) if class.VolumeBindingMode != &bindingMode { t.Errorf("VolumeBindingMode field got unexpectantly modified: %+v", class.VolumeBindingMode) } - if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false"); err != nil { - t.Fatalf("Failed to disable feature gate for VolumeScheduling: %v", err) + if !reflect.DeepEqual(class.AllowedTopologies, allowedTopologies) { + t.Errorf("AllowedTopologies field got unexpectantly modified: %+v", class.AllowedTopologies) + } + + if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false,DynamicProvisioningScheduling=false"); err != nil { + t.Fatalf("Failed to disable feature gate for VolumeScheduling or DynamicProvisioningScheduling: %v", err) } } diff --git a/pkg/apis/storage/v1/zz_generated.conversion.go b/pkg/apis/storage/v1/zz_generated.conversion.go index b43003a9f59..1ec5a534f2b 100644 --- a/pkg/apis/storage/v1/zz_generated.conversion.go +++ b/pkg/apis/storage/v1/zz_generated.conversion.go @@ -54,6 +54,7 @@ func autoConvert_v1_StorageClass_To_storage_StorageClass(in *v1.StorageClass, ou out.MountOptions = *(*[]string)(unsafe.Pointer(&in.MountOptions)) out.AllowVolumeExpansion = (*bool)(unsafe.Pointer(in.AllowVolumeExpansion)) out.VolumeBindingMode = (*storage.VolumeBindingMode)(unsafe.Pointer(in.VolumeBindingMode)) + out.AllowedTopologies = *(*[]core.TopologySelectorTerm)(unsafe.Pointer(&in.AllowedTopologies)) return nil } @@ -70,6 +71,7 @@ func autoConvert_storage_StorageClass_To_v1_StorageClass(in *storage.StorageClas out.MountOptions = *(*[]string)(unsafe.Pointer(&in.MountOptions)) out.AllowVolumeExpansion = (*bool)(unsafe.Pointer(in.AllowVolumeExpansion)) out.VolumeBindingMode = (*v1.VolumeBindingMode)(unsafe.Pointer(in.VolumeBindingMode)) + out.AllowedTopologies = *(*[]core_v1.TopologySelectorTerm)(unsafe.Pointer(&in.AllowedTopologies)) return nil } diff --git a/pkg/apis/storage/v1beta1/zz_generated.conversion.go b/pkg/apis/storage/v1beta1/zz_generated.conversion.go index 68d2ec7316d..8fdadeb46f1 100644 --- a/pkg/apis/storage/v1beta1/zz_generated.conversion.go +++ b/pkg/apis/storage/v1beta1/zz_generated.conversion.go @@ -66,6 +66,7 @@ func autoConvert_v1beta1_StorageClass_To_storage_StorageClass(in *v1beta1.Storag out.MountOptions = *(*[]string)(unsafe.Pointer(&in.MountOptions)) out.AllowVolumeExpansion = (*bool)(unsafe.Pointer(in.AllowVolumeExpansion)) out.VolumeBindingMode = (*storage.VolumeBindingMode)(unsafe.Pointer(in.VolumeBindingMode)) + out.AllowedTopologies = *(*[]core.TopologySelectorTerm)(unsafe.Pointer(&in.AllowedTopologies)) return nil } @@ -82,6 +83,7 @@ func autoConvert_storage_StorageClass_To_v1beta1_StorageClass(in *storage.Storag out.MountOptions = *(*[]string)(unsafe.Pointer(&in.MountOptions)) out.AllowVolumeExpansion = (*bool)(unsafe.Pointer(in.AllowVolumeExpansion)) out.VolumeBindingMode = (*v1beta1.VolumeBindingMode)(unsafe.Pointer(in.VolumeBindingMode)) + out.AllowedTopologies = *(*[]v1.TopologySelectorTerm)(unsafe.Pointer(&in.AllowedTopologies)) return nil } diff --git a/pkg/apis/storage/validation/validation.go b/pkg/apis/storage/validation/validation.go index e9f66e938e8..1c29df8f42d 100644 --- a/pkg/apis/storage/validation/validation.go +++ b/pkg/apis/storage/validation/validation.go @@ -47,6 +47,7 @@ func ValidateStorageClass(storageClass *storage.StorageClass) field.ErrorList { 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"))...) return allErrs } @@ -239,3 +240,22 @@ func validateVolumeBindingMode(mode *storage.VolumeBindingMode, fldPath *field.P return allErrs } + +// validateAllowedTopology tests that AllowedTopologies specifies valid values. +func validateAllowedTopologies(topologies []api.TopologySelectorTerm, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if topologies == nil || len(topologies) == 0 { + return allErrs + } + + if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate DynamicProvisioningScheduling")) + } + + for i, term := range topologies { + allErrs = append(allErrs, apivalidation.ValidateTopologySelectorTerm(term, fldPath.Index(i))...) + } + + return allErrs +} diff --git a/pkg/apis/storage/validation/validation_test.go b/pkg/apis/storage/validation/validation_test.go index 7e6f79687ac..06ed6c7441a 100644 --- a/pkg/apis/storage/validation/validation_test.go +++ b/pkg/apis/storage/validation/validation_test.go @@ -450,21 +450,22 @@ func TestVolumeAttachmentUpdateValidation(t *testing.T) { } } -func makeClassWithBinding(mode *storage.VolumeBindingMode) *storage.StorageClass { +func makeClass(mode *storage.VolumeBindingMode, topologies []api.TopologySelectorTerm) *storage.StorageClass { return &storage.StorageClass{ ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "foo"}, Provisioner: "kubernetes.io/foo-provisioner", ReclaimPolicy: &deleteReclaimPolicy, VolumeBindingMode: mode, + AllowedTopologies: topologies, } } // TODO: Remove these tests once feature gate is not required func TestValidateVolumeBindingModeAlphaDisabled(t *testing.T) { errorCases := map[string]*storage.StorageClass{ - "immediate mode": makeClassWithBinding(&immediateMode1), - "waiting mode": makeClassWithBinding(&waitingMode), - "invalid mode": makeClassWithBinding(&invalidMode), + "immediate mode": makeClass(&immediateMode1, nil), + "waiting mode": makeClass(&waitingMode, nil), + "invalid mode": makeClass(&invalidMode, nil), } err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false") @@ -486,19 +487,19 @@ type bindingTest struct { func TestValidateVolumeBindingMode(t *testing.T) { cases := map[string]bindingTest{ "no mode": { - class: makeClassWithBinding(nil), + class: makeClass(nil, nil), shouldSucceed: false, }, "immediate mode": { - class: makeClassWithBinding(&immediateMode1), + class: makeClass(&immediateMode1, nil), shouldSucceed: true, }, "waiting mode": { - class: makeClassWithBinding(&waitingMode), + class: makeClass(&waitingMode, nil), shouldSucceed: true, }, "invalid mode": { - class: makeClassWithBinding(&invalidMode), + class: makeClass(&invalidMode, nil), shouldSucceed: false, }, } @@ -532,10 +533,10 @@ type updateTest struct { } func TestValidateUpdateVolumeBindingMode(t *testing.T) { - noBinding := makeClassWithBinding(nil) - immediateBinding1 := makeClassWithBinding(&immediateMode1) - immediateBinding2 := makeClassWithBinding(&immediateMode2) - waitBinding := makeClassWithBinding(&waitingMode) + noBinding := makeClass(nil, nil) + immediateBinding1 := makeClass(&immediateMode1, nil) + immediateBinding2 := makeClass(&immediateMode2, nil) + waitBinding := makeClass(&waitingMode, nil) cases := map[string]updateTest{ "old and new no mode": { @@ -591,3 +592,102 @@ func TestValidateUpdateVolumeBindingMode(t *testing.T) { t.Fatalf("Failed to disable feature gate for VolumeScheduling: %v", err) } } + +func TestValidateAllowedTopologies(t *testing.T) { + + validTopology := []api.TopologySelectorTerm{ + { + MatchLabelExpressions: []api.TopologySelectorLabelRequirement{ + { + Key: "failure-domain.beta.kubernetes.io/zone", + Values: []string{"zone1"}, + }, + { + Key: "kubernetes.io/hostname", + Values: []string{"node1"}, + }, + }, + }, + { + MatchLabelExpressions: []api.TopologySelectorLabelRequirement{ + { + Key: "failure-domain.beta.kubernetes.io/zone", + Values: []string{"zone2"}, + }, + { + Key: "kubernetes.io/hostname", + Values: []string{"node2"}, + }, + }, + }, + } + + topologyInvalidKey := []api.TopologySelectorTerm{ + { + MatchLabelExpressions: []api.TopologySelectorLabelRequirement{ + { + Key: "/invalidkey", + Values: []string{"zone1"}, + }, + }, + }, + } + + topologyLackOfValues := []api.TopologySelectorTerm{ + { + MatchLabelExpressions: []api.TopologySelectorLabelRequirement{ + { + Key: "kubernetes.io/hostname", + Values: []string{}, + }, + }, + }, + } + + cases := map[string]bindingTest{ + "no topology": { + class: makeClass(nil, nil), + shouldSucceed: true, + }, + "valid topology": { + class: makeClass(nil, validTopology), + shouldSucceed: true, + }, + "topology invalid key": { + class: makeClass(nil, topologyInvalidKey), + shouldSucceed: false, + }, + "topology lack of values": { + class: makeClass(nil, topologyLackOfValues), + shouldSucceed: false, + }, + } + + // TODO: remove when feature gate not required + err := utilfeature.DefaultFeatureGate.Set("DynamicProvisioningScheduling=true") + if err != nil { + t.Fatalf("Failed to enable feature gate for DynamicProvisioningScheduling: %v", err) + } + + for testName, testCase := range cases { + errs := ValidateStorageClass(testCase.class) + if testCase.shouldSucceed && len(errs) != 0 { + t.Errorf("Expected success for test %q, got %v", testName, errs) + } + if !testCase.shouldSucceed && len(errs) == 0 { + t.Errorf("Expected failure for test %q, got success", testName) + } + } + + err = utilfeature.DefaultFeatureGate.Set("DynamicProvisioningScheduling=false") + if err != nil { + t.Fatalf("Failed to disable feature gate for DynamicProvisioningScheduling: %v", err) + } + + 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/apis/storage/zz_generated.deepcopy.go b/pkg/apis/storage/zz_generated.deepcopy.go index 8cecb7ba9ce..f10b6656315 100644 --- a/pkg/apis/storage/zz_generated.deepcopy.go +++ b/pkg/apis/storage/zz_generated.deepcopy.go @@ -69,6 +69,13 @@ func (in *StorageClass) DeepCopyInto(out *StorageClass) { **out = **in } } + if in.AllowedTopologies != nil { + in, out := &in.AllowedTopologies, &out.AllowedTopologies + *out = make([]core.TopologySelectorTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/pkg/cloudprovider/OWNERS b/pkg/cloudprovider/OWNERS index 07cf4dbda8d..7d96a38ab2d 100644 --- a/pkg/cloudprovider/OWNERS +++ b/pkg/cloudprovider/OWNERS @@ -2,6 +2,7 @@ approvers: - mikedanese - dims - wlan0 +- andrewsykim reviewers: - thockin - lavalamp diff --git a/pkg/cloudprovider/cloud.go b/pkg/cloudprovider/cloud.go index 530475799df..0358890bcd8 100644 --- a/pkg/cloudprovider/cloud.go +++ b/pkg/cloudprovider/cloud.go @@ -131,6 +131,7 @@ type Instances interface { // services cannot be used in this method to obtain nodeaddresses NodeAddressesByProviderID(ctx context.Context, providerID string) ([]v1.NodeAddress, error) // InstanceID returns the cloud provider ID of the node with the specified NodeName. + // Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound) InstanceID(ctx context.Context, nodeName types.NodeName) (string, error) // InstanceType returns the type of the specified instance. InstanceType(ctx context.Context, name types.NodeName) (string, error) diff --git a/pkg/cloudprovider/providers/aws/aws.go b/pkg/cloudprovider/providers/aws/aws.go index 6ea14ef58ef..22a1114fb99 100644 --- a/pkg/cloudprovider/providers/aws/aws.go +++ b/pkg/cloudprovider/providers/aws/aws.go @@ -429,7 +429,7 @@ type Volumes interface { // Attach the disk to the node with the specified NodeName // nodeName can be empty to mean "the instance on which we are running" // Returns the device (e.g. /dev/xvdf) where we attached the volume - AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName, readOnly bool) (string, error) + AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName) (string, error) // Detach the disk from the node with the specified NodeName // nodeName can be empty to mean "the instance on which we are running" // Returns the device where the volume was attached @@ -1363,6 +1363,10 @@ func (c *Cloud) InstanceID(ctx context.Context, nodeName types.NodeName) (string } inst, err := c.getInstanceByNodeName(nodeName) if err != nil { + if err == cloudprovider.InstanceNotFound { + // The Instances interface requires that we return InstanceNotFound (without wrapping) + return "", err + } return "", fmt.Errorf("getInstanceByNodeName failed for %q with %q", nodeName, err) } return "/" + aws.StringValue(inst.Placement.AvailabilityZone) + "/" + aws.StringValue(inst.InstanceId), nil @@ -1956,7 +1960,7 @@ func wrapAttachError(err error, disk *awsDisk, instance string) error { } // AttachDisk implements Volumes.AttachDisk -func (c *Cloud) AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName, readOnly bool) (string, error) { +func (c *Cloud) AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName) (string, error) { disk, err := newAWSDisk(c, diskName) if err != nil { return "", err @@ -1967,12 +1971,6 @@ func (c *Cloud) AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName, return "", fmt.Errorf("error finding instance %s: %q", nodeName, err) } - if readOnly { - // TODO: We could enforce this when we mount the volume (?) - // TODO: We could also snapshot the volume and attach copies of it - return "", errors.New("AWS volumes cannot be mounted read-only") - } - // mountDevice will hold the device where we should try to attach the disk var mountDevice mountDevice // alreadyAttached is true if we have already called AttachVolume on this disk diff --git a/pkg/cloudprovider/providers/aws/aws_loadbalancer.go b/pkg/cloudprovider/providers/aws/aws_loadbalancer.go index 05a1c1a6764..c148be378c5 100644 --- a/pkg/cloudprovider/providers/aws/aws_loadbalancer.go +++ b/pkg/cloudprovider/providers/aws/aws_loadbalancer.go @@ -1375,8 +1375,7 @@ func (c *Cloud) ensureSSLNegotiationPolicy(loadBalancer *elb.LoadBalancerDescrip if err != nil { if aerr, ok := err.(awserr.Error); ok { switch aerr.Code() { - case "PolicyNotFound": - // TODO change from string to `elb.ErrCodePolicyNotFoundException` once the AWS SDK is updated + case elb.ErrCodePolicyNotFoundException: default: return fmt.Errorf("error describing security policies on load balancer: %q", err) } diff --git a/pkg/cloudprovider/providers/azure/BUILD b/pkg/cloudprovider/providers/azure/BUILD index f3eb6e938a0..1adae321e66 100644 --- a/pkg/cloudprovider/providers/azure/BUILD +++ b/pkg/cloudprovider/providers/azure/BUILD @@ -42,6 +42,7 @@ go_library( "//pkg/controller:go_default_library", "//pkg/version:go_default_library", "//pkg/volume:go_default_library", + "//pkg/volume/util:go_default_library", "//vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute:go_default_library", "//vendor/github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network:go_default_library", "//vendor/github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage:go_default_library", @@ -55,6 +56,7 @@ go_library( "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/github.com/rubiojr/go-vhd/vhd:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", diff --git a/pkg/cloudprovider/providers/azure/azure_loadbalancer.go b/pkg/cloudprovider/providers/azure/azure_loadbalancer.go index dcf398ae9a4..fca68fbb404 100644 --- a/pkg/cloudprovider/providers/azure/azure_loadbalancer.go +++ b/pkg/cloudprovider/providers/azure/azure_loadbalancer.go @@ -926,8 +926,8 @@ func (az *Cloud) reconcileSecurityGroup(clusterName string, service *v1.Service, // update security rules dirtySg := false var updatedRules []network.SecurityRule - if sg.SecurityRules != nil { - updatedRules = *sg.SecurityRules + if sg.SecurityGroupPropertiesFormat != nil && sg.SecurityGroupPropertiesFormat.SecurityRules != nil { + updatedRules = *sg.SecurityGroupPropertiesFormat.SecurityRules } for _, r := range updatedRules { diff --git a/pkg/cloudprovider/providers/azure/azure_loadbalancer.md b/pkg/cloudprovider/providers/azure/azure_loadbalancer.md deleted file mode 100644 index 31741cd4e93..00000000000 --- a/pkg/cloudprovider/providers/azure/azure_loadbalancer.md +++ /dev/null @@ -1,77 +0,0 @@ -# Azure LoadBalancer - -The way azure define LoadBalancer is different with GCE or AWS. Azure's LB can have multiple frontend IP refs. The GCE and AWS can only allow one, if you want more, you better to have another LB. Because of the fact, Public IP is not part of the LB in Azure. NSG is not part of LB in Azure either. However, you cannot delete them in parallel, Public IP can only be delete after LB's frontend IP ref is removed. - -For different Azure Resources, such as LB, Public IP, NSG. They are the same tier azure resources. We need to make sure there is no connection in their own ensure loops. In another words, They would be eventually reconciled regardless of other resources' state. They should only depends on service state. - -Despite the ideal philosophy above, we have to face the reality. NSG depends on LB's frontend ip to adjust NSG rules. So when we want to reconcile NSG, the LB should contain the corresponding frontend ip config. - -And also, For Azure, we cannot afford to have more than 1 worker of service_controller. Because, different services could operate on the same LB, concurrent execution could result in conflict or unexpected result. For AWS and GCE, they apparently doesn't have the problem, they use one LB per service, no such conflict. - -There are two load balancers per availability set internal and external. There is a limit on number of services that can be associated with a single load balancer. -By default primary load balancer is selected. Services can be annotated to allow auto selection of available load balancers. Service annotations can also be used to provide specific availability sets that host the load balancers. Note that in case of auto selection or specific availability set selection, when the availability set is lost in case of downtime or cluster scale down the services are currently not auto assigned to an available load balancer. -Service Annotation for Auto and specific load balancer mode - -- service.beta.kubernetes.io/azure-load-balancer-mode" (__auto__|as1,as2...) - -## Introduce Functions - -- reconcileLoadBalancer(clusterName string, service *v1.Service, nodes []*v1.Node, wantLb bool) (*network.LoadBalancer, error) - - Go through lb's properties, update based on wantLb - - If any change on the lb, no matter if the lb exists or not - - Call az cloud to CreateOrUpdate on this lb, or Delete if nothing left - - return lb, err - -- reconcileSecurityGroup(clusterName string, service *v1.Service, lbIP *string, wantLb bool) (*network.SecurityGroup, error) - - Go though NSG' properties, update based on wantLb - - Use destinationIPAddress as target address if possible - - Consolidate NSG rules if possible - - If any change on the NSG, (the NSG should always exists) - - Call az cloud to CreateOrUpdate on this NSG - - return sg, err - -- reconcilePublicIP(clusterName string, service *v1.Service, wantLb bool) (*network.PublicIPAddress, error) - - List all the public ip in the resource group - - Make sure we only touch Public IP resources has tags[service] = "namespace/serviceName" - - skip for wantLb && !isInternal && pipName == desiredPipName - - delete other public ip resources if any - - if !isInternal && wantLb - - ensure Public IP with desiredPipName exists - -- getServiceLoadBalancer(service *v1.Service, clusterName string, nodes []*v1.Node, wantLb bool) (lb, status, exists, error) - - gets the loadbalancer for the service if it already exists - - If wantLb is TRUE then -it selects a new load balancer, the selection helps distribute the services across load balancers - - In case the selected load balancer does not exists it returns network.LoadBalancer struct with added metadata (such as name, location) and existsLB set to FALSE - - By default - cluster default LB is returned - -## Define interface behaviors - -### GetLoadBalancer - -- Get LoadBalancer status, return status, error - - return the load balancer status for this service - - it will not create or update or delete any resource - -### EnsureLoadBalancer - -- Reconcile LB for the flipped service - - Call reconcileLoadBalancer(clusterName, flipedService, nil, false/* wantLb */) -- Reconcile Public IP - - Call reconcilePublicIP(cluster, service, true) -- Reconcile LB's related and owned resources, such as FrontEndIPConfig, Rules, Probe. - - Call reconcileLoadBalancer(clusterName, service, nodes, true /* wantLb */) -- Reconcile NSG rules, it need to be called after reconcileLB - - Call reconcileSecurityGroup(clusterName, service, lbStatus, true /* wantLb */) - -### UpdateLoadBalancer - -- Has no difference with EnsureLoadBalancer - -### EnsureLoadBalancerDeleted - -- Reconcile NSG first, before reconcile LB, because SG need LB to be there - - Call reconcileSecurityGroup(clusterName, service, nil, false /* wantLb */) -- Reconcile LB's related and owned resources, such as FrontEndIPConfig, Rules, Probe. - - Call reconcileLoadBalancer(clusterName, service, nodes, false) -- Reconcile Public IP, public IP needs related LB reconciled first - - Call reconcilePublicIP(cluster, service, false) diff --git a/pkg/cloudprovider/providers/azure/azure_managedDiskController.go b/pkg/cloudprovider/providers/azure/azure_managedDiskController.go index 02df2fd3d28..fac548f1d24 100644 --- a/pkg/cloudprovider/providers/azure/azure_managedDiskController.go +++ b/pkg/cloudprovider/providers/azure/azure_managedDiskController.go @@ -17,13 +17,17 @@ limitations under the License. package azure import ( + "fmt" "path" "strings" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" "github.com/golang/glog" + + "k8s.io/apimachinery/pkg/api/resource" kwait "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/kubernetes/pkg/volume/util" ) //ManagedDiskController : managed disk controller struct @@ -131,3 +135,41 @@ func (c *ManagedDiskController) getDisk(diskName string) (string, string, error) return "", "", err } + +// ResizeDisk Expand the disk to new size +func (c *ManagedDiskController) ResizeDisk(diskName string, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error) { + ctx, cancel := getContextWithCancel() + defer cancel() + + result, err := c.common.cloud.DisksClient.Get(ctx, c.common.resourceGroup, diskName) + if err != nil { + return oldSize, err + } + + if result.DiskProperties == nil || result.DiskProperties.DiskSizeGB == nil { + return oldSize, fmt.Errorf("DiskProperties of disk(%s) is nil", diskName) + } + + requestBytes := newSize.Value() + // Azure resizes in chunks of GiB (not GB) + requestGiB := int32(util.RoundUpSize(requestBytes, 1024*1024*1024)) + newSizeQuant := resource.MustParse(fmt.Sprintf("%dGi", requestGiB)) + + glog.V(2).Infof("azureDisk - begin to resize disk(%s) with new size(%d), old size(%v)", diskName, requestGiB, oldSize) + // If disk already of greater or equal size than requested we return + if *result.DiskProperties.DiskSizeGB >= requestGiB { + return newSizeQuant, nil + } + + result.DiskProperties.DiskSizeGB = &requestGiB + + ctx, cancel = getContextWithCancel() + defer cancel() + if _, err := c.common.cloud.DisksClient.CreateOrUpdate(ctx, c.common.resourceGroup, diskName, result); err != nil { + return oldSize, err + } + + glog.V(2).Infof("azureDisk - resize disk(%s) with new size(%d) completed", diskName, requestGiB) + + return newSizeQuant, nil +} diff --git a/pkg/cloudprovider/providers/azure/azure_wrap.go b/pkg/cloudprovider/providers/azure/azure_wrap.go index 53c17871e88..a02ebae93b2 100644 --- a/pkg/cloudprovider/providers/azure/azure_wrap.go +++ b/pkg/cloudprovider/providers/azure/azure_wrap.go @@ -163,6 +163,10 @@ func (az *Cloud) getAzureLoadBalancer(name string) (lb network.LoadBalancer, exi } func (az *Cloud) getSecurityGroup() (nsg network.SecurityGroup, err error) { + if az.SecurityGroupName == "" { + return nsg, fmt.Errorf("securityGroupName is not configured") + } + securityGroup, err := az.nsgCache.Get(az.SecurityGroupName) if err != nil { return nsg, err diff --git a/pkg/cloudprovider/providers/gce/BUILD b/pkg/cloudprovider/providers/gce/BUILD index 05a1f345e57..9368a8cf62a 100644 --- a/pkg/cloudprovider/providers/gce/BUILD +++ b/pkg/cloudprovider/providers/gce/BUILD @@ -13,7 +13,6 @@ go_library( "gce.go", "gce_address_manager.go", "gce_addresses.go", - "gce_addresses_fakes.go", "gce_alpha.go", "gce_annotations.go", "gce_backendservice.go", @@ -32,7 +31,6 @@ go_library( "gce_loadbalancer_internal.go", "gce_loadbalancer_naming.go", "gce_networkendpointgroup.go", - "gce_op.go", "gce_routes.go", "gce_securitypolicy.go", "gce_targetpool.go", @@ -71,7 +69,7 @@ go_library( "//vendor/google.golang.org/api/compute/v1:go_default_library", "//vendor/google.golang.org/api/container/v1:go_default_library", "//vendor/google.golang.org/api/googleapi:go_default_library", - "//vendor/google.golang.org/api/tpu/v1alpha1:go_default_library", + "//vendor/google.golang.org/api/tpu/v1:go_default_library", "//vendor/gopkg.in/gcfg.v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", diff --git a/pkg/cloudprovider/providers/gce/cloud/BUILD b/pkg/cloudprovider/providers/gce/cloud/BUILD index fa46310777d..04cd70a8119 100644 --- a/pkg/cloudprovider/providers/gce/cloud/BUILD +++ b/pkg/cloudprovider/providers/gce/cloud/BUILD @@ -4,7 +4,9 @@ go_library( name = "go_default_library", srcs = [ "constants.go", + "context.go", "doc.go", + "errors.go", "gce_projects.go", "gen.go", "op.go", @@ -31,6 +33,8 @@ go_test( srcs = [ "gen_test.go", "mock_test.go", + "ratelimit_test.go", + "service_test.go", "utils_test.go", ], embed = [":go_default_library"], diff --git a/pkg/cloudprovider/providers/gce/cloud/context.go b/pkg/cloudprovider/providers/gce/cloud/context.go new file mode 100644 index 00000000000..307a0a7a479 --- /dev/null +++ b/pkg/cloudprovider/providers/gce/cloud/context.go @@ -0,0 +1,31 @@ +/* +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" + "time" +) + +const ( + defaultCallTimeout = 1 * time.Hour +) + +// ContextWithCallTimeout returns a context with a default timeout, used for generated client calls. +func ContextWithCallTimeout() (context.Context, context.CancelFunc) { + return context.WithTimeout(context.Background(), defaultCallTimeout) +} diff --git a/pkg/cloudprovider/providers/gce/cloud/errors.go b/pkg/cloudprovider/providers/gce/cloud/errors.go new file mode 100644 index 00000000000..1896a6d9e02 --- /dev/null +++ b/pkg/cloudprovider/providers/gce/cloud/errors.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 cloud + +import "fmt" + +// OperationPollingError occurs when the GCE Operation cannot be retrieved for a prolonged period. +type OperationPollingError struct { + LastPollError error +} + +// Error returns a string representation including the last poll error encountered. +func (e *OperationPollingError) Error() string { + return fmt.Sprintf("GCE operation polling error: %v", e.LastPollError) +} + +// GCEOperationError occurs when the GCE Operation finishes with an error. +type GCEOperationError struct { + // HTTPStatusCode is the HTTP status code of the final error. + // For example, a failed operation may have 400 - BadRequest. + HTTPStatusCode int + // Code is GCE's code of what went wrong. + // For example, RESOURCE_IN_USE_BY_ANOTHER_RESOURCE + Code string + // Message is a human readable message. + // For example, "The network resource 'xxx' is already being used by 'xxx'" + Message string +} + +// Error returns a string representation including the HTTP Status code, GCE's error code +// and a human readable message. +func (e *GCEOperationError) Error() string { + return fmt.Sprintf("GCE %v - %v: %v", e.HTTPStatusCode, e.Code, e.Message) +} diff --git a/pkg/cloudprovider/providers/gce/cloud/gen.go b/pkg/cloudprovider/providers/gce/cloud/gen.go index 9b08d3c8d3a..2b6e24583d1 100644 --- a/pkg/cloudprovider/providers/gce/cloud/gen.go +++ b/pkg/cloudprovider/providers/gce/cloud/gen.go @@ -48,8 +48,7 @@ type Cloud interface { RegionBackendServices() RegionBackendServices AlphaRegionBackendServices() AlphaRegionBackendServices Disks() Disks - AlphaDisks() AlphaDisks - AlphaRegionDisks() AlphaRegionDisks + BetaRegionDisks() BetaRegionDisks Firewalls() Firewalls ForwardingRules() ForwardingRules AlphaForwardingRules() AlphaForwardingRules @@ -88,8 +87,7 @@ func NewGCE(s *Service) *GCE { gceRegionBackendServices: &GCERegionBackendServices{s}, gceAlphaRegionBackendServices: &GCEAlphaRegionBackendServices{s}, gceDisks: &GCEDisks{s}, - gceAlphaDisks: &GCEAlphaDisks{s}, - gceAlphaRegionDisks: &GCEAlphaRegionDisks{s}, + gceBetaRegionDisks: &GCEBetaRegionDisks{s}, gceFirewalls: &GCEFirewalls{s}, gceForwardingRules: &GCEForwardingRules{s}, gceAlphaForwardingRules: &GCEAlphaForwardingRules{s}, @@ -132,8 +130,7 @@ type GCE struct { gceRegionBackendServices *GCERegionBackendServices gceAlphaRegionBackendServices *GCEAlphaRegionBackendServices gceDisks *GCEDisks - gceAlphaDisks *GCEAlphaDisks - gceAlphaRegionDisks *GCEAlphaRegionDisks + gceBetaRegionDisks *GCEBetaRegionDisks gceFirewalls *GCEFirewalls gceForwardingRules *GCEForwardingRules gceAlphaForwardingRules *GCEAlphaForwardingRules @@ -209,14 +206,9 @@ func (gce *GCE) Disks() Disks { return gce.gceDisks } -// AlphaDisks returns the interface for the alpha Disks. -func (gce *GCE) AlphaDisks() AlphaDisks { - return gce.gceAlphaDisks -} - -// AlphaRegionDisks returns the interface for the alpha RegionDisks. -func (gce *GCE) AlphaRegionDisks() AlphaRegionDisks { - return gce.gceAlphaRegionDisks +// BetaRegionDisks returns the interface for the beta RegionDisks. +func (gce *GCE) BetaRegionDisks() BetaRegionDisks { + return gce.gceBetaRegionDisks } // Firewalls returns the interface for the ga Firewalls. @@ -373,8 +365,7 @@ func NewMockGCE(projectRouter ProjectRouter) *MockGCE { MockRegionBackendServices: NewMockRegionBackendServices(projectRouter, mockRegionBackendServicesObjs), MockAlphaRegionBackendServices: NewMockAlphaRegionBackendServices(projectRouter, mockRegionBackendServicesObjs), MockDisks: NewMockDisks(projectRouter, mockDisksObjs), - MockAlphaDisks: NewMockAlphaDisks(projectRouter, mockDisksObjs), - MockAlphaRegionDisks: NewMockAlphaRegionDisks(projectRouter, mockRegionDisksObjs), + MockBetaRegionDisks: NewMockBetaRegionDisks(projectRouter, mockRegionDisksObjs), MockFirewalls: NewMockFirewalls(projectRouter, mockFirewallsObjs), MockForwardingRules: NewMockForwardingRules(projectRouter, mockForwardingRulesObjs), MockAlphaForwardingRules: NewMockAlphaForwardingRules(projectRouter, mockForwardingRulesObjs), @@ -417,8 +408,7 @@ type MockGCE struct { MockRegionBackendServices *MockRegionBackendServices MockAlphaRegionBackendServices *MockAlphaRegionBackendServices MockDisks *MockDisks - MockAlphaDisks *MockAlphaDisks - MockAlphaRegionDisks *MockAlphaRegionDisks + MockBetaRegionDisks *MockBetaRegionDisks MockFirewalls *MockFirewalls MockForwardingRules *MockForwardingRules MockAlphaForwardingRules *MockAlphaForwardingRules @@ -494,14 +484,9 @@ func (mock *MockGCE) Disks() Disks { return mock.MockDisks } -// AlphaDisks returns the interface for the alpha Disks. -func (mock *MockGCE) AlphaDisks() AlphaDisks { - return mock.MockAlphaDisks -} - -// AlphaRegionDisks returns the interface for the alpha RegionDisks. -func (mock *MockGCE) AlphaRegionDisks() AlphaRegionDisks { - return mock.MockAlphaRegionDisks +// BetaRegionDisks returns the interface for the beta RegionDisks. +func (mock *MockGCE) BetaRegionDisks() BetaRegionDisks { + return mock.MockBetaRegionDisks } // Firewalls returns the interface for the ga Firewalls. @@ -718,19 +703,6 @@ type MockDisksObj struct { Obj interface{} } -// ToAlpha retrieves the given version of the object. -func (m *MockDisksObj) ToAlpha() *alpha.Disk { - if ret, ok := m.Obj.(*alpha.Disk); ok { - return ret - } - // Convert the object via JSON copying to the type that was requested. - ret := &alpha.Disk{} - if err := copyViaJSON(ret, m.Obj); err != nil { - glog.Errorf("Could not convert %T to *alpha.Disk via JSON: %v", m.Obj, err) - } - return ret -} - // ToGA retrieves the given version of the object. func (m *MockDisksObj) ToGA() *ga.Disk { if ret, ok := m.Obj.(*ga.Disk); ok { @@ -1056,15 +1028,15 @@ type MockRegionDisksObj struct { Obj interface{} } -// ToAlpha retrieves the given version of the object. -func (m *MockRegionDisksObj) ToAlpha() *alpha.Disk { - if ret, ok := m.Obj.(*alpha.Disk); ok { +// ToBeta retrieves the given version of the object. +func (m *MockRegionDisksObj) ToBeta() *beta.Disk { + if ret, ok := m.Obj.(*beta.Disk); ok { return ret } // Convert the object via JSON copying to the type that was requested. - ret := &alpha.Disk{} + ret := &beta.Disk{} if err := copyViaJSON(ret, m.Obj); err != nil { - glog.Errorf("Could not convert %T to *alpha.Disk via JSON: %v", m.Obj, err) + glog.Errorf("Could not convert %T to *beta.Disk via JSON: %v", m.Obj, err) } return ret } @@ -3420,6 +3392,7 @@ type AlphaBackendServices interface { List(ctx context.Context, fl *filter.F) ([]*alpha.BackendService, error) Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error Delete(ctx context.Context, key *meta.Key) error + SetSecurityPolicy(context.Context, *meta.Key, *alpha.SecurityPolicyReference) error Update(context.Context, *meta.Key, *alpha.BackendService) error } @@ -3456,11 +3429,12 @@ type MockAlphaBackendServices struct { // 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 *MockAlphaBackendServices) (bool, *alpha.BackendService, error) - ListHook func(ctx context.Context, fl *filter.F, m *MockAlphaBackendServices) (bool, []*alpha.BackendService, error) - InsertHook func(ctx context.Context, key *meta.Key, obj *alpha.BackendService, m *MockAlphaBackendServices) (bool, error) - DeleteHook func(ctx context.Context, key *meta.Key, m *MockAlphaBackendServices) (bool, error) - UpdateHook func(context.Context, *meta.Key, *alpha.BackendService, *MockAlphaBackendServices) error + GetHook func(ctx context.Context, key *meta.Key, m *MockAlphaBackendServices) (bool, *alpha.BackendService, error) + ListHook func(ctx context.Context, fl *filter.F, m *MockAlphaBackendServices) (bool, []*alpha.BackendService, error) + InsertHook func(ctx context.Context, key *meta.Key, obj *alpha.BackendService, m *MockAlphaBackendServices) (bool, error) + DeleteHook func(ctx context.Context, key *meta.Key, m *MockAlphaBackendServices) (bool, error) + SetSecurityPolicyHook func(context.Context, *meta.Key, *alpha.SecurityPolicyReference, *MockAlphaBackendServices) error + UpdateHook func(context.Context, *meta.Key, *alpha.BackendService, *MockAlphaBackendServices) error // X is extra state that can be used as part of the mock. Generated code // will not use this field. @@ -3606,6 +3580,14 @@ func (m *MockAlphaBackendServices) Obj(o *alpha.BackendService) *MockBackendServ return &MockBackendServicesObj{o} } +// SetSecurityPolicy is a mock for the corresponding method. +func (m *MockAlphaBackendServices) SetSecurityPolicy(ctx context.Context, key *meta.Key, arg0 *alpha.SecurityPolicyReference) error { + if m.SetSecurityPolicyHook != nil { + return m.SetSecurityPolicyHook(ctx, key, arg0, m) + } + return nil +} + // Update is a mock for the corresponding method. func (m *MockAlphaBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *alpha.BackendService) error { if m.UpdateHook != nil { @@ -3756,6 +3738,39 @@ func (g *GCEAlphaBackendServices) Delete(ctx context.Context, key *meta.Key) err return err } +// SetSecurityPolicy is a method on GCEAlphaBackendServices. +func (g *GCEAlphaBackendServices) SetSecurityPolicy(ctx context.Context, key *meta.Key, arg0 *alpha.SecurityPolicyReference) error { + glog.V(5).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "SetSecurityPolicy", + Version: meta.Version("alpha"), + Service: "BackendServices", + } + glog.V(5).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.Alpha.BackendServices.SetSecurityPolicy(projectID, key.Name, arg0) + call.Context(ctx) + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...) = %+v", ctx, key, err) + return err +} + // Update is a method on GCEAlphaBackendServices. func (g *GCEAlphaBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *alpha.BackendService) error { glog.V(5).Infof("GCEAlphaBackendServices.Update(%v, %v, ...): called", ctx, key) @@ -4625,6 +4640,7 @@ type Disks interface { List(ctx context.Context, zone string, fl *filter.F) ([]*ga.Disk, error) Insert(ctx context.Context, key *meta.Key, obj *ga.Disk) error Delete(ctx context.Context, key *meta.Key) error + Resize(context.Context, *meta.Key, *ga.DisksResizeRequest) error } // NewMockDisks returns a new mock for Disks. @@ -4664,6 +4680,7 @@ type MockDisks struct { ListHook func(ctx context.Context, zone string, fl *filter.F, m *MockDisks) (bool, []*ga.Disk, error) InsertHook func(ctx context.Context, key *meta.Key, obj *ga.Disk, m *MockDisks) (bool, error) DeleteHook func(ctx context.Context, key *meta.Key, m *MockDisks) (bool, error) + ResizeHook func(context.Context, *meta.Key, *ga.DisksResizeRequest, *MockDisks) error // X is extra state that can be used as part of the mock. Generated code // will not use this field. @@ -4812,6 +4829,14 @@ func (m *MockDisks) Obj(o *ga.Disk) *MockDisksObj { return &MockDisksObj{o} } +// Resize is a mock for the corresponding method. +func (m *MockDisks) Resize(ctx context.Context, key *meta.Key, arg0 *ga.DisksResizeRequest) error { + if m.ResizeHook != nil { + return m.ResizeHook(ctx, key, arg0, m) + } + return nil +} + // GCEDisks is a simplifying adapter for the GCE Disks. type GCEDisks struct { s *Service @@ -4953,17 +4978,51 @@ func (g *GCEDisks) Delete(ctx context.Context, key *meta.Key) error { return err } -// AlphaDisks is an interface that allows for mocking of Disks. -type AlphaDisks interface { - Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) - List(ctx context.Context, zone string, fl *filter.F) ([]*alpha.Disk, error) - Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error - Delete(ctx context.Context, key *meta.Key) error +// Resize is a method on GCEDisks. +func (g *GCEDisks) Resize(ctx context.Context, key *meta.Key, arg0 *ga.DisksResizeRequest) error { + glog.V(5).Infof("GCEDisks.Resize(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEDisks.Resize(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Disks") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Resize", + Version: meta.Version("ga"), + Service: "Disks", + } + glog.V(5).Infof("GCEDisks.Resize(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEDisks.Resize(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.GA.Disks.Resize(projectID, key.Zone, key.Name, arg0) + call.Context(ctx) + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEDisks.Resize(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEDisks.Resize(%v, %v, ...) = %+v", ctx, key, err) + return err } -// NewMockAlphaDisks returns a new mock for Disks. -func NewMockAlphaDisks(pr ProjectRouter, objs map[meta.Key]*MockDisksObj) *MockAlphaDisks { - mock := &MockAlphaDisks{ +// BetaRegionDisks is an interface that allows for mocking of RegionDisks. +type BetaRegionDisks interface { + Get(ctx context.Context, key *meta.Key) (*beta.Disk, error) + List(ctx context.Context, region string, fl *filter.F) ([]*beta.Disk, error) + Insert(ctx context.Context, key *meta.Key, obj *beta.Disk) error + Delete(ctx context.Context, key *meta.Key) error + Resize(context.Context, *meta.Key, *beta.RegionDisksResizeRequest) error +} + +// NewMockBetaRegionDisks returns a new mock for RegionDisks. +func NewMockBetaRegionDisks(pr ProjectRouter, objs map[meta.Key]*MockRegionDisksObj) *MockBetaRegionDisks { + mock := &MockBetaRegionDisks{ ProjectRouter: pr, Objects: objs, @@ -4974,342 +5033,8 @@ func NewMockAlphaDisks(pr ProjectRouter, objs map[meta.Key]*MockDisksObj) *MockA return mock } -// MockAlphaDisks is the mock for Disks. -type MockAlphaDisks struct { - Lock sync.Mutex - - ProjectRouter ProjectRouter - - // Objects maintained by the mock. - Objects map[meta.Key]*MockDisksObj - - // 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 *MockAlphaDisks) (bool, *alpha.Disk, error) - ListHook func(ctx context.Context, zone string, fl *filter.F, m *MockAlphaDisks) (bool, []*alpha.Disk, error) - InsertHook func(ctx context.Context, key *meta.Key, obj *alpha.Disk, m *MockAlphaDisks) (bool, error) - DeleteHook func(ctx context.Context, key *meta.Key, m *MockAlphaDisks) (bool, 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 *MockAlphaDisks) Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) { - if m.GetHook != nil { - if intercept, obj, err := m.GetHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaDisks.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 { - glog.V(5).Infof("MockAlphaDisks.Get(%v, %s) = nil, %v", ctx, key, err) - return nil, err - } - if obj, ok := m.Objects[*key]; ok { - typedObj := obj.ToAlpha() - glog.V(5).Infof("MockAlphaDisks.Get(%v, %s) = %+v, nil", ctx, key, typedObj) - return typedObj, nil - } - - err := &googleapi.Error{ - Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaDisks %v not found", key), - } - glog.V(5).Infof("MockAlphaDisks.Get(%v, %s) = nil, %v", ctx, key, err) - return nil, err -} - -// List all of the objects in the mock in the given zone. -func (m *MockAlphaDisks) List(ctx context.Context, zone string, fl *filter.F) ([]*alpha.Disk, error) { - if m.ListHook != nil { - if intercept, objs, err := m.ListHook(ctx, zone, fl, m); intercept { - glog.V(5).Infof("MockAlphaDisks.List(%v, %q, %v) = [%v items], %v", ctx, zone, fl, len(objs), err) - return objs, err - } - } - - m.Lock.Lock() - defer m.Lock.Unlock() - - if m.ListError != nil { - err := *m.ListError - glog.V(5).Infof("MockAlphaDisks.List(%v, %q, %v) = nil, %v", ctx, zone, fl, err) - - return nil, *m.ListError - } - - var objs []*alpha.Disk - for key, obj := range m.Objects { - if key.Zone != zone { - continue - } - if !fl.Match(obj.ToAlpha()) { - continue - } - objs = append(objs, obj.ToAlpha()) - } - - glog.V(5).Infof("MockAlphaDisks.List(%v, %q, %v) = [%v items], nil", ctx, zone, fl, len(objs)) - return objs, nil -} - -// Insert is a mock for inserting/creating a new object. -func (m *MockAlphaDisks) Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error { - if m.InsertHook != nil { - if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { - glog.V(5).Infof("MockAlphaDisks.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 { - glog.V(5).Infof("MockAlphaDisks.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("MockAlphaDisks %v exists", key), - } - glog.V(5).Infof("MockAlphaDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) - return err - } - - obj.Name = key.Name - projectID := m.ProjectRouter.ProjectID(ctx, "alpha", "disks") - obj.SelfLink = SelfLink(meta.VersionAlpha, projectID, "disks", key) - - m.Objects[*key] = &MockDisksObj{obj} - glog.V(5).Infof("MockAlphaDisks.Insert(%v, %v, %+v) = nil", ctx, key, obj) - return nil -} - -// Delete is a mock for deleting the object. -func (m *MockAlphaDisks) Delete(ctx context.Context, key *meta.Key) error { - if m.DeleteHook != nil { - if intercept, err := m.DeleteHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaDisks.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 { - glog.V(5).Infof("MockAlphaDisks.Delete(%v, %v) = %v", ctx, key, err) - return err - } - if _, ok := m.Objects[*key]; !ok { - err := &googleapi.Error{ - Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaDisks %v not found", key), - } - glog.V(5).Infof("MockAlphaDisks.Delete(%v, %v) = %v", ctx, key, err) - return err - } - - delete(m.Objects, *key) - glog.V(5).Infof("MockAlphaDisks.Delete(%v, %v) = nil", ctx, key) - return nil -} - -// Obj wraps the object for use in the mock. -func (m *MockAlphaDisks) Obj(o *alpha.Disk) *MockDisksObj { - return &MockDisksObj{o} -} - -// GCEAlphaDisks is a simplifying adapter for the GCE Disks. -type GCEAlphaDisks struct { - s *Service -} - -// Get the Disk named by key. -func (g *GCEAlphaDisks) Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) { - glog.V(5).Infof("GCEAlphaDisks.Get(%v, %v): called", ctx, key) - - if !key.Valid() { - glog.V(2).Infof("GCEAlphaDisks.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, "alpha", "Disks") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "Get", - Version: meta.Version("alpha"), - Service: "Disks", - } - glog.V(5).Infof("GCEAlphaDisks.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaDisks.Get(%v, %v): RateLimiter error: %v", ctx, key, err) - return nil, err - } - call := g.s.Alpha.Disks.Get(projectID, key.Zone, key.Name) - call.Context(ctx) - v, err := call.Do() - glog.V(4).Infof("GCEAlphaDisks.Get(%v, %v) = %+v, %v", ctx, key, v, err) - return v, err -} - -// List all Disk objects. -func (g *GCEAlphaDisks) List(ctx context.Context, zone string, fl *filter.F) ([]*alpha.Disk, error) { - glog.V(5).Infof("GCEAlphaDisks.List(%v, %v, %v) called", ctx, zone, fl) - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "Disks") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "List", - Version: meta.Version("alpha"), - Service: "Disks", - } - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - return nil, err - } - glog.V(5).Infof("GCEAlphaDisks.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, zone, fl, projectID, rk) - call := g.s.Alpha.Disks.List(projectID, zone) - if fl != filter.None { - call.Filter(fl.String()) - } - var all []*alpha.Disk - f := func(l *alpha.DiskList) error { - glog.V(5).Infof("GCEAlphaDisks.List(%v, ..., %v): page %+v", ctx, fl, l) - all = append(all, l.Items...) - return nil - } - if err := call.Pages(ctx, f); err != nil { - glog.V(4).Infof("GCEAlphaDisks.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) - return nil, err - } - - if glog.V(4) { - glog.V(4).Infof("GCEAlphaDisks.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) - } else if glog.V(5) { - var asStr []string - for _, o := range all { - asStr = append(asStr, fmt.Sprintf("%+v", o)) - } - glog.V(5).Infof("GCEAlphaDisks.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) - } - - return all, nil -} - -// Insert Disk with key of value obj. -func (g *GCEAlphaDisks) Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error { - glog.V(5).Infof("GCEAlphaDisks.Insert(%v, %v, %+v): called", ctx, key, obj) - if !key.Valid() { - glog.V(2).Infof("GCEAlphaDisks.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) - return fmt.Errorf("invalid GCE key (%+v)", key) - } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "Disks") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "Insert", - Version: meta.Version("alpha"), - Service: "Disks", - } - glog.V(5).Infof("GCEAlphaDisks.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaDisks.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) - return err - } - obj.Name = key.Name - call := g.s.Alpha.Disks.Insert(projectID, key.Zone, obj) - call.Context(ctx) - - op, err := call.Do() - if err != nil { - glog.V(4).Infof("GCEAlphaDisks.Insert(%v, %v, ...) = %+v", ctx, key, err) - return err - } - - err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaDisks.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) - return err -} - -// Delete the Disk referenced by key. -func (g *GCEAlphaDisks) Delete(ctx context.Context, key *meta.Key) error { - glog.V(5).Infof("GCEAlphaDisks.Delete(%v, %v): called", ctx, key) - if !key.Valid() { - glog.V(2).Infof("GCEAlphaDisks.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) - return fmt.Errorf("invalid GCE key (%+v)", key) - } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "Disks") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "Delete", - Version: meta.Version("alpha"), - Service: "Disks", - } - glog.V(5).Infof("GCEAlphaDisks.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaDisks.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) - return err - } - call := g.s.Alpha.Disks.Delete(projectID, key.Zone, key.Name) - call.Context(ctx) - - op, err := call.Do() - if err != nil { - glog.V(4).Infof("GCEAlphaDisks.Delete(%v, %v) = %v", ctx, key, err) - return err - } - - err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaDisks.Delete(%v, %v) = %v", ctx, key, err) - return err -} - -// AlphaRegionDisks is an interface that allows for mocking of RegionDisks. -type AlphaRegionDisks interface { - Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) - List(ctx context.Context, region string, fl *filter.F) ([]*alpha.Disk, error) - Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error - Delete(ctx context.Context, key *meta.Key) error -} - -// NewMockAlphaRegionDisks returns a new mock for RegionDisks. -func NewMockAlphaRegionDisks(pr ProjectRouter, objs map[meta.Key]*MockRegionDisksObj) *MockAlphaRegionDisks { - mock := &MockAlphaRegionDisks{ - ProjectRouter: pr, - - Objects: objs, - GetError: map[meta.Key]error{}, - InsertError: map[meta.Key]error{}, - DeleteError: map[meta.Key]error{}, - } - return mock -} - -// MockAlphaRegionDisks is the mock for RegionDisks. -type MockAlphaRegionDisks struct { +// MockBetaRegionDisks is the mock for RegionDisks. +type MockBetaRegionDisks struct { Lock sync.Mutex ProjectRouter ProjectRouter @@ -5328,10 +5053,11 @@ type MockAlphaRegionDisks struct { // 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 *MockAlphaRegionDisks) (bool, *alpha.Disk, error) - ListHook func(ctx context.Context, region string, fl *filter.F, m *MockAlphaRegionDisks) (bool, []*alpha.Disk, error) - InsertHook func(ctx context.Context, key *meta.Key, obj *alpha.Disk, m *MockAlphaRegionDisks) (bool, error) - DeleteHook func(ctx context.Context, key *meta.Key, m *MockAlphaRegionDisks) (bool, error) + GetHook func(ctx context.Context, key *meta.Key, m *MockBetaRegionDisks) (bool, *beta.Disk, error) + ListHook func(ctx context.Context, region string, fl *filter.F, m *MockBetaRegionDisks) (bool, []*beta.Disk, error) + InsertHook func(ctx context.Context, key *meta.Key, obj *beta.Disk, m *MockBetaRegionDisks) (bool, error) + DeleteHook func(ctx context.Context, key *meta.Key, m *MockBetaRegionDisks) (bool, error) + ResizeHook func(context.Context, *meta.Key, *beta.RegionDisksResizeRequest, *MockBetaRegionDisks) error // X is extra state that can be used as part of the mock. Generated code // will not use this field. @@ -5339,10 +5065,10 @@ type MockAlphaRegionDisks struct { } // Get returns the object from the mock. -func (m *MockAlphaRegionDisks) Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) { +func (m *MockBetaRegionDisks) Get(ctx context.Context, key *meta.Key) (*beta.Disk, error) { if m.GetHook != nil { if intercept, obj, err := m.GetHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaRegionDisks.Get(%v, %s) = %+v, %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaRegionDisks.Get(%v, %s) = %+v, %v", ctx, key, obj, err) return obj, err } } @@ -5354,28 +5080,28 @@ func (m *MockAlphaRegionDisks) Get(ctx context.Context, key *meta.Key) (*alpha.D defer m.Lock.Unlock() if err, ok := m.GetError[*key]; ok { - glog.V(5).Infof("MockAlphaRegionDisks.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockBetaRegionDisks.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } if obj, ok := m.Objects[*key]; ok { - typedObj := obj.ToAlpha() - glog.V(5).Infof("MockAlphaRegionDisks.Get(%v, %s) = %+v, nil", ctx, key, typedObj) + typedObj := obj.ToBeta() + glog.V(5).Infof("MockBetaRegionDisks.Get(%v, %s) = %+v, nil", ctx, key, typedObj) return typedObj, nil } err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaRegionDisks %v not found", key), + Message: fmt.Sprintf("MockBetaRegionDisks %v not found", key), } - glog.V(5).Infof("MockAlphaRegionDisks.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockBetaRegionDisks.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } // List all of the objects in the mock in the given region. -func (m *MockAlphaRegionDisks) List(ctx context.Context, region string, fl *filter.F) ([]*alpha.Disk, error) { +func (m *MockBetaRegionDisks) List(ctx context.Context, region string, fl *filter.F) ([]*beta.Disk, error) { if m.ListHook != nil { if intercept, objs, err := m.ListHook(ctx, region, fl, m); intercept { - glog.V(5).Infof("MockAlphaRegionDisks.List(%v, %q, %v) = [%v items], %v", ctx, region, fl, len(objs), err) + glog.V(5).Infof("MockBetaRegionDisks.List(%v, %q, %v) = [%v items], %v", ctx, region, fl, len(objs), err) return objs, err } } @@ -5385,31 +5111,31 @@ func (m *MockAlphaRegionDisks) List(ctx context.Context, region string, fl *filt if m.ListError != nil { err := *m.ListError - glog.V(5).Infof("MockAlphaRegionDisks.List(%v, %q, %v) = nil, %v", ctx, region, fl, err) + glog.V(5).Infof("MockBetaRegionDisks.List(%v, %q, %v) = nil, %v", ctx, region, fl, err) return nil, *m.ListError } - var objs []*alpha.Disk + var objs []*beta.Disk for key, obj := range m.Objects { if key.Region != region { continue } - if !fl.Match(obj.ToAlpha()) { + if !fl.Match(obj.ToBeta()) { continue } - objs = append(objs, obj.ToAlpha()) + objs = append(objs, obj.ToBeta()) } - glog.V(5).Infof("MockAlphaRegionDisks.List(%v, %q, %v) = [%v items], nil", ctx, region, fl, len(objs)) + glog.V(5).Infof("MockBetaRegionDisks.List(%v, %q, %v) = [%v items], nil", ctx, region, fl, len(objs)) return objs, nil } // Insert is a mock for inserting/creating a new object. -func (m *MockAlphaRegionDisks) Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error { +func (m *MockBetaRegionDisks) Insert(ctx context.Context, key *meta.Key, obj *beta.Disk) error { if m.InsertHook != nil { if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { - glog.V(5).Infof("MockAlphaRegionDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaRegionDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } } @@ -5421,32 +5147,32 @@ func (m *MockAlphaRegionDisks) Insert(ctx context.Context, key *meta.Key, obj *a defer m.Lock.Unlock() if err, ok := m.InsertError[*key]; ok { - glog.V(5).Infof("MockAlphaRegionDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaRegionDisks.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("MockAlphaRegionDisks %v exists", key), + Message: fmt.Sprintf("MockBetaRegionDisks %v exists", key), } - glog.V(5).Infof("MockAlphaRegionDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaRegionDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } obj.Name = key.Name - projectID := m.ProjectRouter.ProjectID(ctx, "alpha", "disks") - obj.SelfLink = SelfLink(meta.VersionAlpha, projectID, "disks", key) + projectID := m.ProjectRouter.ProjectID(ctx, "beta", "disks") + obj.SelfLink = SelfLink(meta.VersionBeta, projectID, "disks", key) m.Objects[*key] = &MockRegionDisksObj{obj} - glog.V(5).Infof("MockAlphaRegionDisks.Insert(%v, %v, %+v) = nil", ctx, key, obj) + glog.V(5).Infof("MockBetaRegionDisks.Insert(%v, %v, %+v) = nil", ctx, key, obj) return nil } // Delete is a mock for deleting the object. -func (m *MockAlphaRegionDisks) Delete(ctx context.Context, key *meta.Key) error { +func (m *MockBetaRegionDisks) Delete(ctx context.Context, key *meta.Key) error { if m.DeleteHook != nil { if intercept, err := m.DeleteHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) return err } } @@ -5458,166 +5184,207 @@ func (m *MockAlphaRegionDisks) Delete(ctx context.Context, key *meta.Key) error defer m.Lock.Unlock() if err, ok := m.DeleteError[*key]; ok { - glog.V(5).Infof("MockAlphaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) return err } if _, ok := m.Objects[*key]; !ok { err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaRegionDisks %v not found", key), + Message: fmt.Sprintf("MockBetaRegionDisks %v not found", key), } - glog.V(5).Infof("MockAlphaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) return err } delete(m.Objects, *key) - glog.V(5).Infof("MockAlphaRegionDisks.Delete(%v, %v) = nil", ctx, key) + glog.V(5).Infof("MockBetaRegionDisks.Delete(%v, %v) = nil", ctx, key) return nil } // Obj wraps the object for use in the mock. -func (m *MockAlphaRegionDisks) Obj(o *alpha.Disk) *MockRegionDisksObj { +func (m *MockBetaRegionDisks) Obj(o *beta.Disk) *MockRegionDisksObj { return &MockRegionDisksObj{o} } -// GCEAlphaRegionDisks is a simplifying adapter for the GCE RegionDisks. -type GCEAlphaRegionDisks struct { +// Resize is a mock for the corresponding method. +func (m *MockBetaRegionDisks) Resize(ctx context.Context, key *meta.Key, arg0 *beta.RegionDisksResizeRequest) error { + if m.ResizeHook != nil { + return m.ResizeHook(ctx, key, arg0, m) + } + return nil +} + +// GCEBetaRegionDisks is a simplifying adapter for the GCE RegionDisks. +type GCEBetaRegionDisks struct { s *Service } // Get the Disk named by key. -func (g *GCEAlphaRegionDisks) Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) { - glog.V(5).Infof("GCEAlphaRegionDisks.Get(%v, %v): called", ctx, key) +func (g *GCEBetaRegionDisks) Get(ctx context.Context, key *meta.Key) (*beta.Disk, error) { + glog.V(5).Infof("GCEBetaRegionDisks.Get(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaRegionDisks.Get(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaRegionDisks.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, "alpha", "RegionDisks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "RegionDisks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Get", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "RegionDisks", } - glog.V(5).Infof("GCEAlphaRegionDisks.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaRegionDisks.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.Get(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Get(%v, %v): RateLimiter error: %v", ctx, key, err) return nil, err } - call := g.s.Alpha.RegionDisks.Get(projectID, key.Region, key.Name) + call := g.s.Beta.RegionDisks.Get(projectID, key.Region, key.Name) call.Context(ctx) v, err := call.Do() - glog.V(4).Infof("GCEAlphaRegionDisks.Get(%v, %v) = %+v, %v", ctx, key, v, err) + glog.V(4).Infof("GCEBetaRegionDisks.Get(%v, %v) = %+v, %v", ctx, key, v, err) return v, err } // List all Disk objects. -func (g *GCEAlphaRegionDisks) List(ctx context.Context, region string, fl *filter.F) ([]*alpha.Disk, error) { - glog.V(5).Infof("GCEAlphaRegionDisks.List(%v, %v, %v) called", ctx, region, fl) - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionDisks") +func (g *GCEBetaRegionDisks) List(ctx context.Context, region string, fl *filter.F) ([]*beta.Disk, error) { + glog.V(5).Infof("GCEBetaRegionDisks.List(%v, %v, %v) called", ctx, region, fl) + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "RegionDisks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "List", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "RegionDisks", } if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { return nil, err } - glog.V(5).Infof("GCEAlphaRegionDisks.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, region, fl, projectID, rk) - call := g.s.Alpha.RegionDisks.List(projectID, region) + glog.V(5).Infof("GCEBetaRegionDisks.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, region, fl, projectID, rk) + call := g.s.Beta.RegionDisks.List(projectID, region) if fl != filter.None { call.Filter(fl.String()) } - var all []*alpha.Disk - f := func(l *alpha.DiskList) error { - glog.V(5).Infof("GCEAlphaRegionDisks.List(%v, ..., %v): page %+v", ctx, fl, l) + var all []*beta.Disk + f := func(l *beta.DiskList) error { + glog.V(5).Infof("GCEBetaRegionDisks.List(%v, ..., %v): page %+v", ctx, fl, l) all = append(all, l.Items...) return nil } if err := call.Pages(ctx, f); err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) + glog.V(4).Infof("GCEBetaRegionDisks.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) return nil, err } if glog.V(4) { - glog.V(4).Infof("GCEAlphaRegionDisks.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) + glog.V(4).Infof("GCEBetaRegionDisks.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) } else if glog.V(5) { var asStr []string for _, o := range all { asStr = append(asStr, fmt.Sprintf("%+v", o)) } - glog.V(5).Infof("GCEAlphaRegionDisks.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) + glog.V(5).Infof("GCEBetaRegionDisks.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) } return all, nil } // Insert Disk with key of value obj. -func (g *GCEAlphaRegionDisks) Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error { - glog.V(5).Infof("GCEAlphaRegionDisks.Insert(%v, %v, %+v): called", ctx, key, obj) +func (g *GCEBetaRegionDisks) Insert(ctx context.Context, key *meta.Key, obj *beta.Disk) error { + glog.V(5).Infof("GCEBetaRegionDisks.Insert(%v, %v, %+v): called", ctx, key, obj) if !key.Valid() { - glog.V(2).Infof("GCEAlphaRegionDisks.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaRegionDisks.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionDisks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "RegionDisks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Insert", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "RegionDisks", } - glog.V(5).Infof("GCEAlphaRegionDisks.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaRegionDisks.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return err } obj.Name = key.Name - call := g.s.Alpha.RegionDisks.Insert(projectID, key.Region, obj) + call := g.s.Beta.RegionDisks.Insert(projectID, key.Region, obj) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.Insert(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Insert(%v, %v, ...) = %+v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaRegionDisks.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) + glog.V(4).Infof("GCEBetaRegionDisks.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) return err } // Delete the Disk referenced by key. -func (g *GCEAlphaRegionDisks) Delete(ctx context.Context, key *meta.Key) error { - glog.V(5).Infof("GCEAlphaRegionDisks.Delete(%v, %v): called", ctx, key) +func (g *GCEBetaRegionDisks) Delete(ctx context.Context, key *meta.Key) error { + glog.V(5).Infof("GCEBetaRegionDisks.Delete(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaRegionDisks.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaRegionDisks.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionDisks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "RegionDisks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Delete", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "RegionDisks", } - glog.V(5).Infof("GCEAlphaRegionDisks.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaRegionDisks.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) return err } - call := g.s.Alpha.RegionDisks.Delete(projectID, key.Region, key.Name) + call := g.s.Beta.RegionDisks.Delete(projectID, key.Region, key.Name) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + return err +} + +// Resize is a method on GCEBetaRegionDisks. +func (g *GCEBetaRegionDisks) Resize(ctx context.Context, key *meta.Key, arg0 *beta.RegionDisksResizeRequest) error { + glog.V(5).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "RegionDisks") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Resize", + Version: meta.Version("beta"), + Service: "RegionDisks", + } + glog.V(5).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.Beta.RegionDisks.Resize(projectID, key.Region, key.Name, arg0) + call.Context(ctx) + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...) = %+v", ctx, key, err) return err } diff --git a/pkg/cloudprovider/providers/gce/cloud/gen_test.go b/pkg/cloudprovider/providers/gce/cloud/gen_test.go index 757a78853eb..bbdeaff704a 100644 --- a/pkg/cloudprovider/providers/gce/cloud/gen_test.go +++ b/pkg/cloudprovider/providers/gce/cloud/gen_test.go @@ -312,28 +312,17 @@ func TestDisksGroup(t *testing.T) { mock := NewMockGCE(pr) var key *meta.Key - keyAlpha := meta.ZonalKey("key-alpha", "location") - key = keyAlpha keyGA := meta.ZonalKey("key-ga", "location") key = keyGA // Ignore unused variables. _, _, _ = ctx, mock, key // Get not found. - if _, err := mock.AlphaDisks().Get(ctx, key); err == nil { - t.Errorf("AlphaDisks().Get(%v, %v) = _, nil; want error", ctx, key) - } if _, err := mock.Disks().Get(ctx, key); err == nil { t.Errorf("Disks().Get(%v, %v) = _, nil; want error", ctx, key) } // Insert. - { - obj := &alpha.Disk{} - if err := mock.AlphaDisks().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaDisks().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) - } - } { obj := &ga.Disk{} if err := mock.Disks().Insert(ctx, keyGA, obj); err != nil { @@ -342,35 +331,16 @@ func TestDisksGroup(t *testing.T) { } // Get across versions. - if obj, err := mock.AlphaDisks().Get(ctx, key); err != nil { - t.Errorf("AlphaDisks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } 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.MockAlphaDisks.Objects[*keyAlpha] = mock.MockAlphaDisks.Obj(&alpha.Disk{Name: keyAlpha.Name}) mock.MockDisks.Objects[*keyGA] = mock.MockDisks.Obj(&ga.Disk{Name: keyGA.Name}) want := map[string]bool{ - "key-alpha": true, - "key-ga": true, + "key-ga": true, } _ = want // ignore unused variables. - { - objs, err := mock.AlphaDisks().List(ctx, location, filter.None) - if err != nil { - t.Errorf("AlphaDisks().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("AlphaDisks().List(); got %+v, want %+v", got, want) - } - } - } { objs, err := mock.Disks().List(ctx, location, filter.None) if err != nil { @@ -387,17 +357,11 @@ func TestDisksGroup(t *testing.T) { } // Delete across versions. - if err := mock.AlphaDisks().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaDisks().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) - } 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.AlphaDisks().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaDisks().Delete(%v, %v) = nil; want error", ctx, keyAlpha) - } if err := mock.Disks().Delete(ctx, keyGA); err == nil { t.Errorf("Disks().Delete(%v, %v) = nil; want error", ctx, keyGA) } @@ -1315,39 +1279,39 @@ func TestRegionDisksGroup(t *testing.T) { mock := NewMockGCE(pr) var key *meta.Key - keyAlpha := meta.RegionalKey("key-alpha", "location") - key = keyAlpha + keyBeta := meta.RegionalKey("key-beta", "location") + key = keyBeta // Ignore unused variables. _, _, _ = ctx, mock, key // Get not found. - if _, err := mock.AlphaRegionDisks().Get(ctx, key); err == nil { - t.Errorf("AlphaRegionDisks().Get(%v, %v) = _, nil; want error", ctx, key) + if _, err := mock.BetaRegionDisks().Get(ctx, key); err == nil { + t.Errorf("BetaRegionDisks().Get(%v, %v) = _, nil; want error", ctx, key) } // Insert. { - obj := &alpha.Disk{} - if err := mock.AlphaRegionDisks().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaRegionDisks().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) + obj := &beta.Disk{} + if err := mock.BetaRegionDisks().Insert(ctx, keyBeta, obj); err != nil { + t.Errorf("BetaRegionDisks().Insert(%v, %v, %v) = %v; want nil", ctx, keyBeta, obj, err) } } // Get across versions. - if obj, err := mock.AlphaRegionDisks().Get(ctx, key); err != nil { - t.Errorf("AlphaRegionDisks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) + if obj, err := mock.BetaRegionDisks().Get(ctx, key); err != nil { + t.Errorf("BetaRegionDisks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) } // List. - mock.MockAlphaRegionDisks.Objects[*keyAlpha] = mock.MockAlphaRegionDisks.Obj(&alpha.Disk{Name: keyAlpha.Name}) + mock.MockBetaRegionDisks.Objects[*keyBeta] = mock.MockBetaRegionDisks.Obj(&beta.Disk{Name: keyBeta.Name}) want := map[string]bool{ - "key-alpha": true, + "key-beta": true, } _ = want // ignore unused variables. { - objs, err := mock.AlphaRegionDisks().List(ctx, location, filter.None) + objs, err := mock.BetaRegionDisks().List(ctx, location, filter.None) if err != nil { - t.Errorf("AlphaRegionDisks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) + t.Errorf("BetaRegionDisks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) } else { got := map[string]bool{} for _, obj := range objs { @@ -1360,13 +1324,13 @@ func TestRegionDisksGroup(t *testing.T) { } // Delete across versions. - if err := mock.AlphaRegionDisks().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaRegionDisks().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) + if err := mock.BetaRegionDisks().Delete(ctx, keyBeta); err != nil { + t.Errorf("BetaRegionDisks().Delete(%v, %v) = %v; want nil", ctx, keyBeta, err) } // Delete not found. - if err := mock.AlphaRegionDisks().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaRegionDisks().Delete(%v, %v) = nil; want error", ctx, keyAlpha) + if err := mock.BetaRegionDisks().Delete(ctx, keyBeta); err == nil { + t.Errorf("BetaRegionDisks().Delete(%v, %v) = nil; want error", ctx, keyBeta) } } diff --git a/pkg/cloudprovider/providers/gce/cloud/meta/meta.go b/pkg/cloudprovider/providers/gce/cloud/meta/meta.go index 7c1139b9400..e9ff33d43da 100644 --- a/pkg/cloudprovider/providers/gce/cloud/meta/meta.go +++ b/pkg/cloudprovider/providers/gce/cloud/meta/meta.go @@ -119,13 +119,16 @@ var AllServices = []*ServiceInfo{ }, }, { - Object: "BackendService", - Service: "BackendServices", - Resource: "backendServices", - version: VersionAlpha, - keyType: Global, - serviceType: reflect.TypeOf(&alpha.BackendServicesService{}), - additionalMethods: []string{"Update"}, + Object: "BackendService", + Service: "BackendServices", + Resource: "backendServices", + version: VersionAlpha, + keyType: Global, + serviceType: reflect.TypeOf(&alpha.BackendServicesService{}), + additionalMethods: []string{ + "Update", + "SetSecurityPolicy", + }, }, { Object: "BackendService", @@ -157,22 +160,20 @@ var AllServices = []*ServiceInfo{ Resource: "disks", keyType: Zonal, serviceType: reflect.TypeOf(&ga.DisksService{}), - }, - { - Object: "Disk", - Service: "Disks", - Resource: "disks", - version: VersionAlpha, - keyType: Zonal, - serviceType: reflect.TypeOf(&alpha.DisksService{}), + additionalMethods: []string{ + "Resize", + }, }, { Object: "Disk", Service: "RegionDisks", Resource: "disks", - version: VersionAlpha, + version: VersionBeta, keyType: Regional, - serviceType: reflect.TypeOf(&alpha.DisksService{}), + serviceType: reflect.TypeOf(&beta.RegionDisksService{}), + additionalMethods: []string{ + "Resize", + }, }, { Object: "Firewall", diff --git a/pkg/cloudprovider/providers/gce/cloud/mock/mock.go b/pkg/cloudprovider/providers/gce/cloud/mock/mock.go index f0e87cf0ce7..6a28c9f8e4b 100644 --- a/pkg/cloudprovider/providers/gce/cloud/mock/mock.go +++ b/pkg/cloudprovider/providers/gce/cloud/mock/mock.go @@ -94,7 +94,7 @@ func RemoveInstanceHook(ctx context.Context, key *meta.Key, req *ga.TargetPoolsR func convertAndInsertAlphaForwardingRule(key *meta.Key, obj gceObject, mRules map[meta.Key]*cloud.MockForwardingRulesObj, version meta.Version, projectID string) (bool, error) { if !key.Valid() { - return false, fmt.Errorf("invalid GCE key (%+v)", key) + return true, fmt.Errorf("invalid GCE key (%+v)", key) } if _, ok := mRules[*key]; ok { @@ -102,16 +102,16 @@ func convertAndInsertAlphaForwardingRule(key *meta.Key, obj gceObject, mRules ma Code: http.StatusConflict, Message: fmt.Sprintf("MockForwardingRule %v exists", key), } - return false, err + return true, err } enc, err := obj.MarshalJSON() if err != nil { - return false, err + return true, err } var fwdRule alpha.ForwardingRule if err := json.Unmarshal(enc, &fwdRule); err != nil { - return false, err + return true, err } // Set the default values for the Alpha fields. if fwdRule.NetworkTier == "" { @@ -162,7 +162,7 @@ type AddressAttributes struct { func convertAndInsertAlphaAddress(key *meta.Key, obj gceObject, mAddrs map[meta.Key]*cloud.MockAddressesObj, version meta.Version, projectID string, addressAttrs AddressAttributes) (bool, error) { if !key.Valid() { - return false, fmt.Errorf("invalid GCE key (%+v)", key) + return true, fmt.Errorf("invalid GCE key (%+v)", key) } if _, ok := mAddrs[*key]; ok { @@ -170,16 +170,16 @@ func convertAndInsertAlphaAddress(key *meta.Key, obj gceObject, mAddrs map[meta. Code: http.StatusConflict, Message: fmt.Sprintf("MockAddresses %v exists", key), } - return false, err + return true, err } enc, err := obj.MarshalJSON() if err != nil { - return false, err + return true, err } var addr alpha.Address if err := json.Unmarshal(enc, &addr); err != nil { - return false, err + return true, err } // Set default address type if not present. @@ -204,7 +204,7 @@ func convertAndInsertAlphaAddress(key *meta.Key, obj gceObject, mAddrs map[meta. errorCode = http.StatusBadRequest } - return false, &googleapi.Error{Code: errorCode, Message: msg} + return true, &googleapi.Error{Code: errorCode, Message: msg} } } diff --git a/pkg/cloudprovider/providers/gce/cloud/op.go b/pkg/cloudprovider/providers/gce/cloud/op.go index 1bd2e0c484b..358598776fc 100644 --- a/pkg/cloudprovider/providers/gce/cloud/op.go +++ b/pkg/cloudprovider/providers/gce/cloud/op.go @@ -29,10 +29,17 @@ import ( "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) +const ( + operationStatusDone = "DONE" +) + // operation is a GCE operation that can be watied on. type operation interface { // isDone queries GCE for the done status. This call can block. isDone(ctx context.Context) (bool, error) + // error returns the resulting error of the operation. This may be nil if the operations + // was successful. + error() error // rateLimitKey returns the rate limit key to use for the given operation. // This rate limit will govern how fast the server will be polled for // operation completion status. @@ -43,6 +50,7 @@ type gaOperation struct { s *Service projectID string key *meta.Key + err error } func (o *gaOperation) String() string { @@ -71,7 +79,15 @@ func (o *gaOperation) isDone(ctx context.Context) (bool, error) { if err != nil { return false, err } - return op != nil && op.Status == "DONE", nil + if op == nil || op.Status != operationStatusDone { + return false, nil + } + + if op.Error != nil && len(op.Error.Errors) > 0 && op.Error.Errors[0] != nil { + e := op.Error.Errors[0] + o.err = &GCEOperationError{HTTPStatusCode: op.HTTPStatusCode, Code: e.Code, Message: e.Message} + } + return true, nil } func (o *gaOperation) rateLimitKey() *RateLimitKey { @@ -83,10 +99,15 @@ func (o *gaOperation) rateLimitKey() *RateLimitKey { } } +func (o *gaOperation) error() error { + return o.err +} + type alphaOperation struct { s *Service projectID string key *meta.Key + err error } func (o *alphaOperation) String() string { @@ -115,7 +136,15 @@ func (o *alphaOperation) isDone(ctx context.Context) (bool, error) { if err != nil { return false, err } - return op != nil && op.Status == "DONE", nil + if op == nil || op.Status != operationStatusDone { + return false, nil + } + + if op.Error != nil && len(op.Error.Errors) > 0 && op.Error.Errors[0] != nil { + e := op.Error.Errors[0] + o.err = &GCEOperationError{HTTPStatusCode: op.HTTPStatusCode, Code: e.Code, Message: e.Message} + } + return true, nil } func (o *alphaOperation) rateLimitKey() *RateLimitKey { @@ -127,10 +156,15 @@ func (o *alphaOperation) rateLimitKey() *RateLimitKey { } } +func (o *alphaOperation) error() error { + return o.err +} + type betaOperation struct { s *Service projectID string key *meta.Key + err error } func (o *betaOperation) String() string { @@ -159,7 +193,15 @@ func (o *betaOperation) isDone(ctx context.Context) (bool, error) { if err != nil { return false, err } - return op != nil && op.Status == "DONE", nil + if op == nil || op.Status != operationStatusDone { + return false, nil + } + + if op.Error != nil && len(op.Error.Errors) > 0 && op.Error.Errors[0] != nil { + e := op.Error.Errors[0] + o.err = &GCEOperationError{HTTPStatusCode: op.HTTPStatusCode, Code: e.Code, Message: e.Message} + } + return true, nil } func (o *betaOperation) rateLimitKey() *RateLimitKey { @@ -170,3 +212,7 @@ func (o *betaOperation) rateLimitKey() *RateLimitKey { Version: meta.VersionBeta, } } + +func (o *betaOperation) error() error { + return o.err +} diff --git a/pkg/cloudprovider/providers/gce/cloud/ratelimit.go b/pkg/cloudprovider/providers/gce/cloud/ratelimit.go index e38b8f7de3c..ca1278a008d 100644 --- a/pkg/cloudprovider/providers/gce/cloud/ratelimit.go +++ b/pkg/cloudprovider/providers/gce/cloud/ratelimit.go @@ -47,22 +47,60 @@ type RateLimiter interface { Accept(ctx context.Context, key *RateLimitKey) error } +// acceptor is an object which blocks within Accept until a call is allowed to run. +// Accept is a behavior of the flowcontrol.RateLimiter interface. +type acceptor interface { + // Accept blocks until a call is allowed to run. + Accept() +} + +// AcceptRateLimiter wraps an Acceptor with RateLimiter parameters. +type AcceptRateLimiter struct { + // Acceptor is the underlying rate limiter. + Acceptor acceptor +} + +// Accept wraps an Acceptor and blocks on Accept or context.Done(). Key is ignored. +func (rl *AcceptRateLimiter) Accept(ctx context.Context, key *RateLimitKey) error { + ch := make(chan struct{}) + go func() { + rl.Acceptor.Accept() + close(ch) + }() + select { + case <-ch: + break + case <-ctx.Done(): + return ctx.Err() + } + return nil +} + // NopRateLimiter is a rate limiter that performs no rate limiting. type NopRateLimiter struct { } -// Accept the operation to be rate limited. +// Accept everything immediately. func (*NopRateLimiter) Accept(ctx context.Context, key *RateLimitKey) error { - // Rate limit polling of the Operation status to avoid hammering GCE - // for the status of an operation. - const pollTime = time.Duration(1) * time.Second - if key.Operation == "Get" && key.Service == "Operations" { - select { - case <-time.NewTimer(pollTime).C: - break - case <-ctx.Done(): - return ctx.Err() - } - } return nil } + +// MinimumRateLimiter wraps a RateLimiter and will only call its Accept until the minimum +// duration has been met or the context is cancelled. +type MinimumRateLimiter struct { + // RateLimiter is the underlying ratelimiter which is called after the mininum time is reacehd. + RateLimiter RateLimiter + // Minimum is the minimum wait time before the underlying ratelimiter is called. + Minimum time.Duration +} + +// Accept blocks on the minimum duration and context. Once the minimum duration is met, +// the func is blocked on the underlying ratelimiter. +func (m *MinimumRateLimiter) Accept(ctx context.Context, key *RateLimitKey) error { + select { + case <-time.After(m.Minimum): + return m.RateLimiter.Accept(ctx, key) + case <-ctx.Done(): + return ctx.Err() + } +} diff --git a/pkg/cloudprovider/providers/gce/cloud/ratelimit_test.go b/pkg/cloudprovider/providers/gce/cloud/ratelimit_test.go new file mode 100644 index 00000000000..4bb4512e133 --- /dev/null +++ b/pkg/cloudprovider/providers/gce/cloud/ratelimit_test.go @@ -0,0 +1,80 @@ +/* +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.go b/pkg/cloudprovider/providers/gce/cloud/service.go index 99ed7d226b7..2f332dfff85 100644 --- a/pkg/cloudprovider/providers/gce/cloud/service.go +++ b/pkg/cloudprovider/providers/gce/cloud/service.go @@ -45,19 +45,19 @@ func (s *Service) wrapOperation(anyOp interface{}) (operation, error) { if err != nil { return nil, err } - return &gaOperation{s, r.ProjectID, r.Key}, nil + return &gaOperation{s: s, projectID: r.ProjectID, key: r.Key}, nil case *alpha.Operation: r, err := ParseResourceURL(o.SelfLink) if err != nil { return nil, err } - return &alphaOperation{s, r.ProjectID, r.Key}, nil + return &alphaOperation{s: s, projectID: r.ProjectID, key: r.Key}, nil case *beta.Operation: r, err := ParseResourceURL(o.SelfLink) if err != nil { return nil, err } - return &betaOperation{s, r.ProjectID, r.Key}, nil + return &betaOperation{s: s, projectID: r.ProjectID, key: r.Key}, nil default: return nil, fmt.Errorf("invalid type %T", anyOp) } @@ -72,14 +72,39 @@ func (s *Service) WaitForCompletion(ctx context.Context, genericOp interface{}) glog.Errorf("wrapOperation(%+v) error: %v", genericOp, err) return err } - for done, err := op.isDone(ctx); !done; done, err = op.isDone(ctx) { - if err != nil { - glog.V(4).Infof("op.isDone(%v) error; op = %v, err = %v", ctx, op, err) - return err - } - glog.V(5).Infof("op.isDone(%v) waiting; op = %v", ctx, op) - s.RateLimiter.Accept(ctx, op.rateLimitKey()) - } - glog.V(5).Infof("op.isDone(%v) complete; op = %v", ctx, op) - return nil + + return s.pollOperation(ctx, op) +} + +// pollOperation calls operations.isDone until the function comes back true or context is Done. +// If an error occurs retrieving the operation, the loop will continue until the context is done. +// This is to prevent a transient error from bubbling up to controller-level logic. +func (s *Service) pollOperation(ctx context.Context, op operation) error { + var pollCount int + for { + // Check if context has been cancelled. Note that ctx.Done() must be checked before + // returning ctx.Err(). + select { + case <-ctx.Done(): + glog.V(5).Infof("op.pollOperation(%v, %v) not completed, poll count = %d, ctx.Err = %v", ctx, op, pollCount, ctx.Err()) + return ctx.Err() + default: + // ctx is not canceled, continue immediately + } + + pollCount++ + glog.V(5).Infof("op.isDone(%v) waiting; op = %v, poll count = %d", ctx, op, pollCount) + s.RateLimiter.Accept(ctx, op.rateLimitKey()) + done, err := op.isDone(ctx) + if err != nil { + glog.V(5).Infof("op.isDone(%v) error; op = %v, poll count = %d, err = %v, retrying", ctx, op, pollCount, err) + } + + if done { + break + } + } + + glog.V(5).Infof("op.isDone(%v) complete; op = %v, poll count = %d, op.err = %v", ctx, op, pollCount, op.error()) + return op.error() } diff --git a/pkg/cloudprovider/providers/gce/cloud/service_test.go b/pkg/cloudprovider/providers/gce/cloud/service_test.go new file mode 100644 index 00000000000..fc6fbb51d89 --- /dev/null +++ b/pkg/cloudprovider/providers/gce/cloud/service_test.go @@ -0,0 +1,84 @@ +/* +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/gce.go b/pkg/cloudprovider/providers/gce/gce.go index 383744f23d4..c2defec3896 100644 --- a/pkg/cloudprovider/providers/gce/gce.go +++ b/pkg/cloudprovider/providers/gce/gce.go @@ -68,7 +68,7 @@ const ( // AffinityTypeClientIPProto - affinity based on Client IP and port. gceAffinityTypeClientIPProto = "CLIENT_IP_PROTO" - operationPollInterval = 3 * time.Second + operationPollInterval = time.Second // Creating Route in very large clusters, may take more than half an hour. operationPollTimeoutDuration = time.Hour @@ -484,7 +484,7 @@ func CreateGCECloud(config *CloudConfig) (*GCECloud, error) { glog.Infof("managing multiple zones: %v", config.ManagedZones) } - operationPollRateLimiter := flowcontrol.NewTokenBucketRateLimiter(10, 100) // 10 qps, 100 bucket size. + operationPollRateLimiter := flowcontrol.NewTokenBucketRateLimiter(5, 5) // 5 qps, 5 burst. gce := &GCECloud{ service: service, diff --git a/pkg/cloudprovider/providers/gce/gce_address_manager_test.go b/pkg/cloudprovider/providers/gce/gce_address_manager_test.go index 3c7d60dc564..3b7409c6c19 100644 --- a/pkg/cloudprovider/providers/gce/gce_address_manager_test.go +++ b/pkg/cloudprovider/providers/gce/gce_address_manager_test.go @@ -26,95 +26,104 @@ import ( ) const testSvcName = "my-service" -const testRegion = "us-central1" const testSubnet = "/projects/x/testRegions/us-central1/testSubnetworks/customsub" const testLBName = "a111111111111111" +var vals = DefaultTestClusterValues() + // TestAddressManagerNoRequestedIP tests the typical case of passing in no requested IP func TestAddressManagerNoRequestedIP(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) targetIP := "" - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) - testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal)) - testReleaseAddress(t, mgr, svc, testLBName, testRegion) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + testHoldAddress(t, mgr, svc, testLBName, vals.Region, targetIP, string(cloud.SchemeInternal)) + testReleaseAddress(t, mgr, svc, testLBName, vals.Region) } // TestAddressManagerBasic tests the typical case of reserving and unreserving an address. func TestAddressManagerBasic(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) targetIP := "1.1.1.1" - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) - testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal)) - testReleaseAddress(t, mgr, svc, testLBName, testRegion) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + testHoldAddress(t, mgr, svc, testLBName, vals.Region, targetIP, string(cloud.SchemeInternal)) + testReleaseAddress(t, mgr, svc, testLBName, vals.Region) } // TestAddressManagerOrphaned tests the case where the address exists with the IP being equal // to the requested address (forwarding rule or loadbalancer IP). func TestAddressManagerOrphaned(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) targetIP := "1.1.1.1" addr := &compute.Address{Name: testLBName, Address: targetIP, AddressType: string(cloud.SchemeInternal)} - err := svc.ReserveRegionAddress(addr, testRegion) + err = svc.ReserveRegionAddress(addr, vals.Region) require.NoError(t, err) - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) - testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal)) - testReleaseAddress(t, mgr, svc, testLBName, testRegion) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + testHoldAddress(t, mgr, svc, testLBName, vals.Region, targetIP, string(cloud.SchemeInternal)) + testReleaseAddress(t, mgr, svc, testLBName, vals.Region) } // TestAddressManagerOutdatedOrphan tests the case where an address exists but points to // an IP other than the forwarding rule or loadbalancer IP. func TestAddressManagerOutdatedOrphan(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) previousAddress := "1.1.0.0" targetIP := "1.1.1.1" addr := &compute.Address{Name: testLBName, Address: previousAddress, AddressType: string(cloud.SchemeExternal)} - err := svc.ReserveRegionAddress(addr, testRegion) + err = svc.ReserveRegionAddress(addr, vals.Region) require.NoError(t, err) - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) - testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal)) - testReleaseAddress(t, mgr, svc, testLBName, testRegion) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + testHoldAddress(t, mgr, svc, testLBName, vals.Region, targetIP, string(cloud.SchemeInternal)) + testReleaseAddress(t, mgr, svc, testLBName, vals.Region) } // TestAddressManagerExternallyOwned tests the case where the address exists but isn't // owned by the controller. func TestAddressManagerExternallyOwned(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) targetIP := "1.1.1.1" addr := &compute.Address{Name: "my-important-address", Address: targetIP, AddressType: string(cloud.SchemeInternal)} - err := svc.ReserveRegionAddress(addr, testRegion) + err = svc.ReserveRegionAddress(addr, vals.Region) require.NoError(t, err) - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) ipToUse, err := mgr.HoldAddress() require.NoError(t, err) assert.NotEmpty(t, ipToUse) - _, err = svc.GetRegionAddress(testLBName, testRegion) + ad, err := svc.GetRegionAddress(testLBName, vals.Region) assert.True(t, isNotFound(err)) + require.Nil(t, ad) - testReleaseAddress(t, mgr, svc, testLBName, testRegion) + testReleaseAddress(t, mgr, svc, testLBName, vals.Region) } // TestAddressManagerExternallyOwned tests the case where the address exists but isn't // owned by the controller. However, this address has the wrong type. func TestAddressManagerBadExternallyOwned(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) targetIP := "1.1.1.1" addr := &compute.Address{Name: "my-important-address", Address: targetIP, AddressType: string(cloud.SchemeExternal)} - err := svc.ReserveRegionAddress(addr, testRegion) + err = svc.ReserveRegionAddress(addr, vals.Region) require.NoError(t, err) - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) - _, err = mgr.HoldAddress() - assert.NotNil(t, err) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + ad, err := mgr.HoldAddress() + assert.NotNil(t, err) // FIXME + require.Equal(t, ad, "") } func testHoldAddress(t *testing.T, mgr *addressManager, svc CloudAddressService, name, region, targetIP, scheme string) { diff --git a/pkg/cloudprovider/providers/gce/gce_addresses.go b/pkg/cloudprovider/providers/gce/gce_addresses.go index 37e2f5e9a7b..2bf3e20b051 100644 --- a/pkg/cloudprovider/providers/gce/gce_addresses.go +++ b/pkg/cloudprovider/providers/gce/gce_addresses.go @@ -17,7 +17,6 @@ limitations under the License. package gce import ( - "context" "fmt" "github.com/golang/glog" @@ -44,72 +43,105 @@ func newAddressMetricContextWithVersion(request, region, version string) *metric // ipAddress is specified, it must belong to the current project, eg: an // ephemeral IP associated with a global forwarding rule. func (gce *GCECloud) ReserveGlobalAddress(addr *compute.Address) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("reserve", "") - return mc.Observe(gce.c.GlobalAddresses().Insert(context.Background(), meta.GlobalKey(addr.Name), addr)) + return mc.Observe(gce.c.GlobalAddresses().Insert(ctx, meta.GlobalKey(addr.Name), addr)) } // DeleteGlobalAddress deletes a global address by name. func (gce *GCECloud) DeleteGlobalAddress(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("delete", "") - return mc.Observe(gce.c.GlobalAddresses().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.GlobalAddresses().Delete(ctx, meta.GlobalKey(name))) } // GetGlobalAddress returns the global address by name. func (gce *GCECloud) GetGlobalAddress(name string) (*compute.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("get", "") - v, err := gce.c.GlobalAddresses().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.GlobalAddresses().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // ReserveRegionAddress creates a region address func (gce *GCECloud) ReserveRegionAddress(addr *compute.Address, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("reserve", region) - return mc.Observe(gce.c.Addresses().Insert(context.Background(), meta.RegionalKey(addr.Name, region), addr)) + return mc.Observe(gce.c.Addresses().Insert(ctx, meta.RegionalKey(addr.Name, region), addr)) } // ReserveAlphaRegionAddress creates an Alpha, regional address. func (gce *GCECloud) ReserveAlphaRegionAddress(addr *computealpha.Address, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("reserve", region) - return mc.Observe(gce.c.AlphaAddresses().Insert(context.Background(), meta.RegionalKey(addr.Name, region), addr)) + return mc.Observe(gce.c.AlphaAddresses().Insert(ctx, meta.RegionalKey(addr.Name, region), addr)) } // ReserveBetaRegionAddress creates a beta region address func (gce *GCECloud) ReserveBetaRegionAddress(addr *computebeta.Address, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("reserve", region) - return mc.Observe(gce.c.BetaAddresses().Insert(context.Background(), meta.RegionalKey(addr.Name, region), addr)) + return mc.Observe(gce.c.BetaAddresses().Insert(ctx, meta.RegionalKey(addr.Name, region), addr)) } // DeleteRegionAddress deletes a region address by name. func (gce *GCECloud) DeleteRegionAddress(name, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("delete", region) - return mc.Observe(gce.c.Addresses().Delete(context.Background(), meta.RegionalKey(name, region))) + return mc.Observe(gce.c.Addresses().Delete(ctx, meta.RegionalKey(name, region))) } // GetRegionAddress returns the region address by name func (gce *GCECloud) GetRegionAddress(name, region string) (*compute.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("get", region) - v, err := gce.c.Addresses().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.Addresses().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // GetAlphaRegionAddress returns the Alpha, regional address by name. func (gce *GCECloud) GetAlphaRegionAddress(name, region string) (*computealpha.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("get", region) - v, err := gce.c.AlphaAddresses().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.AlphaAddresses().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // GetBetaRegionAddress returns the beta region address by name func (gce *GCECloud) GetBetaRegionAddress(name, region string) (*computebeta.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("get", region) - v, err := gce.c.BetaAddresses().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.BetaAddresses().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // GetRegionAddressByIP returns the regional address matching the given IP address. func (gce *GCECloud) GetRegionAddressByIP(region, ipAddress string) (*compute.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("list", region) - addrs, err := gce.c.Addresses().List(context.Background(), region, filter.Regexp("address", ipAddress)) + addrs, err := gce.c.Addresses().List(ctx, region, filter.Regexp("address", ipAddress)) mc.Observe(err) if err != nil { @@ -129,8 +161,11 @@ func (gce *GCECloud) GetRegionAddressByIP(region, ipAddress string) (*compute.Ad // GetBetaRegionAddressByIP returns the beta regional address matching the given IP address. func (gce *GCECloud) GetBetaRegionAddressByIP(region, ipAddress string) (*computebeta.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("list", region) - addrs, err := gce.c.BetaAddresses().List(context.Background(), region, filter.Regexp("address", ipAddress)) + addrs, err := gce.c.BetaAddresses().List(ctx, region, filter.Regexp("address", ipAddress)) mc.Observe(err) if err != nil { diff --git a/pkg/cloudprovider/providers/gce/gce_addresses_fakes.go b/pkg/cloudprovider/providers/gce/gce_addresses_fakes.go deleted file mode 100644 index 75dfa571c9c..00000000000 --- a/pkg/cloudprovider/providers/gce/gce_addresses_fakes.go +++ /dev/null @@ -1,239 +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 gce - -import ( - "bytes" - "encoding/json" - "fmt" - "net/http" - - computealpha "google.golang.org/api/compute/v0.alpha" - computebeta "google.golang.org/api/compute/v0.beta" - compute "google.golang.org/api/compute/v1" - - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" -) - -// test - -type FakeCloudAddressService struct { - count int - // reservedAddrs tracks usage of IP addresses - // Key is the IP address as a string - reservedAddrs map[string]bool - // addrsByRegionAndName - // Outer key is for region string; inner key is for address name. - addrsByRegionAndName map[string]map[string]*computealpha.Address -} - -// FakeCloudAddressService Implements CloudAddressService -var _ CloudAddressService = &FakeCloudAddressService{} - -func NewFakeCloudAddressService() *FakeCloudAddressService { - return &FakeCloudAddressService{ - reservedAddrs: make(map[string]bool), - addrsByRegionAndName: make(map[string]map[string]*computealpha.Address), - } -} - -// SetRegionalAddresses sets the addresses of there region. This is used for -// setting the test environment. -func (cas *FakeCloudAddressService) SetRegionalAddresses(region string, addrs []*computealpha.Address) { - // Reset addresses in the region. - cas.addrsByRegionAndName[region] = make(map[string]*computealpha.Address) - - for _, addr := range addrs { - cas.reservedAddrs[addr.Address] = true - cas.addrsByRegionAndName[region][addr.Name] = addr - } -} - -func (cas *FakeCloudAddressService) ReserveAlphaRegionAddress(addr *computealpha.Address, region string) error { - if addr.Address == "" { - addr.Address = fmt.Sprintf("1.2.3.%d", cas.count) - cas.count++ - } - - if addr.AddressType == "" { - addr.AddressType = string(cloud.SchemeExternal) - } - - if cas.reservedAddrs[addr.Address] { - msg := "IP in use" - // When the IP is already in use, this call returns an error code based - // on the type (internal vs external) of the address. This is to be - // consistent with actual GCE API. - switch cloud.LbScheme(addr.AddressType) { - case cloud.SchemeExternal: - return makeGoogleAPIError(http.StatusBadRequest, msg) - default: - return makeGoogleAPIError(http.StatusConflict, msg) - } - } - - if _, exists := cas.addrsByRegionAndName[region]; !exists { - cas.addrsByRegionAndName[region] = make(map[string]*computealpha.Address) - } - - if _, exists := cas.addrsByRegionAndName[region][addr.Name]; exists { - return makeGoogleAPIError(http.StatusConflict, "name in use") - } - - cas.addrsByRegionAndName[region][addr.Name] = addr - cas.reservedAddrs[addr.Address] = true - return nil -} - -func (cas *FakeCloudAddressService) ReserveBetaRegionAddress(addr *computebeta.Address, region string) error { - alphaAddr := convertToAlphaAddress(addr) - return cas.ReserveAlphaRegionAddress(alphaAddr, region) -} - -func (cas *FakeCloudAddressService) ReserveRegionAddress(addr *compute.Address, region string) error { - alphaAddr := convertToAlphaAddress(addr) - return cas.ReserveAlphaRegionAddress(alphaAddr, region) -} - -func (cas *FakeCloudAddressService) GetAlphaRegionAddress(name, region string) (*computealpha.Address, error) { - if _, exists := cas.addrsByRegionAndName[region]; !exists { - return nil, makeGoogleAPINotFoundError("") - } - - if addr, exists := cas.addrsByRegionAndName[region][name]; !exists { - return nil, makeGoogleAPINotFoundError("") - } else { - return addr, nil - } -} - -func (cas *FakeCloudAddressService) GetBetaRegionAddress(name, region string) (*computebeta.Address, error) { - addr, err := cas.GetAlphaRegionAddress(name, region) - if addr != nil { - return convertToBetaAddress(addr), err - } - return nil, err -} - -func (cas *FakeCloudAddressService) GetRegionAddress(name, region string) (*compute.Address, error) { - addr, err := cas.GetAlphaRegionAddress(name, region) - if addr != nil { - return convertToV1Address(addr), err - } - return nil, err -} - -func (cas *FakeCloudAddressService) DeleteRegionAddress(name, region string) error { - if _, exists := cas.addrsByRegionAndName[region]; !exists { - return makeGoogleAPINotFoundError("") - } - - addr, exists := cas.addrsByRegionAndName[region][name] - if !exists { - return makeGoogleAPINotFoundError("") - } - - delete(cas.reservedAddrs, addr.Address) - delete(cas.addrsByRegionAndName[region], name) - return nil -} - -func (cas *FakeCloudAddressService) GetAlphaRegionAddressByIP(region, ipAddress string) (*computealpha.Address, error) { - if _, exists := cas.addrsByRegionAndName[region]; !exists { - return nil, makeGoogleAPINotFoundError("") - } - - for _, addr := range cas.addrsByRegionAndName[region] { - if addr.Address == ipAddress { - return addr, nil - } - } - return nil, makeGoogleAPINotFoundError("") -} - -func (cas *FakeCloudAddressService) GetBetaRegionAddressByIP(name, region string) (*computebeta.Address, error) { - addr, err := cas.GetAlphaRegionAddressByIP(name, region) - if addr != nil { - return convertToBetaAddress(addr), nil - } - return nil, err -} - -func (cas *FakeCloudAddressService) GetRegionAddressByIP(name, region string) (*compute.Address, error) { - addr, err := cas.GetAlphaRegionAddressByIP(name, region) - if addr != nil { - return convertToV1Address(addr), nil - } - return nil, err -} - -func (cas *FakeCloudAddressService) getNetworkTierFromAddress(name, region string) (string, error) { - addr, err := cas.GetAlphaRegionAddress(name, region) - if err != nil { - return "", err - } - return addr.NetworkTier, nil -} - -func convertToV1Address(object gceObject) *compute.Address { - enc, err := object.MarshalJSON() - if err != nil { - panic(fmt.Sprintf("Failed to encode to json: %v", err)) - } - var addr compute.Address - if err := json.Unmarshal(enc, &addr); err != nil { - panic(fmt.Sprintf("Failed to convert GCE apiObject %v to v1 address: %v", object, err)) - } - return &addr -} - -func convertToAlphaAddress(object gceObject) *computealpha.Address { - enc, err := object.MarshalJSON() - if err != nil { - panic(fmt.Sprintf("Failed to encode to json: %v", err)) - } - var addr computealpha.Address - if err := json.Unmarshal(enc, &addr); err != nil { - panic(fmt.Sprintf("Failed to convert GCE apiObject %v to alpha address: %v", object, err)) - } - // Set the default values for the Alpha fields. - addr.NetworkTier = cloud.NetworkTierDefault.ToGCEValue() - return &addr -} - -func convertToBetaAddress(object gceObject) *computebeta.Address { - enc, err := object.MarshalJSON() - if err != nil { - panic(fmt.Sprintf("Failed to encode to json: %v", err)) - } - var addr computebeta.Address - if err := json.Unmarshal(enc, &addr); err != nil { - panic(fmt.Sprintf("Failed to convert GCE apiObject %v to beta address: %v", object, err)) - } - return &addr -} - -func (cas *FakeCloudAddressService) String() string { - var b bytes.Buffer - for region, regAddresses := range cas.addrsByRegionAndName { - b.WriteString(fmt.Sprintf("%v:\n", region)) - for name, addr := range regAddresses { - b.WriteString(fmt.Sprintf(" %v: %v\n", name, addr.Address)) - } - } - return b.String() -} diff --git a/pkg/cloudprovider/providers/gce/gce_backendservice.go b/pkg/cloudprovider/providers/gce/gce_backendservice.go index a059b2c9bae..4b330a49ede 100644 --- a/pkg/cloudprovider/providers/gce/gce_backendservice.go +++ b/pkg/cloudprovider/providers/gce/gce_backendservice.go @@ -17,12 +17,11 @@ limitations under the License. package gce import ( - "context" - computealpha "google.golang.org/api/compute/v0.alpha" 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" ) @@ -37,54 +36,88 @@ func newBackendServiceMetricContextWithVersion(request, region, version string) // GetGlobalBackendService retrieves a backend by name. func (gce *GCECloud) GetGlobalBackendService(name string) (*compute.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("get", "") - v, err := gce.c.BackendServices().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.BackendServices().Get(ctx, meta.GlobalKey(name)) + return v, mc.Observe(err) +} + +// GetBetaGlobalBackendService retrieves beta backend by name. +func (gce *GCECloud) GetBetaGlobalBackendService(name string) (*computebeta.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newBackendServiceMetricContextWithVersion("get", "", computeBetaVersion) + v, err := gce.c.BetaBackendServices().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // GetAlphaGlobalBackendService retrieves alpha backend by name. func (gce *GCECloud) GetAlphaGlobalBackendService(name string) (*computealpha.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContextWithVersion("get", "", computeAlphaVersion) - v, err := gce.c.AlphaBackendServices().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.AlphaBackendServices().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // UpdateGlobalBackendService applies the given BackendService as an update to // an existing service. func (gce *GCECloud) UpdateGlobalBackendService(bg *compute.BackendService) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("update", "") - return mc.Observe(gce.c.BackendServices().Update(context.Background(), meta.GlobalKey(bg.Name), bg)) + return mc.Observe(gce.c.BackendServices().Update(ctx, meta.GlobalKey(bg.Name), bg)) } // UpdateAlphaGlobalBackendService applies the given alpha BackendService as an // update to an existing service. func (gce *GCECloud) UpdateAlphaGlobalBackendService(bg *computealpha.BackendService) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("update", "") - return mc.Observe(gce.c.AlphaBackendServices().Update(context.Background(), meta.GlobalKey(bg.Name), bg)) + return mc.Observe(gce.c.AlphaBackendServices().Update(ctx, meta.GlobalKey(bg.Name), bg)) } // DeleteGlobalBackendService deletes the given BackendService by name. func (gce *GCECloud) DeleteGlobalBackendService(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("delete", "") - return mc.Observe(gce.c.BackendServices().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.BackendServices().Delete(ctx, meta.GlobalKey(name))) } // CreateGlobalBackendService creates the given BackendService. func (gce *GCECloud) CreateGlobalBackendService(bg *compute.BackendService) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("create", "") - return mc.Observe(gce.c.BackendServices().Insert(context.Background(), meta.GlobalKey(bg.Name), bg)) + return mc.Observe(gce.c.BackendServices().Insert(ctx, meta.GlobalKey(bg.Name), bg)) } // CreateAlphaGlobalBackendService creates the given alpha BackendService. func (gce *GCECloud) CreateAlphaGlobalBackendService(bg *computealpha.BackendService) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("create", "") - return mc.Observe(gce.c.AlphaBackendServices().Insert(context.Background(), meta.GlobalKey(bg.Name), bg)) + return mc.Observe(gce.c.AlphaBackendServices().Insert(ctx, meta.GlobalKey(bg.Name), bg)) } // ListGlobalBackendServices lists all backend services in the project. func (gce *GCECloud) ListGlobalBackendServices() ([]*compute.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("list", "") - v, err := gce.c.BackendServices().List(context.Background(), filter.None) + v, err := gce.c.BackendServices().List(ctx, filter.None) return v, mc.Observe(err) } @@ -92,42 +125,60 @@ func (gce *GCECloud) ListGlobalBackendServices() ([]*compute.BackendService, err // identified by the given name, in the given instanceGroup. The // instanceGroupLink is the fully qualified self link of an instance group. func (gce *GCECloud) GetGlobalBackendServiceHealth(name string, instanceGroupLink string) (*compute.BackendServiceGroupHealth, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("get_health", "") groupRef := &compute.ResourceGroupReference{Group: instanceGroupLink} - v, err := gce.c.BackendServices().GetHealth(context.Background(), meta.GlobalKey(name), groupRef) + v, err := gce.c.BackendServices().GetHealth(ctx, meta.GlobalKey(name), groupRef) return v, mc.Observe(err) } // GetRegionBackendService retrieves a backend by name. func (gce *GCECloud) GetRegionBackendService(name, region string) (*compute.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("get", region) - v, err := gce.c.RegionBackendServices().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.RegionBackendServices().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // UpdateRegionBackendService applies the given BackendService as an update to // an existing service. func (gce *GCECloud) UpdateRegionBackendService(bg *compute.BackendService, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("update", region) - return mc.Observe(gce.c.RegionBackendServices().Update(context.Background(), meta.RegionalKey(bg.Name, region), bg)) + return mc.Observe(gce.c.RegionBackendServices().Update(ctx, meta.RegionalKey(bg.Name, region), bg)) } // DeleteRegionBackendService deletes the given BackendService by name. func (gce *GCECloud) DeleteRegionBackendService(name, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("delete", region) - return mc.Observe(gce.c.RegionBackendServices().Delete(context.Background(), meta.RegionalKey(name, region))) + return mc.Observe(gce.c.RegionBackendServices().Delete(ctx, meta.RegionalKey(name, region))) } // CreateRegionBackendService creates the given BackendService. func (gce *GCECloud) CreateRegionBackendService(bg *compute.BackendService, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("create", region) - return mc.Observe(gce.c.RegionBackendServices().Insert(context.Background(), meta.RegionalKey(bg.Name, region), bg)) + return mc.Observe(gce.c.RegionBackendServices().Insert(ctx, meta.RegionalKey(bg.Name, region), bg)) } // ListRegionBackendServices lists all backend services in the project. func (gce *GCECloud) ListRegionBackendServices(region string) ([]*compute.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("list", region) - v, err := gce.c.RegionBackendServices().List(context.Background(), region, filter.None) + v, err := gce.c.RegionBackendServices().List(ctx, region, filter.None) return v, mc.Observe(err) } @@ -135,15 +186,31 @@ func (gce *GCECloud) ListRegionBackendServices(region string) ([]*compute.Backen // identified by the given name, in the given instanceGroup. The // instanceGroupLink is the fully qualified self link of an instance group. func (gce *GCECloud) GetRegionalBackendServiceHealth(name, region string, instanceGroupLink string) (*compute.BackendServiceGroupHealth, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("get_health", region) ref := &compute.ResourceGroupReference{Group: instanceGroupLink} - v, err := gce.c.RegionBackendServices().GetHealth(context.Background(), meta.RegionalKey(name, region), ref) + v, err := gce.c.RegionBackendServices().GetHealth(ctx, meta.RegionalKey(name, region), ref) return v, mc.Observe(err) } // SetSecurityPolicyForBetaGlobalBackendService sets the given // SecurityPolicyReference for the BackendService identified by the given name. func (gce *GCECloud) SetSecurityPolicyForBetaGlobalBackendService(backendServiceName string, securityPolicyReference *computebeta.SecurityPolicyReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContextWithVersion("set_security_policy", "", computeBetaVersion) - return mc.Observe(gce.c.BetaBackendServices().SetSecurityPolicy(context.Background(), meta.GlobalKey(backendServiceName), securityPolicyReference)) + return mc.Observe(gce.c.BetaBackendServices().SetSecurityPolicy(ctx, meta.GlobalKey(backendServiceName), securityPolicyReference)) +} + +// SetSecurityPolicyForAlphaGlobalBackendService sets the given +// SecurityPolicyReference for the BackendService identified by the given name. +func (gce *GCECloud) SetSecurityPolicyForAlphaGlobalBackendService(backendServiceName string, securityPolicyReference *computealpha.SecurityPolicyReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newBackendServiceMetricContextWithVersion("set_security_policy", "", computeAlphaVersion) + return mc.Observe(gce.c.AlphaBackendServices().SetSecurityPolicy(ctx, meta.GlobalKey(backendServiceName), securityPolicyReference)) } diff --git a/pkg/cloudprovider/providers/gce/gce_cert.go b/pkg/cloudprovider/providers/gce/gce_cert.go index f91ce879e39..3b6614f816f 100644 --- a/pkg/cloudprovider/providers/gce/gce_cert.go +++ b/pkg/cloudprovider/providers/gce/gce_cert.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - 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" ) @@ -31,15 +30,21 @@ func newCertMetricContext(request string) *metricContext { // GetSslCertificate returns the SslCertificate by name. func (gce *GCECloud) GetSslCertificate(name string) (*compute.SslCertificate, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newCertMetricContext("get") - v, err := gce.c.SslCertificates().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.SslCertificates().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // CreateSslCertificate creates and returns a SslCertificate. func (gce *GCECloud) CreateSslCertificate(sslCerts *compute.SslCertificate) (*compute.SslCertificate, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newCertMetricContext("create") - err := gce.c.SslCertificates().Insert(context.Background(), meta.GlobalKey(sslCerts.Name), sslCerts) + err := gce.c.SslCertificates().Insert(ctx, meta.GlobalKey(sslCerts.Name), sslCerts) if err != nil { return nil, mc.Observe(err) } @@ -48,13 +53,19 @@ func (gce *GCECloud) CreateSslCertificate(sslCerts *compute.SslCertificate) (*co // DeleteSslCertificate deletes the SslCertificate by name. func (gce *GCECloud) DeleteSslCertificate(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newCertMetricContext("delete") - return mc.Observe(gce.c.SslCertificates().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.SslCertificates().Delete(ctx, meta.GlobalKey(name))) } // ListSslCertificates lists all SslCertificates in the project. func (gce *GCECloud) ListSslCertificates() ([]*compute.SslCertificate, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newCertMetricContext("list") - v, err := gce.c.SslCertificates().List(context.Background(), filter.None) + v, err := gce.c.SslCertificates().List(ctx, filter.None) return v, mc.Observe(err) } diff --git a/pkg/cloudprovider/providers/gce/gce_disks.go b/pkg/cloudprovider/providers/gce/gce_disks.go index 18b1c080932..7b7bb2dded3 100644 --- a/pkg/cloudprovider/providers/gce/gce_disks.go +++ b/pkg/cloudprovider/providers/gce/gce_disks.go @@ -38,6 +38,8 @@ import ( compute "google.golang.org/api/compute/v1" "google.golang.org/api/googleapi" utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" "k8s.io/kubernetes/pkg/features" ) @@ -65,7 +67,7 @@ type diskServiceManager interface { sizeGb int64, tagsStr string, diskType string, - zone string) (gceObject, error) + zone string) error // Creates a new regional persistent disk on GCE with the given disk spec. CreateRegionalDiskOnCloudProvider( @@ -73,41 +75,35 @@ type diskServiceManager interface { sizeGb int64, tagsStr string, diskType string, - zones sets.String) (gceObject, error) + zones sets.String) error // Deletes the persistent disk from GCE with the given diskName. - DeleteDiskOnCloudProvider(zone string, disk string) (gceObject, error) + DeleteDiskOnCloudProvider(zone string, disk string) error // Deletes the regional persistent disk from GCE with the given diskName. - DeleteRegionalDiskOnCloudProvider(diskName string) (gceObject, error) + DeleteRegionalDiskOnCloudProvider(diskName string) error // Attach a persistent disk on GCE with the given disk spec to the specified instance. AttachDiskOnCloudProvider( disk *GCEDisk, readWrite string, instanceZone string, - instanceName string) (gceObject, error) + instanceName string) error // Detach a persistent disk on GCE with the given disk spec from the specified instance. DetachDiskOnCloudProvider( instanceZone string, instanceName string, - devicePath string) (gceObject, error) + devicePath string) error - ResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64, zone string) (gceObject, error) - RegionalResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64) (gceObject, error) + ResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64, zone string) error + RegionalResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64) error // Gets the persistent disk from GCE with the given diskName. GetDiskFromCloudProvider(zone string, diskName string) (*GCEDisk, error) // Gets the regional persistent disk from GCE with the given diskName. GetRegionalDiskFromCloudProvider(diskName string) (*GCEDisk, error) - - // Waits until GCE reports the given operation in the given zone as done. - WaitForZoneOp(op gceObject, zone string, mc *metricContext) error - - // Waits until GCE reports the given operation in the given region is done. - WaitForRegionalOp(op gceObject, mc *metricContext) error } type gceServiceManager struct { @@ -121,11 +117,11 @@ func (manager *gceServiceManager) CreateDiskOnCloudProvider( sizeGb int64, tagsStr string, diskType string, - zone string) (gceObject, error) { + zone string) error { diskTypeURI, err := manager.getDiskTypeURI( manager.gce.region /* diskRegion */, singleZone{zone}, diskType, false /* useBetaAPI */) if err != nil { - return nil, err + return err } diskToCreateV1 := &compute.Disk{ @@ -134,8 +130,10 @@ func (manager *gceServiceManager) CreateDiskOnCloudProvider( Description: tagsStr, Type: diskTypeURI, } - return manager.gce.service.Disks.Insert( - manager.gce.projectID, zone, diskToCreateV1).Do() + + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.Disks().Insert(ctx, meta.ZonalKey(name, zone), diskToCreateV1) } func (manager *gceServiceManager) CreateRegionalDiskOnCloudProvider( @@ -143,42 +141,44 @@ func (manager *gceServiceManager) CreateRegionalDiskOnCloudProvider( sizeGb int64, tagsStr string, diskType string, - replicaZones sets.String) (gceObject, error) { + replicaZones sets.String) error { - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - diskTypeURI, err := manager.getDiskTypeURI( - manager.gce.region /* diskRegion */, multiZone{replicaZones}, diskType, true /* useBetaAPI */) - if err != nil { - return nil, err - } - fullyQualifiedReplicaZones := []string{} - for _, replicaZone := range replicaZones.UnsortedList() { - fullyQualifiedReplicaZones = append( - fullyQualifiedReplicaZones, manager.getReplicaZoneURI(replicaZone, true)) - } - - diskToCreateBeta := &computebeta.Disk{ - Name: name, - SizeGb: sizeGb, - Description: tagsStr, - Type: diskTypeURI, - ReplicaZones: fullyQualifiedReplicaZones, - } - return manager.gce.serviceBeta.RegionDisks.Insert( - manager.gce.projectID, manager.gce.region, diskToCreateBeta).Do() + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) } - return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) + diskTypeURI, err := manager.getDiskTypeURI( + manager.gce.region /* diskRegion */, multiZone{replicaZones}, diskType, true /* useBetaAPI */) + if err != nil { + return err + } + fullyQualifiedReplicaZones := []string{} + for _, replicaZone := range replicaZones.UnsortedList() { + fullyQualifiedReplicaZones = append( + fullyQualifiedReplicaZones, manager.getReplicaZoneURI(replicaZone, true)) + } + + diskToCreateBeta := &computebeta.Disk{ + Name: name, + SizeGb: sizeGb, + Description: tagsStr, + Type: diskTypeURI, + ReplicaZones: fullyQualifiedReplicaZones, + } + + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.BetaRegionDisks().Insert(ctx, meta.RegionalKey(name, manager.gce.region), diskToCreateBeta) } func (manager *gceServiceManager) AttachDiskOnCloudProvider( disk *GCEDisk, readWrite string, instanceZone string, - instanceName string) (gceObject, error) { + instanceName string) error { source, err := manager.getDiskSourceURI(disk) if err != nil { - return nil, err + return err } attachedDiskV1 := &compute.AttachedDisk{ @@ -188,16 +188,19 @@ func (manager *gceServiceManager) AttachDiskOnCloudProvider( Source: source, Type: diskTypePersistent, } - return manager.gce.service.Instances.AttachDisk( - manager.gce.projectID, instanceZone, instanceName, attachedDiskV1).Do() + + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.Instances().AttachDisk(ctx, meta.ZonalKey(instanceName, instanceZone), attachedDiskV1) } func (manager *gceServiceManager) DetachDiskOnCloudProvider( instanceZone string, instanceName string, - devicePath string) (gceObject, error) { - return manager.gce.service.Instances.DetachDisk( - manager.gce.projectID, instanceZone, instanceName, devicePath).Do() + devicePath string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.Instances().DetachDisk(ctx, meta.ZonalKey(instanceName, instanceZone), devicePath) } func (manager *gceServiceManager) GetDiskFromCloudProvider( @@ -211,8 +214,9 @@ func (manager *gceServiceManager) GetDiskFromCloudProvider( return nil, fmt.Errorf("Can not fetch disk. Zone is specified (%q). But disk name is empty.", zone) } - diskStable, err := manager.gce.service.Disks.Get( - manager.gce.projectID, zone, diskName).Do() + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + diskStable, err := manager.gce.c.Disks().Get(ctx, meta.ZonalKey(diskName, zone)) if err != nil { return nil, err } @@ -240,56 +244,50 @@ func (manager *gceServiceManager) GetDiskFromCloudProvider( func (manager *gceServiceManager) GetRegionalDiskFromCloudProvider( diskName string) (*GCEDisk, error) { - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - diskBeta, err := manager.gce.serviceBeta.RegionDisks.Get( - manager.gce.projectID, manager.gce.region, diskName).Do() - if err != nil { - return nil, err - } - - zones := sets.NewString() - for _, zoneURI := range diskBeta.ReplicaZones { - zones.Insert(lastComponent(zoneURI)) - } - - return &GCEDisk{ - ZoneInfo: multiZone{zones}, - Region: lastComponent(diskBeta.Region), - Name: diskBeta.Name, - Kind: diskBeta.Kind, - Type: diskBeta.Type, - SizeGb: diskBeta.SizeGb, - }, nil + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) } - return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + diskBeta, err := manager.gce.c.BetaRegionDisks().Get(ctx, meta.RegionalKey(diskName, manager.gce.region)) + if err != nil { + return nil, err + } + + zones := sets.NewString() + for _, zoneURI := range diskBeta.ReplicaZones { + zones.Insert(lastComponent(zoneURI)) + } + + return &GCEDisk{ + ZoneInfo: multiZone{zones}, + Region: lastComponent(diskBeta.Region), + Name: diskBeta.Name, + Kind: diskBeta.Kind, + Type: diskBeta.Type, + SizeGb: diskBeta.SizeGb, + }, nil } func (manager *gceServiceManager) DeleteDiskOnCloudProvider( zone string, - diskName string) (gceObject, error) { - return manager.gce.service.Disks.Delete( - manager.gce.projectID, zone, diskName).Do() + diskName string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.Disks().Delete(ctx, meta.ZonalKey(diskName, zone)) } func (manager *gceServiceManager) DeleteRegionalDiskOnCloudProvider( - diskName string) (gceObject, error) { - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - return manager.gce.serviceBeta.RegionDisks.Delete( - manager.gce.projectID, manager.gce.region, diskName).Do() + diskName string) error { + + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) } - return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) -} - -func (manager *gceServiceManager) WaitForZoneOp( - op gceObject, zone string, mc *metricContext) error { - return manager.gce.waitForZoneOp(op, zone, mc) -} - -func (manager *gceServiceManager) WaitForRegionalOp( - op gceObject, mc *metricContext) error { - return manager.gce.waitForRegionOp(op, manager.gce.region, mc) + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.BetaRegionDisks().Delete(ctx, meta.RegionalKey(diskName, manager.gce.region)) } func (manager *gceServiceManager) getDiskSourceURI(disk *GCEDisk) (string, error) { @@ -411,21 +409,28 @@ func (manager *gceServiceManager) getRegionFromZone(zoneInfo zoneType) (string, return region, nil } -func (manager *gceServiceManager) ResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64, zone string) (gceObject, error) { +func (manager *gceServiceManager) ResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64, zone string) error { resizeServiceRequest := &compute.DisksResizeRequest{ SizeGb: sizeGb, } - return manager.gce.service.Disks.Resize(manager.gce.projectID, zone, disk.Name, resizeServiceRequest).Do() + + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.Disks().Resize(ctx, meta.ZonalKey(disk.Name, zone), resizeServiceRequest) } -func (manager *gceServiceManager) RegionalResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64) (gceObject, error) { - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - resizeServiceRequest := &computebeta.RegionDisksResizeRequest{ - SizeGb: sizeGb, - } - return manager.gce.serviceBeta.RegionDisks.Resize(manager.gce.projectID, disk.Region, disk.Name, resizeServiceRequest).Do() +func (manager *gceServiceManager) RegionalResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64) error { + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) } - return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) + + resizeServiceRequest := &computebeta.RegionDisksResizeRequest{ + SizeGb: sizeGb, + } + + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.BetaRegionDisks().Resize(ctx, meta.RegionalKey(disk.Name, disk.Region), resizeServiceRequest) } // Disks is interface for manipulation with GCE PDs. @@ -535,14 +540,10 @@ func (gce *GCECloud) AttachDisk(diskName string, nodeName types.NodeName, readOn if regional && utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { disk, err = gce.getRegionalDiskByName(diskName) if err != nil { - glog.V(5).Infof("Could not find regional PD named %q to Attach. Will look for a zonal PD", diskName) - err = nil - } else { - mc = newDiskMetricContextRegional("attach", gce.region) + return err } - } - - if disk == nil { + mc = newDiskMetricContextRegional("attach", gce.region) + } else { disk, err = gce.getDiskByName(diskName, instance.Zone) if err != nil { return err @@ -555,14 +556,7 @@ func (gce *GCECloud) AttachDisk(diskName string, nodeName types.NodeName, readOn readWrite = "READ_ONLY" } - attachOp, err := gce.manager.AttachDiskOnCloudProvider( - disk, readWrite, instance.Zone, instance.Name) - - if err != nil { - return mc.Observe(err) - } - - return gce.manager.WaitForZoneOp(attachOp, instance.Zone, mc) + return mc.Observe(gce.manager.AttachDiskOnCloudProvider(disk, readWrite, instance.Zone, instance.Name)) } func (gce *GCECloud) DetachDisk(devicePath string, nodeName types.NodeName) error { @@ -582,12 +576,7 @@ func (gce *GCECloud) DetachDisk(devicePath string, nodeName types.NodeName) erro } mc := newDiskMetricContextZonal("detach", gce.region, inst.Zone) - detachOp, err := gce.manager.DetachDiskOnCloudProvider(inst.Zone, inst.Name, devicePath) - if err != nil { - return mc.Observe(err) - } - - return gce.manager.WaitForZoneOp(detachOp, inst.Zone, mc) + return mc.Observe(gce.manager.DetachDiskOnCloudProvider(inst.Zone, inst.Name, devicePath)) } func (gce *GCECloud) DiskIsAttached(diskName string, nodeName types.NodeName) (bool, error) { @@ -675,17 +664,10 @@ func (gce *GCECloud) CreateDisk( mc := newDiskMetricContextZonal("create", gce.region, zone) - createOp, err := gce.manager.CreateDiskOnCloudProvider( + err = gce.manager.CreateDiskOnCloudProvider( name, sizeGb, tagsStr, diskType, zone) - if isGCEError(err, "alreadyExists") { - glog.Warningf("GCE PD %q already exists, reusing", name) - return nil - } else if err != nil { - return mc.Observe(err) - } - - err = gce.manager.WaitForZoneOp(createOp, zone, mc) + mc.Observe(err) if isGCEError(err, "alreadyExists") { glog.Warningf("GCE PD %q already exists, reusing", name) return nil @@ -723,17 +705,10 @@ func (gce *GCECloud) CreateRegionalDisk( mc := newDiskMetricContextRegional("create", gce.region) - createOp, err := gce.manager.CreateRegionalDiskOnCloudProvider( + err = gce.manager.CreateRegionalDiskOnCloudProvider( name, sizeGb, tagsStr, diskType, replicaZones) - if isGCEError(err, "alreadyExists") { - glog.Warningf("GCE PD %q already exists, reusing", name) - return nil - } else if err != nil { - return mc.Observe(err) - } - - err = gce.manager.WaitForRegionalOp(createOp, mc) + mc.Observe(err) if isGCEError(err, "alreadyExists") { glog.Warningf("GCE PD %q already exists, reusing", name) return nil @@ -786,31 +761,26 @@ func (gce *GCECloud) ResizeDisk(diskToResize string, oldSize resource.Quantity, switch zoneInfo := disk.ZoneInfo.(type) { case singleZone: mc = newDiskMetricContextZonal("resize", disk.Region, zoneInfo.zone) - resizeOp, err := gce.manager.ResizeDiskOnCloudProvider(disk, requestGB, zoneInfo.zone) + err := gce.manager.ResizeDiskOnCloudProvider(disk, requestGB, zoneInfo.zone) if err != nil { return oldSize, mc.Observe(err) + } else { + return newSizeQuant, mc.Observe(err) } - waitErr := gce.manager.WaitForZoneOp(resizeOp, zoneInfo.zone, mc) - if waitErr != nil { - return oldSize, waitErr - } - return newSizeQuant, nil case multiZone: - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - mc = newDiskMetricContextRegional("resize", disk.Region) - resizeOp, err := gce.manager.RegionalResizeDiskOnCloudProvider(disk, requestGB) - - if err != nil { - return oldSize, mc.Observe(err) - } - waitErr := gce.manager.WaitForRegionalOp(resizeOp, mc) - if waitErr != nil { - return oldSize, waitErr - } - return newSizeQuant, nil + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return oldSize, fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo) + } + + mc = newDiskMetricContextRegional("resize", disk.Region) + err := gce.manager.RegionalResizeDiskOnCloudProvider(disk, requestGB) + + if err != nil { + return oldSize, mc.Observe(err) + } else { + return newSizeQuant, mc.Observe(err) } - return oldSize, fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo) case nil: return oldSize, fmt.Errorf("PD has nil ZoneInfo: %v", disk) default: @@ -1026,21 +996,14 @@ func (gce *GCECloud) doDeleteDisk(diskToDelete string) error { switch zoneInfo := disk.ZoneInfo.(type) { case singleZone: mc = newDiskMetricContextZonal("delete", disk.Region, zoneInfo.zone) - deleteOp, err := gce.manager.DeleteDiskOnCloudProvider(zoneInfo.zone, disk.Name) - if err != nil { - return mc.Observe(err) - } - return gce.manager.WaitForZoneOp(deleteOp, zoneInfo.zone, mc) + return mc.Observe(gce.manager.DeleteDiskOnCloudProvider(zoneInfo.zone, disk.Name)) case multiZone: - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - mc = newDiskMetricContextRegional("delete", disk.Region) - deleteOp, err := gce.manager.DeleteRegionalDiskOnCloudProvider(disk.Name) - if err != nil { - return mc.Observe(err) - } - return gce.manager.WaitForRegionalOp(deleteOp, mc) + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo) } - return fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo) + + mc = newDiskMetricContextRegional("delete", disk.Region) + return mc.Observe(gce.manager.DeleteRegionalDiskOnCloudProvider(disk.Name)) case nil: return fmt.Errorf("PD has nil ZoneInfo: %v", disk) default: diff --git a/pkg/cloudprovider/providers/gce/gce_disks_test.go b/pkg/cloudprovider/providers/gce/gce_disks_test.go index bb8242fcf16..5cc6f5f582f 100644 --- a/pkg/cloudprovider/providers/gce/gce_disks_test.go +++ b/pkg/cloudprovider/providers/gce/gce_disks_test.go @@ -70,9 +70,6 @@ func TestCreateDisk_Basic(t *testing.T) { if !fakeManager.createDiskCalled { t.Error("Never called GCE disk create.") } - if !fakeManager.doesOpMatch { - t.Error("Ops used in WaitForZoneOp does not match what's returned by CreateDisk.") - } // Partial check of equality between disk description sent to GCE and parameters of method. diskToCreate := fakeManager.diskToCreateStable @@ -127,9 +124,6 @@ func TestCreateRegionalDisk_Basic(t *testing.T) { if !fakeManager.createDiskCalled { t.Error("Never called GCE disk create.") } - if !fakeManager.doesOpMatch { - t.Error("Ops used in WaitForZoneOp does not match what's returned by CreateDisk.") - } // Partial check of equality between disk description sent to GCE and parameters of method. diskToCreate := fakeManager.diskToCreateStable @@ -165,7 +159,7 @@ func TestCreateDisk_DiskAlreadyExists(t *testing.T) { // Inject disk AlreadyExists error. alreadyExistsError := googleapi.ErrorItem{Reason: "alreadyExists"} - fakeManager.waitForOpError = &googleapi.Error{ + fakeManager.opError = &googleapi.Error{ Errors: []googleapi.ErrorItem{alreadyExistsError}, } @@ -314,9 +308,6 @@ func TestDeleteDisk_Basic(t *testing.T) { if !fakeManager.deleteDiskCalled { t.Error("Never called GCE disk delete.") } - if !fakeManager.doesOpMatch { - t.Error("Ops used in WaitForZoneOp does not match what's returned by DeleteDisk.") - } } @@ -644,16 +635,12 @@ const ( type FakeServiceManager struct { // Common fields shared among tests - targetAPI targetClientAPI - gceProjectID string - gceRegion string - opAlpha *computealpha.Operation // Mocks an operation returned by GCE API calls - opBeta *computebeta.Operation // Mocks an operation returned by GCE API calls - opStable *compute.Operation // Mocks an operation returned by GCE API calls - doesOpMatch bool - zonalDisks map[string]string // zone: diskName - regionalDisks map[string]sets.String // diskName: zones - waitForOpError error // Error to be returned by WaitForZoneOp or WaitForRegionalOp + targetAPI targetClientAPI + gceProjectID string + gceRegion string + zonalDisks map[string]string // zone: diskName + regionalDisks map[string]sets.String // diskName: zones + opError error // Fields for TestCreateDisk createDiskCalled bool @@ -684,12 +671,11 @@ func (manager *FakeServiceManager) CreateDiskOnCloudProvider( sizeGb int64, tagsStr string, diskType string, - zone string) (gceObject, error) { + zone string) error { manager.createDiskCalled = true switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} diskTypeURI := gceComputeAPIEndpoint + "projects/" + fmt.Sprintf(diskTypeURITemplateSingleZone, manager.gceProjectID, zone, diskType) diskToCreateV1 := &compute.Disk{ Name: name, @@ -699,9 +685,8 @@ func (manager *FakeServiceManager) CreateDiskOnCloudProvider( } manager.diskToCreateStable = diskToCreateV1 manager.zonalDisks[zone] = diskToCreateV1.Name - return manager.opStable, nil + return nil case targetBeta: - manager.opBeta = &computebeta.Operation{} diskTypeURI := gceComputeAPIEndpoint + "projects/" + fmt.Sprintf(diskTypeURITemplateSingleZone, manager.gceProjectID, zone, diskType) diskToCreateBeta := &computebeta.Disk{ Name: name, @@ -711,9 +696,8 @@ func (manager *FakeServiceManager) CreateDiskOnCloudProvider( } manager.diskToCreateBeta = diskToCreateBeta manager.zonalDisks[zone] = diskToCreateBeta.Name - return manager.opBeta, nil + return nil case targetAlpha: - manager.opAlpha = &computealpha.Operation{} diskTypeURI := gceComputeAPIEndpointBeta + "projects/" + fmt.Sprintf(diskTypeURITemplateSingleZone, manager.gceProjectID, zone, diskType) diskToCreateAlpha := &computealpha.Disk{ Name: name, @@ -723,9 +707,9 @@ func (manager *FakeServiceManager) CreateDiskOnCloudProvider( } manager.diskToCreateAlpha = diskToCreateAlpha manager.zonalDisks[zone] = diskToCreateAlpha.Name - return manager.opAlpha, nil + return nil default: - return nil, fmt.Errorf("unexpected type: %T", t) + return fmt.Errorf("unexpected type: %T", t) } } @@ -738,13 +722,12 @@ func (manager *FakeServiceManager) CreateRegionalDiskOnCloudProvider( sizeGb int64, tagsStr string, diskType string, - zones sets.String) (gceObject, error) { + zones sets.String) error { manager.createDiskCalled = true diskTypeURI := gceComputeAPIEndpointBeta + "projects/" + fmt.Sprintf(diskTypeURITemplateRegional, manager.gceProjectID, manager.gceRegion, diskType) switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} diskToCreateV1 := &compute.Disk{ Name: name, SizeGb: sizeGb, @@ -753,13 +736,13 @@ func (manager *FakeServiceManager) CreateRegionalDiskOnCloudProvider( } manager.diskToCreateStable = diskToCreateV1 manager.regionalDisks[diskToCreateV1.Name] = zones - return manager.opStable, nil + return nil case targetBeta: - return nil, fmt.Errorf("RegionalDisk CreateDisk op not supported in beta.") + return fmt.Errorf("RegionalDisk CreateDisk op not supported in beta.") case targetAlpha: - return nil, fmt.Errorf("RegionalDisk CreateDisk op not supported in alpha.") + return fmt.Errorf("RegionalDisk CreateDisk op not supported in alpha.") default: - return nil, fmt.Errorf("unexpected type: %T", t) + return fmt.Errorf("unexpected type: %T", t) } } @@ -767,39 +750,33 @@ func (manager *FakeServiceManager) AttachDiskOnCloudProvider( disk *GCEDisk, readWrite string, instanceZone string, - instanceName string) (gceObject, error) { + instanceName string) error { switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} - return manager.opStable, nil + return nil case targetBeta: - manager.opBeta = &computebeta.Operation{} - return manager.opBeta, nil + return nil case targetAlpha: - manager.opAlpha = &computealpha.Operation{} - return manager.opAlpha, nil + return nil default: - return nil, fmt.Errorf("unexpected type: %T", t) + return fmt.Errorf("unexpected type: %T", t) } } func (manager *FakeServiceManager) DetachDiskOnCloudProvider( instanceZone string, instanceName string, - devicePath string) (gceObject, error) { + devicePath string) error { switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} - return manager.opStable, nil + return nil case targetBeta: - manager.opBeta = &computebeta.Operation{} - return manager.opBeta, nil + return nil case targetAlpha: - manager.opAlpha = &computealpha.Operation{} - return manager.opAlpha, nil + return nil default: - return nil, fmt.Errorf("unexpected type: %T", t) + return fmt.Errorf("unexpected type: %T", t) } } @@ -856,13 +833,13 @@ func (manager *FakeServiceManager) GetRegionalDiskFromCloudProvider( func (manager *FakeServiceManager) ResizeDiskOnCloudProvider( disk *GCEDisk, size int64, - zone string) (gceObject, error) { + zone string) error { panic("Not implmented") } func (manager *FakeServiceManager) RegionalResizeDiskOnCloudProvider( disk *GCEDisk, - size int64) (gceObject, error) { + size int64) error { panic("Not implemented") } @@ -871,91 +848,41 @@ func (manager *FakeServiceManager) RegionalResizeDiskOnCloudProvider( */ func (manager *FakeServiceManager) DeleteDiskOnCloudProvider( zone string, - disk string) (gceObject, error) { + disk string) error { manager.deleteDiskCalled = true delete(manager.zonalDisks, zone) switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} - return manager.opStable, nil + return nil case targetBeta: - manager.opBeta = &computebeta.Operation{} - return manager.opBeta, nil + return nil case targetAlpha: - manager.opAlpha = &computealpha.Operation{} - return manager.opAlpha, nil + return nil default: - return nil, fmt.Errorf("unexpected type: %T", t) + return fmt.Errorf("unexpected type: %T", t) } } func (manager *FakeServiceManager) DeleteRegionalDiskOnCloudProvider( - disk string) (gceObject, error) { + disk string) error { manager.deleteDiskCalled = true delete(manager.regionalDisks, disk) switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} - return manager.opStable, nil + return nil case targetBeta: - manager.opBeta = &computebeta.Operation{} - return manager.opBeta, nil + return nil case targetAlpha: - manager.opAlpha = &computealpha.Operation{} - return manager.opAlpha, nil + return nil default: - return nil, fmt.Errorf("unexpected type: %T", t) + return fmt.Errorf("unexpected type: %T", t) } } -func (manager *FakeServiceManager) WaitForZoneOp( - op gceObject, - zone string, - mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - if op.(*computealpha.Operation) == manager.opAlpha { - manager.doesOpMatch = true - } - case *computebeta.Operation: - if op.(*computebeta.Operation) == manager.opBeta { - manager.doesOpMatch = true - } - case *compute.Operation: - if op.(*compute.Operation) == manager.opStable { - manager.doesOpMatch = true - } - default: - return fmt.Errorf("unexpected type: %T", v) - } - return manager.waitForOpError -} - -func (manager *FakeServiceManager) WaitForRegionalOp( - op gceObject, mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - if op.(*computealpha.Operation) == manager.opAlpha { - manager.doesOpMatch = true - } - case *computebeta.Operation: - if op.(*computebeta.Operation) == manager.opBeta { - manager.doesOpMatch = true - } - case *compute.Operation: - if op.(*compute.Operation) == manager.opStable { - manager.doesOpMatch = true - } - default: - return fmt.Errorf("unexpected type: %T", v) - } - return manager.waitForOpError -} - func createNodeZones(zones []string) map[string]sets.String { nodeZones := map[string]sets.String{} for _, zone := range zones { diff --git a/pkg/cloudprovider/providers/gce/gce_firewall.go b/pkg/cloudprovider/providers/gce/gce_firewall.go index 88db0ebd3b9..e138df87471 100644 --- a/pkg/cloudprovider/providers/gce/gce_firewall.go +++ b/pkg/cloudprovider/providers/gce/gce_firewall.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - compute "google.golang.org/api/compute/v1" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) @@ -30,25 +29,37 @@ func newFirewallMetricContext(request string) *metricContext { // GetFirewall returns the Firewall by name. func (gce *GCECloud) GetFirewall(name string) (*compute.Firewall, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newFirewallMetricContext("get") - v, err := gce.c.Firewalls().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.Firewalls().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // CreateFirewall creates the passed firewall func (gce *GCECloud) CreateFirewall(f *compute.Firewall) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newFirewallMetricContext("create") - return mc.Observe(gce.c.Firewalls().Insert(context.Background(), meta.GlobalKey(f.Name), f)) + return mc.Observe(gce.c.Firewalls().Insert(ctx, meta.GlobalKey(f.Name), f)) } // DeleteFirewall deletes the given firewall rule. func (gce *GCECloud) DeleteFirewall(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newFirewallMetricContext("delete") - return mc.Observe(gce.c.Firewalls().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.Firewalls().Delete(ctx, meta.GlobalKey(name))) } // UpdateFirewall applies the given firewall as an update to an existing service. func (gce *GCECloud) UpdateFirewall(f *compute.Firewall) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newFirewallMetricContext("update") - return mc.Observe(gce.c.Firewalls().Update(context.Background(), meta.GlobalKey(f.Name), f)) + return mc.Observe(gce.c.Firewalls().Update(ctx, meta.GlobalKey(f.Name), f)) } diff --git a/pkg/cloudprovider/providers/gce/gce_forwardingrule.go b/pkg/cloudprovider/providers/gce/gce_forwardingrule.go index 9fe0da9f7cc..b40652c98e3 100644 --- a/pkg/cloudprovider/providers/gce/gce_forwardingrule.go +++ b/pkg/cloudprovider/providers/gce/gce_forwardingrule.go @@ -17,8 +17,6 @@ limitations under the License. package gce import ( - "context" - computealpha "google.golang.org/api/compute/v0.alpha" compute "google.golang.org/api/compute/v1" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" @@ -35,84 +33,120 @@ func newForwardingRuleMetricContextWithVersion(request, region, version string) // CreateGlobalForwardingRule creates the passed GlobalForwardingRule func (gce *GCECloud) CreateGlobalForwardingRule(rule *compute.ForwardingRule) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("create", "") - return mc.Observe(gce.c.GlobalForwardingRules().Insert(context.Background(), meta.GlobalKey(rule.Name), rule)) + return mc.Observe(gce.c.GlobalForwardingRules().Insert(ctx, meta.GlobalKey(rule.Name), rule)) } // SetProxyForGlobalForwardingRule links the given TargetHttp(s)Proxy with the given GlobalForwardingRule. // targetProxyLink is the SelfLink of a TargetHttp(s)Proxy. func (gce *GCECloud) SetProxyForGlobalForwardingRule(forwardingRuleName, targetProxyLink string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("set_proxy", "") target := &compute.TargetReference{Target: targetProxyLink} - return mc.Observe(gce.c.GlobalForwardingRules().SetTarget(context.Background(), meta.GlobalKey(forwardingRuleName), target)) + return mc.Observe(gce.c.GlobalForwardingRules().SetTarget(ctx, meta.GlobalKey(forwardingRuleName), target)) } // DeleteGlobalForwardingRule deletes the GlobalForwardingRule by name. func (gce *GCECloud) DeleteGlobalForwardingRule(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("delete", "") - return mc.Observe(gce.c.GlobalForwardingRules().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.GlobalForwardingRules().Delete(ctx, meta.GlobalKey(name))) } // GetGlobalForwardingRule returns the GlobalForwardingRule by name. func (gce *GCECloud) GetGlobalForwardingRule(name string) (*compute.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("get", "") - v, err := gce.c.GlobalForwardingRules().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.GlobalForwardingRules().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // ListGlobalForwardingRules lists all GlobalForwardingRules in the project. func (gce *GCECloud) ListGlobalForwardingRules() ([]*compute.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("list", "") - v, err := gce.c.GlobalForwardingRules().List(context.Background(), filter.None) + v, err := gce.c.GlobalForwardingRules().List(ctx, filter.None) return v, mc.Observe(err) } // GetRegionForwardingRule returns the RegionalForwardingRule by name & region. func (gce *GCECloud) GetRegionForwardingRule(name, region string) (*compute.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("get", region) - v, err := gce.c.ForwardingRules().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.ForwardingRules().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // GetAlphaRegionForwardingRule returns the Alpha forwarding rule by name & region. func (gce *GCECloud) GetAlphaRegionForwardingRule(name, region string) (*computealpha.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContextWithVersion("get", region, computeAlphaVersion) - v, err := gce.c.AlphaForwardingRules().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.AlphaForwardingRules().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // ListRegionForwardingRules lists all RegionalForwardingRules in the project & region. func (gce *GCECloud) ListRegionForwardingRules(region string) ([]*compute.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("list", region) - v, err := gce.c.ForwardingRules().List(context.Background(), region, filter.None) + v, err := gce.c.ForwardingRules().List(ctx, region, filter.None) return v, mc.Observe(err) } // ListAlphaRegionForwardingRules lists all RegionalForwardingRules in the project & region. func (gce *GCECloud) ListAlphaRegionForwardingRules(region string) ([]*computealpha.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContextWithVersion("list", region, computeAlphaVersion) - v, err := gce.c.AlphaForwardingRules().List(context.Background(), region, filter.None) + v, err := gce.c.AlphaForwardingRules().List(ctx, region, filter.None) return v, mc.Observe(err) } // CreateRegionForwardingRule creates and returns a // RegionalForwardingRule that points to the given BackendService func (gce *GCECloud) CreateRegionForwardingRule(rule *compute.ForwardingRule, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("create", region) - return mc.Observe(gce.c.ForwardingRules().Insert(context.Background(), meta.RegionalKey(rule.Name, region), rule)) + return mc.Observe(gce.c.ForwardingRules().Insert(ctx, meta.RegionalKey(rule.Name, region), rule)) } // CreateAlphaRegionForwardingRule creates and returns an Alpha // forwarding fule in the given region. func (gce *GCECloud) CreateAlphaRegionForwardingRule(rule *computealpha.ForwardingRule, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContextWithVersion("create", region, computeAlphaVersion) - return mc.Observe(gce.c.AlphaForwardingRules().Insert(context.Background(), meta.RegionalKey(rule.Name, region), rule)) + return mc.Observe(gce.c.AlphaForwardingRules().Insert(ctx, meta.RegionalKey(rule.Name, region), rule)) } // DeleteRegionForwardingRule deletes the RegionalForwardingRule by name & region. func (gce *GCECloud) DeleteRegionForwardingRule(name, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("delete", region) - return mc.Observe(gce.c.ForwardingRules().Delete(context.Background(), meta.RegionalKey(name, region))) + return mc.Observe(gce.c.ForwardingRules().Delete(ctx, meta.RegionalKey(name, region))) } // TODO(#51665): retire this function once Network Tiers becomes Beta in GCP. diff --git a/pkg/cloudprovider/providers/gce/gce_healthchecks.go b/pkg/cloudprovider/providers/gce/gce_healthchecks.go index e4c0829e108..937ba295079 100644 --- a/pkg/cloudprovider/providers/gce/gce_healthchecks.go +++ b/pkg/cloudprovider/providers/gce/gce_healthchecks.go @@ -17,14 +17,13 @@ limitations under the License. package gce import ( - "context" - "github.com/golang/glog" computealpha "google.golang.org/api/compute/v0.alpha" compute "google.golang.org/api/compute/v1" "k8s.io/api/core/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" "k8s.io/kubernetes/pkg/master/ports" @@ -58,33 +57,48 @@ func newHealthcheckMetricContextWithVersion(request, version string) *metricCont // GetHttpHealthCheck returns the given HttpHealthCheck by name. func (gce *GCECloud) GetHttpHealthCheck(name string) (*compute.HttpHealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("get_legacy") - v, err := gce.c.HttpHealthChecks().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.HttpHealthChecks().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // UpdateHttpHealthCheck applies the given HttpHealthCheck as an update. func (gce *GCECloud) UpdateHttpHealthCheck(hc *compute.HttpHealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("update_legacy") - return mc.Observe(gce.c.HttpHealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HttpHealthChecks().Update(ctx, meta.GlobalKey(hc.Name), hc)) } // DeleteHttpHealthCheck deletes the given HttpHealthCheck by name. func (gce *GCECloud) DeleteHttpHealthCheck(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("delete_legacy") - return mc.Observe(gce.c.HttpHealthChecks().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.HttpHealthChecks().Delete(ctx, meta.GlobalKey(name))) } // CreateHttpHealthCheck creates the given HttpHealthCheck. func (gce *GCECloud) CreateHttpHealthCheck(hc *compute.HttpHealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("create_legacy") - return mc.Observe(gce.c.HttpHealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HttpHealthChecks().Insert(ctx, meta.GlobalKey(hc.Name), hc)) } // ListHttpHealthChecks lists all HttpHealthChecks in the project. func (gce *GCECloud) ListHttpHealthChecks() ([]*compute.HttpHealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("list_legacy") - v, err := gce.c.HttpHealthChecks().List(context.Background(), filter.None) + v, err := gce.c.HttpHealthChecks().List(ctx, filter.None) return v, mc.Observe(err) } @@ -92,33 +106,48 @@ func (gce *GCECloud) ListHttpHealthChecks() ([]*compute.HttpHealthCheck, error) // GetHttpsHealthCheck returns the given HttpsHealthCheck by name. func (gce *GCECloud) GetHttpsHealthCheck(name string) (*compute.HttpsHealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("get_legacy") - v, err := gce.c.HttpsHealthChecks().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.HttpsHealthChecks().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // UpdateHttpsHealthCheck applies the given HttpsHealthCheck as an update. func (gce *GCECloud) UpdateHttpsHealthCheck(hc *compute.HttpsHealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("update_legacy") - return mc.Observe(gce.c.HttpsHealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HttpsHealthChecks().Update(ctx, meta.GlobalKey(hc.Name), hc)) } // DeleteHttpsHealthCheck deletes the given HttpsHealthCheck by name. func (gce *GCECloud) DeleteHttpsHealthCheck(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("delete_legacy") - return mc.Observe(gce.c.HttpsHealthChecks().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.HttpsHealthChecks().Delete(ctx, meta.GlobalKey(name))) } // CreateHttpsHealthCheck creates the given HttpsHealthCheck. func (gce *GCECloud) CreateHttpsHealthCheck(hc *compute.HttpsHealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("create_legacy") - return mc.Observe(gce.c.HttpsHealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HttpsHealthChecks().Insert(ctx, meta.GlobalKey(hc.Name), hc)) } // ListHttpsHealthChecks lists all HttpsHealthChecks in the project. func (gce *GCECloud) ListHttpsHealthChecks() ([]*compute.HttpsHealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("list_legacy") - v, err := gce.c.HttpsHealthChecks().List(context.Background(), filter.None) + v, err := gce.c.HttpsHealthChecks().List(ctx, filter.None) return v, mc.Observe(err) } @@ -126,52 +155,76 @@ func (gce *GCECloud) ListHttpsHealthChecks() ([]*compute.HttpsHealthCheck, error // GetHealthCheck returns the given HealthCheck by name. func (gce *GCECloud) GetHealthCheck(name string) (*compute.HealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("get") - v, err := gce.c.HealthChecks().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.HealthChecks().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // GetAlphaHealthCheck returns the given alpha HealthCheck by name. func (gce *GCECloud) GetAlphaHealthCheck(name string) (*computealpha.HealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContextWithVersion("get", computeAlphaVersion) - v, err := gce.c.AlphaHealthChecks().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.AlphaHealthChecks().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // UpdateHealthCheck applies the given HealthCheck as an update. func (gce *GCECloud) UpdateHealthCheck(hc *compute.HealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("update") - return mc.Observe(gce.c.HealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HealthChecks().Update(ctx, meta.GlobalKey(hc.Name), hc)) } // UpdateAlphaHealthCheck applies the given alpha HealthCheck as an update. func (gce *GCECloud) UpdateAlphaHealthCheck(hc *computealpha.HealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContextWithVersion("update", computeAlphaVersion) - return mc.Observe(gce.c.AlphaHealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.AlphaHealthChecks().Update(ctx, meta.GlobalKey(hc.Name), hc)) } // DeleteHealthCheck deletes the given HealthCheck by name. func (gce *GCECloud) DeleteHealthCheck(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("delete") - return mc.Observe(gce.c.HealthChecks().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.HealthChecks().Delete(ctx, meta.GlobalKey(name))) } // CreateHealthCheck creates the given HealthCheck. func (gce *GCECloud) CreateHealthCheck(hc *compute.HealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("create") - return mc.Observe(gce.c.HealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HealthChecks().Insert(ctx, meta.GlobalKey(hc.Name), hc)) } // CreateAlphaHealthCheck creates the given alpha HealthCheck. func (gce *GCECloud) CreateAlphaHealthCheck(hc *computealpha.HealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContextWithVersion("create", computeAlphaVersion) - return mc.Observe(gce.c.AlphaHealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.AlphaHealthChecks().Insert(ctx, meta.GlobalKey(hc.Name), hc)) } // ListHealthChecks lists all HealthCheck in the project. func (gce *GCECloud) ListHealthChecks() ([]*compute.HealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("list") - v, err := gce.c.HealthChecks().List(context.Background(), filter.None) + v, err := gce.c.HealthChecks().List(ctx, filter.None) return v, mc.Observe(err) } diff --git a/pkg/cloudprovider/providers/gce/gce_instancegroup.go b/pkg/cloudprovider/providers/gce/gce_instancegroup.go index 84b9724bfae..13b2c51e503 100644 --- a/pkg/cloudprovider/providers/gce/gce_instancegroup.go +++ b/pkg/cloudprovider/providers/gce/gce_instancegroup.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - 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" ) @@ -32,36 +31,51 @@ func newInstanceGroupMetricContext(request string, zone string) *metricContext { // CreateInstanceGroup creates an instance group with the given // instances. It is the callers responsibility to add named ports. func (gce *GCECloud) CreateInstanceGroup(ig *compute.InstanceGroup, zone string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("create", zone) - return mc.Observe(gce.c.InstanceGroups().Insert(context.Background(), meta.ZonalKey(ig.Name, zone), ig)) + return mc.Observe(gce.c.InstanceGroups().Insert(ctx, meta.ZonalKey(ig.Name, zone), ig)) } // DeleteInstanceGroup deletes an instance group. func (gce *GCECloud) DeleteInstanceGroup(name string, zone string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("delete", zone) - return mc.Observe(gce.c.InstanceGroups().Delete(context.Background(), meta.ZonalKey(name, zone))) + return mc.Observe(gce.c.InstanceGroups().Delete(ctx, meta.ZonalKey(name, zone))) } // ListInstanceGroups lists all InstanceGroups in the project and // zone. func (gce *GCECloud) ListInstanceGroups(zone string) ([]*compute.InstanceGroup, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("list", zone) - v, err := gce.c.InstanceGroups().List(context.Background(), zone, filter.None) + v, err := gce.c.InstanceGroups().List(ctx, zone, filter.None) return v, mc.Observe(err) } // ListInstancesInInstanceGroup lists all the instances in a given // instance group and state. func (gce *GCECloud) ListInstancesInInstanceGroup(name string, zone string, state string) ([]*compute.InstanceWithNamedPorts, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("list_instances", zone) req := &compute.InstanceGroupsListInstancesRequest{InstanceState: state} - v, err := gce.c.InstanceGroups().ListInstances(context.Background(), meta.ZonalKey(name, zone), req, filter.None) + v, err := gce.c.InstanceGroups().ListInstances(ctx, meta.ZonalKey(name, zone), req, filter.None) return v, mc.Observe(err) } // AddInstancesToInstanceGroup adds the given instances to the given // instance group. func (gce *GCECloud) AddInstancesToInstanceGroup(name string, zone string, instanceRefs []*compute.InstanceReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("add_instances", zone) // TODO: should cull operation above this layer. if len(instanceRefs) == 0 { @@ -70,12 +84,15 @@ func (gce *GCECloud) AddInstancesToInstanceGroup(name string, zone string, insta req := &compute.InstanceGroupsAddInstancesRequest{ Instances: instanceRefs, } - return mc.Observe(gce.c.InstanceGroups().AddInstances(context.Background(), meta.ZonalKey(name, zone), req)) + return mc.Observe(gce.c.InstanceGroups().AddInstances(ctx, meta.ZonalKey(name, zone), req)) } // RemoveInstancesFromInstanceGroup removes the given instances from // the instance group. func (gce *GCECloud) RemoveInstancesFromInstanceGroup(name string, zone string, instanceRefs []*compute.InstanceReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("remove_instances", zone) // TODO: should cull operation above this layer. if len(instanceRefs) == 0 { @@ -84,19 +101,25 @@ func (gce *GCECloud) RemoveInstancesFromInstanceGroup(name string, zone string, req := &compute.InstanceGroupsRemoveInstancesRequest{ Instances: instanceRefs, } - return mc.Observe(gce.c.InstanceGroups().RemoveInstances(context.Background(), meta.ZonalKey(name, zone), req)) + return mc.Observe(gce.c.InstanceGroups().RemoveInstances(ctx, meta.ZonalKey(name, zone), req)) } // SetNamedPortsOfInstanceGroup sets the list of named ports on a given instance group func (gce *GCECloud) SetNamedPortsOfInstanceGroup(igName, zone string, namedPorts []*compute.NamedPort) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("set_namedports", zone) req := &compute.InstanceGroupsSetNamedPortsRequest{NamedPorts: namedPorts} - return mc.Observe(gce.c.InstanceGroups().SetNamedPorts(context.Background(), meta.ZonalKey(igName, zone), req)) + return mc.Observe(gce.c.InstanceGroups().SetNamedPorts(ctx, meta.ZonalKey(igName, zone), req)) } // GetInstanceGroup returns an instance group by name. func (gce *GCECloud) GetInstanceGroup(name string, zone string) (*compute.InstanceGroup, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("get", zone) - v, err := gce.c.InstanceGroups().Get(context.Background(), meta.ZonalKey(name, zone)) + v, err := gce.c.InstanceGroups().Get(ctx, meta.ZonalKey(name, zone)) return v, mc.Observe(err) } diff --git a/pkg/cloudprovider/providers/gce/gce_instances.go b/pkg/cloudprovider/providers/gce/gce_instances.go index 69c487ecfc4..0d4dc631494 100644 --- a/pkg/cloudprovider/providers/gce/gce_instances.go +++ b/pkg/cloudprovider/providers/gce/gce_instances.go @@ -34,6 +34,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/cloudprovider" + "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" @@ -99,12 +100,15 @@ func (gce *GCECloud) NodeAddresses(_ context.Context, _ types.NodeName) ([]v1.No // NodeAddressesByProviderID will not be called from the node that is requesting this ID. // i.e. metadata service and other local methods cannot be used here func (gce *GCECloud) NodeAddressesByProviderID(ctx context.Context, providerID string) ([]v1.NodeAddress, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + _, zone, name, err := splitProviderID(providerID) if err != nil { return []v1.NodeAddress{}, err } - instance, err := gce.c.Instances().Get(context.Background(), meta.ZonalKey(canonicalizeInstanceName(name), zone)) + instance, err := gce.c.Instances().Get(ctx, meta.ZonalKey(canonicalizeInstanceName(name), zone)) if err != nil { return []v1.NodeAddress{}, fmt.Errorf("error while querying for providerID %q: %v", providerID, err) } @@ -212,8 +216,11 @@ func (gce *GCECloud) InstanceType(ctx context.Context, nodeName types.NodeName) } func (gce *GCECloud) AddSSHKeyToAllInstances(ctx context.Context, user string, keyData []byte) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return wait.Poll(2*time.Second, 30*time.Second, func() (bool, error) { - project, err := gce.c.Projects().Get(context.Background(), gce.projectID) + project, err := gce.c.Projects().Get(ctx, gce.projectID) if err != nil { glog.Errorf("Could not get project: %v", err) return false, nil @@ -244,7 +251,7 @@ func (gce *GCECloud) AddSSHKeyToAllInstances(ctx context.Context, user string, k } mc := newInstancesMetricContext("add_ssh_key", "") - err = gce.c.Projects().SetCommonInstanceMetadata(context.Background(), gce.projectID, project.CommonInstanceMetadata) + err = gce.c.Projects().SetCommonInstanceMetadata(ctx, gce.projectID, project.CommonInstanceMetadata) mc.Observe(err) if err != nil { @@ -284,9 +291,12 @@ func (gce *GCECloud) GetAllCurrentZones() (sets.String, error) { // // TODO: this should be removed from the cloud provider. func (gce *GCECloud) GetAllZonesFromCloudProvider() (sets.String, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + zones := sets.NewString() for _, zone := range gce.managedZones { - instances, err := gce.c.Instances().List(context.Background(), zone, filter.None) + instances, err := gce.c.Instances().List(ctx, zone, filter.None) if err != nil { return sets.NewString(), err } @@ -299,15 +309,21 @@ func (gce *GCECloud) GetAllZonesFromCloudProvider() (sets.String, error) { // InsertInstance creates a new instance on GCP func (gce *GCECloud) InsertInstance(project string, zone string, i *compute.Instance) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstancesMetricContext("create", zone) - return mc.Observe(gce.c.Instances().Insert(context.Background(), meta.ZonalKey(i.Name, zone), i)) + return mc.Observe(gce.c.Instances().Insert(ctx, meta.ZonalKey(i.Name, zone), i)) } // ListInstanceNames returns a string of instance names separated by spaces. // This method should only be used for e2e testing. // TODO: remove this method. func (gce *GCECloud) ListInstanceNames(project, zone string) (string, error) { - l, err := gce.c.Instances().List(context.Background(), zone, filter.None) + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + l, err := gce.c.Instances().List(ctx, zone, filter.None) if err != nil { return "", err } @@ -320,7 +336,10 @@ func (gce *GCECloud) ListInstanceNames(project, zone string) (string, error) { // DeleteInstance deletes an instance specified by project, zone, and name func (gce *GCECloud) DeleteInstance(project, zone, name string) error { - return gce.c.Instances().Delete(context.Background(), meta.ZonalKey(name, zone)) + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + return gce.c.Instances().Delete(ctx, meta.ZonalKey(name, zone)) } // Implementation of Instances.CurrentNodeName @@ -332,6 +351,9 @@ func (gce *GCECloud) CurrentNodeName(ctx context.Context, hostname string) (type // `node` for allocation to pods. Returns a list of the form // "/". func (gce *GCECloud) AliasRanges(nodeName types.NodeName) (cidrs []string, err error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + var instance *gceInstance instance, err = gce.getInstanceByName(mapNodeNameToInstanceName(nodeName)) if err != nil { @@ -339,7 +361,7 @@ func (gce *GCECloud) AliasRanges(nodeName types.NodeName) (cidrs []string, err e } var res *computebeta.Instance - res, err = gce.c.BetaInstances().Get(context.Background(), meta.ZonalKey(instance.Name, lastComponent(instance.Zone))) + res, err = gce.c.BetaInstances().Get(ctx, meta.ZonalKey(instance.Name, lastComponent(instance.Zone))) if err != nil { return } @@ -355,12 +377,14 @@ func (gce *GCECloud) AliasRanges(nodeName types.NodeName) (cidrs []string, err e // AddAliasToInstance adds an alias to the given instance from the named // secondary range. func (gce *GCECloud) AddAliasToInstance(nodeName types.NodeName, alias *net.IPNet) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() v1instance, err := gce.getInstanceByName(mapNodeNameToInstanceName(nodeName)) if err != nil { return err } - instance, err := gce.c.BetaInstances().Get(context.Background(), meta.ZonalKey(v1instance.Name, lastComponent(v1instance.Zone))) + instance, err := gce.c.BetaInstances().Get(ctx, meta.ZonalKey(v1instance.Name, lastComponent(v1instance.Zone))) if err != nil { return err } @@ -383,13 +407,16 @@ func (gce *GCECloud) AddAliasToInstance(nodeName types.NodeName, alias *net.IPNe }) mc := newInstancesMetricContext("add_alias", v1instance.Zone) - err = gce.c.BetaInstances().UpdateNetworkInterface(context.Background(), meta.ZonalKey(instance.Name, lastComponent(instance.Zone)), iface.Name, iface) + err = gce.c.BetaInstances().UpdateNetworkInterface(ctx, meta.ZonalKey(instance.Name, lastComponent(instance.Zone)), iface.Name, iface) return mc.Observe(err) } // Gets the named instances, returning cloudprovider.InstanceNotFound if any // instance is not found func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + found := map[string]*gceInstance{} remaining := len(names) @@ -407,7 +434,7 @@ func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error) if remaining == 0 { break } - instances, err := gce.c.Instances().List(context.Background(), zone, filter.Regexp("name", nodeInstancePrefix+".*")) + instances, err := gce.c.Instances().List(ctx, zone, filter.Regexp("name", nodeInstancePrefix+".*")) if err != nil { return nil, err } @@ -471,9 +498,12 @@ func (gce *GCECloud) getInstanceByName(name string) (*gceInstance, error) { } func (gce *GCECloud) getInstanceFromProjectInZoneByName(project, zone, name string) (*gceInstance, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + name = canonicalizeInstanceName(name) mc := newInstancesMetricContext("get", zone) - res, err := gce.c.Instances().Get(context.Background(), meta.ZonalKey(name, zone)) + res, err := gce.c.Instances().Get(ctx, meta.ZonalKey(name, zone)) mc.Observe(err) if err != nil { return nil, err @@ -532,6 +562,9 @@ func (gce *GCECloud) isCurrentInstance(instanceID string) bool { // format of the host names in the cluster. Only use it as a fallback if // gce.nodeTags is unspecified func (gce *GCECloud) computeHostTags(hosts []*gceInstance) ([]string, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + // TODO: We could store the tags in gceInstance, so we could have already fetched it hostNamesByZone := make(map[string]map[string]bool) // map of zones -> map of names -> bool (for easy lookup) nodeInstancePrefix := gce.nodeInstancePrefix @@ -556,7 +589,7 @@ func (gce *GCECloud) computeHostTags(hosts []*gceInstance) ([]string, error) { filt = filter.Regexp("name", nodeInstancePrefix+".*") } for zone, hostNames := range hostNamesByZone { - instances, err := gce.c.Instances().List(context.Background(), zone, filt) + instances, err := gce.c.Instances().List(ctx, zone, filt) if err != nil { return nil, err } diff --git a/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go b/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go index f0e3fb538d2..efa4dcf4be9 100644 --- a/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go +++ b/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go @@ -17,12 +17,12 @@ limitations under the License. package gce import ( - "context" "fmt" "strings" computealpha "google.golang.org/api/compute/v0.alpha" + "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" ) @@ -37,31 +37,40 @@ func newNetworkEndpointGroupMetricContext(request string, zone string) *metricCo } func (gce *GCECloud) GetNetworkEndpointGroup(name string, zone string) (*computealpha.NetworkEndpointGroup, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("get", zone) if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return nil, mc.Observe(err) } - v, err := gce.c.AlphaNetworkEndpointGroups().Get(context.Background(), meta.ZonalKey(name, zone)) + v, err := gce.c.AlphaNetworkEndpointGroups().Get(ctx, meta.ZonalKey(name, zone)) return v, mc.Observe(err) } func (gce *GCECloud) ListNetworkEndpointGroup(zone string) ([]*computealpha.NetworkEndpointGroup, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("list", zone) if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return nil, mc.Observe(err) } - negs, err := gce.c.AlphaNetworkEndpointGroups().List(context.Background(), zone, filter.None) + negs, err := gce.c.AlphaNetworkEndpointGroups().List(ctx, zone, filter.None) return negs, mc.Observe(err) } // AggregatedListNetworkEndpointGroup returns a map of zone -> endpoint group. func (gce *GCECloud) AggregatedListNetworkEndpointGroup() (map[string][]*computealpha.NetworkEndpointGroup, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("aggregated_list", "") if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return nil, mc.Observe(err) } // TODO: filter for the region the cluster is in. - all, err := gce.c.AlphaNetworkEndpointGroups().AggregatedList(context.Background(), filter.None) + all, err := gce.c.AlphaNetworkEndpointGroups().AggregatedList(ctx, filter.None) if err != nil { return nil, mc.Observe(err) } @@ -79,22 +88,31 @@ func (gce *GCECloud) AggregatedListNetworkEndpointGroup() (map[string][]*compute } func (gce *GCECloud) CreateNetworkEndpointGroup(neg *computealpha.NetworkEndpointGroup, zone string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return err } mc := newNetworkEndpointGroupMetricContext("create", zone) - return mc.Observe(gce.c.AlphaNetworkEndpointGroups().Insert(context.Background(), meta.ZonalKey(neg.Name, zone), neg)) + return mc.Observe(gce.c.AlphaNetworkEndpointGroups().Insert(ctx, meta.ZonalKey(neg.Name, zone), neg)) } func (gce *GCECloud) DeleteNetworkEndpointGroup(name string, zone string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return err } mc := newNetworkEndpointGroupMetricContext("delete", zone) - return mc.Observe(gce.c.AlphaNetworkEndpointGroups().Delete(context.Background(), meta.ZonalKey(name, zone))) + return mc.Observe(gce.c.AlphaNetworkEndpointGroups().Delete(ctx, meta.ZonalKey(name, zone))) } func (gce *GCECloud) AttachNetworkEndpoints(name, zone string, endpoints []*computealpha.NetworkEndpoint) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("attach", zone) if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return mc.Observe(err) @@ -102,10 +120,13 @@ func (gce *GCECloud) AttachNetworkEndpoints(name, zone string, endpoints []*comp req := &computealpha.NetworkEndpointGroupsAttachEndpointsRequest{ NetworkEndpoints: endpoints, } - return mc.Observe(gce.c.AlphaNetworkEndpointGroups().AttachNetworkEndpoints(context.Background(), meta.ZonalKey(name, zone), req)) + return mc.Observe(gce.c.AlphaNetworkEndpointGroups().AttachNetworkEndpoints(ctx, meta.ZonalKey(name, zone), req)) } func (gce *GCECloud) DetachNetworkEndpoints(name, zone string, endpoints []*computealpha.NetworkEndpoint) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("detach", zone) if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return mc.Observe(err) @@ -113,10 +134,13 @@ func (gce *GCECloud) DetachNetworkEndpoints(name, zone string, endpoints []*comp req := &computealpha.NetworkEndpointGroupsDetachEndpointsRequest{ NetworkEndpoints: endpoints, } - return mc.Observe(gce.c.AlphaNetworkEndpointGroups().DetachNetworkEndpoints(context.Background(), meta.ZonalKey(name, zone), req)) + return mc.Observe(gce.c.AlphaNetworkEndpointGroups().DetachNetworkEndpoints(ctx, meta.ZonalKey(name, zone), req)) } func (gce *GCECloud) ListNetworkEndpoints(name, zone string, showHealthStatus bool) ([]*computealpha.NetworkEndpointWithHealthStatus, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("list_networkendpoints", zone) if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return nil, mc.Observe(err) @@ -128,6 +152,6 @@ func (gce *GCECloud) ListNetworkEndpoints(name, zone string, showHealthStatus bo req := &computealpha.NetworkEndpointGroupsListEndpointsRequest{ HealthStatus: healthStatus, } - l, err := gce.c.AlphaNetworkEndpointGroups().ListNetworkEndpoints(context.Background(), meta.ZonalKey(name, zone), req, filter.None) + l, err := gce.c.AlphaNetworkEndpointGroups().ListNetworkEndpoints(ctx, meta.ZonalKey(name, zone), req, filter.None) return l, mc.Observe(err) } diff --git a/pkg/cloudprovider/providers/gce/gce_op.go b/pkg/cloudprovider/providers/gce/gce_op.go deleted file mode 100644 index 7c8c3a815ba..00000000000 --- a/pkg/cloudprovider/providers/gce/gce_op.go +++ /dev/null @@ -1,180 +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 gce - -import ( - "encoding/json" - "fmt" - "time" - - "k8s.io/apimachinery/pkg/util/wait" - - "github.com/golang/glog" - computealpha "google.golang.org/api/compute/v0.alpha" - computebeta "google.golang.org/api/compute/v0.beta" - computev1 "google.golang.org/api/compute/v1" - "google.golang.org/api/googleapi" -) - -func (gce *GCECloud) waitForOp(op *computev1.Operation, getOperation func(operationName string) (*computev1.Operation, error), mc *metricContext) error { - if op == nil { - return mc.Observe(fmt.Errorf("operation must not be nil")) - } - - if opIsDone(op) { - return getErrorFromOp(op) - } - - opStart := time.Now() - opName := op.Name - - return wait.Poll(operationPollInterval, operationPollTimeoutDuration, func() (bool, error) { - start := time.Now() - gce.operationPollRateLimiter.Accept() - duration := time.Since(start) - if duration > 5*time.Second { - glog.V(2).Infof("pollOperation: throttled %v for %v", duration, opName) - } - pollOp, err := getOperation(opName) - if err != nil { - glog.Warningf("GCE poll operation %s failed: pollOp: [%v] err: [%v] getErrorFromOp: [%v]", - opName, pollOp, err, getErrorFromOp(pollOp)) - } - - done := opIsDone(pollOp) - if done { - duration := time.Since(opStart) - if duration > 1*time.Minute { - // Log the JSON. It's cleaner than the %v structure. - enc, err := pollOp.MarshalJSON() - if err != nil { - glog.Warningf("waitForOperation: long operation (%v): %v (failed to encode to JSON: %v)", - duration, pollOp, err) - } else { - glog.V(2).Infof("waitForOperation: long operation (%v): %v", - duration, string(enc)) - } - } - } - - return done, mc.Observe(getErrorFromOp(pollOp)) - }) -} - -func opIsDone(op *computev1.Operation) bool { - return op != nil && op.Status == "DONE" -} - -func getErrorFromOp(op *computev1.Operation) error { - if op != nil && op.Error != nil && len(op.Error.Errors) > 0 { - err := &googleapi.Error{ - Code: int(op.HttpErrorStatusCode), - Message: op.Error.Errors[0].Message, - } - glog.Errorf("GCE operation failed: %v", err) - return err - } - - return nil -} - -func (gce *GCECloud) waitForGlobalOp(op gceObject, mc *metricContext) error { - return gce.waitForGlobalOpInProject(op, gce.ProjectID(), mc) -} - -func (gce *GCECloud) waitForRegionOp(op gceObject, region string, mc *metricContext) error { - return gce.waitForRegionOpInProject(op, gce.ProjectID(), region, mc) -} - -func (gce *GCECloud) waitForZoneOp(op gceObject, zone string, mc *metricContext) error { - return gce.waitForZoneOpInProject(op, gce.ProjectID(), zone, mc) -} - -func (gce *GCECloud) waitForGlobalOpInProject(op gceObject, projectID string, mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceAlpha.GlobalOperations.Get(projectID, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computebeta.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceBeta.GlobalOperations.Get(projectID, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computev1.Operation: - return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) { - return gce.service.GlobalOperations.Get(projectID, operationName).Do() - }, mc) - default: - return fmt.Errorf("unexpected type: %T", v) - } -} - -func (gce *GCECloud) waitForRegionOpInProject(op gceObject, projectID, region string, mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceAlpha.RegionOperations.Get(projectID, region, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computebeta.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceBeta.RegionOperations.Get(projectID, region, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computev1.Operation: - return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) { - return gce.service.RegionOperations.Get(projectID, region, operationName).Do() - }, mc) - default: - return fmt.Errorf("unexpected type: %T", v) - } -} - -func (gce *GCECloud) waitForZoneOpInProject(op gceObject, projectID, zone string, mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceAlpha.ZoneOperations.Get(projectID, zone, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computebeta.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceBeta.ZoneOperations.Get(projectID, zone, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computev1.Operation: - return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) { - return gce.service.ZoneOperations.Get(projectID, zone, operationName).Do() - }, mc) - default: - return fmt.Errorf("unexpected type: %T", v) - } -} - -func convertToV1Operation(object gceObject) *computev1.Operation { - enc, err := object.MarshalJSON() - if err != nil { - panic(fmt.Sprintf("Failed to encode to json: %v", err)) - } - var op computev1.Operation - if err := json.Unmarshal(enc, &op); err != nil { - panic(fmt.Sprintf("Failed to convert GCE apiObject %v to v1 operation: %v", object, err)) - } - return &op -} diff --git a/pkg/cloudprovider/providers/gce/gce_routes.go b/pkg/cloudprovider/providers/gce/gce_routes.go index 4a7cea5b382..624b581cbd9 100644 --- a/pkg/cloudprovider/providers/gce/gce_routes.go +++ b/pkg/cloudprovider/providers/gce/gce_routes.go @@ -27,6 +27,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/cloudprovider" + "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" ) @@ -37,10 +38,13 @@ func newRoutesMetricContext(request string) *metricContext { // ListRoutes in the cloud environment. func (gce *GCECloud) ListRoutes(ctx context.Context, clusterName string) ([]*cloudprovider.Route, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newRoutesMetricContext("list") prefix := truncateClusterName(clusterName) f := filter.Regexp("name", prefix+"-.*").AndRegexp("network", gce.NetworkURL()).AndRegexp("description", k8sNodeRouteTag) - routes, err := gce.c.Routes().List(context.Background(), f) + routes, err := gce.c.Routes().List(ctx, f) if err != nil { return nil, mc.Observe(err) } @@ -60,6 +64,9 @@ func (gce *GCECloud) ListRoutes(ctx context.Context, clusterName string) ([]*clo // CreateRoute in the cloud environment. func (gce *GCECloud) CreateRoute(ctx context.Context, clusterName string, nameHint string, route *cloudprovider.Route) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newRoutesMetricContext("create") targetInstance, err := gce.getInstanceByName(mapNodeNameToInstanceName(route.TargetNode)) @@ -74,7 +81,7 @@ func (gce *GCECloud) CreateRoute(ctx context.Context, clusterName string, nameHi Priority: 1000, Description: k8sNodeRouteTag, } - err = gce.c.Routes().Insert(context.Background(), meta.GlobalKey(cr.Name), cr) + err = gce.c.Routes().Insert(ctx, meta.GlobalKey(cr.Name), cr) if isHTTPErrorCode(err, http.StatusConflict) { glog.Infof("Route %q already exists.", cr.Name) err = nil @@ -84,8 +91,11 @@ func (gce *GCECloud) CreateRoute(ctx context.Context, clusterName string, nameHi // DeleteRoute from the cloud environment. func (gce *GCECloud) DeleteRoute(ctx context.Context, clusterName string, route *cloudprovider.Route) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newRoutesMetricContext("delete") - return mc.Observe(gce.c.Routes().Delete(context.Background(), meta.GlobalKey(route.Name))) + return mc.Observe(gce.c.Routes().Delete(ctx, meta.GlobalKey(route.Name))) } func truncateClusterName(clusterName string) string { diff --git a/pkg/cloudprovider/providers/gce/gce_securitypolicy.go b/pkg/cloudprovider/providers/gce/gce_securitypolicy.go index bec23a644f6..293946590b3 100644 --- a/pkg/cloudprovider/providers/gce/gce_securitypolicy.go +++ b/pkg/cloudprovider/providers/gce/gce_securitypolicy.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - 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" ) @@ -31,60 +30,87 @@ func newSecurityPolicyMetricContextWithVersion(request, version string) *metricC // GetBetaSecurityPolicy retrieves a security policy. func (gce *GCECloud) GetBetaSecurityPolicy(name string) (*computebeta.SecurityPolicy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newSecurityPolicyMetricContextWithVersion("get", computeBetaVersion) - v, err := gce.c.BetaSecurityPolicies().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.BetaSecurityPolicies().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // ListBetaSecurityPolicy lists all security policies in the project. func (gce *GCECloud) ListBetaSecurityPolicy() ([]*computebeta.SecurityPolicy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newSecurityPolicyMetricContextWithVersion("list", computeBetaVersion) - v, err := gce.c.BetaSecurityPolicies().List(context.Background(), filter.None) + v, err := gce.c.BetaSecurityPolicies().List(ctx, filter.None) return v, mc.Observe(err) } // CreateBetaSecurityPolicy creates the given security policy. func (gce *GCECloud) CreateBetaSecurityPolicy(sp *computebeta.SecurityPolicy) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newSecurityPolicyMetricContextWithVersion("create", computeBetaVersion) - return mc.Observe(gce.c.BetaSecurityPolicies().Insert(context.Background(), meta.GlobalKey(sp.Name), sp)) + return mc.Observe(gce.c.BetaSecurityPolicies().Insert(ctx, meta.GlobalKey(sp.Name), sp)) } // DeleteBetaSecurityPolicy deletes the given security policy. func (gce *GCECloud) DeleteBetaSecurityPolicy(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newSecurityPolicyMetricContextWithVersion("delete", computeBetaVersion) - return mc.Observe(gce.c.BetaSecurityPolicies().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.BetaSecurityPolicies().Delete(ctx, meta.GlobalKey(name))) } // PatchBetaSecurityPolicy applies the given security policy as a // patch to an existing security policy. func (gce *GCECloud) PatchBetaSecurityPolicy(sp *computebeta.SecurityPolicy) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newSecurityPolicyMetricContextWithVersion("patch", computeBetaVersion) - return mc.Observe(gce.c.BetaSecurityPolicies().Patch(context.Background(), meta.GlobalKey(sp.Name), sp)) + return mc.Observe(gce.c.BetaSecurityPolicies().Patch(ctx, meta.GlobalKey(sp.Name), sp)) } // GetRuleForBetaSecurityPolicy gets rule from a security policy. func (gce *GCECloud) GetRuleForBetaSecurityPolicy(name string) (*computebeta.SecurityPolicyRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newSecurityPolicyMetricContextWithVersion("get_rule", computeBetaVersion) - v, err := gce.c.BetaSecurityPolicies().GetRule(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.BetaSecurityPolicies().GetRule(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // AddRuletoBetaSecurityPolicy adds the given security policy rule to // a security policy. func (gce *GCECloud) AddRuletoBetaSecurityPolicy(name string, spr *computebeta.SecurityPolicyRule) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newSecurityPolicyMetricContextWithVersion("add_rule", computeBetaVersion) - return mc.Observe(gce.c.BetaSecurityPolicies().AddRule(context.Background(), meta.GlobalKey(name), spr)) + return mc.Observe(gce.c.BetaSecurityPolicies().AddRule(ctx, meta.GlobalKey(name), spr)) } // PatchRuleForBetaSecurityPolicy patches the given security policy // rule to a security policy. func (gce *GCECloud) PatchRuleForBetaSecurityPolicy(name string, spr *computebeta.SecurityPolicyRule) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newSecurityPolicyMetricContextWithVersion("patch_rule", computeBetaVersion) - return mc.Observe(gce.c.BetaSecurityPolicies().PatchRule(context.Background(), meta.GlobalKey(name), spr)) + return mc.Observe(gce.c.BetaSecurityPolicies().PatchRule(ctx, meta.GlobalKey(name), spr)) } // RemoveRuleFromBetaSecurityPolicy removes rule from a security policy. func (gce *GCECloud) RemoveRuleFromBetaSecurityPolicy(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newSecurityPolicyMetricContextWithVersion("remove_rule", computeBetaVersion) - return mc.Observe(gce.c.BetaSecurityPolicies().RemoveRule(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.BetaSecurityPolicies().RemoveRule(ctx, meta.GlobalKey(name))) } diff --git a/pkg/cloudprovider/providers/gce/gce_targetpool.go b/pkg/cloudprovider/providers/gce/gce_targetpool.go index 8fd3b3704e5..8c1127e749e 100644 --- a/pkg/cloudprovider/providers/gce/gce_targetpool.go +++ b/pkg/cloudprovider/providers/gce/gce_targetpool.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - compute "google.golang.org/api/compute/v1" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) @@ -30,37 +29,52 @@ func newTargetPoolMetricContext(request, region string) *metricContext { // GetTargetPool returns the TargetPool by name. func (gce *GCECloud) GetTargetPool(name, region string) (*compute.TargetPool, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetPoolMetricContext("get", region) - v, err := gce.c.TargetPools().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.TargetPools().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // CreateTargetPool creates the passed TargetPool func (gce *GCECloud) CreateTargetPool(tp *compute.TargetPool, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetPoolMetricContext("create", region) - return mc.Observe(gce.c.TargetPools().Insert(context.Background(), meta.RegionalKey(tp.Name, region), tp)) + return mc.Observe(gce.c.TargetPools().Insert(ctx, meta.RegionalKey(tp.Name, region), tp)) } // DeleteTargetPool deletes TargetPool by name. func (gce *GCECloud) DeleteTargetPool(name, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetPoolMetricContext("delete", region) - return mc.Observe(gce.c.TargetPools().Delete(context.Background(), meta.RegionalKey(name, region))) + return mc.Observe(gce.c.TargetPools().Delete(ctx, meta.RegionalKey(name, region))) } // AddInstancesToTargetPool adds instances by link to the TargetPool func (gce *GCECloud) AddInstancesToTargetPool(name, region string, instanceRefs []*compute.InstanceReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + req := &compute.TargetPoolsAddInstanceRequest{ Instances: instanceRefs, } mc := newTargetPoolMetricContext("add_instances", region) - return mc.Observe(gce.c.TargetPools().AddInstance(context.Background(), meta.RegionalKey(name, region), req)) + return mc.Observe(gce.c.TargetPools().AddInstance(ctx, meta.RegionalKey(name, region), req)) } // RemoveInstancesFromTargetPool removes instances by link to the TargetPool func (gce *GCECloud) RemoveInstancesFromTargetPool(name, region string, instanceRefs []*compute.InstanceReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + req := &compute.TargetPoolsRemoveInstanceRequest{ Instances: instanceRefs, } mc := newTargetPoolMetricContext("remove_instances", region) - return mc.Observe(gce.c.TargetPools().RemoveInstance(context.Background(), meta.RegionalKey(name, region), req)) + return mc.Observe(gce.c.TargetPools().RemoveInstance(ctx, meta.RegionalKey(name, region), req)) } diff --git a/pkg/cloudprovider/providers/gce/gce_targetproxy.go b/pkg/cloudprovider/providers/gce/gce_targetproxy.go index 36d21bcff6b..f266d13e611 100644 --- a/pkg/cloudprovider/providers/gce/gce_targetproxy.go +++ b/pkg/cloudprovider/providers/gce/gce_targetproxy.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - 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" ) @@ -31,34 +30,49 @@ func newTargetProxyMetricContext(request string) *metricContext { // GetTargetHttpProxy returns the UrlMap by name. func (gce *GCECloud) GetTargetHttpProxy(name string) (*compute.TargetHttpProxy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("get") - v, err := gce.c.TargetHttpProxies().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.TargetHttpProxies().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // CreateTargetHttpProxy creates a TargetHttpProxy func (gce *GCECloud) CreateTargetHttpProxy(proxy *compute.TargetHttpProxy) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("create") - return mc.Observe(gce.c.TargetHttpProxies().Insert(context.Background(), meta.GlobalKey(proxy.Name), proxy)) + return mc.Observe(gce.c.TargetHttpProxies().Insert(ctx, meta.GlobalKey(proxy.Name), proxy)) } // SetUrlMapForTargetHttpProxy sets the given UrlMap for the given TargetHttpProxy. func (gce *GCECloud) SetUrlMapForTargetHttpProxy(proxy *compute.TargetHttpProxy, urlMap *compute.UrlMap) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + ref := &compute.UrlMapReference{UrlMap: urlMap.SelfLink} mc := newTargetProxyMetricContext("set_url_map") - return mc.Observe(gce.c.TargetHttpProxies().SetUrlMap(context.Background(), meta.GlobalKey(proxy.Name), ref)) + return mc.Observe(gce.c.TargetHttpProxies().SetUrlMap(ctx, meta.GlobalKey(proxy.Name), ref)) } // DeleteTargetHttpProxy deletes the TargetHttpProxy by name. func (gce *GCECloud) DeleteTargetHttpProxy(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("delete") - return mc.Observe(gce.c.TargetHttpProxies().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.TargetHttpProxies().Delete(ctx, meta.GlobalKey(name))) } // ListTargetHttpProxies lists all TargetHttpProxies in the project. func (gce *GCECloud) ListTargetHttpProxies() ([]*compute.TargetHttpProxy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("list") - v, err := gce.c.TargetHttpProxies().List(context.Background(), filter.None) + v, err := gce.c.TargetHttpProxies().List(ctx, filter.None) return v, mc.Observe(err) } @@ -66,42 +80,60 @@ func (gce *GCECloud) ListTargetHttpProxies() ([]*compute.TargetHttpProxy, error) // GetTargetHttpsProxy returns the UrlMap by name. func (gce *GCECloud) GetTargetHttpsProxy(name string) (*compute.TargetHttpsProxy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("get") - v, err := gce.c.TargetHttpsProxies().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.TargetHttpsProxies().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // CreateTargetHttpsProxy creates a TargetHttpsProxy func (gce *GCECloud) CreateTargetHttpsProxy(proxy *compute.TargetHttpsProxy) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("create") - return mc.Observe(gce.c.TargetHttpsProxies().Insert(context.Background(), meta.GlobalKey(proxy.Name), proxy)) + return mc.Observe(gce.c.TargetHttpsProxies().Insert(ctx, meta.GlobalKey(proxy.Name), proxy)) } // SetUrlMapForTargetHttpsProxy sets the given UrlMap for the given TargetHttpsProxy. func (gce *GCECloud) SetUrlMapForTargetHttpsProxy(proxy *compute.TargetHttpsProxy, urlMap *compute.UrlMap) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("set_url_map") ref := &compute.UrlMapReference{UrlMap: urlMap.SelfLink} - return mc.Observe(gce.c.TargetHttpsProxies().SetUrlMap(context.Background(), meta.GlobalKey(proxy.Name), ref)) + return mc.Observe(gce.c.TargetHttpsProxies().SetUrlMap(ctx, meta.GlobalKey(proxy.Name), ref)) } // SetSslCertificateForTargetHttpsProxy sets the given SslCertificate for the given TargetHttpsProxy. func (gce *GCECloud) SetSslCertificateForTargetHttpsProxy(proxy *compute.TargetHttpsProxy, sslCertURLs []string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("set_ssl_cert") req := &compute.TargetHttpsProxiesSetSslCertificatesRequest{ SslCertificates: sslCertURLs, } - return mc.Observe(gce.c.TargetHttpsProxies().SetSslCertificates(context.Background(), meta.GlobalKey(proxy.Name), req)) + return mc.Observe(gce.c.TargetHttpsProxies().SetSslCertificates(ctx, meta.GlobalKey(proxy.Name), req)) } // DeleteTargetHttpsProxy deletes the TargetHttpsProxy by name. func (gce *GCECloud) DeleteTargetHttpsProxy(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("delete") - return mc.Observe(gce.c.TargetHttpsProxies().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.TargetHttpsProxies().Delete(ctx, meta.GlobalKey(name))) } // ListTargetHttpsProxies lists all TargetHttpsProxies in the project. func (gce *GCECloud) ListTargetHttpsProxies() ([]*compute.TargetHttpsProxy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("list") - v, err := gce.c.TargetHttpsProxies().List(context.Background(), filter.None) + v, err := gce.c.TargetHttpsProxies().List(ctx, filter.None) return v, mc.Observe(err) } diff --git a/pkg/cloudprovider/providers/gce/gce_test.go b/pkg/cloudprovider/providers/gce/gce_test.go index cb88f3a486a..9747dfea5e5 100644 --- a/pkg/cloudprovider/providers/gce/gce_test.go +++ b/pkg/cloudprovider/providers/gce/gce_test.go @@ -18,16 +18,12 @@ package gce import ( "context" - "encoding/json" "reflect" "strings" "testing" "golang.org/x/oauth2/google" - computealpha "google.golang.org/api/compute/v0.alpha" - computebeta "google.golang.org/api/compute/v0.beta" - computev1 "google.golang.org/api/compute/v1" "k8s.io/kubernetes/pkg/cloudprovider" ) @@ -480,56 +476,6 @@ func TestGenerateCloudConfigs(t *testing.T) { } } -func TestConvertToV1Operation(t *testing.T) { - v1Op := getTestOperation() - enc, _ := v1Op.MarshalJSON() - var op interface{} - var alphaOp computealpha.Operation - var betaOp computebeta.Operation - - if err := json.Unmarshal(enc, &alphaOp); err != nil { - t.Errorf("Failed to unmarshal operation: %v", err) - } - - if err := json.Unmarshal(enc, &betaOp); err != nil { - t.Errorf("Failed to unmarshal operation: %v", err) - } - - op = convertToV1Operation(&alphaOp) - if _, ok := op.(*computev1.Operation); ok { - if !reflect.DeepEqual(op, v1Op) { - t.Errorf("Failed to maintain consistency across conversion") - } - } else { - t.Errorf("Expect output to be type v1 operation, but got %v", op) - } - - op = convertToV1Operation(&betaOp) - if _, ok := op.(*computev1.Operation); ok { - if !reflect.DeepEqual(op, v1Op) { - t.Errorf("Failed to maintain consistency across conversion") - } - } else { - t.Errorf("Expect output to be type v1 operation, but got %v", op) - } -} - -func getTestOperation() *computev1.Operation { - return &computev1.Operation{ - Name: "test", - Description: "test", - Id: uint64(12345), - Error: &computev1.OperationError{ - Errors: []*computev1.OperationErrorErrors{ - { - Code: "555", - Message: "error", - }, - }, - }, - } -} - func TestNewAlphaFeatureGate(t *testing.T) { testCases := []struct { alphaFeatures []string diff --git a/pkg/cloudprovider/providers/gce/gce_tpu.go b/pkg/cloudprovider/providers/gce/gce_tpu.go index fe71e57abdc..0026bdd8ecb 100644 --- a/pkg/cloudprovider/providers/gce/gce_tpu.go +++ b/pkg/cloudprovider/providers/gce/gce_tpu.go @@ -25,7 +25,7 @@ import ( "github.com/golang/glog" "google.golang.org/api/googleapi" - tpuapi "google.golang.org/api/tpu/v1alpha1" + tpuapi "google.golang.org/api/tpu/v1" "k8s.io/apimachinery/pkg/util/wait" ) @@ -165,7 +165,7 @@ func (gce *GCECloud) waitForTPUOp(interval, timeout time.Duration, op *tpuapi.Op // newTPUMetricContext returns a new metricContext used for recording metrics // of Cloud TPU API calls. func newTPUMetricContext(request, zone string) *metricContext { - return newGenericMetricContext("tpus", request, unusedMetricLabel, zone, "alpha") + return newGenericMetricContext("tpus", request, unusedMetricLabel, zone, "v1") } // getErrorFromTPUOp returns the error in the failed op, or nil if the op diff --git a/pkg/cloudprovider/providers/gce/gce_urlmap.go b/pkg/cloudprovider/providers/gce/gce_urlmap.go index 54ceccbf54d..b0e60093c15 100644 --- a/pkg/cloudprovider/providers/gce/gce_urlmap.go +++ b/pkg/cloudprovider/providers/gce/gce_urlmap.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - 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" ) @@ -31,32 +30,47 @@ func newUrlMapMetricContext(request string) *metricContext { // GetUrlMap returns the UrlMap by name. func (gce *GCECloud) GetUrlMap(name string) (*compute.UrlMap, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newUrlMapMetricContext("get") - v, err := gce.c.UrlMaps().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.UrlMaps().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // CreateUrlMap creates a url map func (gce *GCECloud) CreateUrlMap(urlMap *compute.UrlMap) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newUrlMapMetricContext("create") - return mc.Observe(gce.c.UrlMaps().Insert(context.Background(), meta.GlobalKey(urlMap.Name), urlMap)) + return mc.Observe(gce.c.UrlMaps().Insert(ctx, meta.GlobalKey(urlMap.Name), urlMap)) } // UpdateUrlMap applies the given UrlMap as an update func (gce *GCECloud) UpdateUrlMap(urlMap *compute.UrlMap) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newUrlMapMetricContext("update") - return mc.Observe(gce.c.UrlMaps().Update(context.Background(), meta.GlobalKey(urlMap.Name), urlMap)) + return mc.Observe(gce.c.UrlMaps().Update(ctx, meta.GlobalKey(urlMap.Name), urlMap)) } // DeleteUrlMap deletes a url map by name. func (gce *GCECloud) DeleteUrlMap(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newUrlMapMetricContext("delete") - return mc.Observe(gce.c.UrlMaps().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.UrlMaps().Delete(ctx, meta.GlobalKey(name))) } // ListUrlMaps lists all UrlMaps in the project. func (gce *GCECloud) ListUrlMaps() ([]*compute.UrlMap, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newUrlMapMetricContext("list") - v, err := gce.c.UrlMaps().List(context.Background(), filter.None) + v, err := gce.c.UrlMaps().List(ctx, filter.None) return v, mc.Observe(err) } diff --git a/pkg/cloudprovider/providers/gce/gce_zones.go b/pkg/cloudprovider/providers/gce/gce_zones.go index 6c745e34c2c..503ca348f48 100644 --- a/pkg/cloudprovider/providers/gce/gce_zones.go +++ b/pkg/cloudprovider/providers/gce/gce_zones.go @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" ) @@ -72,8 +73,11 @@ func (gce *GCECloud) GetZoneByNodeName(ctx context.Context, nodeName types.NodeN // ListZonesInRegion returns all zones in a GCP region func (gce *GCECloud) ListZonesInRegion(region string) ([]*compute.Zone, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newZonesMetricContext("list", region) - list, err := gce.c.Zones().List(context.Background(), filter.Regexp("region", gce.getRegionLink(region))) + list, err := gce.c.Zones().List(ctx, filter.Regexp("region", gce.getRegionLink(region))) if err != nil { return nil, mc.Observe(err) } diff --git a/pkg/cloudprovider/providers/gce/support.go b/pkg/cloudprovider/providers/gce/support.go index 37dc75b0b0a..7861e08acbc 100644 --- a/pkg/cloudprovider/providers/gce/support.go +++ b/pkg/cloudprovider/providers/gce/support.go @@ -50,17 +50,15 @@ type gceRateLimiter struct { // operations. func (l *gceRateLimiter) Accept(ctx context.Context, key *cloud.RateLimitKey) error { if key.Operation == "Get" && key.Service == "Operations" { - ch := make(chan struct{}) - go func() { - l.gce.operationPollRateLimiter.Accept() - close(ch) - }() - select { - case <-ch: - break - case <-ctx.Done(): - return ctx.Err() + // Wait a minimum amount of time regardless of rate limiter. + rl := &cloud.MinimumRateLimiter{ + // Convert flowcontrol.RateLimiter into cloud.RateLimiter + RateLimiter: &cloud.AcceptRateLimiter{ + Acceptor: l.gce.operationPollRateLimiter, + }, + Minimum: operationPollInterval, } + return rl.Accept(ctx, key) } return nil } diff --git a/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go b/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go index e38d2d157bd..72bccb7e35a 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go +++ b/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go @@ -487,21 +487,27 @@ func (lbaas *LbaasV2) GetLoadBalancer(ctx context.Context, clusterName string, s // The LB needs to be configured with instance addresses on the same // subnet as the LB (aka opts.SubnetID). Currently we're just -// guessing that the node's InternalIP is the right address - and that -// should be sufficient for all "normal" cases. +// guessing that the node's InternalIP is the right address. +// In case no InternalIP can be found, ExternalIP is tried. +// If neither InternalIP nor ExternalIP can be found an error is +// returned. func nodeAddressForLB(node *v1.Node) (string, error) { addrs := node.Status.Addresses if len(addrs) == 0 { return "", ErrNoAddressFound } - for _, addr := range addrs { - if addr.Type == v1.NodeInternalIP { - return addr.Address, nil + allowedAddrTypes := []v1.NodeAddressType{v1.NodeInternalIP, v1.NodeExternalIP} + + for _, allowedAddrType := range allowedAddrTypes { + for _, addr := range addrs { + if addr.Type == allowedAddrType { + return addr.Address, nil + } } } - return addrs[0].Address, nil + return "", ErrNoAddressFound } //getStringFromServiceAnnotation searches a given v1.Service for a specific annotationKey and either returns the annotation's value or a specified defaultSetting diff --git a/pkg/controller/cloud/node_controller.go b/pkg/controller/cloud/node_controller.go index 0867ee8bbbc..9655feee741 100644 --- a/pkg/controller/cloud/node_controller.go +++ b/pkg/controller/cloud/node_controller.go @@ -18,6 +18,7 @@ package cloud import ( "context" + "errors" "fmt" "time" @@ -168,6 +169,12 @@ func (cnc *CloudNodeController) updateNodeAddress(node *v1.Node, instances cloud glog.Errorf("%v", err) return } + + if len(nodeAddresses) == 0 { + glog.V(5).Infof("Skipping node address update for node %q since cloud provider did not return any", node.Name) + return + } + // Check if a hostname address exists in the cloud provided addresses hostnameExists := false for i := range nodeAddresses { @@ -349,21 +356,18 @@ func (cnc *CloudNodeController) AddCloudNode(obj interface{}) { nodeAddresses, err := getNodeAddressesByProviderIDOrName(instances, curNode) if err != nil { - glog.Errorf("%v", err) - return nil + return err } // If user provided an IP address, ensure that IP address is found // in the cloud provider before removing the taint on the node if nodeIP, ok := ensureNodeProvidedIPExists(curNode, nodeAddresses); ok { if nodeIP == nil { - glog.Errorf("failed to get specified nodeIP in cloudprovider") - return nil + return errors.New("failed to find kubelet node IP from cloud provider") } } if instanceType, err := getInstanceTypeByProviderIDOrName(instances, curNode); err != nil { - glog.Errorf("%v", err) return err } else if instanceType != "" { glog.V(2).Infof("Adding node label from cloud provider: %s=%s", kubeletapis.LabelInstanceType, instanceType) @@ -445,6 +449,9 @@ func ensureNodeExistsByProviderID(instances cloudprovider.Instances, node *v1.No var err error providerID, err = instances.InstanceID(context.TODO(), types.NodeName(node.Name)) if err != nil { + if err == cloudprovider.InstanceNotFound { + return false, nil + } return false, err } diff --git a/pkg/controller/daemon/BUILD b/pkg/controller/daemon/BUILD index 81c11c383dc..a456c978b79 100644 --- a/pkg/controller/daemon/BUILD +++ b/pkg/controller/daemon/BUILD @@ -23,7 +23,7 @@ go_library( "//pkg/kubelet/types:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/util/labels:go_default_library", "//pkg/util/metrics:go_default_library", "//vendor/github.com/golang/glog:go_default_library", @@ -33,6 +33,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", diff --git a/pkg/controller/daemon/daemon_controller.go b/pkg/controller/daemon/daemon_controller.go index 10fa761485a..92cdb15b9ca 100644 --- a/pkg/controller/daemon/daemon_controller.go +++ b/pkg/controller/daemon/daemon_controller.go @@ -30,6 +30,7 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/sets" @@ -55,7 +56,7 @@ import ( kubelettypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/util/metrics" ) @@ -112,6 +113,8 @@ type DaemonSetsController struct { historyStoreSynced cache.InformerSynced // podLister get list/get pods from the shared informers's store podLister corelisters.PodLister + // podNodeIndex indexes pods by their nodeName + podNodeIndex cache.Indexer // podStoreSynced returns true if the pod store has been synced at least once. // Added as a member to the struct to allow injection for testing. podStoreSynced cache.InformerSynced @@ -190,6 +193,12 @@ func NewDaemonSetsController(daemonSetInformer appsinformers.DaemonSetInformer, DeleteFunc: dsc.deletePod, }) dsc.podLister = podInformer.Lister() + + // This custom indexer will index pods based on their NodeName which will decrease the amount of pods we need to get in simulate() call. + podInformer.Informer().GetIndexer().AddIndexers(cache.Indexers{ + "nodeName": indexByPodNodeName, + }) + dsc.podNodeIndex = podInformer.Informer().GetIndexer() dsc.podStoreSynced = podInformer.Informer().HasSynced nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -206,6 +215,18 @@ func NewDaemonSetsController(daemonSetInformer appsinformers.DaemonSetInformer, return dsc, nil } +func indexByPodNodeName(obj interface{}) ([]string, error) { + pod, ok := obj.(*v1.Pod) + if !ok { + return []string{}, nil + } + // We are only interested in active pods with nodeName set + if len(pod.Spec.NodeName) == 0 || pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed { + return []string{}, nil + } + return []string{pod.Spec.NodeName}, nil +} + func (dsc *DaemonSetsController) deleteDaemonset(obj interface{}) { ds, ok := obj.(*apps.DaemonSet) if !ok { @@ -762,7 +783,7 @@ func (dsc *DaemonSetsController) getDaemonPods(ds *apps.DaemonSet) ([]*v1.Pod, e return cm.ClaimPods(pods) } -// getNodesToDaemonPods returns a map from nodes to daemon pods (corresponding to ds) running on the nodes. +// getNodesToDaemonPods returns a map from nodes to daemon pods (corresponding to ds) created for the nodes. // This also reconciles ControllerRef by adopting/orphaning. // Note that returned Pods are pointers to objects in the cache. // If you want to modify one, you need to deep-copy it first. @@ -774,9 +795,16 @@ func (dsc *DaemonSetsController) getNodesToDaemonPods(ds *apps.DaemonSet) (map[s // Group Pods by Node name. nodeToDaemonPods := make(map[string][]*v1.Pod) for _, pod := range claimedPods { - nodeName := pod.Spec.NodeName + nodeName, err := util.GetTargetNodeName(pod) + if err != nil { + glog.Warningf("Failed to get target node name of Pod %v/%v in DaemonSet %v/%v", + pod.Namespace, pod.Name, ds.Namespace, ds.Name) + continue + } + nodeToDaemonPods[nodeName] = append(nodeToDaemonPods[nodeName], pod) } + return nodeToDaemonPods, nil } @@ -850,7 +878,7 @@ func (dsc *DaemonSetsController) podsShouldBeOnNode( // If daemon pod is supposed to be running on node, but more than 1 daemon pod is running, delete the excess daemon pods. // Sort the daemon pods by creation time, so the oldest is preserved. if len(daemonPodsRunning) > 1 { - sort.Sort(podByCreationTimestamp(daemonPodsRunning)) + sort.Sort(podByCreationTimestampAndPhase(daemonPodsRunning)) for i := 1; i < len(daemonPodsRunning); i++ { podsToDelete = append(podsToDelete, daemonPodsRunning[i].Name) } @@ -870,7 +898,7 @@ func (dsc *DaemonSetsController) podsShouldBeOnNode( // which nodes should not run a Pod of ds but currently running one, it calls function // syncNodes with a list of pods to remove and a list of nodes to run a Pod of ds. func (dsc *DaemonSetsController) manage(ds *apps.DaemonSet, hash string) error { - // Find out which nodes are running the daemon pods controlled by ds. + // Find out the pods which are created for the nodes by DaemonSet. nodeToDaemonPods, err := dsc.getNodesToDaemonPods(ds) if err != nil { return fmt.Errorf("couldn't get node to daemon pod mapping for daemon set %q: %v", ds.Name, err) @@ -962,9 +990,12 @@ func (dsc *DaemonSetsController) syncNodes(ds *apps.DaemonSet, podsToDelete, nod podTemplate := &template - if false /*disabled for 1.10*/ && utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { + if utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { podTemplate = template.DeepCopy() - podTemplate.Spec.Affinity = util.ReplaceDaemonSetPodHostnameNodeAffinity( + // 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. + podTemplate.Spec.Affinity = util.ReplaceDaemonSetPodNodeNameNodeAffinity( podTemplate.Spec.Affinity, nodesNeedingDaemonPods[ix]) podTemplate.Spec.Tolerations = util.AppendNoScheduleTolerationIfNotExist(podTemplate.Spec.Tolerations) @@ -1098,7 +1129,7 @@ func (dsc *DaemonSetsController) updateDaemonSetStatus(ds *apps.DaemonSet, hash currentNumberScheduled++ // Sort the daemon pods by creation time, so that the oldest is first. daemonPods, _ := nodeToDaemonPods[node.Name] - sort.Sort(podByCreationTimestamp(daemonPods)) + sort.Sort(podByCreationTimestampAndPhase(daemonPods)) pod := daemonPods[0] if podutil.IsPodReady(pod) { numberReady++ @@ -1166,6 +1197,18 @@ func (dsc *DaemonSetsController) syncDaemonSet(key string) error { return fmt.Errorf("couldn't get key for object %#v: %v", ds, err) } + // If the DaemonSet is being deleted (either by foreground deletion or + // orphan deletion), we cannot be sure if the DaemonSet history objects + // it owned still exist -- those history objects can either be deleted + // or orphaned. Garbage collector doesn't guarantee that it will delete + // DaemonSet pods before deleting DaemonSet history objects, because + // DaemonSet history doesn't own DaemonSet pods. We cannot reliably + // calculate the status of a DaemonSet being deleted. Therefore, return + // here without updating status for the DaemonSet being deleted. + if ds.DeletionTimestamp != nil { + return nil + } + // Construct histories of the DaemonSet, and get the hash of current history cur, old, err := dsc.constructHistory(ds) if err != nil { @@ -1173,7 +1216,7 @@ func (dsc *DaemonSetsController) syncDaemonSet(key string) error { } hash := cur.Labels[apps.DefaultDaemonSetUniqueLabelKey] - if ds.DeletionTimestamp != nil || !dsc.expectations.SatisfiedExpectations(dsKey) { + if !dsc.expectations.SatisfiedExpectations(dsKey) { // Only update status. return dsc.updateDaemonSetStatus(ds, hash) } @@ -1249,30 +1292,27 @@ func (dsc *DaemonSetsController) simulate(newPod *v1.Pod, node *v1.Node, ds *app }) } - pods := []*v1.Pod{} - - podList, err := dsc.podLister.List(labels.Everything()) + objects, err := dsc.podNodeIndex.ByIndex("nodeName", node.Name) if err != nil { return nil, nil, err } - for _, pod := range podList { - if pod.Spec.NodeName != node.Name { - continue - } - if pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed { - continue - } - // ignore pods that belong to the daemonset when taking into account whether - // a daemonset should bind to a node. - if metav1.IsControlledBy(pod, ds) { - continue - } - pods = append(pods, pod) - } - nodeInfo := schedulercache.NewNodeInfo(pods...) + nodeInfo := schedulercache.NewNodeInfo() nodeInfo.SetNode(node) + for _, obj := range objects { + // Ignore pods that belong to the daemonset when taking into account whether a daemonset should bind to a node. + // TODO: replace this with metav1.IsControlledBy() in 1.12 + pod, ok := obj.(*v1.Pod) + if !ok { + continue + } + if isControlledByDaemonSet(pod, ds.GetUID()) { + continue + } + nodeInfo.AddPod(pod) + } + _, reasons, err := Predicates(newPod, nodeInfo) return reasons, nodeInfo, err } @@ -1414,7 +1454,7 @@ func Predicates(pod *v1.Pod, nodeInfo *schedulercache.NodeInfo) (bool, []algorit var predicateFails []algorithm.PredicateFailureReason // If ScheduleDaemonSetPods is enabled, only check nodeSelector and nodeAffinity. - if false /*disabled for 1.10*/ && utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { + if utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { fit, reasons, err := nodeSelectionPredicates(pod, nil, nodeInfo) if err != nil { return false, predicateFails, err @@ -1466,14 +1506,32 @@ func (o byCreationTimestamp) Less(i, j int) bool { return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp) } -type podByCreationTimestamp []*v1.Pod +type podByCreationTimestampAndPhase []*v1.Pod -func (o podByCreationTimestamp) Len() int { return len(o) } -func (o podByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } +func (o podByCreationTimestampAndPhase) Len() int { return len(o) } +func (o podByCreationTimestampAndPhase) Swap(i, j int) { o[i], o[j] = o[j], o[i] } + +func (o podByCreationTimestampAndPhase) Less(i, j int) bool { + // Scheduled Pod first + if len(o[i].Spec.NodeName) != 0 && len(o[j].Spec.NodeName) == 0 { + return true + } + + if len(o[i].Spec.NodeName) == 0 && len(o[j].Spec.NodeName) != 0 { + return false + } -func (o podByCreationTimestamp) Less(i, j int) bool { if o[i].CreationTimestamp.Equal(&o[j].CreationTimestamp) { return o[i].Name < o[j].Name } return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp) } + +func isControlledByDaemonSet(p *v1.Pod, uuid types.UID) bool { + for _, ref := range p.OwnerReferences { + if ref.Controller != nil && *ref.Controller && ref.UID == uuid { + return true + } + } + return false +} diff --git a/pkg/controller/daemon/daemon_controller_test.go b/pkg/controller/daemon/daemon_controller_test.go index 12577c017bb..67940259495 100644 --- a/pkg/controller/daemon/daemon_controller_test.go +++ b/pkg/controller/daemon/daemon_controller_test.go @@ -1953,6 +1953,7 @@ func TestNodeShouldRunDaemonPod(t *testing.T) { for _, p := range c.podsOnNode { manager.podStore.Add(p) p.Spec.NodeName = "test-node" + manager.podNodeIndex.Add(p) } c.ds.Spec.UpdateStrategy = *strategy wantToRun, shouldSchedule, shouldContinueRunning, err := manager.nodeShouldRunDaemonPod(node, c.ds) diff --git a/pkg/controller/daemon/util/BUILD b/pkg/controller/daemon/util/BUILD index 9a64e9a62e0..3d92cbd88a9 100644 --- a/pkg/controller/daemon/util/BUILD +++ b/pkg/controller/daemon/util/BUILD @@ -14,7 +14,6 @@ go_library( "//pkg/api/v1/pod:go_default_library", "//pkg/apis/core/v1/helper:go_default_library", "//pkg/features:go_default_library", - "//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", @@ -45,9 +44,12 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/api/testapi:go_default_library", + "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", + "//pkg/scheduler/algorithm:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/pkg/controller/daemon/util/daemonset_util.go b/pkg/controller/daemon/util/daemonset_util.go index e39f1620f17..ffb7033bd3d 100644 --- a/pkg/controller/daemon/util/daemonset_util.go +++ b/pkg/controller/daemon/util/daemonset_util.go @@ -29,7 +29,6 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/features" - kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" kubelettypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/scheduler/algorithm" ) @@ -136,19 +135,20 @@ func SplitByAvailablePods(minReadySeconds int32, pods []*v1.Pod) ([]*v1.Pod, []* return availablePods, unavailablePods } -// ReplaceDaemonSetPodHostnameNodeAffinity replaces the 'kubernetes.io/hostname' NodeAffinity term with -// the given "nodeName" in the "affinity" terms. -func ReplaceDaemonSetPodHostnameNodeAffinity(affinity *v1.Affinity, nodename string) *v1.Affinity { +// ReplaceDaemonSetPodNodeNameNodeAffinity replaces the RequiredDuringSchedulingIgnoredDuringExecution +// NodeAffinity of the given affinity with a new NodeAffinity that selects the given nodeName. +// Note that this function assumes that no NodeAffinity conflicts with the selected nodeName. +func ReplaceDaemonSetPodNodeNameNodeAffinity(affinity *v1.Affinity, nodename string) *v1.Affinity { + nodeSelReq := v1.NodeSelectorRequirement{ + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{nodename}, + } + nodeSelector := &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: kubeletapis.LabelHostname, - Operator: v1.NodeSelectorOpIn, - Values: []string{nodename}, - }, - }, + MatchFields: []v1.NodeSelectorRequirement{nodeSelReq}, }, }, } @@ -175,28 +175,12 @@ func ReplaceDaemonSetPodHostnameNodeAffinity(affinity *v1.Affinity, nodename str return affinity } - nodeSelectorTerms := []v1.NodeSelectorTerm{} - - // Removes hostname node selector, as only the target hostname will take effect. - for _, term := range nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { - exps := []v1.NodeSelectorRequirement{} - for _, exp := range term.MatchExpressions { - if exp.Key != kubeletapis.LabelHostname { - exps = append(exps, exp) - } - } - - if len(exps) > 0 { - term.MatchExpressions = exps - nodeSelectorTerms = append(nodeSelectorTerms, term) - } - } - - // Adds target hostname NodeAffinity term. - nodeSelectorTerms = append(nodeSelectorTerms, nodeSelector.NodeSelectorTerms[0]) - // Replace node selector with the new one. - nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms = nodeSelectorTerms + nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms = []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{nodeSelReq}, + }, + } return affinity } @@ -225,3 +209,42 @@ func AppendNoScheduleTolerationIfNotExist(tolerations []v1.Toleration) []v1.Tole return tolerations } + +// GetTargetNodeName get the target node name of DaemonSet pods. If `.spec.NodeName` is not empty (nil), +// return `.spec.NodeName`; otherwise, retrieve node name of pending pods from NodeAffinity. Return error +// if failed to retrieve node name from `.spec.NodeName` and NodeAffinity. +func GetTargetNodeName(pod *v1.Pod) (string, error) { + if len(pod.Spec.NodeName) != 0 { + return pod.Spec.NodeName, nil + } + + // If ScheduleDaemonSetPods was enabled before, retrieve node name of unscheduled pods from NodeAffinity + if pod.Spec.Affinity == nil || + pod.Spec.Affinity.NodeAffinity == nil || + pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil { + return "", fmt.Errorf("no spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution for pod %s/%s", + pod.Namespace, pod.Name) + } + + terms := pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms + if len(terms) < 1 { + return "", fmt.Errorf("no nodeSelectorTerms in requiredDuringSchedulingIgnoredDuringExecution of pod %s/%s", + pod.Namespace, pod.Name) + } + + for _, term := range terms { + for _, exp := range term.MatchFields { + if exp.Key == algorithm.NodeFieldSelectorKeyNodeName && + exp.Operator == v1.NodeSelectorOpIn { + if len(exp.Values) != 1 { + return "", fmt.Errorf("the matchFields value of '%s' is not unique for pod %s/%s", + algorithm.NodeFieldSelectorKeyNodeName, pod.Namespace, pod.Name) + } + + return exp.Values[0], nil + } + } + } + + return "", fmt.Errorf("no node name found for pod %s/%s", pod.Namespace, pod.Name) +} diff --git a/pkg/controller/daemon/util/daemonset_util_test.go b/pkg/controller/daemon/util/daemonset_util_test.go index cf23be4015b..5ed8d999021 100644 --- a/pkg/controller/daemon/util/daemonset_util_test.go +++ b/pkg/controller/daemon/util/daemonset_util_test.go @@ -24,8 +24,11 @@ import ( "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/api/testapi" + "k8s.io/kubernetes/pkg/features" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" + "k8s.io/kubernetes/pkg/scheduler/algorithm" ) func newPod(podName string, nodeName string, label map[string]string) *v1.Pod { @@ -171,7 +174,7 @@ func int64Ptr(i int) *int64 { return &li } -func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { +func TestReplaceDaemonSetPodNodeNameNodeAffinity(t *testing.T) { tests := []struct { affinity *v1.Affinity hostname string @@ -181,6 +184,25 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { affinity: nil, hostname: "host_1", expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }, + }, + }, + }, + }, + }, + }, + }, + { + affinity: &v1.Affinity{ NodeAffinity: &v1.NodeAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ @@ -197,6 +219,24 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { }, }, }, + hostname: "host_1", + expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }, + }, + }, + }, + }, + }, + }, }, { affinity: &v1.Affinity{ @@ -235,9 +275,9 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ { - MatchExpressions: []v1.NodeSelectorRequirement{ + MatchFields: []v1.NodeSelectorRequirement{ { - Key: kubeletapis.LabelHostname, + Key: algorithm.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"host_1"}, }, @@ -254,55 +294,9 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ { - MatchExpressions: []v1.NodeSelectorRequirement{ + MatchFields: []v1.NodeSelectorRequirement{ { - Key: "not-host-label", - Operator: v1.NodeSelectorOpIn, - Values: []string{"label_value_1", "label_value_2"}, - }, - }, - }, - }, - }, - }, - }, - hostname: "host_1", - expected: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "not-host-label", - Operator: v1.NodeSelectorOpIn, - Values: []string{"label_value_1", "label_value_2"}, - }, - }, - }, - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: kubeletapis.LabelHostname, - Operator: v1.NodeSelectorOpIn, - Values: []string{"host_1"}, - }, - }, - }, - }, - }, - }, - }, - }, - { - affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: kubeletapis.LabelHostname, + Key: algorithm.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"host_1", "host_2"}, }, @@ -314,13 +308,157 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { }, hostname: "host_1", expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }, + }, + }, + }, + }, + }, + }, + }, + { + affinity: nil, + hostname: "host_1", + expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }, + }, + }, + }, + }, + }, + }, + }, + { + affinity: &v1.Affinity{ NodeAffinity: &v1.NodeAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ { MatchExpressions: []v1.NodeSelectorRequirement{ { - Key: kubeletapis.LabelHostname, + Key: "hostname", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }, + }, + }, + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_2"}, + }, + }, + }, + }, + }, + }, + }, + hostname: "host_1", + expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }, + }, + }, + }, + }, + }, + }, + }, + { + affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpNotIn, + Values: []string{"host_2"}, + }, + }, + }, + }, + }, + }, + }, + hostname: "host_1", + expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }, + }, + }, + }, + }, + }, + }, + }, + { + affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + // NOTE: Only `metadata.name` is valid key in `MatchFields` in 1.11; + // added this case for compatibility: the feature works as normal + // when new Keys introduced. + Key: "metadata.foo", + Operator: v1.NodeSelectorOpIn, + Values: []string{"bar"}, + }, + }, + }, + }, + }, + }, + }, + hostname: "host_1", + expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"host_1"}, }, @@ -333,10 +471,129 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { }, } - for _, test := range tests { - got := ReplaceDaemonSetPodHostnameNodeAffinity(test.affinity, test.hostname) + for i, test := range tests { + got := ReplaceDaemonSetPodNodeNameNodeAffinity(test.affinity, test.hostname) if !reflect.DeepEqual(test.expected, got) { - t.Errorf("Failed to append NodeAffinity, got: %v, expected: %v", got, test.expected) + t.Errorf("Failed to append NodeAffinity in case %d, got: %v, expected: %v", + i, got, test.expected) } } } + +func forEachFeatureGate(t *testing.T, tf func(t *testing.T), gates ...utilfeature.Feature) { + for _, fg := range gates { + func() { + enabled := utilfeature.DefaultFeatureGate.Enabled(fg) + defer func() { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%v=%t", fg, enabled)) + }() + + for _, f := range []bool{true, false} { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%v=%t", fg, f)) + t.Run(fmt.Sprintf("%v (%t)", fg, f), tf) + } + }() + } +} + +func TestGetTargetNodeName(t *testing.T) { + testFun := func(t *testing.T) { + tests := []struct { + pod *v1.Pod + nodeName string + expectedErr bool + }{ + { + pod: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Namespace: "default", + }, + Spec: v1.PodSpec{ + NodeName: "node-1", + }, + }, + nodeName: "node-1", + }, + { + pod: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod2", + Namespace: "default", + }, + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node-1"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + nodeName: "node-1", + }, + { + pod: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod3", + Namespace: "default", + }, + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node-1", "node-2"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + expectedErr: true, + }, + { + pod: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod4", + Namespace: "default", + }, + Spec: v1.PodSpec{}, + }, + expectedErr: true, + }, + } + + for _, test := range tests { + got, err := GetTargetNodeName(test.pod) + if test.expectedErr != (err != nil) { + t.Errorf("Unexpected error, expectedErr: %v, err: %v", test.expectedErr, err) + } else if !test.expectedErr { + if test.nodeName != got { + t.Errorf("Failed to get target node name, got: %v, expected: %v", got, test.nodeName) + } + } + } + } + + forEachFeatureGate(t, testFun, features.ScheduleDaemonSetPods) +} diff --git a/pkg/controller/garbagecollector/garbagecollector.go b/pkg/controller/garbagecollector/garbagecollector.go index 7f93386a86d..644949eca8b 100644 --- a/pkg/controller/garbagecollector/garbagecollector.go +++ b/pkg/controller/garbagecollector/garbagecollector.go @@ -32,6 +32,7 @@ import ( "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" @@ -170,10 +171,8 @@ func (gc *GarbageCollector) Sync(discoveryClient discovery.ServerResourcesInterf newResources := GetDeletableResources(discoveryClient) // This can occur if there is an internal error in GetDeletableResources. - // If the gc attempts to sync with 0 resources it will block forever. - // TODO: Implement a more complete solution for the garbage collector hanging. if len(newResources) == 0 { - glog.V(5).Infof("no resources reported by discovery, skipping garbage collector sync") + glog.V(2).Infof("no resources reported by discovery, skipping garbage collector sync") return } @@ -183,39 +182,61 @@ func (gc *GarbageCollector) Sync(discoveryClient discovery.ServerResourcesInterf return } - // Something has changed, time to sync. - glog.V(2).Infof("syncing garbage collector with updated resources from discovery: %v", newResources) - // Ensure workers are paused to avoid processing events before informers // have resynced. gc.workerLock.Lock() defer gc.workerLock.Unlock() - // Resetting the REST mapper will also invalidate the underlying discovery - // client. This is a leaky abstraction and assumes behavior about the REST - // mapper, but we'll deal with it for now. - gc.restMapper.Reset() + // Once we get here, we should not unpause workers until we've successfully synced + attempt := 0 + wait.PollImmediateUntil(100*time.Millisecond, func() (bool, error) { + attempt++ - // Perform the monitor resync and wait for controllers to report cache sync. - // - // NOTE: It's possible that newResources will diverge from the resources - // discovered by restMapper during the call to Reset, since they are - // distinct discovery clients invalidated at different times. For example, - // newResources may contain resources not returned in the restMapper's - // discovery call if the resources appeared in-between the calls. In that - // case, the restMapper will fail to map some of newResources until the next - // sync period. - if err := gc.resyncMonitors(newResources); err != nil { - utilruntime.HandleError(fmt.Errorf("failed to sync resource monitors: %v", err)) - return - } - // TODO: WaitForCacheSync can block forever during normal operation. Could - // pass a timeout channel, but we have to consider the implications of - // un-pausing the GC with a partially synced graph builder. - if !controller.WaitForCacheSync("garbage collector", stopCh, gc.dependencyGraphBuilder.IsSynced) { - utilruntime.HandleError(fmt.Errorf("timed out waiting for dependency graph builder sync during GC sync")) - return - } + // On a reattempt, check if available resources have changed + if attempt > 1 { + newResources = GetDeletableResources(discoveryClient) + if len(newResources) == 0 { + glog.V(2).Infof("no resources reported by discovery (attempt %d)", attempt) + return false, nil + } + } + + glog.V(2).Infof("syncing garbage collector with updated resources from discovery (attempt %d): %s", attempt, printDiff(oldResources, newResources)) + + // Resetting the REST mapper will also invalidate the underlying discovery + // client. This is a leaky abstraction and assumes behavior about the REST + // mapper, but we'll deal with it for now. + gc.restMapper.Reset() + glog.V(4).Infof("reset restmapper") + + // Perform the monitor resync and wait for controllers to report cache sync. + // + // NOTE: It's possible that newResources will diverge from the resources + // discovered by restMapper during the call to Reset, since they are + // distinct discovery clients invalidated at different times. For example, + // newResources may contain resources not returned in the restMapper's + // discovery call if the resources appeared in-between the calls. In that + // case, the restMapper will fail to map some of newResources until the next + // attempt. + if err := gc.resyncMonitors(newResources); err != nil { + utilruntime.HandleError(fmt.Errorf("failed to sync resource monitors (attempt %d): %v", attempt, err)) + return false, nil + } + glog.V(4).Infof("resynced monitors") + + // wait for caches to fill for a while (our sync period) before attempting to rediscover resources and retry syncing. + // this protects us from deadlocks where available resources changed and one of our informer caches will never fill. + // informers keep attempting to sync in the background, so retrying doesn't interrupt them. + // the call to resyncMonitors on the reattempt will no-op for resources that still exist. + // note that workers stay paused until we successfully resync. + if !controller.WaitForCacheSync("garbage collector", waitForStopOrTimeout(stopCh, period), gc.dependencyGraphBuilder.IsSynced) { + utilruntime.HandleError(fmt.Errorf("timed out waiting for dependency graph builder sync during GC sync (attempt %d)", attempt)) + return false, nil + } + + // success, break out of the loop + return true, nil + }, stopCh) // Finally, keep track of our new state. Do this after all preceding steps // have succeeded to ensure we'll retry on subsequent syncs if an error @@ -225,6 +246,36 @@ func (gc *GarbageCollector) Sync(discoveryClient discovery.ServerResourcesInterf }, period, stopCh) } +// printDiff returns a human-readable summary of what resources were added and removed +func printDiff(oldResources, newResources map[schema.GroupVersionResource]struct{}) string { + removed := sets.NewString() + for oldResource := range oldResources { + if _, ok := newResources[oldResource]; !ok { + removed.Insert(fmt.Sprintf("%+v", oldResource)) + } + } + added := sets.NewString() + for newResource := range newResources { + if _, ok := oldResources[newResource]; !ok { + added.Insert(fmt.Sprintf("%+v", newResource)) + } + } + return fmt.Sprintf("added: %v, removed: %v", added.List(), removed.List()) +} + +// waitForStopOrTimeout returns a stop channel that closes when the provided stop channel closes or when the specified timeout is reached +func waitForStopOrTimeout(stopCh <-chan struct{}, timeout time.Duration) <-chan struct{} { + stopChWithTimeout := make(chan struct{}) + go func() { + select { + case <-stopCh: + case <-time.After(timeout): + } + close(stopChWithTimeout) + }() + return stopChWithTimeout +} + func (gc *GarbageCollector) IsSynced() bool { return gc.dependencyGraphBuilder.IsSynced() } @@ -417,8 +468,11 @@ func (gc *GarbageCollector) attemptToDeleteItem(item *node) error { // waitingForDependentsDeletion needs to be deleted from the // ownerReferences, otherwise the referenced objects will be stuck with // the FinalizerDeletingDependents and never get deleted. - patch := deleteOwnerRefPatch(item.identity.UID, append(ownerRefsToUIDs(dangling), ownerRefsToUIDs(waitingForDependentsDeletion)...)...) - _, err = gc.patchObject(item.identity, patch) + ownerUIDs := append(ownerRefsToUIDs(dangling), ownerRefsToUIDs(waitingForDependentsDeletion)...) + patch := deleteOwnerRefStrategicMergePatch(item.identity.UID, ownerUIDs...) + _, err = gc.patch(item, patch, func(n *node) ([]byte, error) { + return gc.deleteOwnerRefJSONMergePatch(n, ownerUIDs...) + }) return err case len(waitingForDependentsDeletion) != 0 && item.dependentsLength() != 0: deps := item.getDependents() @@ -430,11 +484,11 @@ func (gc *GarbageCollector) attemptToDeleteItem(item *node) error { // there are multiple workers run attemptToDeleteItem in // parallel, the circle detection can fail in a race condition. glog.V(2).Infof("processing object %s, some of its owners and its dependent [%s] have FinalizerDeletingDependents, to prevent potential cycle, its ownerReferences are going to be modified to be non-blocking, then the object is going to be deleted with Foreground", item.identity, dep.identity) - patch, err := item.patchToUnblockOwnerReferences() + patch, err := item.unblockOwnerReferencesStrategicMergePatch() if err != nil { return err } - if _, err := gc.patchObject(item.identity, patch); err != nil { + if _, err := gc.patch(item, patch, gc.unblockOwnerReferencesJSONMergePatch); err != nil { return err } break @@ -494,8 +548,10 @@ func (gc *GarbageCollector) orphanDependents(owner objectReference, dependents [ go func(dependent *node) { defer wg.Done() // the dependent.identity.UID is used as precondition - patch := deleteOwnerRefPatch(dependent.identity.UID, owner.UID) - _, err := gc.patchObject(dependent.identity, patch) + patch := deleteOwnerRefStrategicMergePatch(dependent.identity.UID, owner.UID) + _, err := gc.patch(dependent, patch, func(n *node) ([]byte, error) { + return gc.deleteOwnerRefJSONMergePatch(n, owner.UID) + }) // note that if the target ownerReference doesn't exist in the // dependent, strategic merge patch will NOT return an error. if err != nil && !errors.IsNotFound(err) { diff --git a/pkg/controller/garbagecollector/garbagecollector_test.go b/pkg/controller/garbagecollector/garbagecollector_test.go index 96682e4c6da..60aab9ff19b 100644 --- a/pkg/controller/garbagecollector/garbagecollector_test.go +++ b/pkg/controller/garbagecollector/garbagecollector_test.go @@ -593,7 +593,7 @@ func TestDeleteOwnerRefPatch(t *testing.T) { }, }, } - patch := deleteOwnerRefPatch("100", "2", "3") + patch := deleteOwnerRefStrategicMergePatch("100", "2", "3") patched, err := strategicpatch.StrategicMergePatch(originalData, patch, v1.Pod{}) if err != nil { t.Fatal(err) @@ -638,7 +638,7 @@ func TestUnblockOwnerReference(t *testing.T) { n := node{ owners: accessor.GetOwnerReferences(), } - patch, err := n.patchToUnblockOwnerReferences() + patch, err := n.unblockOwnerReferencesStrategicMergePatch() if err != nil { t.Fatal(err) } @@ -800,6 +800,15 @@ func TestGarbageCollectorSync(t *testing.T) { }, }, } + unsyncableServerResources := []*metav1.APIResourceList{ + { + GroupVersion: "v1", + APIResources: []metav1.APIResource{ + {Name: "pods", Namespaced: true, Kind: "Pod", Verbs: metav1.Verbs{"delete", "list", "watch"}}, + {Name: "secrets", Namespaced: true, Kind: "Secret", Verbs: metav1.Verbs{"delete", "list", "watch"}}, + }, + }, + } fakeDiscoveryClient := &fakeServerResources{ PreferredResources: serverResources, Error: nil, @@ -813,6 +822,10 @@ func TestGarbageCollectorSync(t *testing.T) { 200, []byte("{}"), }, + "GET" + "/api/v1/secrets": { + 404, + []byte("{}"), + }, }, } srv, clientConfig := testServerAndClientConfig(testHandler.ServeHTTP) @@ -849,7 +862,7 @@ func TestGarbageCollectorSync(t *testing.T) { fmt.Printf("Test output") time.Sleep(1 * time.Second) - err = expectSyncNotBlocked(fakeDiscoveryClient) + err = expectSyncNotBlocked(fakeDiscoveryClient, &gc.workerLock) if err != nil { t.Fatalf("Expected garbagecollector.Sync to be running but it is blocked: %v", err) } @@ -865,13 +878,29 @@ func TestGarbageCollectorSync(t *testing.T) { fakeDiscoveryClient.setPreferredResources(serverResources) fakeDiscoveryClient.setError(nil) - err = expectSyncNotBlocked(fakeDiscoveryClient) + err = expectSyncNotBlocked(fakeDiscoveryClient, &gc.workerLock) + if err != nil { + t.Fatalf("Expected garbagecollector.Sync to still be running but it is blocked: %v", err) + } + + // Simulate the discovery client returning a resource the restmapper can resolve, but will not sync caches + fakeDiscoveryClient.setPreferredResources(unsyncableServerResources) + fakeDiscoveryClient.setError(nil) + + // Wait until sync discovers the change + time.Sleep(1 * time.Second) + + // Put the resources back to normal and ensure garbage collector sync recovers + fakeDiscoveryClient.setPreferredResources(serverResources) + fakeDiscoveryClient.setError(nil) + + err = expectSyncNotBlocked(fakeDiscoveryClient, &gc.workerLock) if err != nil { t.Fatalf("Expected garbagecollector.Sync to still be running but it is blocked: %v", err) } } -func expectSyncNotBlocked(fakeDiscoveryClient *fakeServerResources) error { +func expectSyncNotBlocked(fakeDiscoveryClient *fakeServerResources, workerLock *sync.RWMutex) error { before := fakeDiscoveryClient.getInterfaceUsedCount() t := 1 * time.Second time.Sleep(t) @@ -879,7 +908,19 @@ func expectSyncNotBlocked(fakeDiscoveryClient *fakeServerResources) error { if before == after { return fmt.Errorf("discoveryClient.ServerPreferredResources() called %d times over %v", after-before, t) } - return nil + + workerLockAcquired := make(chan struct{}) + go func() { + workerLock.Lock() + workerLock.Unlock() + close(workerLockAcquired) + }() + select { + case <-workerLockAcquired: + return nil + case <-time.After(t): + return fmt.Errorf("workerLock blocked for at least %v", t) + } } type fakeServerResources struct { diff --git a/pkg/controller/garbagecollector/graph_builder.go b/pkg/controller/garbagecollector/graph_builder.go index 4e18b1c2678..dd4193a0522 100644 --- a/pkg/controller/garbagecollector/graph_builder.go +++ b/pkg/controller/garbagecollector/graph_builder.go @@ -78,7 +78,7 @@ type GraphBuilder struct { // each monitor list/watches a resource, the results are funneled to the // dependencyGraphBuilder monitors monitors - monitorLock sync.Mutex + monitorLock sync.RWMutex // informersStarted is closed after after all of the controllers have been initialized and are running. // After that it is safe to start them here, before that it is not. informersStarted <-chan struct{} @@ -111,6 +111,7 @@ type GraphBuilder struct { // monitor runs a Controller with a local stop channel. type monitor struct { controller cache.Controller + store cache.Store // stopCh stops Controller. If stopCh is nil, the monitor is considered to be // not yet started. @@ -138,7 +139,7 @@ func listWatcher(client dynamic.Interface, resource schema.GroupVersionResource) } } -func (gb *GraphBuilder) controllerFor(resource schema.GroupVersionResource, kind schema.GroupVersionKind) (cache.Controller, error) { +func (gb *GraphBuilder) controllerFor(resource schema.GroupVersionResource, kind schema.GroupVersionKind) (cache.Controller, cache.Store, error) { handlers := cache.ResourceEventHandlerFuncs{ // add the event to the dependencyGraphBuilder's graphChanges. AddFunc: func(obj interface{}) { @@ -178,21 +179,21 @@ func (gb *GraphBuilder) controllerFor(resource schema.GroupVersionResource, kind glog.V(4).Infof("using a shared informer for resource %q, kind %q", resource.String(), kind.String()) // need to clone because it's from a shared cache shared.Informer().AddEventHandlerWithResyncPeriod(handlers, ResourceResyncTime) - return shared.Informer().GetController(), nil + return shared.Informer().GetController(), shared.Informer().GetStore(), nil } else { glog.V(4).Infof("unable to use a shared informer for resource %q, kind %q: %v", resource.String(), kind.String(), err) } // TODO: consider store in one storage. glog.V(5).Infof("create storage for resource %s", resource) - _, monitor := cache.NewInformer( + store, monitor := cache.NewInformer( listWatcher(gb.dynamicClient, resource), nil, ResourceResyncTime, // don't need to clone because it's not from shared cache handlers, ) - return monitor, nil + return monitor, store, nil } // syncMonitors rebuilds the monitor set according to the supplied resources, @@ -228,12 +229,12 @@ func (gb *GraphBuilder) syncMonitors(resources map[schema.GroupVersionResource]s errs = append(errs, fmt.Errorf("couldn't look up resource %q: %v", resource, err)) continue } - c, err := gb.controllerFor(resource, kind) + c, s, err := gb.controllerFor(resource, kind) if err != nil { errs = append(errs, fmt.Errorf("couldn't start monitor for resource %q: %v", resource, err)) continue } - current[resource] = &monitor{controller: c} + current[resource] = &monitor{store: s, controller: c} added++ } gb.monitors = current @@ -288,11 +289,13 @@ func (gb *GraphBuilder) IsSynced() bool { defer gb.monitorLock.Unlock() if len(gb.monitors) == 0 { + glog.V(4).Info("garbage controller monitor not synced: no monitors") return false } - for _, monitor := range gb.monitors { + for resource, monitor := range gb.monitors { if !monitor.controller.HasSynced() { + glog.V(4).Infof("garbage controller monitor not yet synced: %+v", resource) return false } } diff --git a/pkg/controller/garbagecollector/operations.go b/pkg/controller/garbagecollector/operations.go index 29025692b89..9f0145869c1 100644 --- a/pkg/controller/garbagecollector/operations.go +++ b/pkg/controller/garbagecollector/operations.go @@ -76,12 +76,12 @@ func (gc *GarbageCollector) updateObject(item objectReference, obj *unstructured return gc.dynamicClient.Resource(resource).Namespace(resourceDefaultNamespace(namespaced, item.Namespace)).Update(obj) } -func (gc *GarbageCollector) patchObject(item objectReference, patch []byte) (*unstructured.Unstructured, error) { +func (gc *GarbageCollector) patchObject(item objectReference, patch []byte, pt types.PatchType) (*unstructured.Unstructured, error) { resource, namespaced, err := gc.apiResource(item.APIVersion, item.Kind) if err != nil { return nil, err } - return gc.dynamicClient.Resource(resource).Namespace(resourceDefaultNamespace(namespaced, item.Namespace)).Patch(item.Name, types.StrategicMergePatchType, patch) + return gc.dynamicClient.Resource(resource).Namespace(resourceDefaultNamespace(namespaced, item.Namespace)).Patch(item.Name, pt, patch) } // TODO: Using Patch when strategicmerge supports deleting an entry from a diff --git a/pkg/controller/garbagecollector/patch.go b/pkg/controller/garbagecollector/patch.go index 8f8f9fb75ab..b0169adeaab 100644 --- a/pkg/controller/garbagecollector/patch.go +++ b/pkg/controller/garbagecollector/patch.go @@ -21,12 +21,16 @@ import ( "fmt" "strings" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly" ) -func deleteOwnerRefPatch(dependentUID types.UID, ownerUIDs ...types.UID) []byte { +func deleteOwnerRefStrategicMergePatch(dependentUID types.UID, ownerUIDs ...types.UID) []byte { var pieces []string for _, ownerUID := range ownerUIDs { pieces = append(pieces, fmt.Sprintf(`{"$patch":"delete","uid":"%s"}`, ownerUID)) @@ -35,9 +39,97 @@ func deleteOwnerRefPatch(dependentUID types.UID, ownerUIDs ...types.UID) []byte return []byte(patch) } -// generate a patch that unsets the BlockOwnerDeletion field of all +// getMetadata tries getting object metadata from local cache, and sends GET request to apiserver when +// local cache is not available or not latest. +func (gc *GarbageCollector) getMetadata(apiVersion, kind, namespace, name string) (metav1.Object, error) { + apiResource, _, err := gc.apiResource(apiVersion, kind) + if err != nil { + return nil, err + } + gc.dependencyGraphBuilder.monitorLock.RLock() + defer gc.dependencyGraphBuilder.monitorLock.RUnlock() + m, ok := gc.dependencyGraphBuilder.monitors[apiResource] + if !ok || m == nil { + // If local cache doesn't exist for mapping.Resource, send a GET request to API server + return gc.dynamicClient.Resource(apiResource).Namespace(namespace).Get(name, metav1.GetOptions{}) + } + key := name + if len(namespace) != 0 { + key = namespace + "/" + name + } + raw, exist, err := m.store.GetByKey(key) + if err != nil { + return nil, err + } + if !exist { + // If local cache doesn't contain the object, send a GET request to API server + return gc.dynamicClient.Resource(apiResource).Namespace(namespace).Get(name, metav1.GetOptions{}) + } + obj, ok := raw.(runtime.Object) + if !ok { + return nil, fmt.Errorf("expect a runtime.Object, got %v", raw) + } + return meta.Accessor(obj) +} + +type objectForPatch struct { + ObjectMetaForPatch `json:"metadata"` +} + +type ObjectMetaForPatch struct { + ResourceVersion string `json:"resourceVersion"` + OwnerReferences []metav1.OwnerReference `json:"ownerReferences"` +} + +// jsonMergePatchFunc defines the interface for functions that construct json merge patches that manipulate +// owner reference array. +type jsonMergePatchFunc func(*node) ([]byte, error) + +// patch tries strategic merge patch on item first, and if SMP is not supported, it fallbacks to JSON merge +// patch. +func (gc *GarbageCollector) patch(item *node, smp []byte, jmp jsonMergePatchFunc) (*unstructured.Unstructured, error) { + smpResult, err := gc.patchObject(item.identity, smp, types.StrategicMergePatchType) + if err == nil { + return smpResult, nil + } + if !errors.IsUnsupportedMediaType(err) { + return nil, err + } + // StrategicMergePatch is not supported, use JSON merge patch instead + patch, err := jmp(item) + if err != nil { + return nil, err + } + return gc.patchObject(item.identity, patch, types.MergePatchType) +} + +// Returns JSON merge patch that removes the ownerReferences matching ownerUIDs. +func (gc *GarbageCollector) deleteOwnerRefJSONMergePatch(item *node, ownerUIDs ...types.UID) ([]byte, error) { + accessor, err := gc.getMetadata(item.identity.APIVersion, item.identity.Kind, item.identity.Namespace, item.identity.Name) + if err != nil { + return nil, err + } + expectedObjectMeta := ObjectMetaForPatch{} + expectedObjectMeta.ResourceVersion = accessor.GetResourceVersion() + refs := accessor.GetOwnerReferences() + for _, ref := range refs { + var skip bool + for _, ownerUID := range ownerUIDs { + if ref.UID == ownerUID { + skip = true + break + } + } + if !skip { + expectedObjectMeta.OwnerReferences = append(expectedObjectMeta.OwnerReferences, ref) + } + } + return json.Marshal(objectForPatch{expectedObjectMeta}) +} + +// Generate a patch that unsets the BlockOwnerDeletion field of all // ownerReferences of node. -func (n *node) patchToUnblockOwnerReferences() ([]byte, error) { +func (n *node) unblockOwnerReferencesStrategicMergePatch() ([]byte, error) { var dummy metaonly.MetadataOnlyObject var blockingRefs []metav1.OwnerReference falseVar := false @@ -52,3 +144,22 @@ func (n *node) patchToUnblockOwnerReferences() ([]byte, error) { dummy.ObjectMeta.UID = n.identity.UID return json.Marshal(dummy) } + +// Generate a JSON merge patch that unsets the BlockOwnerDeletion field of all +// ownerReferences of node. +func (gc *GarbageCollector) unblockOwnerReferencesJSONMergePatch(n *node) ([]byte, error) { + accessor, err := gc.getMetadata(n.identity.APIVersion, n.identity.Kind, n.identity.Namespace, n.identity.Name) + if err != nil { + return nil, err + } + expectedObjectMeta := ObjectMetaForPatch{} + expectedObjectMeta.ResourceVersion = accessor.GetResourceVersion() + var expectedOwners []metav1.OwnerReference + falseVar := false + for _, owner := range n.owners { + owner.BlockOwnerDeletion = &falseVar + expectedOwners = append(expectedOwners, owner) + } + expectedObjectMeta.OwnerReferences = expectedOwners + return json.Marshal(objectForPatch{expectedObjectMeta}) +} diff --git a/pkg/controller/job/job_controller.go b/pkg/controller/job/job_controller.go index 3d25623df98..7578653d3dd 100644 --- a/pkg/controller/job/job_controller.go +++ b/pkg/controller/job/job_controller.go @@ -48,6 +48,8 @@ import ( "github.com/golang/glog" ) +const statusUpdateRetries = 3 + // controllerKind contains the schema.GroupVersionKind for this controller type. var controllerKind = batch.SchemeGroupVersion.WithKind("Job") @@ -356,10 +358,10 @@ func (jm *JobController) enqueueController(obj interface{}, immediate bool) { return } - if immediate { - jm.queue.Forget(key) + backoff := time.Duration(0) + if !immediate { + backoff = getBackoff(jm.queue, key) } - backoff := getBackoff(jm.queue, key) // TODO: Handle overlapping controllers better. Either disallow them at admission time or // deterministically avoid syncing controllers that fight over pods. Currently, we only @@ -495,7 +497,11 @@ func (jm *JobController) syncJob(key string) (bool, error) { var failureMessage string jobHaveNewFailure := failed > job.Status.Failed - exceedsBackoffLimit := jobHaveNewFailure && (int32(previousRetry)+1 > *job.Spec.BackoffLimit) + // new failures happen when status does not reflect the failures and active + // is different than parallelism, otherwise the previous controller loop + // failed updating status so even if we pick up failure it is not a new one + exceedsBackoffLimit := jobHaveNewFailure && (active != *job.Spec.Parallelism) && + (int32(previousRetry)+1 > *job.Spec.BackoffLimit) if exceedsBackoffLimit || pastBackoffLimitOnFailure(&job, pods) { // check if the number of pod restart exceeds backoff (for restart OnFailure only) @@ -813,7 +819,20 @@ func (jm *JobController) manageJob(activePods []*v1.Pod, succeeded int32, job *b } func (jm *JobController) updateJobStatus(job *batch.Job) error { - _, err := jm.kubeClient.BatchV1().Jobs(job.Namespace).UpdateStatus(job) + jobClient := jm.kubeClient.BatchV1().Jobs(job.Namespace) + var err error + for i := 0; i <= statusUpdateRetries; i = i + 1 { + var newJob *batch.Job + newJob, err = jobClient.Get(job.Name, metav1.GetOptions{}) + if err != nil { + break + } + newJob.Status = job.Status + if _, err = jobClient.UpdateStatus(newJob); err == nil { + break + } + } + return err } diff --git a/pkg/controller/job/job_controller_test.go b/pkg/controller/job/job_controller_test.go index de381e0eb21..b0533c963c6 100644 --- a/pkg/controller/job/job_controller_test.go +++ b/pkg/controller/job/job_controller_test.go @@ -412,8 +412,8 @@ func TestSyncJobPastDeadline(t *testing.T) { }, "activeDeadlineSeconds with backofflimit reach": { 1, 1, 1, 10, 0, - 1, 0, 2, - true, 1, 0, 0, 3, "BackoffLimitExceeded", + 0, 0, 1, + true, 0, 0, 0, 1, "BackoffLimitExceeded", }, } diff --git a/pkg/controller/nodelifecycle/OWNERS b/pkg/controller/nodelifecycle/OWNERS index 99dd2eda0e1..274351a0ed1 100755 --- a/pkg/controller/nodelifecycle/OWNERS +++ b/pkg/controller/nodelifecycle/OWNERS @@ -1,6 +1,7 @@ approvers: - gmarek - bowei +- k82cn reviewers: - gmarek - smarterclayton diff --git a/pkg/controller/nodelifecycle/scheduler/taint_manager.go b/pkg/controller/nodelifecycle/scheduler/taint_manager.go index 67f27f90e39..2388ac20f51 100644 --- a/pkg/controller/nodelifecycle/scheduler/taint_manager.go +++ b/pkg/controller/nodelifecycle/scheduler/taint_manager.go @@ -18,6 +18,8 @@ package scheduler import ( "fmt" + "hash/fnv" + "io" "sync" "time" @@ -58,6 +60,32 @@ type podUpdateItem struct { newTolerations []v1.Toleration } +func (n *nodeUpdateItem) name() string { + if n.newNode != nil { + return n.newNode.ObjectMeta.Name + } + if n.oldNode != nil { + return n.oldNode.ObjectMeta.Name + } + return "" +} + +func (p *podUpdateItem) nodeName() string { + if p.newPod != nil { + return p.newPod.Spec.NodeName + } + if p.oldPod != nil { + return p.oldPod.Spec.NodeName + } + return "" +} + +func hash(val string) int { + hasher := fnv.New32a() + io.WriteString(hasher, val) + return int(hasher.Sum32()) +} + // NoExecuteTaintManager listens to Taint/Toleration changes and is responsible for removing Pods // from Nodes tainted with NoExecute Taints. type NoExecuteTaintManager struct { @@ -69,8 +97,8 @@ type NoExecuteTaintManager struct { taintedNodesLock sync.Mutex taintedNodes map[string][]v1.Taint - nodeUpdateChannel chan *nodeUpdateItem - podUpdateChannel chan *podUpdateItem + nodeUpdateChannels []chan *nodeUpdateItem + podUpdateChannels []chan *podUpdateItem nodeUpdateQueue workqueue.Interface podUpdateQueue workqueue.Interface @@ -160,11 +188,9 @@ func NewNoExecuteTaintManager(c clientset.Interface) *NoExecuteTaintManager { } tm := &NoExecuteTaintManager{ - client: c, - recorder: recorder, - taintedNodes: make(map[string][]v1.Taint), - nodeUpdateChannel: make(chan *nodeUpdateItem, nodeUpdateChannelSize), - podUpdateChannel: make(chan *podUpdateItem, podUpdateChannelSize), + client: c, + recorder: recorder, + taintedNodes: make(map[string][]v1.Taint), nodeUpdateQueue: workqueue.New(), podUpdateQueue: workqueue.New(), @@ -177,6 +203,15 @@ func NewNoExecuteTaintManager(c clientset.Interface) *NoExecuteTaintManager { // Run starts NoExecuteTaintManager which will run in loop until `stopCh` is closed. func (tc *NoExecuteTaintManager) Run(stopCh <-chan struct{}) { glog.V(0).Infof("Starting NoExecuteTaintManager") + + // TODO: Figure out a reasonable number of workers and propagate the + // number of workers up making it a paramater of Run() function. + workers := 8 + for i := 0; i < workers; i++ { + tc.nodeUpdateChannels = append(tc.nodeUpdateChannels, make(chan *nodeUpdateItem, nodeUpdateChannelSize)) + tc.podUpdateChannels = append(tc.podUpdateChannels, make(chan *podUpdateItem, podUpdateChannelSize)) + } + // Functions that are responsible for taking work items out of the workqueues and putting them // into channels. go func(stopCh <-chan struct{}) { @@ -186,10 +221,11 @@ func (tc *NoExecuteTaintManager) Run(stopCh <-chan struct{}) { break } nodeUpdate := item.(*nodeUpdateItem) + hash := hash(nodeUpdate.name()) select { case <-stopCh: break - case tc.nodeUpdateChannel <- nodeUpdate: + case tc.nodeUpdateChannels[hash%workers] <- nodeUpdate: } } }(stopCh) @@ -201,14 +237,26 @@ func (tc *NoExecuteTaintManager) Run(stopCh <-chan struct{}) { break } podUpdate := item.(*podUpdateItem) + hash := hash(podUpdate.nodeName()) select { case <-stopCh: break - case tc.podUpdateChannel <- podUpdate: + case tc.podUpdateChannels[hash%workers] <- podUpdate: } } }(stopCh) + wg := sync.WaitGroup{} + wg.Add(workers) + for i := 0; i < workers; i++ { + go tc.worker(i, wg.Done, stopCh) + } + wg.Wait() +} + +func (tc *NoExecuteTaintManager) worker(worker int, done func(), stopCh <-chan struct{}) { + defer done() + // When processing events we want to prioritize Node updates over Pod updates, // as NodeUpdates that interest NoExecuteTaintManager should be handled as soon as possible - // we don't want user (or system) to wait until PodUpdate queue is drained before it can @@ -216,15 +264,15 @@ func (tc *NoExecuteTaintManager) Run(stopCh <-chan struct{}) { for { select { case <-stopCh: - break - case nodeUpdate := <-tc.nodeUpdateChannel: + return + case nodeUpdate := <-tc.nodeUpdateChannels[worker]: tc.handleNodeUpdate(nodeUpdate) - case podUpdate := <-tc.podUpdateChannel: + case podUpdate := <-tc.podUpdateChannels[worker]: // If we found a Pod update we need to empty Node queue first. priority: for { select { - case nodeUpdate := <-tc.nodeUpdateChannel: + case nodeUpdate := <-tc.nodeUpdateChannels[worker]: tc.handleNodeUpdate(nodeUpdate) default: break priority diff --git a/pkg/controller/resourcequota/resource_quota_controller.go b/pkg/controller/resourcequota/resource_quota_controller.go index 75878d9d0e4..1aacea38786 100644 --- a/pkg/controller/resourcequota/resource_quota_controller.go +++ b/pkg/controller/resourcequota/resource_quota_controller.go @@ -337,7 +337,7 @@ func (rq *ResourceQuotaController) syncResourceQuota(v1ResourceQuota *v1.Resourc } hardLimits := quota.Add(api.ResourceList{}, resourceQuota.Spec.Hard) - newUsage, err := quota.CalculateUsage(resourceQuota.Namespace, resourceQuota.Spec.Scopes, hardLimits, rq.registry) + newUsage, err := quota.CalculateUsage(resourceQuota.Namespace, resourceQuota.Spec.Scopes, hardLimits, rq.registry, resourceQuota.Spec.ScopeSelector) if err != nil { return err } diff --git a/pkg/controller/statefulset/stateful_set_test.go b/pkg/controller/statefulset/stateful_set_test.go index 3893753d1df..7d9a7cc1629 100644 --- a/pkg/controller/statefulset/stateful_set_test.go +++ b/pkg/controller/statefulset/stateful_set_test.go @@ -496,7 +496,6 @@ func TestStatefulSetControllerGetStatefulSetsForPod(t *testing.T) { func TestGetPodsForStatefulSetAdopt(t *testing.T) { set := newStatefulSet(5) - ssc, spc := newFakeStatefulSetController(set) pod1 := newStatefulSetPod(set, 1) // pod2 is an orphan with matching labels and name. pod2 := newStatefulSetPod(set, 2) @@ -510,6 +509,8 @@ func TestGetPodsForStatefulSetAdopt(t *testing.T) { pod4.OwnerReferences = nil pod4.Name = "x" + pod4.Name + ssc, spc := newFakeStatefulSetController(set, pod1, pod2, pod3, pod4) + spc.podsIndexer.Add(pod1) spc.podsIndexer.Add(pod2) spc.podsIndexer.Add(pod3) diff --git a/pkg/controller/testutil/test_utils.go b/pkg/controller/testutil/test_utils.go index 770df607c41..02119191028 100644 --- a/pkg/controller/testutil/test_utils.go +++ b/pkg/controller/testutil/test_utils.go @@ -365,6 +365,11 @@ func (f *FakeRecorder) Eventf(obj runtime.Object, eventtype, reason, messageFmt func (f *FakeRecorder) PastEventf(obj runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) { } +// AnnotatedEventf emits a fake formatted event to the fake recorder +func (f *FakeRecorder) AnnotatedEventf(obj runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { + f.Eventf(obj, eventtype, reason, messageFmt, args) +} + func (f *FakeRecorder) generateEvent(obj runtime.Object, timestamp metav1.Time, eventtype, reason, message string) { f.Lock() defer f.Unlock() diff --git a/pkg/controller/volume/attachdetach/BUILD b/pkg/controller/volume/attachdetach/BUILD index 4d5908494ed..f30b4b8d4a3 100644 --- a/pkg/controller/volume/attachdetach/BUILD +++ b/pkg/controller/volume/attachdetach/BUILD @@ -25,6 +25,7 @@ go_library( "//pkg/volume/util/operationexecutor:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", diff --git a/pkg/controller/volume/attachdetach/attach_detach_controller.go b/pkg/controller/volume/attachdetach/attach_detach_controller.go index c7397f57535..805a304952f 100644 --- a/pkg/controller/volume/attachdetach/attach_detach_controller.go +++ b/pkg/controller/volume/attachdetach/attach_detach_controller.go @@ -24,6 +24,7 @@ import ( "time" "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" @@ -586,6 +587,12 @@ func (adc *attachDetachController) GetConfigMapFunc() func(namespace, name strin } } +func (adc *attachDetachController) GetServiceAccountTokenFunc() func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return nil, fmt.Errorf("GetServiceAccountToken unsupported in attachDetachController") + } +} + func (adc *attachDetachController) GetExec(pluginName string) mount.Exec { return mount.NewOsExec() } diff --git a/pkg/controller/volume/attachdetach/reconciler/reconciler.go b/pkg/controller/volume/attachdetach/reconciler/reconciler.go index 47c690f83a7..5c57b2093ee 100644 --- a/pkg/controller/volume/attachdetach/reconciler/reconciler.go +++ b/pkg/controller/volume/attachdetach/reconciler/reconciler.go @@ -257,13 +257,17 @@ func (rc *reconciler) attachDesiredVolumes() { for _, volumeToAttach := range rc.desiredStateOfWorld.GetVolumesToAttach() { if rc.actualStateOfWorld.VolumeNodeExists(volumeToAttach.VolumeName, volumeToAttach.NodeName) { // Volume/Node exists, touch it to reset detachRequestedTime - glog.V(5).Infof(volumeToAttach.GenerateMsgDetailed("Volume attached--touching", "")) + if glog.V(5) { + glog.Infof(volumeToAttach.GenerateMsgDetailed("Volume attached--touching", "")) + } rc.actualStateOfWorld.ResetDetachRequestTime(volumeToAttach.VolumeName, volumeToAttach.NodeName) continue } // Don't even try to start an operation if there is already one running if rc.attacherDetacher.IsOperationPending(volumeToAttach.VolumeName, "") { - glog.V(10).Infof("Operation for volume %q is already running. Can't start attach for %q", volumeToAttach.VolumeName, volumeToAttach.NodeName) + if glog.V(10) { + glog.Infof("Operation for volume %q is already running. Can't start attach for %q", volumeToAttach.VolumeName, volumeToAttach.NodeName) + } continue } @@ -279,7 +283,9 @@ func (rc *reconciler) attachDesiredVolumes() { } // Volume/Node doesn't exist, spawn a goroutine to attach it - glog.V(5).Infof(volumeToAttach.GenerateMsgDetailed("Starting attacherDetacher.AttachVolume", "")) + if glog.V(5) { + glog.Infof(volumeToAttach.GenerateMsgDetailed("Starting attacherDetacher.AttachVolume", "")) + } err := rc.attacherDetacher.AttachVolume(volumeToAttach.VolumeToAttach, rc.actualStateOfWorld) if err == nil { glog.Infof(volumeToAttach.GenerateMsgDetailed("attacherDetacher.AttachVolume started", "")) diff --git a/pkg/controller/volume/expand/BUILD b/pkg/controller/volume/expand/BUILD index 5a067da6a44..69c1101426d 100644 --- a/pkg/controller/volume/expand/BUILD +++ b/pkg/controller/volume/expand/BUILD @@ -25,6 +25,7 @@ go_library( "//pkg/volume/util/operationexecutor:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", diff --git a/pkg/controller/volume/expand/expand_controller.go b/pkg/controller/volume/expand/expand_controller.go index caceb853ef1..9a8e8d37978 100644 --- a/pkg/controller/volume/expand/expand_controller.go +++ b/pkg/controller/volume/expand/expand_controller.go @@ -26,6 +26,7 @@ import ( "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/runtime" @@ -295,6 +296,12 @@ func (expc *expandController) GetConfigMapFunc() func(namespace, name string) (* } } +func (expc *expandController) GetServiceAccountTokenFunc() func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return nil, fmt.Errorf("GetServiceAccountToken unsupported in expandController") + } +} + func (expc *expandController) GetNodeLabels() (map[string]string, error) { return nil, fmt.Errorf("GetNodeLabels unsupported in expandController") } diff --git a/pkg/controller/volume/persistentvolume/BUILD b/pkg/controller/volume/persistentvolume/BUILD index 5367ef78fab..ec57338d75d 100644 --- a/pkg/controller/volume/persistentvolume/BUILD +++ b/pkg/controller/volume/persistentvolume/BUILD @@ -34,6 +34,7 @@ go_library( "//pkg/volume/util:go_default_library", "//pkg/volume/util/recyclerclient:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/pkg/controller/volume/persistentvolume/framework_test.go b/pkg/controller/volume/persistentvolume/framework_test.go index 5197f053c9e..13e36c25df9 100644 --- a/pkg/controller/volume/persistentvolume/framework_test.go +++ b/pkg/controller/volume/persistentvolume/framework_test.go @@ -612,6 +612,7 @@ func newTestController(kubeClient clientset.Interface, informerFactory informers ClaimInformer: informerFactory.Core().V1().PersistentVolumeClaims(), ClassInformer: informerFactory.Storage().V1().StorageClasses(), PodInformer: informerFactory.Core().V1().Pods(), + NodeInformer: informerFactory.Core().V1().Nodes(), EventRecorder: record.NewFakeRecorder(1000), EnableDynamicProvisioning: enableDynamicProvisioning, } @@ -1192,7 +1193,7 @@ func (plugin *mockVolumePlugin) NewProvisioner(options vol.VolumeOptions) (vol.P } } -func (plugin *mockVolumePlugin) Provision() (*v1.PersistentVolume, error) { +func (plugin *mockVolumePlugin) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if len(plugin.provisionCalls) <= plugin.provisionCallCounter { return nil, fmt.Errorf("Mock plugin error: unexpected provisioner call %d", plugin.provisionCallCounter) } diff --git a/pkg/controller/volume/persistentvolume/pv_controller.go b/pkg/controller/volume/persistentvolume/pv_controller.go index a46c75510dd..4743c4749df 100644 --- a/pkg/controller/volume/persistentvolume/pv_controller.go +++ b/pkg/controller/volume/persistentvolume/pv_controller.go @@ -174,6 +174,8 @@ type PersistentVolumeController struct { classListerSynced cache.InformerSynced podLister corelisters.PodLister podListerSynced cache.InformerSynced + NodeLister corelisters.NodeLister + NodeListerSynced cache.InformerSynced kubeClient clientset.Interface eventRecorder record.EventRecorder @@ -1434,13 +1436,26 @@ func (ctrl *PersistentVolumeController) provisionClaimOperation(claim *v1.Persis return } + var selectedNode *v1.Node = nil + var allowedTopologies []v1.TopologySelectorTerm = nil + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + if nodeName, ok := claim.Annotations[annSelectedNode]; ok { + selectedNode, err = ctrl.NodeLister.Get(nodeName) + if err != nil { + strerr := fmt.Sprintf("Failed to get target node: %v", err) + glog.V(3).Infof("unexpected error getting target node %q for claim %q: %v", nodeName, claimToClaimKey(claim), err) + ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr) + return + } + } + allowedTopologies = storageClass.AllowedTopologies + } + opComplete := util.OperationCompleteHook(plugin.GetPluginName(), "volume_provision") - // TODO: modify the Provision() interface to pass in the allowed topology information - // of the provisioned volume. - volume, err = provisioner.Provision() + volume, err = provisioner.Provision(selectedNode, allowedTopologies) opComplete(&err) if err != nil { - // Other places of failure has nothing to do with DynamicProvisioningScheduling, + // Other places of failure have nothing to do with DynamicProvisioningScheduling, // so just let controller retry in the next sync. We'll only call func // rescheduleProvisioning here when the underlying provisioning actually failed. ctrl.rescheduleProvisioning(claim) diff --git a/pkg/controller/volume/persistentvolume/pv_controller_base.go b/pkg/controller/volume/persistentvolume/pv_controller_base.go index 297f23d2a4d..40e78824843 100644 --- a/pkg/controller/volume/persistentvolume/pv_controller_base.go +++ b/pkg/controller/volume/persistentvolume/pv_controller_base.go @@ -63,6 +63,7 @@ type ControllerParameters struct { ClaimInformer coreinformers.PersistentVolumeClaimInformer ClassInformer storageinformers.StorageClassInformer PodInformer coreinformers.PodInformer + NodeInformer coreinformers.NodeInformer EventRecorder record.EventRecorder EnableDynamicProvisioning bool } @@ -122,6 +123,8 @@ func NewController(p ControllerParameters) (*PersistentVolumeController, error) controller.classListerSynced = p.ClassInformer.Informer().HasSynced controller.podLister = p.PodInformer.Lister() controller.podListerSynced = p.PodInformer.Informer().HasSynced + controller.NodeLister = p.NodeInformer.Lister() + controller.NodeListerSynced = p.NodeInformer.Informer().HasSynced return controller, nil } @@ -268,7 +271,7 @@ func (ctrl *PersistentVolumeController) Run(stopCh <-chan struct{}) { glog.Infof("Starting persistent volume controller") defer glog.Infof("Shutting down persistent volume controller") - if !controller.WaitForCacheSync("persistent volume", stopCh, ctrl.volumeListerSynced, ctrl.claimListerSynced, ctrl.classListerSynced, ctrl.podListerSynced) { + if !controller.WaitForCacheSync("persistent volume", stopCh, ctrl.volumeListerSynced, ctrl.claimListerSynced, ctrl.classListerSynced, ctrl.podListerSynced, ctrl.NodeListerSynced) { return } diff --git a/pkg/controller/volume/persistentvolume/scheduler_binder.go b/pkg/controller/volume/persistentvolume/scheduler_binder.go index 0c5ccc9ec42..bec90c1b8ae 100644 --- a/pkg/controller/volume/persistentvolume/scheduler_binder.go +++ b/pkg/controller/volume/persistentvolume/scheduler_binder.go @@ -24,6 +24,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" utilfeature "k8s.io/apiserver/pkg/util/feature" coreinformers "k8s.io/client-go/informers/core/v1" storageinformers "k8s.io/client-go/informers/storage/v1" @@ -481,7 +482,11 @@ func (b *volumeBinder) checkVolumeProvisions(pod *v1.Pod, claimsToProvision []*v return false, nil } - // TODO: Check if the node can satisfy the topology requirement in the class + // Check if the node can satisfy the topology requirement in the class + if !v1helper.MatchTopologySelectorTerms(class.AllowedTopologies, labels.Set(node.Labels)) { + glog.V(4).Infof("Node %q cannot satisfy provisioning topology requirements of claim %q", node.Name, getPVCName(claim)) + return false, nil + } // TODO: Check if capacity of the node domain in the storage class // can satisfy resource requirement of given claim diff --git a/pkg/controller/volume/persistentvolume/scheduler_binder_test.go b/pkg/controller/volume/persistentvolume/scheduler_binder_test.go index 98bc9e8bcd2..e1e49d0e3ff 100644 --- a/pkg/controller/volume/persistentvolume/scheduler_binder_test.go +++ b/pkg/controller/volume/persistentvolume/scheduler_binder_test.go @@ -50,6 +50,7 @@ var ( provisionedPVC2 = makeTestPVC("provisioned-pvc2", "1Gi", pvcUnbound, "", "1", &waitClass) provisionedPVCHigherVersion = makeTestPVC("provisioned-pvc2", "1Gi", pvcUnbound, "", "2", &waitClass) noProvisionerPVC = makeTestPVC("no-provisioner-pvc", "1Gi", pvcUnbound, "", "1", &provisionNotSupportClass) + topoMismatchPVC = makeTestPVC("topo-mismatch-pvc", "1Gi", pvcUnbound, "", "1", &topoMismatchClass) pvNoNode = makeTestPV("pv-no-node", "", "1G", "1", nil, waitClass) pvNode1a = makeTestPV("pv-node1a", "node1", "5G", "1", nil, waitClass) @@ -74,6 +75,7 @@ var ( waitClass = "waitClass" immediateClass = "immediateClass" provisionNotSupportClass = "provisionNotSupportedClass" + topoMismatchClass = "topoMismatchClass" nodeLabelKey = "nodeKey" nodeLabelValue = "node1" @@ -112,6 +114,16 @@ func newTestBinder(t *testing.T) *testEnv { }, VolumeBindingMode: &waitMode, Provisioner: "test-provisioner", + AllowedTopologies: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ + { + Key: nodeLabelKey, + Values: []string{nodeLabelValue, "reference-value"}, + }, + }, + }, + }, }, { ObjectMeta: metav1.ObjectMeta{ @@ -126,6 +138,23 @@ func newTestBinder(t *testing.T) *testEnv { VolumeBindingMode: &waitMode, Provisioner: "kubernetes.io/no-provisioner", }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: topoMismatchClass, + }, + VolumeBindingMode: &waitMode, + Provisioner: "test-provisioner", + AllowedTopologies: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ + { + Key: nodeLabelKey, + Values: []string{"reference-value"}, + }, + }, + }, + }, + }, } for _, class := range classes { if err := classInformer.Informer().GetIndexer().Add(class); err != nil { @@ -740,6 +769,11 @@ func TestFindPodVolumesWithProvisioning(t *testing.T) { expectedUnbound: false, expectedBound: true, }, + "volume-topology-unsatisfied": { + podPVCs: []*v1.PersistentVolumeClaim{topoMismatchPVC}, + expectedUnbound: false, + expectedBound: true, + }, } // Set VolumeScheduling and DynamicProvisioningScheduling feature gate diff --git a/pkg/controller/volume/persistentvolume/volume_host.go b/pkg/controller/volume/persistentvolume/volume_host.go index 14878c12e92..7fa54790c62 100644 --- a/pkg/controller/volume/persistentvolume/volume_host.go +++ b/pkg/controller/volume/persistentvolume/volume_host.go @@ -20,6 +20,7 @@ import ( "fmt" "net" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" clientset "k8s.io/client-go/kubernetes" @@ -94,18 +95,24 @@ func (ctrl *PersistentVolumeController) GetNodeAllocatable() (v1.ResourceList, e return v1.ResourceList{}, nil } -func (adc *PersistentVolumeController) GetSecretFunc() func(namespace, name string) (*v1.Secret, error) { +func (ctrl *PersistentVolumeController) GetSecretFunc() func(namespace, name string) (*v1.Secret, error) { return func(_, _ string) (*v1.Secret, error) { return nil, fmt.Errorf("GetSecret unsupported in PersistentVolumeController") } } -func (adc *PersistentVolumeController) GetConfigMapFunc() func(namespace, name string) (*v1.ConfigMap, error) { +func (ctrl *PersistentVolumeController) GetConfigMapFunc() func(namespace, name string) (*v1.ConfigMap, error) { return func(_, _ string) (*v1.ConfigMap, error) { return nil, fmt.Errorf("GetConfigMap unsupported in PersistentVolumeController") } } +func (ctrl *PersistentVolumeController) GetServiceAccountTokenFunc() func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return nil, fmt.Errorf("GetServiceAccountToken unsupported in PersistentVolumeController") + } +} + func (adc *PersistentVolumeController) GetExec(pluginName string) mount.Exec { return mount.NewOsExec() } diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index e95a0fcc155..855ede1066d 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -99,6 +99,11 @@ const ( // Ability to Expand persistent volumes ExpandPersistentVolumes utilfeature.Feature = "ExpandPersistentVolumes" + // owner: @mlmhl + // alpha: v1.11 + // Ability to expand persistent volumes' file system without unmounting volumes. + ExpandInUsePersistentVolumes utilfeature.Feature = "ExpandInUsePersistentVolumes" + // owner: @verb // alpha: v1.10 // @@ -155,6 +160,12 @@ const ( // Enable pods to consume pre-allocated huge pages of varying page sizes HugePages utilfeature.Feature = "HugePages" + // owner: @sjenning + // beta: v1.11 + // + // Enable pods to set sysctls on a pod + Sysctls utilfeature.Feature = "Sysctls" + // owner @brendandburns // alpha: v1.9 // @@ -212,7 +223,7 @@ const ( ResourceLimitsPriorityFunction utilfeature.Feature = "ResourceLimitsPriorityFunction" // owner: @m1093782566 - // beta: v1.9 + // GA: v1.11 // // Implement IPVS-based in-cluster service load balancing SupportIPVSProxyMode utilfeature.Feature = "SupportIPVSProxyMode" @@ -248,6 +259,12 @@ const ( // Implement TokenRequest endpoint on service account resources. TokenRequest utilfeature.Feature = "TokenRequest" + // owner: @mikedanese + // alpha: v1.11 + // + // Enable ServiceAccountTokenVolumeProjection support in ProjectedVolumes. + TokenRequestProjection utilfeature.Feature = "TokenRequestProjection" + // owner: @Random-Liu // beta: v1.11 // @@ -273,6 +290,13 @@ const ( // Do not remove this feature gate even though it's GA VolumeSubpath utilfeature.Feature = "VolumeSubpath" + // owner: @gnufied + // alpha : v1.11 + // + // Add support for volume plugins to report node specific + // volume limits + AttachVolumeLimit utilfeature.Feature = "AttachVolumeLimit" + // owner: @ravig // alpha: v1.11 // @@ -281,11 +305,44 @@ const ( // while making decisions. BalanceAttachedNodeVolumes utilfeature.Feature = "BalanceAttachedNodeVolumes" + // owner @freehan + // beta: v1.11 + // + // Support Pod Ready++ + PodReadinessGates utilfeature.Feature = "PodReadinessGates" + // owner: @lichuqiang // alpha: v1.11 // // Extend the default scheduler to be aware of volume topology and handle PV provisioning DynamicProvisioningScheduling utilfeature.Feature = "DynamicProvisioningScheduling" + + // owner: @kevtaylor + // alpha: v1.11 + // + // Allow subpath environment variable substitution + // Only applicable if the VolumeSubpath feature is also enabled + VolumeSubpathEnvExpansion utilfeature.Feature = "VolumeSubpathEnvExpansion" + + // owner: @vikaschoudhary16 + // alpha: v1.11 + // + // + // Enable probe based plugin watcher utility for discovering Kubelet plugins + KubeletPluginsWatcher utilfeature.Feature = "KubeletPluginsWatcher" + + // owner: @vikaschoudhary16 + // alpha: v1.11 + // + // + // Enable resource quota scope selectors + ResourceQuotaScopeSelectors utilfeature.Feature = "ResourceQuotaScopeSelectors" + + // owner: @vladimirvivien + // alpha: v1.11 + // + // Enables CSI to use raw block storage volumes + CSIBlockVolume utilfeature.Feature = "CSIBlockVolume" ) func init() { @@ -307,14 +364,17 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS PersistentLocalVolumes: {Default: true, PreRelease: utilfeature.Beta}, LocalStorageCapacityIsolation: {Default: true, PreRelease: utilfeature.Beta}, HugePages: {Default: true, PreRelease: utilfeature.Beta}, + Sysctls: {Default: true, PreRelease: utilfeature.Beta}, DebugContainers: {Default: false, PreRelease: utilfeature.Alpha}, PodShareProcessNamespace: {Default: false, PreRelease: utilfeature.Alpha}, - PodPriority: {Default: false, PreRelease: utilfeature.Alpha}, + PodPriority: {Default: true, PreRelease: utilfeature.Beta}, EnableEquivalenceClassCache: {Default: false, PreRelease: utilfeature.Alpha}, TaintNodesByCondition: {Default: false, PreRelease: utilfeature.Alpha}, MountPropagation: {Default: true, PreRelease: utilfeature.Beta}, QOSReserved: {Default: false, PreRelease: utilfeature.Alpha}, ExpandPersistentVolumes: {Default: true, PreRelease: utilfeature.Beta}, + ExpandInUsePersistentVolumes: {Default: false, PreRelease: utilfeature.Alpha}, + AttachVolumeLimit: {Default: false, PreRelease: utilfeature.Alpha}, CPUManager: {Default: true, PreRelease: utilfeature.Beta}, ServiceNodeExclusion: {Default: false, PreRelease: utilfeature.Alpha}, MountContainers: {Default: false, PreRelease: utilfeature.Alpha}, @@ -324,17 +384,23 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS BlockVolume: {Default: false, PreRelease: utilfeature.Alpha}, StorageObjectInUseProtection: {Default: true, PreRelease: utilfeature.GA}, ResourceLimitsPriorityFunction: {Default: false, PreRelease: utilfeature.Alpha}, - SupportIPVSProxyMode: {Default: true, PreRelease: utilfeature.Beta}, + SupportIPVSProxyMode: {Default: true, PreRelease: utilfeature.GA}, SupportPodPidsLimit: {Default: false, PreRelease: utilfeature.Alpha}, HyperVContainer: {Default: false, PreRelease: utilfeature.Alpha}, ScheduleDaemonSetPods: {Default: false, PreRelease: utilfeature.Alpha}, TokenRequest: {Default: false, PreRelease: utilfeature.Alpha}, + TokenRequestProjection: {Default: false, PreRelease: utilfeature.Alpha}, CRIContainerLogRotation: {Default: true, PreRelease: utilfeature.Beta}, GCERegionalPersistentDisk: {Default: true, PreRelease: utilfeature.Beta}, RunAsGroup: {Default: false, PreRelease: utilfeature.Alpha}, VolumeSubpath: {Default: true, PreRelease: utilfeature.GA}, BalanceAttachedNodeVolumes: {Default: false, PreRelease: utilfeature.Alpha}, DynamicProvisioningScheduling: {Default: false, PreRelease: utilfeature.Alpha}, + PodReadinessGates: {Default: false, PreRelease: utilfeature.Beta}, + VolumeSubpathEnvExpansion: {Default: false, PreRelease: utilfeature.Alpha}, + KubeletPluginsWatcher: {Default: false, PreRelease: utilfeature.Alpha}, + ResourceQuotaScopeSelectors: {Default: false, PreRelease: utilfeature.Alpha}, + CSIBlockVolume: {Default: false, PreRelease: utilfeature.Alpha}, // inherited features from generic apiserver, relisted here to get a conflict if it is changed // unintentionally on either side: diff --git a/pkg/generated/openapi/BUILD b/pkg/generated/openapi/BUILD index 59bac6592ed..99b5a64b712 100644 --- a/pkg/generated/openapi/BUILD +++ b/pkg/generated/openapi/BUILD @@ -65,6 +65,7 @@ openapi_library( "k8s.io/apiserver/pkg/apis/example/v1", "k8s.io/apiserver/pkg/apis/example2/v1", "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1", + "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", "k8s.io/client-go/pkg/version", "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1", "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1", diff --git a/pkg/kubeapiserver/options/plugins.go b/pkg/kubeapiserver/options/plugins.go index 2ba2783404f..a25643a09b7 100644 --- a/pkg/kubeapiserver/options/plugins.go +++ b/pkg/kubeapiserver/options/plugins.go @@ -131,7 +131,6 @@ func DefaultOffAdmissionPlugins() sets.String { lifecycle.PluginName, //NamespaceLifecycle limitranger.PluginName, //LimitRanger serviceaccount.PluginName, //ServiceAccount - label.PluginName, //PersistentVolumeLabel setdefault.PluginName, //DefaultStorageClass resize.PluginName, //PersistentVolumeClaimResize defaulttolerationseconds.PluginName, //DefaultTolerationSeconds diff --git a/pkg/kubectl/.import-restrictions b/pkg/kubectl/.import-restrictions index 6d8fdf7cb8c..8dc23442f02 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/schedulercache", + "k8s.io/kubernetes/pkg/scheduler/cache", "k8s.io/kubernetes/pkg/scheduler/util", "k8s.io/kubernetes/pkg/scheduler/volumebinder", "k8s.io/kubernetes/pkg/security/apparmor", diff --git a/pkg/kubectl/BUILD b/pkg/kubectl/BUILD index 8cc818887be..9701a1ad2f9 100644 --- a/pkg/kubectl/BUILD +++ b/pkg/kubectl/BUILD @@ -82,7 +82,6 @@ go_library( srcs = [ "apply.go", "autoscale.go", - "bash_comp_utils.go", "clusterrolebinding.go", "conditions.go", "configmap.go", @@ -125,7 +124,6 @@ go_library( "//pkg/controller/deployment/util:go_default_library", "//pkg/credentialprovider:go_default_library", "//pkg/kubectl/apps:go_default_library", - "//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/util:go_default_library", "//pkg/kubectl/util/hash:go_default_library", "//pkg/kubectl/util/slice:go_default_library", diff --git a/pkg/kubectl/bash_comp_utils.go b/pkg/kubectl/bash_comp_utils.go deleted file mode 100644 index 94df450a4a9..00000000000 --- a/pkg/kubectl/bash_comp_utils.go +++ /dev/null @@ -1,36 +0,0 @@ -/* -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. -*/ - -// A set of common functions needed by cmd/kubectl and pkg/kubectl packages. - -package kubectl - -import ( - "strings" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" -) - -func AddJsonFilenameFlag(cmd *cobra.Command, value *[]string, usage string) { - cmd.Flags().StringSliceVarP(value, "filename", "f", *value, usage) - annotations := make([]string, 0, len(resource.FileExtensions)) - for _, ext := range resource.FileExtensions { - annotations = append(annotations, strings.TrimLeft(ext, ".")) - } - cmd.Flags().SetAnnotation("filename", cobra.BashCompFilenameExt, annotations) -} diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index 20e12bd2b3f..7df91f9b74a 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -177,7 +177,7 @@ func (o *AnnotateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [ return printer.PrintObj(obj, out) } - o.namespace, o.enforceNamespace, err = f.DefaultNamespace() + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/annotate_test.go b/pkg/kubectl/cmd/annotate_test.go index f54fcf0ff11..172eb23309c 100644 --- a/pkg/kubectl/cmd/annotate_test.go +++ b/pkg/kubectl/cmd/annotate_test.go @@ -418,10 +418,9 @@ func TestAnnotateErrors(t *testing.T) { for k, testCase := range testCases { t.Run(k, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() iostreams, _, bufOut, bufErr := genericclioptions.NewTestIOStreams() @@ -453,7 +452,7 @@ func TestAnnotateErrors(t *testing.T) { func TestAnnotateObject(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -485,7 +484,6 @@ func TestAnnotateObject(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() iostreams, _, bufOut, _ := genericclioptions.NewTestIOStreams() @@ -507,7 +505,7 @@ func TestAnnotateObject(t *testing.T) { func TestAnnotateObjectFromFile(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -539,7 +537,6 @@ func TestAnnotateObjectFromFile(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() iostreams, _, bufOut, _ := genericclioptions.NewTestIOStreams() @@ -560,7 +557,7 @@ func TestAnnotateObjectFromFile(t *testing.T) { } func TestAnnotateLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -571,7 +568,6 @@ func TestAnnotateLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() iostreams, _, _, _ := genericclioptions.NewTestIOStreams() @@ -594,7 +590,7 @@ func TestAnnotateLocal(t *testing.T) { func TestAnnotateMultipleObjects(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -627,7 +623,6 @@ func TestAnnotateMultipleObjects(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() iostreams, _, _, _ := genericclioptions.NewTestIOStreams() diff --git a/pkg/kubectl/cmd/apiresources.go b/pkg/kubectl/cmd/apiresources.go index dadc13d8a25..982bbb02fea 100644 --- a/pkg/kubectl/cmd/apiresources.go +++ b/pkg/kubectl/cmd/apiresources.go @@ -34,7 +34,7 @@ import ( ) var ( - apiresources_example = templates.Examples(` + apiresourcesExample = templates.Examples(` # Print the supported API Resources kubectl api-resources @@ -84,7 +84,7 @@ func NewCmdApiResources(f cmdutil.Factory, ioStreams genericclioptions.IOStreams Use: "api-resources", Short: "Print the supported API resources on the server", Long: "Print the supported API resources on the server", - Example: apiresources_example, + Example: apiresourcesExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Validate(cmd)) cmdutil.CheckErr(o.RunApiResources(cmd, f)) @@ -104,7 +104,7 @@ func NewCmdApiResources(f cmdutil.Factory, ioStreams genericclioptions.IOStreams func (o *ApiResourcesOptions) Validate(cmd *cobra.Command) error { supportedOutputTypes := sets.NewString("", "wide", "name") if !supportedOutputTypes.Has(o.Output) { - return fmt.Errorf("--output %v is not available in kubectl api-resources", o.Output) + return fmt.Errorf("--output %v is not available", o.Output) } return nil } diff --git a/pkg/kubectl/cmd/apply.go b/pkg/kubectl/cmd/apply.go index fc8f67626dc..976915a4502 100644 --- a/pkg/kubectl/cmd/apply.go +++ b/pkg/kubectl/cmd/apply.go @@ -40,7 +40,6 @@ import ( "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/dynamic" - scaleclient "k8s.io/client-go/scale" oapi "k8s.io/kube-openapi/pkg/util/proto" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubectl" @@ -79,7 +78,6 @@ type ApplyOptions struct { Validator validation.Schema Builder *resource.Builder Mapper meta.RESTMapper - Scaler scaleclient.ScalesGetter DynamicClient dynamic.Interface OpenAPISchema openapi.Resources @@ -220,17 +218,12 @@ func (o *ApplyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { return err } - o.Scaler, err = f.ScaleClient() - if err != nil { - return err - } - o.DynamicClient, err = f.DynamicClient() if err != nil { return err } - o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -493,7 +486,6 @@ func (o *ApplyOptions) Run() error { cascade: o.DeleteOptions.Cascade, dryRun: o.DryRun, gracePeriod: o.DeleteOptions.GracePeriod, - scaler: o.Scaler, toPrinter: o.ToPrinter, @@ -547,6 +539,7 @@ func getRESTMappings(mapper meta.RESTMapper, pruneResources *[]pruneResource) (n {"", "v1", "Secret", true}, {"", "v1", "Service", true}, {"batch", "v1", "Job", true}, + {"batch", "v1beta1", "CronJob", true}, {"extensions", "v1beta1", "DaemonSet", true}, {"extensions", "v1beta1", "Deployment", true}, {"extensions", "v1beta1", "Ingress", true}, @@ -583,8 +576,6 @@ type pruner struct { dryRun bool gracePeriod int - scaler scaleclient.ScalesGetter - toPrinter func(string) (printers.ResourcePrinter, error) out io.Writer diff --git a/pkg/kubectl/cmd/apply_set_last_applied.go b/pkg/kubectl/cmd/apply_set_last_applied.go index 8b39bfd2b6f..809515d2442 100644 --- a/pkg/kubectl/cmd/apply_set_last_applied.go +++ b/pkg/kubectl/cmd/apply_set_last_applied.go @@ -107,7 +107,7 @@ func NewCmdApplySetLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IO cmdutil.AddDryRunFlag(cmd) cmd.Flags().BoolVar(&o.CreateAnnotation, "create-annotation", o.CreateAnnotation, "Will create 'last-applied-configuration' annotations if current objects doesn't have one") - kubectl.AddJsonFilenameFlag(cmd, &o.FilenameOptions.Filenames, "Filename, directory, or URL to files that contains the last-applied-configuration annotations") + cmdutil.AddJsonFilenameFlag(cmd.Flags(), &o.FilenameOptions.Filenames, "Filename, directory, or URL to files that contains the last-applied-configuration annotations") return cmd } @@ -118,7 +118,7 @@ func (o *SetLastAppliedOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) o.shortOutput = o.output == "name" var err error - o.namespace, o.enforceNamespace, err = f.DefaultNamespace() + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/apply_test.go b/pkg/kubectl/cmd/apply_test.go index abc4df764c0..81f7464219d 100644 --- a/pkg/kubectl/cmd/apply_test.go +++ b/pkg/kubectl/cmd/apply_test.go @@ -273,7 +273,7 @@ func TestRunApplyPrintsValidObjectList(t *testing.T) { cmBytes := readConfigMapList(t, filenameCM) pathCM := "/namespaces/test/configmaps" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -292,7 +292,6 @@ func TestRunApplyPrintsValidObjectList(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -393,7 +392,7 @@ func TestRunApplyViewLastApplied(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -419,7 +418,6 @@ func TestRunApplyViewLastApplied(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() cmdutil.BehaviorOnFatal(func(str string, code int) { @@ -453,7 +451,7 @@ func TestApplyObjectWithoutAnnotation(t *testing.T) { nameRC, rcBytes := readReplicationController(t, filenameRC) pathRC := "/namespaces/test/replicationcontrollers/" + nameRC - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -472,7 +470,6 @@ func TestApplyObjectWithoutAnnotation(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() @@ -499,7 +496,7 @@ func TestApplyObject(t *testing.T) { for _, fn := range testingOpenAPISchemaFns { t.Run("test apply when a local object is specified", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -520,7 +517,6 @@ func TestApplyObject(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() @@ -564,7 +560,7 @@ func TestApplyObjectOutput(t *testing.T) { for _, fn := range testingOpenAPISchemaFns { t.Run("test apply returns correct output", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -585,7 +581,6 @@ func TestApplyObjectOutput(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() @@ -617,7 +612,7 @@ func TestApplyRetry(t *testing.T) { firstPatch := true retry := false getCount := 0 - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -647,7 +642,6 @@ func TestApplyRetry(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() @@ -677,7 +671,7 @@ func TestApplyNonExistObject(t *testing.T) { pathRC := "/namespaces/test/replicationcontrollers" pathNameRC := pathRC + "/" + nameRC - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -697,7 +691,6 @@ func TestApplyNonExistObject(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -723,7 +716,7 @@ func TestApplyEmptyPatch(t *testing.T) { var body []byte - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -750,7 +743,6 @@ func TestApplyEmptyPatch(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() // 1. apply non exist object @@ -797,7 +789,7 @@ func testApplyMultipleObjects(t *testing.T, asList bool) { for _, fn := range testingOpenAPISchemaFns { t.Run("test apply on multiple objects", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -825,7 +817,6 @@ func testApplyMultipleObjects(t *testing.T, asList bool) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() @@ -884,7 +875,7 @@ func TestApplyNULLPreservation(t *testing.T) { for _, fn := range testingOpenAPISchemaFns { t.Run("test apply preserves NULL fields", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -926,7 +917,6 @@ func TestApplyNULLPreservation(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() @@ -960,7 +950,7 @@ func TestUnstructuredApply(t *testing.T) { for _, fn := range testingOpenAPISchemaFns { t.Run("test apply works correctly with unstructured objects", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -993,7 +983,6 @@ func TestUnstructuredApply(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() @@ -1029,7 +1018,7 @@ func TestUnstructuredIdempotentApply(t *testing.T) { for _, fn := range testingOpenAPISchemaFns { t.Run("test repeated apply operations on an unstructured object", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -1059,7 +1048,6 @@ func TestUnstructuredIdempotentApply(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() @@ -1131,7 +1119,7 @@ func TestRunApplySetLastApplied(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -1161,7 +1149,6 @@ func TestRunApplySetLastApplied(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() cmdutil.BehaviorOnFatal(func(str string, code int) { @@ -1227,7 +1214,7 @@ func TestForceApply(t *testing.T) { deleted := false isScaledDownToZero := false counts := map[string]int{} - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.ClientConfigVal = defaultClientConfig() @@ -1312,7 +1299,6 @@ func TestForceApply(t *testing.T) { tf.OpenAPISchemaFunc = fn tf.Client = tf.UnstructuredClient tf.ClientConfigVal = &restclient.Config{} - tf.Namespace = "test" ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() cmd := NewCmdApply("kubectl", tf, ioStreams) diff --git a/pkg/kubectl/cmd/apply_view_last_applied.go b/pkg/kubectl/cmd/apply_view_last_applied.go index ce5c7722e19..5fa5cd12c2a 100644 --- a/pkg/kubectl/cmd/apply_view_last_applied.go +++ b/pkg/kubectl/cmd/apply_view_last_applied.go @@ -91,7 +91,7 @@ func NewCmdApplyViewLastApplied(f cmdutil.Factory, ioStreams genericclioptions.I } func (o *ViewLastAppliedOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args []string) error { - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/attach.go b/pkg/kubectl/cmd/attach.go index 2195eee1ced..88ff4f7d415 100644 --- a/pkg/kubectl/cmd/attach.go +++ b/pkg/kubectl/cmd/attach.go @@ -135,7 +135,7 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [ return cmdutil.UsageErrorf(cmd, "expected POD, TYPE/NAME, or TYPE NAME, (at most 2 arguments) saw %d: %v", len(argsIn), argsIn) } - namespace, _, err := f.DefaultNamespace() + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/attach_test.go b/pkg/kubectl/cmd/attach_test.go index 55e0aad17ed..007df0dccdf 100644 --- a/pkg/kubectl/cmd/attach_test.go +++ b/pkg/kubectl/cmd/attach_test.go @@ -140,7 +140,7 @@ func TestPodAndContainerAttach(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -156,7 +156,6 @@ func TestPodAndContainerAttach(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() cmd := &cobra.Command{} @@ -224,7 +223,7 @@ func TestAttach(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -247,7 +246,6 @@ func TestAttach(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &schema.GroupVersion{Version: test.version}}} remoteAttach := &fakeRemoteAttach{} if test.remoteAttachErr { @@ -312,7 +310,7 @@ func TestAttachWarnings(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -335,7 +333,6 @@ func TestAttachWarnings(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &schema.GroupVersion{Version: test.version}}} streams, _, _, bufErr := genericclioptions.NewTestIOStreams() ex := &fakeRemoteAttach{} diff --git a/pkg/kubectl/cmd/auth/cani.go b/pkg/kubectl/cmd/auth/cani.go index 3d771af8703..118f0876d46 100644 --- a/pkg/kubectl/cmd/auth/cani.go +++ b/pkg/kubectl/cmd/auth/cani.go @@ -97,7 +97,7 @@ func NewCmdCanI(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.C allowed, err := o.RunAccessCheck() if err == nil { - if o.Quiet && !allowed { + if !allowed { os.Exit(1) } } @@ -146,7 +146,7 @@ func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error { o.Namespace = "" if !o.AllNamespaces { - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/auth/cani_test.go b/pkg/kubectl/cmd/auth/cani_test.go index 84dc9826868..8ce36cdd680 100644 --- a/pkg/kubectl/cmd/auth/cani_test.go +++ b/pkg/kubectl/cmd/auth/cani_test.go @@ -121,7 +121,7 @@ func TestRunAccessCheck(t *testing.T) { test.o.Out = ioutil.Discard test.o.ErrOut = ioutil.Discard - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() ns := legacyscheme.Codecs @@ -157,7 +157,6 @@ func TestRunAccessCheck(t *testing.T) { test.serverErr }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}} if err := test.o.Complete(tf, test.args); err != nil { diff --git a/pkg/kubectl/cmd/auth/reconcile.go b/pkg/kubectl/cmd/auth/reconcile.go index 555244ca61f..3346812deef 100644 --- a/pkg/kubectl/cmd/auth/reconcile.go +++ b/pkg/kubectl/cmd/auth/reconcile.go @@ -39,6 +39,7 @@ import ( type ReconcileOptions struct { PrintFlags *genericclioptions.PrintFlags FilenameOptions *resource.FilenameOptions + DryRun bool Visitor resource.Visitor RBACClient rbacv1client.RbacV1Interface @@ -87,6 +88,7 @@ func NewCmdReconcile(f cmdutil.Factory, streams genericclioptions.IOStreams) *co o.PrintFlags.AddFlags(cmd) cmdutil.AddFilenameOptionFlags(cmd, o.FilenameOptions, "identifying the resource to reconcile.") + cmd.Flags().BoolVar(&o.DryRun, "dry-run", o.DryRun, "If true, display results but do not submit changes") cmd.MarkFlagRequired("filename") return cmd @@ -97,7 +99,7 @@ func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args return errors.New("no arguments are allowed") } - namespace, enforceNamespace, err := f.DefaultNamespace() + namespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -128,6 +130,9 @@ func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args return err } + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } printer, err := o.PrintFlags.ToPrinter() if err != nil { return err @@ -168,7 +173,7 @@ func (o *ReconcileOptions) RunReconcile() error { switch t := info.Object.(type) { case *rbacv1.Role: reconcileOptions := reconciliation.ReconcileRoleOptions{ - Confirm: true, + Confirm: !o.DryRun, RemoveExtraPermissions: false, Role: reconciliation.RoleRuleOwner{Role: t}, Client: reconciliation.RoleModifier{ @@ -184,7 +189,7 @@ func (o *ReconcileOptions) RunReconcile() error { case *rbacv1.ClusterRole: reconcileOptions := reconciliation.ReconcileRoleOptions{ - Confirm: true, + Confirm: !o.DryRun, RemoveExtraPermissions: false, Role: reconciliation.ClusterRoleRuleOwner{ClusterRole: t}, Client: reconciliation.ClusterRoleModifier{ @@ -199,7 +204,7 @@ func (o *ReconcileOptions) RunReconcile() error { case *rbacv1.RoleBinding: reconcileOptions := reconciliation.ReconcileRoleBindingOptions{ - Confirm: true, + Confirm: !o.DryRun, RemoveExtraSubjects: false, RoleBinding: reconciliation.RoleBindingAdapter{RoleBinding: t}, Client: reconciliation.RoleBindingClientAdapter{ @@ -215,7 +220,7 @@ func (o *ReconcileOptions) RunReconcile() error { case *rbacv1.ClusterRoleBinding: reconcileOptions := reconciliation.ReconcileRoleBindingOptions{ - Confirm: true, + Confirm: !o.DryRun, RemoveExtraSubjects: false, RoleBinding: reconciliation.ClusterRoleBindingAdapter{ClusterRoleBinding: t}, Client: reconciliation.ClusterRoleBindingClientAdapter{ diff --git a/pkg/kubectl/cmd/autoscale.go b/pkg/kubectl/cmd/autoscale.go index 7c1875cf4d2..e2fc589982f 100644 --- a/pkg/kubectl/cmd/autoscale.go +++ b/pkg/kubectl/cmd/autoscale.go @@ -165,7 +165,7 @@ func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args } } - o.namespace, o.enforceNamespace, err = f.DefaultNamespace() + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/clusterinfo_dump.go b/pkg/kubectl/cmd/clusterinfo_dump.go index 0c3af8d4974..9e55ca45d77 100644 --- a/pkg/kubectl/cmd/clusterinfo_dump.go +++ b/pkg/kubectl/cmd/clusterinfo_dump.go @@ -134,7 +134,7 @@ func (o *ClusterInfoDumpOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) if err != nil { return err } - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/config/config_test.go b/pkg/kubectl/cmd/config/config_test.go index 9678014878b..fcf381f4e64 100644 --- a/pkg/kubectl/cmd/config/config_test.go +++ b/pkg/kubectl/cmd/config/config_test.go @@ -865,12 +865,12 @@ func testConfigCommand(args []string, startingConfig clientcmdapi.Config, t *tes streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdConfig(cmdutil.NewFactory(genericclioptions.NewTestConfigFlags()), clientcmd.NewDefaultPathOptions(), streams) + // "context" is a global flag, inherited from base kubectl command in the real world + cmd.PersistentFlags().String("context", "", "The name of the kubeconfig context to use") cmd.SetArgs(argsToUse) cmd.Execute() - // outBytes, _ := ioutil.ReadFile(fakeKubeFile.Name()) config := clientcmd.GetConfigFromFileOrDie(fakeKubeFile.Name()) - return buf.String(), *config } diff --git a/pkg/kubectl/cmd/config/flags.go b/pkg/kubectl/cmd/config/flags.go index cf8b00cd6a6..5e2f3ed8067 100644 --- a/pkg/kubectl/cmd/config/flags.go +++ b/pkg/kubectl/cmd/config/flags.go @@ -42,6 +42,13 @@ func (f *kubectlConfigPrintFlags) Complete(successTemplate string) error { return f.NamePrintFlags.Complete(successTemplate) } +func (f *kubectlConfigPrintFlags) AllowedFormats() []string { + formats := f.JSONYamlPrintFlags.AllowedFormats() + formats = append(formats, f.NamePrintFlags.AllowedFormats()...) + formats = append(formats, f.TemplateFlags.AllowedFormats()...) + return formats +} + func (f *kubectlConfigPrintFlags) ToPrinter() (printers.ResourcePrinter, error) { outputFormat := "" if f.OutputFormat != nil { @@ -60,7 +67,7 @@ func (f *kubectlConfigPrintFlags) ToPrinter() (printers.ResourcePrinter, error) return f.TypeSetter.WrapToPrinter(p, err) } - return nil, genericclioptions.NoCompatiblePrinterError{Options: f} + return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()} } func (f *kubectlConfigPrintFlags) AddFlags(cmd *cobra.Command) { diff --git a/pkg/kubectl/cmd/config/view.go b/pkg/kubectl/cmd/config/view.go index 5a0466126f1..eb82a7731a0 100644 --- a/pkg/kubectl/cmd/config/view.go +++ b/pkg/kubectl/cmd/config/view.go @@ -43,6 +43,7 @@ type ViewOptions struct { Minify bool RawByteData bool + Context string OutputFormat string genericclioptions.IOStreams @@ -110,6 +111,7 @@ func (o *ViewOptions) Complete(cmd *cobra.Command) error { return err } o.PrintObject = printer.PrintObj + o.Context = cmdutil.GetFlagString(cmd, "context") return nil } @@ -129,6 +131,9 @@ func (o ViewOptions) Run() error { } if o.Minify { + if len(o.Context) > 0 { + config.CurrentContext = o.Context + } if err := clientcmdapi.MinifyConfig(config); err != nil { return err } diff --git a/pkg/kubectl/cmd/config/view_test.go b/pkg/kubectl/cmd/config/view_test.go index 98f02651e86..936f1d9cd37 100644 --- a/pkg/kubectl/cmd/config/view_test.go +++ b/pkg/kubectl/cmd/config/view_test.go @@ -43,19 +43,19 @@ func TestViewCluster(t *testing.T) { "my-cluster": {Server: "https://192.168.0.1:3434"}, }, Contexts: map[string]*clientcmdapi.Context{ - "minikube": {AuthInfo: "minikube", Cluster: "minikube"}, - "my-cluser": {AuthInfo: "mu-cluster", Cluster: "my-cluster"}, + "minikube": {AuthInfo: "minikube", Cluster: "minikube"}, + "my-cluster": {AuthInfo: "mu-cluster", Cluster: "my-cluster"}, }, CurrentContext: "minikube", AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "minikube": {Token: "minikube-token"}, - "my-cluser": {Token: "minikube-token"}, + "minikube": {Token: "minikube-token"}, + "mu-cluster": {Token: "minikube-token"}, }, } + test := viewClusterTest{ description: "Testing for kubectl config view", config: conf, - flags: []string{}, expected: `apiVersion: v1 clusters: - cluster: @@ -72,7 +72,7 @@ contexts: - context: cluster: my-cluster user: mu-cluster - name: my-cluser + name: my-cluster current-context: minikube kind: Config preferences: {} @@ -80,10 +80,13 @@ users: - name: minikube user: token: minikube-token -- name: my-cluser +- name: mu-cluster user: - token: minikube-token` + "\n"} + token: minikube-token` + "\n", + } + test.run(t) + } func TestViewClusterMinify(t *testing.T) { @@ -95,20 +98,27 @@ func TestViewClusterMinify(t *testing.T) { "my-cluster": {Server: "https://192.168.0.1:3434"}, }, Contexts: map[string]*clientcmdapi.Context{ - "minikube": {AuthInfo: "minikube", Cluster: "minikube"}, - "my-cluser": {AuthInfo: "mu-cluster", Cluster: "my-cluster"}, + "minikube": {AuthInfo: "minikube", Cluster: "minikube"}, + "my-cluster": {AuthInfo: "mu-cluster", Cluster: "my-cluster"}, }, CurrentContext: "minikube", AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "minikube": {Token: "minikube-token"}, - "my-cluser": {Token: "minikube-token"}, + "minikube": {Token: "minikube-token"}, + "mu-cluster": {Token: "minikube-token"}, }, } - test := viewClusterTest{ - description: "Testing for kubectl config view --minify=true", - config: conf, - flags: []string{"--minify=true"}, - expected: `apiVersion: v1 + + testCases := []struct { + description string + config clientcmdapi.Config + flags []string + expected string + }{ + { + description: "Testing for kubectl config view --minify=true", + config: conf, + flags: []string{"--minify=true"}, + expected: `apiVersion: v1 clusters: - cluster: server: https://192.168.99.100:8443 @@ -124,8 +134,41 @@ preferences: {} users: - name: minikube user: - token: minikube-token` + "\n"} - test.run(t) + token: minikube-token` + "\n", + }, + { + description: "Testing for kubectl config view --minify=true --context=my-cluster", + config: conf, + flags: []string{"--minify=true", "--context=my-cluster"}, + expected: `apiVersion: v1 +clusters: +- cluster: + server: https://192.168.0.1:3434 + name: my-cluster +contexts: +- context: + cluster: my-cluster + user: mu-cluster + name: my-cluster +current-context: my-cluster +kind: Config +preferences: {} +users: +- name: mu-cluster + user: + token: minikube-token` + "\n", + }, + } + + for _, test := range testCases { + cmdTest := viewClusterTest{ + description: test.description, + config: test.config, + flags: test.flags, + expected: test.expected, + } + cmdTest.run(t) + } } func (test viewClusterTest) run(t *testing.T) { @@ -143,7 +186,10 @@ func (test viewClusterTest) run(t *testing.T) { pathOptions.EnvVar = "" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdConfigView(cmdutil.NewFactory(genericclioptions.NewTestConfigFlags()), streams, pathOptions) + // "context" is a global flag, inherited from base kubectl command in the real world + cmd.Flags().String("context", "", "The name of the kubeconfig context to use") cmd.Flags().Parse(test.flags) + if err := cmd.Execute(); err != nil { t.Fatalf("unexpected error executing command: %v,kubectl config view flags: %v", err, test.flags) } diff --git a/pkg/kubectl/cmd/convert.go b/pkg/kubectl/cmd/convert.go index ec29cdca15a..c22c2990dad 100644 --- a/pkg/kubectl/cmd/convert.go +++ b/pkg/kubectl/cmd/convert.go @@ -139,7 +139,7 @@ func (o *ConvertOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) (err er o.builder.Schema(schema) } - cmdNamespace, _, err := f.DefaultNamespace() + cmdNamespace, _, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/convert_test.go b/pkg/kubectl/cmd/convert_test.go index 72ff0755ee5..8f3e8cf85e4 100644 --- a/pkg/kubectl/cmd/convert_test.go +++ b/pkg/kubectl/cmd/convert_test.go @@ -95,7 +95,7 @@ func TestConvertObject(t *testing.T) { for _, tc := range testcases { for _, field := range tc.fields { t.Run(fmt.Sprintf("%s %s", tc.name, field), func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -104,7 +104,6 @@ func TestConvertObject(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" buf := bytes.NewBuffer([]byte{}) cmd := NewCmdConvert(tf, genericclioptions.IOStreams{Out: buf, ErrOut: buf}) diff --git a/pkg/kubectl/cmd/cp.go b/pkg/kubectl/cmd/cp.go index ff486853baa..aaa066dc2f2 100644 --- a/pkg/kubectl/cmd/cp.go +++ b/pkg/kubectl/cmd/cp.go @@ -113,30 +113,25 @@ var ( ) func extractFileSpec(arg string) (fileSpec, error) { - pieces := strings.Split(arg, ":") - if len(pieces) == 1 { + if i := strings.Index(arg, ":"); i == -1 { return fileSpec{File: arg}, nil - } - if len(pieces) != 2 { - // FIXME Kubernetes can't copy files that contain a ':' - // character. - return fileSpec{}, errFileSpecDoesntMatchFormat - } - file := pieces[1] - - pieces = strings.Split(pieces[0], "/") - if len(pieces) == 1 { - return fileSpec{ - PodName: pieces[0], - File: file, - }, nil - } - if len(pieces) == 2 { - return fileSpec{ - PodNamespace: pieces[0], - PodName: pieces[1], - File: file, - }, nil + } else if i > 0 { + file := arg[i+1:] + pod := arg[:i] + pieces := strings.Split(pod, "/") + if len(pieces) == 1 { + return fileSpec{ + PodName: pieces[0], + File: file, + }, nil + } + if len(pieces) == 2 { + return fileSpec{ + PodNamespace: pieces[0], + PodName: pieces[1], + File: file, + }, nil + } } return fileSpec{}, errFileSpecDoesntMatchFormat @@ -144,7 +139,7 @@ func extractFileSpec(arg string) (fileSpec, error) { func (o *CopyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { var err error - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -177,13 +172,21 @@ func (o *CopyOptions) Run(args []string) error { if err != nil { return err } + + if len(srcSpec.PodName) != 0 && len(destSpec.PodName) != 0 { + if _, err := os.Stat(args[0]); err == nil { + return o.copyToPod(fileSpec{File: args[0]}, destSpec) + } + return fmt.Errorf("src doesn't exist in local filesystem") + } + if len(srcSpec.PodName) != 0 { return o.copyFromPod(srcSpec, destSpec) } if len(destSpec.PodName) != 0 { return o.copyToPod(srcSpec, destSpec) } - return fmt.Errorf("One of src or dest must be a remote file specification") + return fmt.Errorf("one of src or dest must be a remote file specification") } // checkDestinationIsDir receives a destination fileSpec and @@ -287,9 +290,22 @@ func (o *CopyOptions) copyFromPod(src, dest fileSpec) error { }() prefix := getPrefix(src.File) prefix = path.Clean(prefix) + // remove extraneous path shortcuts - these could occur if a path contained extra "../" + // and attempted to navigate beyond "/" in a remote filesystem + prefix = stripPathShortcuts(prefix) return untarAll(reader, dest.File, prefix) } +// stripPathShortcuts removes any leading or trailing "../" from a given path +func stripPathShortcuts(p string) string { + newPath := path.Clean(p) + if len(newPath) > 0 && string(newPath[0]) == "/" { + return newPath[1:] + } + + return newPath +} + func makeTar(srcPath, destPath string, writer io.Writer) error { // TODO: use compression here? tarWriter := tar.NewWriter(writer) diff --git a/pkg/kubectl/cmd/cp_test.go b/pkg/kubectl/cmd/cp_test.go index 925383a7260..a01747e8089 100644 --- a/pkg/kubectl/cmd/cp_test.go +++ b/pkg/kubectl/cmd/cp_test.go @@ -71,13 +71,18 @@ func TestExtractFileSpec(t *testing.T) { expectedFile: "/some/file", }, { - spec: "some:bad:spec", + spec: ":file:not:exist:in:local:filesystem", expectErr: true, }, { spec: "namespace/pod/invalid:/some/file", expectErr: true, }, + { + spec: "pod:/some/filenamewith:in", + expectedPod: "pod", + expectedFile: "/some/filenamewith:in", + }, } for _, test := range tests { spec, err := extractFileSpec(test.spec) @@ -514,8 +519,7 @@ func TestClean(t *testing.T) { } func TestCopyToPod(t *testing.T) { - tf := cmdtesting.NewTestFactory() - tf.Namespace = "test" + tf := cmdtesting.NewTestFactory().WithNamespace("test") ns := legacyscheme.Codecs codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) diff --git a/pkg/kubectl/cmd/create/create.go b/pkg/kubectl/cmd/create/create.go index 1be7fc47562..556e6d15afa 100644 --- a/pkg/kubectl/cmd/create/create.go +++ b/pkg/kubectl/cmd/create/create.go @@ -216,7 +216,7 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error { return err } - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -386,7 +386,7 @@ func (o *CreateSubcommandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command return printer.PrintObj(obj, out) } - o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/create/create_clusterrole_test.go b/pkg/kubectl/cmd/create/create_clusterrole_test.go index 4dc876f9a9e..647c0865751 100644 --- a/pkg/kubectl/cmd/create/create_clusterrole_test.go +++ b/pkg/kubectl/cmd/create/create_clusterrole_test.go @@ -36,10 +36,9 @@ import ( func TestCreateClusterRole(t *testing.T) { clusterRoleName := "my-cluster-role" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.Client = &fake.RESTClient{} tf.ClientConfigVal = defaultClientConfig() @@ -178,11 +177,9 @@ func TestCreateClusterRole(t *testing.T) { } func TestClusterRoleValidate(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" - tests := map[string]struct { clusterRoleOptions *CreateClusterRoleOptions expectErr bool diff --git a/pkg/kubectl/cmd/create/create_clusterrolebinding_test.go b/pkg/kubectl/cmd/create/create_clusterrolebinding_test.go index 206d6da73b2..69f1559aac9 100644 --- a/pkg/kubectl/cmd/create/create_clusterrolebinding_test.go +++ b/pkg/kubectl/cmd/create/create_clusterrolebinding_test.go @@ -68,7 +68,7 @@ func TestCreateClusterRoleBinding(t *testing.T) { }, } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() ns := legacyscheme.Codecs @@ -77,7 +77,6 @@ func TestCreateClusterRoleBinding(t *testing.T) { encoder := ns.EncoderForVersion(info.Serializer, groupVersion) decoder := ns.DecoderToVersion(info.Serializer, groupVersion) - tf.Namespace = "test" tf.Client = &ClusterRoleBindingRESTClient{ RESTClient: &fake.RESTClient{ NegotiatedSerializer: ns, diff --git a/pkg/kubectl/cmd/create/create_configmap_test.go b/pkg/kubectl/cmd/create/create_configmap_test.go index 65aac513988..8ee9501bcbf 100644 --- a/pkg/kubectl/cmd/create/create_configmap_test.go +++ b/pkg/kubectl/cmd/create/create_configmap_test.go @@ -36,7 +36,7 @@ import ( func TestCreateConfigMap(t *testing.T) { configMap := &v1.ConfigMap{} configMap.Name = "my-configmap" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -55,7 +55,6 @@ func TestCreateConfigMap(t *testing.T) { } }), } - tf.Namespace = "test" ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreateConfigMap(tf, ioStreams) cmd.Flags().Set("output", "name") diff --git a/pkg/kubectl/cmd/create/create_deployment_test.go b/pkg/kubectl/cmd/create/create_deployment_test.go index af1e48f081e..bd42fcfedd0 100644 --- a/pkg/kubectl/cmd/create/create_deployment_test.go +++ b/pkg/kubectl/cmd/create/create_deployment_test.go @@ -89,7 +89,7 @@ func Test_generatorFromName(t *testing.T) { func TestCreateDeployment(t *testing.T) { depName := "jonny-dep" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() ns := legacyscheme.Codecs @@ -104,7 +104,6 @@ func TestCreateDeployment(t *testing.T) { }), } tf.ClientConfigVal = &restclient.Config{} - tf.Namespace = "test" ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreateDeployment(tf, ioStreams) @@ -120,7 +119,7 @@ func TestCreateDeployment(t *testing.T) { func TestCreateDeploymentNoImage(t *testing.T) { depName := "jonny-dep" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() ns := legacyscheme.Codecs @@ -135,7 +134,6 @@ func TestCreateDeploymentNoImage(t *testing.T) { }), } tf.ClientConfigVal = &restclient.Config{} - tf.Namespace = "test" ioStreams := genericclioptions.NewTestIOStreamsDiscard() cmd := NewCmdCreateDeployment(tf, ioStreams) diff --git a/pkg/kubectl/cmd/create/create_job.go b/pkg/kubectl/cmd/create/create_job.go index 9980fa2866d..d4f024e470b 100644 --- a/pkg/kubectl/cmd/create/create_job.go +++ b/pkg/kubectl/cmd/create/create_job.go @@ -100,7 +100,7 @@ func (o *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args } o.Name = args[0] - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/create/create_pdb_test.go b/pkg/kubectl/cmd/create/create_pdb_test.go index 06a7fd80c80..01d6ee99e8d 100644 --- a/pkg/kubectl/cmd/create/create_pdb_test.go +++ b/pkg/kubectl/cmd/create/create_pdb_test.go @@ -32,7 +32,7 @@ import ( func TestCreatePdb(t *testing.T) { pdbName := "my-pdb" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() ns := legacyscheme.Codecs @@ -48,7 +48,6 @@ func TestCreatePdb(t *testing.T) { }), } tf.ClientConfigVal = &restclient.Config{} - tf.Namespace = "test" outputFormat := "name" diff --git a/pkg/kubectl/cmd/create/create_priorityclass_test.go b/pkg/kubectl/cmd/create/create_priorityclass_test.go index c4048820ab3..2f775be6385 100644 --- a/pkg/kubectl/cmd/create/create_priorityclass_test.go +++ b/pkg/kubectl/cmd/create/create_priorityclass_test.go @@ -38,7 +38,7 @@ func TestCreatePriorityClass(t *testing.T) { ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Group: "scheduling.k8s.io", Version: "v1alpha1"}, + GroupVersion: schema.GroupVersion{Group: "scheduling.k8s.io", Version: "v1beta1"}, NegotiatedSerializer: ns, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { return &http.Response{ diff --git a/pkg/kubectl/cmd/create/create_quota_test.go b/pkg/kubectl/cmd/create/create_quota_test.go index c9bf1333eb5..c780beafefd 100644 --- a/pkg/kubectl/cmd/create/create_quota_test.go +++ b/pkg/kubectl/cmd/create/create_quota_test.go @@ -51,11 +51,9 @@ func TestCreateQuota(t *testing.T) { } for name, test := range tests { t.Run(name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" - ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreateQuota(tf, ioStreams) cmd.Flags().Parse(test.flags) diff --git a/pkg/kubectl/cmd/create/create_role.go b/pkg/kubectl/cmd/create/create_role.go index 53243761dc0..d01014b45f1 100644 --- a/pkg/kubectl/cmd/create/create_role.go +++ b/pkg/kubectl/cmd/create/create_role.go @@ -226,7 +226,7 @@ func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args return printer.PrintObj(obj, o.Out) } - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/create/create_role_test.go b/pkg/kubectl/cmd/create/create_role_test.go index c2284c3ec8a..4551bea8541 100644 --- a/pkg/kubectl/cmd/create/create_role_test.go +++ b/pkg/kubectl/cmd/create/create_role_test.go @@ -34,10 +34,9 @@ import ( func TestCreateRole(t *testing.T) { roleName := "my-role" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.Client = &fake.RESTClient{} tf.ClientConfigVal = defaultClientConfig() @@ -152,11 +151,9 @@ func TestCreateRole(t *testing.T) { } func TestValidate(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" - tests := map[string]struct { roleOptions *CreateRoleOptions expectErr bool @@ -357,10 +354,9 @@ func TestValidate(t *testing.T) { func TestComplete(t *testing.T) { roleName := "my-role" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.Client = &fake.RESTClient{} tf.ClientConfigVal = defaultClientConfig() diff --git a/pkg/kubectl/cmd/create/create_rolebinding_test.go b/pkg/kubectl/cmd/create/create_rolebinding_test.go index f57b2351204..f9cb82518f7 100644 --- a/pkg/kubectl/cmd/create/create_rolebinding_test.go +++ b/pkg/kubectl/cmd/create/create_rolebinding_test.go @@ -70,7 +70,7 @@ func TestCreateRoleBinding(t *testing.T) { }, } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() ns := legacyscheme.Codecs @@ -79,7 +79,6 @@ func TestCreateRoleBinding(t *testing.T) { encoder := ns.EncoderForVersion(info.Serializer, groupVersion) decoder := ns.DecoderToVersion(info.Serializer, groupVersion) - tf.Namespace = "test" tf.Client = &RoleBindingRESTClient{ RESTClient: &fake.RESTClient{ NegotiatedSerializer: ns, diff --git a/pkg/kubectl/cmd/create/create_secret_test.go b/pkg/kubectl/cmd/create/create_secret_test.go index 21b41a8520c..6bdf4475966 100644 --- a/pkg/kubectl/cmd/create/create_secret_test.go +++ b/pkg/kubectl/cmd/create/create_secret_test.go @@ -37,7 +37,7 @@ func TestCreateSecretGeneric(t *testing.T) { }, } secretObject.Name = "my-secret" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -56,7 +56,6 @@ func TestCreateSecretGeneric(t *testing.T) { } }), } - tf.Namespace = "test" ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreateSecretGeneric(tf, ioStreams) cmd.Flags().Set("output", "name") @@ -72,7 +71,7 @@ func TestCreateSecretGeneric(t *testing.T) { func TestCreateSecretDockerRegistry(t *testing.T) { secretObject := &v1.Secret{} secretObject.Name = "my-secret" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs @@ -89,7 +88,6 @@ func TestCreateSecretDockerRegistry(t *testing.T) { } }), } - tf.Namespace = "test" ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreateSecretDockerRegistry(tf, ioStreams) cmd.Flags().Set("docker-username", "test-user") diff --git a/pkg/kubectl/cmd/create/create_service_test.go b/pkg/kubectl/cmd/create/create_service_test.go index 9fd018f1852..eb622922214 100644 --- a/pkg/kubectl/cmd/create/create_service_test.go +++ b/pkg/kubectl/cmd/create/create_service_test.go @@ -32,7 +32,7 @@ import ( func TestCreateService(t *testing.T) { service := &v1.Service{} service.Name = "my-service" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -51,7 +51,6 @@ func TestCreateService(t *testing.T) { } }), } - tf.Namespace = "test" ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreateServiceClusterIP(tf, ioStreams) cmd.Flags().Set("output", "name") @@ -66,7 +65,7 @@ func TestCreateService(t *testing.T) { func TestCreateServiceNodePort(t *testing.T) { service := &v1.Service{} service.Name = "my-node-port-service" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -85,7 +84,6 @@ func TestCreateServiceNodePort(t *testing.T) { } }), } - tf.Namespace = "test" ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreateServiceNodePort(tf, ioStreams) cmd.Flags().Set("output", "name") @@ -100,7 +98,7 @@ func TestCreateServiceNodePort(t *testing.T) { func TestCreateServiceExternalName(t *testing.T) { service := &v1.Service{} service.Name = "my-external-name-service" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -119,7 +117,6 @@ func TestCreateServiceExternalName(t *testing.T) { } }), } - tf.Namespace = "test" ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreateServiceExternalName(tf, ioStreams) cmd.Flags().Set("output", "name") diff --git a/pkg/kubectl/cmd/create/create_serviceaccount_test.go b/pkg/kubectl/cmd/create/create_serviceaccount_test.go index 2f62c05fd3c..06f9e35642a 100644 --- a/pkg/kubectl/cmd/create/create_serviceaccount_test.go +++ b/pkg/kubectl/cmd/create/create_serviceaccount_test.go @@ -32,7 +32,7 @@ import ( func TestCreateServiceAccount(t *testing.T) { serviceAccountObject := &v1.ServiceAccount{} serviceAccountObject.Name = "my-service-account" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -51,7 +51,6 @@ func TestCreateServiceAccount(t *testing.T) { } }), } - tf.Namespace = "test" ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreateServiceAccount(tf, ioStreams) cmd.Flags().Set("output", "name") diff --git a/pkg/kubectl/cmd/create/create_test.go b/pkg/kubectl/cmd/create/create_test.go index 607a3bfbd3f..dba513d8b93 100644 --- a/pkg/kubectl/cmd/create/create_test.go +++ b/pkg/kubectl/cmd/create/create_test.go @@ -51,7 +51,7 @@ func TestCreateObject(t *testing.T) { _, _, rc := testData() rc.Items[0].Name = "redis-master-controller" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -69,7 +69,6 @@ func TestCreateObject(t *testing.T) { } }), } - tf.Namespace = "test" ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreate(tf, ioStreams) @@ -87,7 +86,7 @@ func TestCreateMultipleObject(t *testing.T) { initTestErrorHandler(t) _, svc, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -107,7 +106,6 @@ func TestCreateMultipleObject(t *testing.T) { } }), } - tf.Namespace = "test" ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreate(tf, ioStreams) @@ -127,7 +125,7 @@ func TestCreateDirectory(t *testing.T) { _, _, rc := testData() rc.Items[0].Name = "name" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -145,7 +143,6 @@ func TestCreateDirectory(t *testing.T) { } }), } - tf.Namespace = "test" ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdCreate(tf, ioStreams) diff --git a/pkg/kubectl/cmd/create/flags.go b/pkg/kubectl/cmd/create/flags.go index 7c7540c9bdc..e1bf63cf465 100644 --- a/pkg/kubectl/cmd/create/flags.go +++ b/pkg/kubectl/cmd/create/flags.go @@ -38,6 +38,11 @@ type PrintFlags struct { OutputFormat *string } +func (f *PrintFlags) AllowedFormats() []string { + return append(append(f.JSONYamlPrintFlags.AllowedFormats(), f.NamePrintFlags.AllowedFormats()...), + f.TemplateFlags.AllowedFormats()...) +} + func (f *PrintFlags) Complete(successTemplate string) error { return f.NamePrintFlags.Complete(successTemplate) } @@ -60,7 +65,7 @@ func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) { return f.TypeSetter.WrapToPrinter(p, err) } - return nil, genericclioptions.NoCompatiblePrinterError{Options: f} + return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()} } func (f *PrintFlags) AddFlags(cmd *cobra.Command) { diff --git a/pkg/kubectl/cmd/delete.go b/pkg/kubectl/cmd/delete.go index 2f2bd91508a..dc0d63ca198 100644 --- a/pkg/kubectl/cmd/delete.go +++ b/pkg/kubectl/cmd/delete.go @@ -139,14 +139,12 @@ func NewCmdDelete(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra deleteFlags.AddFlags(cmd) - cmd.Flags().Bool("wait", true, `If true, wait for resources to be gone before returning. This waits for finalizers.`) - cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } func (o *DeleteOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Command) error { - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -165,14 +163,9 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Co } if o.GracePeriod == 0 && !o.ForceDeletion { // To preserve backwards compatibility, but prevent accidental data loss, we convert --grace-period=0 - // into --grace-period=1 and wait until the object is successfully deleted. Users may provide --force - // to bypass this wait. - o.WaitForDeletion = true + // into --grace-period=1. Users may provide --force to bypass this conversion. o.GracePeriod = 1 } - if b, err := cmd.Flags().GetBool("wait"); err == nil { - o.WaitForDeletion = b - } includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) r := f.NewBuilder(). @@ -218,6 +211,11 @@ func (o *DeleteOptions) Validate(cmd *cobra.Command) error { return fmt.Errorf("cannot set --all and --field-selector at the same time") } + if o.GracePeriod == 0 && !o.ForceDeletion && !o.WaitForDeletion { + // With the explicit --wait flag we need extra validation for backward compatibility + return fmt.Errorf("--grace-period=0 must have either --force specified, or --wait to be set to true") + } + switch { case o.GracePeriod == 0 && o.ForceDeletion: fmt.Fprintf(o.ErrOut, "warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.\n") @@ -275,7 +273,7 @@ func (o *DeleteOptions) DeleteResult(r *resource.Result) error { effectiveTimeout = 168 * time.Hour } waitOptions := kubectlwait.WaitOptions{ - ResourceFinder: kubectlwait.ResourceFinderForResult(o.Result), + ResourceFinder: genericclioptions.ResourceFinderForResult(r), DynamicClient: o.DynamicClient, Timeout: effectiveTimeout, @@ -293,8 +291,8 @@ func (o *DeleteOptions) DeleteResult(r *resource.Result) error { } func (o *DeleteOptions) deleteResource(info *resource.Info, deleteOptions *metav1.DeleteOptions) error { - // TODO: this should be removed as soon as DaemonSet controller properly handles object deletion - // see https://github.com/kubernetes/kubernetes/issues/64313 for details + // TODO: Remove this in or after 1.12 release. + // Server version >= 1.11 no longer needs this hack. mapping := info.ResourceMapping() if mapping.Resource.GroupResource() == (schema.GroupResource{Group: "extensions", Resource: "daemonsets"}) || mapping.Resource.GroupResource() == (schema.GroupResource{Group: "apps", Resource: "daemonsets"}) { @@ -311,6 +309,8 @@ func (o *DeleteOptions) deleteResource(info *resource.Info, deleteOptions *metav return nil } +// TODO: Remove this in or after 1.12 release. +// Server version >= 1.11 no longer needs this hack. func updateDaemonSet(namespace, name string, dynamicClient dynamic.Interface) error { dsClient := dynamicClient.Resource(schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"}).Namespace(namespace) obj, err := dsClient.Get(name, metav1.GetOptions{}) diff --git a/pkg/kubectl/cmd/delete_flags.go b/pkg/kubectl/cmd/delete_flags.go index 1a5a6db3e2c..c98d1fce0f5 100644 --- a/pkg/kubectl/cmd/delete_flags.go +++ b/pkg/kubectl/cmd/delete_flags.go @@ -22,44 +22,13 @@ import ( "github.com/spf13/cobra" "k8s.io/client-go/dynamic" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" - "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" ) -type FileNameFlags struct { - Usage string - - Filenames *[]string - Recursive *bool -} - -func (o *FileNameFlags) ToOptions() resource.FilenameOptions { - options := resource.FilenameOptions{} - - if o.Recursive != nil { - options.Recursive = *o.Recursive - } - if o.Filenames != nil { - options.Filenames = *o.Filenames - } - - return options -} - -func (o *FileNameFlags) AddFlags(cmd *cobra.Command) { - if o.Recursive != nil { - cmd.Flags().BoolVarP(o.Recursive, "recursive", "R", *o.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") - } - if o.Filenames != nil { - kubectl.AddJsonFilenameFlag(cmd, o.Filenames, "Filename, directory, or URL to files "+o.Usage) - } -} - // PrintFlags composes common printer flag structs // used for commands requiring deletion logic. type DeleteFlags struct { - FileNameFlags *FileNameFlags + FileNameFlags *genericclioptions.FileNameFlags LabelSelector *string FieldSelector *string @@ -70,6 +39,7 @@ type DeleteFlags struct { IgnoreNotFound *bool Now *bool Timeout *time.Duration + Wait *bool Output *string } @@ -116,12 +86,15 @@ func (f *DeleteFlags) ToOptions(dynamicClient dynamic.Interface, streams generic if f.Timeout != nil { options.Timeout = *f.Timeout } + if f.Wait != nil { + options.WaitForDeletion = *f.Wait + } return options } func (f *DeleteFlags) AddFlags(cmd *cobra.Command) { - f.FileNameFlags.AddFlags(cmd) + f.FileNameFlags.AddFlags(cmd.Flags()) if f.LabelSelector != nil { cmd.Flags().StringVarP(f.LabelSelector, "selector", "l", *f.LabelSelector, "Selector (label query) to filter on, not including uninitialized ones.") } @@ -149,11 +122,12 @@ func (f *DeleteFlags) AddFlags(cmd *cobra.Command) { if f.IgnoreNotFound != nil { cmd.Flags().BoolVar(f.IgnoreNotFound, "ignore-not-found", *f.IgnoreNotFound, "Treat \"resource not found\" as a successful delete. Defaults to \"true\" when --all is specified.") } - + if f.Wait != nil { + cmd.Flags().BoolVar(f.Wait, "wait", *f.Wait, "If true, wait for resources to be gone before returning. This waits for finalizers.") + } if f.Output != nil { cmd.Flags().StringVarP(f.Output, "output", "o", *f.Output, "Output mode. Use \"-o name\" for shorter output (resource/name).") } - } // NewDeleteCommandFlags provides default flags and values for use with the "delete" command @@ -170,12 +144,13 @@ func NewDeleteCommandFlags(usage string) *DeleteFlags { labelSelector := "" fieldSelector := "" timeout := time.Duration(0) + wait := true filenames := []string{} recursive := false return &DeleteFlags{ - FileNameFlags: &FileNameFlags{Usage: usage, Filenames: &filenames, Recursive: &recursive}, + FileNameFlags: &genericclioptions.FileNameFlags{Usage: usage, Filenames: &filenames, Recursive: &recursive}, LabelSelector: &labelSelector, FieldSelector: &fieldSelector, @@ -187,6 +162,7 @@ func NewDeleteCommandFlags(usage string) *DeleteFlags { IgnoreNotFound: &ignoreNotFound, Now: &now, Timeout: &timeout, + Wait: &wait, Output: &output, } } @@ -198,12 +174,13 @@ func NewDeleteFlags(usage string) *DeleteFlags { force := false timeout := time.Duration(0) + wait := false filenames := []string{} recursive := false return &DeleteFlags{ - FileNameFlags: &FileNameFlags{Usage: usage, Filenames: &filenames, Recursive: &recursive}, + FileNameFlags: &genericclioptions.FileNameFlags{Usage: usage, Filenames: &filenames, Recursive: &recursive}, Cascade: &cascade, GracePeriod: &gracePeriod, @@ -211,5 +188,6 @@ func NewDeleteFlags(usage string) *DeleteFlags { // add non-defaults Force: &force, Timeout: &timeout, + Wait: &wait, } } diff --git a/pkg/kubectl/cmd/delete_test.go b/pkg/kubectl/cmd/delete_test.go index 51fb4a887c7..71e4405f3a2 100644 --- a/pkg/kubectl/cmd/delete_test.go +++ b/pkg/kubectl/cmd/delete_test.go @@ -52,7 +52,7 @@ func TestDeleteObjectByTuple(t *testing.T) { initTestErrorHandler(t) _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -77,7 +77,6 @@ func TestDeleteObjectByTuple(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdDelete(tf, streams) @@ -118,7 +117,7 @@ func TestOrphanDependentsInDeleteObject(t *testing.T) { initTestErrorHandler(t) _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -137,7 +136,6 @@ func TestOrphanDependentsInDeleteObject(t *testing.T) { } }), } - tf.Namespace = "test" // DeleteOptions.PropagationPolicy should be Foreground, when cascade is true (default). foregroundPolicy := metav1.DeletePropagationForeground @@ -170,7 +168,7 @@ func TestDeleteNamedObject(t *testing.T) { initTestErrorHandler(t) _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -195,7 +193,6 @@ func TestDeleteNamedObject(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdDelete(tf, streams) @@ -223,7 +220,7 @@ func TestDeleteObject(t *testing.T) { initTestErrorHandler(t) _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -240,7 +237,6 @@ func TestDeleteObject(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdDelete(tf, streams) @@ -260,7 +256,7 @@ func TestDeleteObjectGraceZero(t *testing.T) { pods, _, _ := testData() count := 0 - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -288,7 +284,6 @@ func TestDeleteObjectGraceZero(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, errBuf := genericclioptions.NewTestIOStreams() cmd := NewCmdDelete(tf, streams) @@ -307,7 +302,7 @@ func TestDeleteObjectGraceZero(t *testing.T) { func TestDeleteObjectNotFound(t *testing.T) { initTestErrorHandler(t) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -322,7 +317,6 @@ func TestDeleteObjectNotFound(t *testing.T) { } }), } - tf.Namespace = "test" options := &DeleteOptions{ FilenameOptions: resource.FilenameOptions{ @@ -345,7 +339,7 @@ func TestDeleteObjectNotFound(t *testing.T) { func TestDeleteObjectIgnoreNotFound(t *testing.T) { initTestErrorHandler(t) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -360,7 +354,6 @@ func TestDeleteObjectIgnoreNotFound(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdDelete(tf, streams) @@ -382,7 +375,7 @@ func TestDeleteAllNotFound(t *testing.T) { svc.Items = append(svc.Items, api.Service{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}) notFoundError := &errors.NewNotFound(api.Resource("services"), "foo").ErrStatus - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -403,7 +396,6 @@ func TestDeleteAllNotFound(t *testing.T) { } }), } - tf.Namespace = "test" // Make sure we can explicitly choose to fail on NotFound errors, even with --all options := &DeleteOptions{ @@ -429,7 +421,7 @@ func TestDeleteAllIgnoreNotFound(t *testing.T) { initTestErrorHandler(t) _, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -454,7 +446,6 @@ func TestDeleteAllIgnoreNotFound(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdDelete(tf, streams) @@ -472,7 +463,7 @@ func TestDeleteMultipleObject(t *testing.T) { initTestErrorHandler(t) _, svc, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -491,7 +482,6 @@ func TestDeleteMultipleObject(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdDelete(tf, streams) @@ -510,7 +500,7 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { initTestErrorHandler(t) _, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -529,7 +519,6 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() options := &DeleteOptions{ @@ -558,7 +547,7 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { func TestDeleteMultipleResourcesWithTheSameName(t *testing.T) { initTestErrorHandler(t) _, svc, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -582,7 +571,6 @@ func TestDeleteMultipleResourcesWithTheSameName(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdDelete(tf, streams) @@ -599,7 +587,7 @@ func TestDeleteDirectory(t *testing.T) { initTestErrorHandler(t) _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -616,7 +604,6 @@ func TestDeleteDirectory(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdDelete(tf, streams) @@ -634,7 +621,7 @@ func TestDeleteMultipleSelector(t *testing.T) { initTestErrorHandler(t) pods, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -663,7 +650,6 @@ func TestDeleteMultipleSelector(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdDelete(tf, streams) @@ -703,10 +689,9 @@ func TestResourceErrors(t *testing.T) { for k, testCase := range testCases { t.Run(k, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() diff --git a/pkg/kubectl/cmd/describe.go b/pkg/kubectl/cmd/describe.go index 848f82100f8..3a0feafdd8f 100644 --- a/pkg/kubectl/cmd/describe.go +++ b/pkg/kubectl/cmd/describe.go @@ -122,7 +122,7 @@ func NewCmdDescribe(parent string, f cmdutil.Factory, streams genericclioptions. func (o *DescribeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { var err error - o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/describe_test.go b/pkg/kubectl/cmd/describe_test.go index ecc0fc8c4ed..daac115ed6f 100644 --- a/pkg/kubectl/cmd/describe_test.go +++ b/pkg/kubectl/cmd/describe_test.go @@ -41,7 +41,7 @@ func TestDescribeUnknownSchemaObject(t *testing.T) { }() cmdutil.DescriberFn = d.describerFor - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("non-default") defer tf.Cleanup() _, _, codec := cmdtesting.NewExternalScheme() @@ -52,7 +52,6 @@ func TestDescribeUnknownSchemaObject(t *testing.T) { streams, _, buf, _ := genericclioptions.NewTestIOStreams() - tf.Namespace = "non-default" cmd := NewCmdDescribe("kubectl", tf, streams) cmd.Run(cmd, []string{"type", "foo"}) @@ -82,7 +81,7 @@ func TestDescribeUnknownNamespacedSchemaObject(t *testing.T) { NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, cmdtesting.NewInternalNamespacedType("", "", "foo", "non-default"))}, } - tf.Namespace = "non-default" + tf.WithNamespace("non-default") streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -107,7 +106,7 @@ func TestDescribeObject(t *testing.T) { cmdutil.DescriberFn = d.describerFor _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -123,7 +122,6 @@ func TestDescribeObject(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -149,7 +147,7 @@ func TestDescribeListObjects(t *testing.T) { cmdutil.DescriberFn = d.describerFor pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -160,7 +158,6 @@ func TestDescribeListObjects(t *testing.T) { streams, _, buf, _ := genericclioptions.NewTestIOStreams() - tf.Namespace = "test" cmd := NewCmdDescribe("kubectl", tf, streams) cmd.Run(cmd, []string{"pods"}) if buf.String() != fmt.Sprintf("%s\n\n%s", d.Output, d.Output) { @@ -177,7 +174,7 @@ func TestDescribeObjectShowEvents(t *testing.T) { cmdutil.DescriberFn = d.describerFor pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -186,7 +183,6 @@ func TestDescribeObjectShowEvents(t *testing.T) { Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, } - tf.Namespace = "test" cmd := NewCmdDescribe("kubectl", tf, genericclioptions.NewTestIOStreamsDiscard()) cmd.Flags().Set("show-events", "true") cmd.Run(cmd, []string{"pods"}) @@ -204,7 +200,7 @@ func TestDescribeObjectSkipEvents(t *testing.T) { cmdutil.DescriberFn = d.describerFor pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -213,7 +209,6 @@ func TestDescribeObjectSkipEvents(t *testing.T) { Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, } - tf.Namespace = "test" cmd := NewCmdDescribe("kubectl", tf, genericclioptions.NewTestIOStreamsDiscard()) cmd.Flags().Set("show-events", "false") cmd.Run(cmd, []string{"pods"}) diff --git a/pkg/kubectl/cmd/diff.go b/pkg/kubectl/cmd/diff.go index d513c7ab762..d4cda1261b4 100644 --- a/pkg/kubectl/cmd/diff.go +++ b/pkg/kubectl/cmd/diff.go @@ -407,7 +407,7 @@ func NewDownloader(f cmdutil.Factory) (*Downloader, error) { if err != nil { return nil, err } - d.ns, _, _ = f.DefaultNamespace() + d.ns, _, _ = f.ToRawKubeConfigLoader().Namespace() return &d, nil } @@ -451,7 +451,7 @@ func RunDiff(f cmdutil.Factory, diff *DiffProgram, options *DiffOptions, from, t printer := Printer{} - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/drain.go b/pkg/kubectl/cmd/drain.go index 8a6383f9a2e..19a4b249ee9 100644 --- a/pkg/kubectl/cmd/drain.go +++ b/pkg/kubectl/cmd/drain.go @@ -263,7 +263,7 @@ func (o *DrainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st o.nodeInfos = []*resource.Info{} - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -586,6 +586,7 @@ func (o *DrainOptions) evictPods(pods []corev1.Pod, policyGroupVersion string, g doneCh <- true return } else if apierrors.IsTooManyRequests(err) { + fmt.Fprintf(o.ErrOut, "error when evicting pod %q (will retry after 5s): %v\n", pod.Name, err) time.Sleep(5 * time.Second) } else { errCh <- fmt.Errorf("error when evicting pod %q: %v", pod.Name, err) @@ -610,6 +611,7 @@ func (o *DrainOptions) evictPods(pods []corev1.Pod, policyGroupVersion string, g } else { globalTimeout = o.Timeout } + globalTimeoutCh := time.After(globalTimeout) for { select { case err := <-errCh: @@ -619,7 +621,7 @@ func (o *DrainOptions) evictPods(pods []corev1.Pod, policyGroupVersion string, g if doneCount == len(pods) { return nil } - case <-time.After(globalTimeout): + case <-globalTimeoutCh: return fmt.Errorf("Drain did not complete within %v", globalTimeout) } } diff --git a/pkg/kubectl/cmd/edit_test.go b/pkg/kubectl/cmd/edit_test.go index fe5fd28ae44..6820d64e7ad 100644 --- a/pkg/kubectl/cmd/edit_test.go +++ b/pkg/kubectl/cmd/edit_test.go @@ -224,12 +224,8 @@ func TestEdit(t *testing.T) { Client: fake.CreateHTTPClient(reqResp), }, nil } - - if len(testcase.Namespace) > 0 { - tf.Namespace = testcase.Namespace - } + tf.WithNamespace(testcase.Namespace) tf.ClientConfigVal = defaultClientConfig() - tf.CommandVal = "edit test cmd invocation" ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() var cmd *cobra.Command diff --git a/pkg/kubectl/cmd/exec.go b/pkg/kubectl/cmd/exec.go index 1866da37b42..5290b0fd22c 100644 --- a/pkg/kubectl/cmd/exec.go +++ b/pkg/kubectl/cmd/exec.go @@ -166,7 +166,7 @@ func (p *ExecOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []s } } - namespace, _, err := f.DefaultNamespace() + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/exec_test.go b/pkg/kubectl/cmd/exec_test.go index 90c0e4be2ee..187c6ff8f8d 100644 --- a/pkg/kubectl/cmd/exec_test.go +++ b/pkg/kubectl/cmd/exec_test.go @@ -132,7 +132,7 @@ func TestPodAndContainer(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() ns := legacyscheme.Codecs @@ -141,7 +141,6 @@ func TestPodAndContainer(t *testing.T) { NegotiatedSerializer: ns, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() cmd := &cobra.Command{} @@ -193,7 +192,7 @@ func TestExec(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -212,7 +211,6 @@ func TestExec(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ex := &fakeRemoteExecutor{} if test.execErr { diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index d36d47d736d..f0e309eb74f 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -188,7 +188,7 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e return err } - o.Generators = f.Generators + o.Generators = cmdutil.GeneratorFn o.Builder = f.NewBuilder() o.CanBeExposed = polymorphichelpers.CanBeExposedFn o.ClientForMapping = f.ClientForMapping @@ -201,7 +201,7 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e return err } - o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/expose_test.go b/pkg/kubectl/cmd/expose_test.go index 548a44ac5cb..7c4fa01e93c 100644 --- a/pkg/kubectl/cmd/expose_test.go +++ b/pkg/kubectl/cmd/expose_test.go @@ -467,7 +467,7 @@ func TestRunExposeService(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace(test.ns) defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -486,7 +486,6 @@ func TestRunExposeService(t *testing.T) { } }), } - tf.Namespace = test.ns ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdExposeService(tf, ioStreams) diff --git a/pkg/kubectl/cmd/get/get.go b/pkg/kubectl/cmd/get/get.go index ad6554c0ef8..8c4738d02c4 100644 --- a/pkg/kubectl/cmd/get/get.go +++ b/pkg/kubectl/cmd/get/get.go @@ -189,7 +189,7 @@ func (o *GetOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri } var err error - o.Namespace, o.ExplicitNamespace, err = f.DefaultNamespace() + o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -344,7 +344,7 @@ func (o *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e objs := make([]runtime.Object, len(infos)) for ix := range infos { if o.ServerPrint { - table, err := o.decodeIntoTable(cmdutil.InternalVersionJSONEncoder(), infos[ix].Object) + table, err := o.decodeIntoTable(infos[ix].Object) if err == nil { infos[ix].Object = table } else { @@ -597,34 +597,28 @@ func attemptToConvertToInternal(obj runtime.Object, converter runtime.ObjectConv return internalObject } -func (o *GetOptions) decodeIntoTable(encoder runtime.Encoder, obj runtime.Object) (runtime.Object, error) { +func (o *GetOptions) decodeIntoTable(obj runtime.Object) (runtime.Object, error) { if obj.GetObjectKind().GroupVersionKind().Kind != "Table" { return nil, fmt.Errorf("attempt to decode non-Table object into a v1beta1.Table") } - b, err := runtime.Encode(encoder, obj) - if err != nil { - return nil, err + unstr, ok := obj.(*unstructured.Unstructured) + if !ok { + return nil, fmt.Errorf("attempt to decode non-Unstructured object") } - table := &metav1beta1.Table{} - err = json.Unmarshal(b, table) - if err != nil { + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstr.Object, table); err != nil { return nil, err } for i := range table.Rows { row := &table.Rows[i] if row.Object.Raw == nil || row.Object.Object != nil { - //if row already has Object.Object - //we don't change it continue } - converted, err := runtime.Decode(unstructured.UnstructuredJSONScheme, row.Object.Raw) if err != nil { - //if error happens, we just continue - continue + return nil, err } row.Object.Object = converted } diff --git a/pkg/kubectl/cmd/get/get_flags.go b/pkg/kubectl/cmd/get/get_flags.go index e36321c8c13..0c479175b69 100644 --- a/pkg/kubectl/cmd/get/get_flags.go +++ b/pkg/kubectl/cmd/get/get_flags.go @@ -64,6 +64,15 @@ func (f *PrintFlags) Copy() PrintFlags { return printFlags } +func (f *PrintFlags) AllowedFormats() []string { + formats := f.JSONYamlPrintFlags.AllowedFormats() + formats = append(formats, f.NamePrintFlags.AllowedFormats()...) + formats = append(formats, f.TemplateFlags.AllowedFormats()...) + formats = append(formats, f.CustomColumnsFlags.AllowedFormats()...) + formats = append(formats, f.HumanReadableFlags.AllowedFormats()...) + return formats +} + // UseOpenAPIColumns modifies the output format, as well as the // "allowMissingKeys" option for template printers, to values // defined in the OpenAPI schema of a resource. @@ -132,7 +141,7 @@ func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) { return p, err } - return nil, genericclioptions.NoCompatiblePrinterError{Options: f} + return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()} } // AddFlags receives a *cobra.Command reference and binds diff --git a/pkg/kubectl/cmd/get/get_test.go b/pkg/kubectl/cmd/get/get_test.go index bdea31c0671..a6ab8990423 100644 --- a/pkg/kubectl/cmd/get/get_test.go +++ b/pkg/kubectl/cmd/get/get_test.go @@ -172,7 +172,7 @@ func testComponentStatusData() *api.ComponentStatusList { // Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. func TestGetUnknownSchemaObject(t *testing.T) { t.Skip("This test is completely broken. The first thing it does is add the object to the scheme!") - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() _, _, codec := cmdtesting.NewExternalScheme() tf.OpenAPISchemaFunc = openapitesting.CreateOpenAPISchemaFunc(openapiSchemaPath) @@ -190,7 +190,6 @@ func TestGetUnknownSchemaObject(t *testing.T) { Body: objBody(codec, obj), }, } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -225,7 +224,7 @@ func TestGetUnknownSchemaObject(t *testing.T) { // Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. func TestGetSchemaObject(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(schema.GroupVersion{Version: "v1"}) t.Logf("%v", string(runtime.EncodeOrDie(codec, &api.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}))) @@ -234,7 +233,6 @@ func TestGetSchemaObject(t *testing.T) { NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &api.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})}, } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -249,7 +247,7 @@ func TestGetSchemaObject(t *testing.T) { func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -260,7 +258,6 @@ func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) { NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -306,7 +303,7 @@ func testOpenAPISchemaData() (openapi.Resources, error) { func TestGetObjects(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -314,7 +311,6 @@ func TestGetObjects(t *testing.T) { NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -332,7 +328,7 @@ foo 0/0 0 func TestGetObjectsShowKind(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -340,7 +336,6 @@ func TestGetObjectsShowKind(t *testing.T) { NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -359,7 +354,7 @@ pod/foo 0/0 0 func TestGetObjectsShowLabels(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -367,7 +362,6 @@ func TestGetObjectsShowLabels(t *testing.T) { NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -398,7 +392,7 @@ func TestGetObjectIgnoreNotFound(t *testing.T) { }, } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -416,7 +410,6 @@ func TestGetObjectIgnoreNotFound(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -451,7 +444,7 @@ func TestGetSortedObjects(t *testing.T) { }, } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -459,7 +452,6 @@ func TestGetSortedObjects(t *testing.T) { NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: "v1"}}} streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -483,7 +475,7 @@ c 0/0 0 func TestGetObjectsIdentifiedByFile(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -491,7 +483,6 @@ func TestGetObjectsIdentifiedByFile(t *testing.T) { NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -510,7 +501,7 @@ foo 0/0 0 func TestGetListObjects(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -518,7 +509,6 @@ func TestGetListObjects(t *testing.T) { NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -537,7 +527,7 @@ bar 0/0 0 func TestGetListComponentStatus(t *testing.T) { statuses := testComponentStatusData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -545,7 +535,6 @@ func TestGetListComponentStatus(t *testing.T) { NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, statuses)}, } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -578,7 +567,7 @@ func TestGetMixedGenericObjects(t *testing.T) { Code: 0, } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -594,7 +583,6 @@ func TestGetMixedGenericObjects(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -628,7 +616,7 @@ func TestGetMixedGenericObjects(t *testing.T) { func TestGetMultipleTypeObjects(t *testing.T) { pods, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -646,7 +634,6 @@ func TestGetMultipleTypeObjects(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -667,7 +654,7 @@ service/baz ClusterIP func TestGetMultipleTypeObjectsAsList(t *testing.T) { pods, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -685,7 +672,6 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -767,7 +753,7 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) { func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) { pods, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -788,7 +774,6 @@ func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -811,7 +796,7 @@ service/baz ClusterIP func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) { pods, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -832,7 +817,6 @@ func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -860,7 +844,7 @@ func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) { }, } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -878,7 +862,6 @@ func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -969,7 +952,7 @@ func watchTestData() ([]api.Pod, []watch.Event) { func TestWatchLabelSelector(t *testing.T) { pods, events := watchTestData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -997,7 +980,6 @@ func TestWatchLabelSelector(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -1021,7 +1003,7 @@ foo 0/0 0 func TestWatchFieldSelector(t *testing.T) { pods, events := watchTestData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -1049,7 +1031,6 @@ func TestWatchFieldSelector(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -1073,7 +1054,7 @@ foo 0/0 0 func TestWatchResource(t *testing.T) { pods, events := watchTestData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -1095,7 +1076,6 @@ func TestWatchResource(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -1117,7 +1097,7 @@ foo 0/0 0 func TestWatchResourceIdentifiedByFile(t *testing.T) { pods, events := watchTestData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -1139,7 +1119,6 @@ func TestWatchResourceIdentifiedByFile(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -1162,7 +1141,7 @@ foo 0/0 0 func TestWatchOnlyResource(t *testing.T) { pods, events := watchTestData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -1184,7 +1163,6 @@ func TestWatchOnlyResource(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) @@ -1205,7 +1183,7 @@ foo 0/0 0 func TestWatchOnlyList(t *testing.T) { pods, events := watchTestData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -1230,7 +1208,6 @@ func TestWatchOnlyList(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdGet("kubectl", tf, streams) diff --git a/pkg/kubectl/cmd/get/humanreadable_flags.go b/pkg/kubectl/cmd/get/humanreadable_flags.go index 43c303a5f92..28b0e8f8b4c 100644 --- a/pkg/kubectl/cmd/get/humanreadable_flags.go +++ b/pkg/kubectl/cmd/get/humanreadable_flags.go @@ -61,11 +61,15 @@ func (f *HumanPrintFlags) EnsureWithNamespace() error { return nil } +func (f *HumanPrintFlags) AllowedFormats() []string { + return []string{"wide"} +} + // ToPrinter receives an outputFormat and returns a printer capable of // handling human-readable output. func (f *HumanPrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinter, error) { if len(outputFormat) > 0 && outputFormat != "wide" { - return nil, genericclioptions.NoCompatiblePrinterError{Options: f} + return nil, genericclioptions.NoCompatiblePrinterError{Options: f, AllowedFormats: f.AllowedFormats()} } decoder := scheme.Codecs.UniversalDecoder() diff --git a/pkg/kubectl/cmd/label.go b/pkg/kubectl/cmd/label.go index ce22d4af0bf..f89024770d6 100644 --- a/pkg/kubectl/cmd/label.go +++ b/pkg/kubectl/cmd/label.go @@ -188,7 +188,7 @@ func (o *LabelOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st return fmt.Errorf("--list and --output may not be specified together") } - o.namespace, o.enforceNamespace, err = f.DefaultNamespace() + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/label_test.go b/pkg/kubectl/cmd/label_test.go index 4bb226fa81d..f0264645e8d 100644 --- a/pkg/kubectl/cmd/label_test.go +++ b/pkg/kubectl/cmd/label_test.go @@ -322,10 +322,9 @@ func TestLabelErrors(t *testing.T) { for k, testCase := range testCases { t.Run(k, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, _, _ := genericclioptions.NewTestIOStreams() @@ -357,7 +356,7 @@ func TestLabelErrors(t *testing.T) { func TestLabelForResourceFromFile(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -388,7 +387,6 @@ func TestLabelForResourceFromFile(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -411,7 +409,7 @@ func TestLabelForResourceFromFile(t *testing.T) { } func TestLabelLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -421,7 +419,6 @@ func TestLabelLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -446,7 +443,7 @@ func TestLabelLocal(t *testing.T) { func TestLabelMultipleObjects(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -479,7 +476,6 @@ func TestLabelMultipleObjects(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() diff --git a/pkg/kubectl/cmd/logs.go b/pkg/kubectl/cmd/logs.go index 71eb390c6a9..9b5e55cf5ab 100644 --- a/pkg/kubectl/cmd/logs.go +++ b/pkg/kubectl/cmd/logs.go @@ -156,7 +156,7 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []str return cmdutil.UsageErrorf(cmd, "%s", logsUsageStr) } var err error - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/logs_test.go b/pkg/kubectl/cmd/logs_test.go index e95e67a01fc..7b82432532e 100644 --- a/pkg/kubectl/cmd/logs_test.go +++ b/pkg/kubectl/cmd/logs_test.go @@ -58,7 +58,7 @@ func TestLog(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { logContent := "test log content" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -80,7 +80,6 @@ func TestLog(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() oldLogFn := polymorphichelpers.LogsForObjectFn defer func() { @@ -123,6 +122,7 @@ func testPod() *api.Pod { func TestValidateLogFlags(t *testing.T) { f := cmdtesting.NewTestFactory() defer f.Cleanup() + f.WithNamespace("") tests := []struct { name string diff --git a/pkg/kubectl/cmd/patch.go b/pkg/kubectl/cmd/patch.go index f773632e18c..14fa2c6a510 100644 --- a/pkg/kubectl/cmd/patch.go +++ b/pkg/kubectl/cmd/patch.go @@ -152,7 +152,7 @@ func (o *PatchOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st return o.PrintFlags.ToPrinter() } - o.namespace, o.enforceNamespace, err = f.DefaultNamespace() + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/patch_test.go b/pkg/kubectl/cmd/patch_test.go index 1311f188439..9a6ee38cae2 100644 --- a/pkg/kubectl/cmd/patch_test.go +++ b/pkg/kubectl/cmd/patch_test.go @@ -31,7 +31,7 @@ import ( func TestPatchObject(t *testing.T) { _, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -55,7 +55,6 @@ func TestPatchObject(t *testing.T) { } }), } - tf.Namespace = "test" stream, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdPatch(tf, stream) @@ -73,7 +72,7 @@ func TestPatchObject(t *testing.T) { func TestPatchObjectFromFile(t *testing.T) { _, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -90,7 +89,6 @@ func TestPatchObjectFromFile(t *testing.T) { } }), } - tf.Namespace = "test" stream, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdPatch(tf, stream) @@ -111,7 +109,7 @@ func TestPatchNoop(t *testing.T) { getObject := &svc.Items[0] patchObject := &svc.Items[0] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -130,7 +128,6 @@ func TestPatchNoop(t *testing.T) { } }), } - tf.Namespace = "test" // Patched { @@ -159,7 +156,7 @@ func TestPatchObjectFromFileOutput(t *testing.T) { } svcCopy.Labels["post-patch"] = "post-patch-value" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -178,7 +175,6 @@ func TestPatchObjectFromFileOutput(t *testing.T) { } }), } - tf.Namespace = "test" stream, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdPatch(tf, stream) diff --git a/pkg/kubectl/cmd/plugin.go b/pkg/kubectl/cmd/plugin.go index 35c4662a59b..feb35253146 100644 --- a/pkg/kubectl/cmd/plugin.go +++ b/pkg/kubectl/cmd/plugin.go @@ -158,7 +158,7 @@ type factoryAttrsPluginEnvProvider struct { } func (p *factoryAttrsPluginEnvProvider) Env() (plugins.EnvList, error) { - cmdNamespace, _, err := p.factory.DefaultNamespace() + cmdNamespace, _, err := p.factory.ToRawKubeConfigLoader().Namespace() if err != nil { return plugins.EnvList{}, err } diff --git a/pkg/kubectl/cmd/portforward.go b/pkg/kubectl/cmd/portforward.go index b6f73348e26..3baa3bee0b1 100644 --- a/pkg/kubectl/cmd/portforward.go +++ b/pkg/kubectl/cmd/portforward.go @@ -174,7 +174,7 @@ func (o *PortForwardOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg return cmdutil.UsageErrorf(cmd, "TYPE/NAME and list of ports are required for port-forward") } - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/portforward_test.go b/pkg/kubectl/cmd/portforward_test.go index 87642e1c853..c2ddde7fa98 100644 --- a/pkg/kubectl/cmd/portforward_test.go +++ b/pkg/kubectl/cmd/portforward_test.go @@ -73,7 +73,7 @@ func testPortForward(t *testing.T, flags map[string]string, args []string) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { var err error - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -94,7 +94,6 @@ func testPortForward(t *testing.T, flags map[string]string, args []string) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ff := &fakePortForwarder{} if test.pfErr { diff --git a/pkg/kubectl/cmd/replace.go b/pkg/kubectl/cmd/replace.go index 3f210c6a57a..7c94ddf4973 100644 --- a/pkg/kubectl/cmd/replace.go +++ b/pkg/kubectl/cmd/replace.go @@ -179,7 +179,7 @@ func (o *ReplaceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [] o.Builder = f.NewBuilder o.BuilderArgs = args - o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/replace_test.go b/pkg/kubectl/cmd/replace_test.go index e40bde5148c..13e69d907c6 100644 --- a/pkg/kubectl/cmd/replace_test.go +++ b/pkg/kubectl/cmd/replace_test.go @@ -32,7 +32,7 @@ import ( func TestReplaceObject(t *testing.T) { _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -62,7 +62,6 @@ func TestReplaceObject(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdReplace(tf, streams) @@ -89,7 +88,7 @@ func TestReplaceObject(t *testing.T) { func TestReplaceMultipleObject(t *testing.T) { _, svc, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -133,7 +132,6 @@ func TestReplaceMultipleObject(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdReplace(tf, streams) @@ -160,7 +158,7 @@ func TestReplaceMultipleObject(t *testing.T) { func TestReplaceDirectory(t *testing.T) { _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -191,7 +189,6 @@ func TestReplaceDirectory(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdReplace(tf, streams) @@ -218,7 +215,7 @@ func TestReplaceDirectory(t *testing.T) { func TestForceReplaceObjectNotFound(t *testing.T) { _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -238,7 +235,6 @@ func TestForceReplaceObjectNotFound(t *testing.T) { } }), } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdReplace(tf, streams) diff --git a/pkg/kubectl/cmd/rollingupdate.go b/pkg/kubectl/cmd/rollingupdate.go index 24cde12b467..c304fdcaa1f 100644 --- a/pkg/kubectl/cmd/rollingupdate.go +++ b/pkg/kubectl/cmd/rollingupdate.go @@ -150,7 +150,7 @@ func NewCmdRollingUpdate(f cmdutil.Factory, ioStreams genericclioptions.IOStream cmd.Flags().DurationVar(&o.Interval, "poll-interval", o.Interval, `Time delay between polling for replication controller status after the update. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) cmd.Flags().DurationVar(&o.Timeout, "timeout", o.Timeout, `Max time to wait for a replication controller to update before giving up. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) usage := "Filename or URL to file to use to create the new replication controller." - kubectl.AddJsonFilenameFlag(cmd, &o.FilenameOptions.Filenames, usage) + cmdutil.AddJsonFilenameFlag(cmd.Flags(), &o.FilenameOptions.Filenames, usage) cmd.Flags().StringVar(&o.Image, "image", o.Image, i18n.T("Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f")) cmd.Flags().StringVar(&o.DeploymentKey, "deployment-label-key", o.DeploymentKey, i18n.T("The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise")) cmd.Flags().StringVar(&o.Container, "container", o.Container, i18n.T("Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod")) @@ -209,12 +209,12 @@ func (o *RollingUpdateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a } var err error - o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - o.ScaleClient, err = f.ScaleClient() + o.ScaleClient, err = cmdutil.ScaleClientFn(f) if err != nil { return err } @@ -242,7 +242,6 @@ func (o *RollingUpdateOptions) Validate(cmd *cobra.Command, args []string) error } func (o *RollingUpdateOptions) Run() error { - filename := "" if len(o.FilenameOptions.Filenames) > 0 { filename = o.FilenameOptions.Filenames[0] diff --git a/pkg/kubectl/cmd/rollout/rollout_history.go b/pkg/kubectl/cmd/rollout/rollout_history.go index 5ace22c993f..b438bc30d1d 100644 --- a/pkg/kubectl/cmd/rollout/rollout_history.go +++ b/pkg/kubectl/cmd/rollout/rollout_history.go @@ -74,7 +74,7 @@ func RunHistory(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []str return fmt.Errorf("revision must be a positive integer: %v", revision) } - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/rollout/rollout_pause.go b/pkg/kubectl/cmd/rollout/rollout_pause.go index 51d8ea3faac..7ab8a851934 100644 --- a/pkg/kubectl/cmd/rollout/rollout_pause.go +++ b/pkg/kubectl/cmd/rollout/rollout_pause.go @@ -104,7 +104,7 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, args o.Pauser = polymorphichelpers.ObjectPauserFn - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/rollout/rollout_pause_test.go b/pkg/kubectl/cmd/rollout/rollout_pause_test.go index a40e0327305..965a52163be 100644 --- a/pkg/kubectl/cmd/rollout/rollout_pause_test.go +++ b/pkg/kubectl/cmd/rollout/rollout_pause_test.go @@ -40,7 +40,7 @@ var rolloutPauseGroupVersionDecoder = schema.GroupVersion{Group: "extensions", V func TestRolloutPause(t *testing.T) { deploymentName := "deployment/nginx-deployment" ns := legacyscheme.Codecs - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") info, _ := runtime.SerializerInfoForMediaType(ns.SupportedMediaTypes(), runtime.ContentTypeJSON) encoder := ns.EncoderForVersion(info.Serializer, rolloutPauseGroupVersionEncoder) @@ -62,7 +62,6 @@ func TestRolloutPause(t *testing.T) { }, } - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdRolloutPause(tf, streams) diff --git a/pkg/kubectl/cmd/rollout/rollout_resume.go b/pkg/kubectl/cmd/rollout/rollout_resume.go index 8ca44d8a762..aca0534f8eb 100644 --- a/pkg/kubectl/cmd/rollout/rollout_resume.go +++ b/pkg/kubectl/cmd/rollout/rollout_resume.go @@ -102,7 +102,7 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, arg o.Resumer = polymorphichelpers.ObjectResumerFn - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/rollout/rollout_status.go b/pkg/kubectl/cmd/rollout/rollout_status.go index 3182c4a8f37..e705bd8d163 100644 --- a/pkg/kubectl/cmd/rollout/rollout_status.go +++ b/pkg/kubectl/cmd/rollout/rollout_status.go @@ -104,7 +104,7 @@ func (o *RolloutStatusOptions) Complete(f cmdutil.Factory, args []string) error o.Builder = f.NewBuilder() var err error - o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/rollout/rollout_undo.go b/pkg/kubectl/cmd/rollout/rollout_undo.go index 46a66a0dd7b..f2840eebeb9 100644 --- a/pkg/kubectl/cmd/rollout/rollout_undo.go +++ b/pkg/kubectl/cmd/rollout/rollout_undo.go @@ -109,7 +109,7 @@ func (o *UndoOptions) CompleteUndo(f cmdutil.Factory, cmd *cobra.Command, out io o.Out = out o.DryRun = cmdutil.GetDryRunFlag(cmd) - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index de450080765..7157b72c8bd 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -265,7 +265,7 @@ func (o *RunOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e return cmdutil.UsageErrorf(cmd, "--port must be set when exposing a service") } - namespace, _, err := f.DefaultNamespace() + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -321,7 +321,7 @@ func (o *RunOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e } } - generators := f.Generators("run") + generators := cmdutil.GeneratorFn("run") generator, found := generators[generatorName] if !found { return cmdutil.UsageErrorf(cmd, "generator %q not found", generatorName) @@ -573,7 +573,7 @@ func verifyImagePullPolicy(cmd *cobra.Command) error { } func (o *RunOptions) generateService(f cmdutil.Factory, cmd *cobra.Command, serviceGenerator string, paramsIn map[string]interface{}, namespace string) (*RunObject, error) { - generators := f.Generators("expose") + generators := cmdutil.GeneratorFn("expose") generator, found := generators[serviceGenerator] if !found { return nil, fmt.Errorf("missing service generator: %s", serviceGenerator) diff --git a/pkg/kubectl/cmd/run_test.go b/pkg/kubectl/cmd/run_test.go index b4a6f6850e6..3ffd79f1c5e 100644 --- a/pkg/kubectl/cmd/run_test.go +++ b/pkg/kubectl/cmd/run_test.go @@ -170,7 +170,7 @@ func TestRunArgsFollowDashRules(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -190,7 +190,6 @@ func TestRunArgsFollowDashRules(t *testing.T) { }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{} cmd := NewCmdRun(tf, genericclioptions.NewTestIOStreamsDiscard()) @@ -505,7 +504,7 @@ func TestRunValidations(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() _, _, codec := cmdtesting.NewExternalScheme() @@ -513,7 +512,6 @@ func TestRunValidations(t *testing.T) { NegotiatedSerializer: scheme.Codecs, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, cmdtesting.NewInternalType("", "", ""))}, } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, _, bufErr := genericclioptions.NewTestIOStreams() diff --git a/pkg/kubectl/cmd/scale.go b/pkg/kubectl/cmd/scale.go index 6b4ffb1b5ff..1f8c4f2577c 100644 --- a/pkg/kubectl/cmd/scale.go +++ b/pkg/kubectl/cmd/scale.go @@ -156,7 +156,7 @@ func (o *ScaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st } o.PrintObj = printer.PrintObj - o.namespace, o.enforceNamespace, err = f.DefaultNamespace() + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -289,7 +289,7 @@ func ScaleJob(info *resource.Info, jobsClient batchclient.JobsGetter, count uint } func scaler(f cmdutil.Factory) (kubectl.Scaler, error) { - scalesGetter, err := f.ScaleClient() + scalesGetter, err := cmdutil.ScaleClientFn(f) if err != nil { return nil, err } diff --git a/pkg/kubectl/cmd/set/BUILD b/pkg/kubectl/cmd/set/BUILD index aba25208706..ba61c44cb99 100644 --- a/pkg/kubectl/cmd/set/BUILD +++ b/pkg/kubectl/cmd/set/BUILD @@ -21,9 +21,9 @@ go_library( deps = [ "//pkg/apis/rbac:go_default_library", "//pkg/kubectl:go_default_library", + "//pkg/kubectl/cmd/set/env:go_default_library", "//pkg/kubectl/cmd/templates:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", - "//pkg/kubectl/cmd/util/env:go_default_library", "//pkg/kubectl/genericclioptions:go_default_library", "//pkg/kubectl/genericclioptions/printers:go_default_library", "//pkg/kubectl/genericclioptions/resource:go_default_library", @@ -68,6 +68,7 @@ go_test( "//pkg/kubectl/cmd/testing:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", "//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", @@ -96,7 +97,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//pkg/kubectl/cmd/set/env:all-srcs", + ], tags = ["automanaged"], visibility = [ "//build/visible_to:pkg_kubectl_cmd_set_CONSUMERS", diff --git a/pkg/kubectl/cmd/util/env/BUILD b/pkg/kubectl/cmd/set/env/BUILD similarity index 94% rename from pkg/kubectl/cmd/util/env/BUILD rename to pkg/kubectl/cmd/set/env/BUILD index ecdf11acb37..97fb91a2072 100644 --- a/pkg/kubectl/cmd/util/env/BUILD +++ b/pkg/kubectl/cmd/set/env/BUILD @@ -7,7 +7,7 @@ go_library( "env_parse.go", "env_resolve.go", ], - importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/env", + importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/set/env", visibility = ["//visibility:public"], deps = [ "//pkg/api/v1/resource:go_default_library", diff --git a/pkg/kubectl/cmd/util/env/doc.go b/pkg/kubectl/cmd/set/env/doc.go similarity index 86% rename from pkg/kubectl/cmd/util/env/doc.go rename to pkg/kubectl/cmd/set/env/doc.go index 39adb0adf0c..25e4c04a70f 100644 --- a/pkg/kubectl/cmd/util/env/doc.go +++ b/pkg/kubectl/cmd/set/env/doc.go @@ -14,5 +14,5 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package env provides functions to incorporate environment variables into kubectl commands. -package env // import "k8s.io/kubernetes/pkg/kubectl/cmd/util/env" +// Package env provides functions to incorporate environment variables into set env. +package env diff --git a/pkg/kubectl/cmd/util/env/env_parse.go b/pkg/kubectl/cmd/set/env/env_parse.go similarity index 91% rename from pkg/kubectl/cmd/util/env/env_parse.go rename to pkg/kubectl/cmd/set/env/env_parse.go index 1d1686af647..5e2e529088d 100644 --- a/pkg/kubectl/cmd/util/env/env_parse.go +++ b/pkg/kubectl/cmd/set/env/env_parse.go @@ -20,7 +20,6 @@ import ( "bufio" "fmt" "io" - "os" "regexp" "strings" @@ -28,24 +27,6 @@ import ( "k8s.io/apimachinery/pkg/util/sets" ) -// Env returns an environment variable if not nil, or a default value. -func Env(key string, defaultValue string) string { - val := os.Getenv(key) - if len(val) == 0 { - return defaultValue - } - return val -} - -// GetEnv returns an environment value if not nil, and an ok boolean. -func GetEnv(key string) (string, bool) { - val := os.Getenv(key) - if len(val) == 0 { - return "", false - } - return val, true -} - var argumentEnvironment = regexp.MustCompile("(?ms)^(.+)\\=(.*)$") var validArgumentEnvironment = regexp.MustCompile("(?ms)^(\\w+)\\=(.*)$") diff --git a/pkg/kubectl/cmd/util/env/env_parse_test.go b/pkg/kubectl/cmd/set/env/env_parse_test.go similarity index 76% rename from pkg/kubectl/cmd/util/env/env_parse_test.go rename to pkg/kubectl/cmd/set/env/env_parse_test.go index 32be9833c76..5cff84a1849 100644 --- a/pkg/kubectl/cmd/util/env/env_parse_test.go +++ b/pkg/kubectl/cmd/set/env/env_parse_test.go @@ -19,36 +19,9 @@ package env import ( "fmt" "io" - "os" "strings" ) -func ExampleEnv_defaultValue() { - fmt.Println(Env("TESTENVVAR", "default")) - // Output: default -} - -func ExampleEnv_variableExists() { - os.Setenv("TESTENVVAR", "test value") - defer os.Unsetenv("TESTENVVAR") - fmt.Println(Env("TESTENVVAR", "default")) - // Output: test value -} - -func ExampleGetEnv_variableExists() { - os.Setenv("THISVAREXISTS", "value") - defer os.Unsetenv("THISVAREXISTS") - fmt.Println(GetEnv("THISVAREXISTS")) - // Output: - // value true -} - -func ExampleGetEnv_variableDoesNotExist() { - fmt.Println(GetEnv("THISVARDOESNOTEXIST")) - // Output: - // false -} - func ExampleIsEnvironmentArgument_true() { test := "returns=true" fmt.Println(IsEnvironmentArgument(test)) diff --git a/pkg/kubectl/cmd/util/env/env_resolve.go b/pkg/kubectl/cmd/set/env/env_resolve.go similarity index 100% rename from pkg/kubectl/cmd/util/env/env_resolve.go rename to pkg/kubectl/cmd/set/env/env_resolve.go diff --git a/pkg/kubectl/cmd/set/set_env.go b/pkg/kubectl/cmd/set/set_env.go index d2ec28e1a7f..f1e6c0cc65d 100644 --- a/pkg/kubectl/cmd/set/set_env.go +++ b/pkg/kubectl/cmd/set/set_env.go @@ -31,9 +31,9 @@ import ( "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/client-go/kubernetes" + envutil "k8s.io/kubernetes/pkg/kubectl/cmd/set/env" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - envutil "k8s.io/kubernetes/pkg/kubectl/cmd/util/env" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" @@ -233,7 +233,7 @@ func (o *EnvOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri if err != nil { return err } - o.namespace, o.enforceNamespace, err = f.DefaultNamespace() + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/set/set_env_test.go b/pkg/kubectl/cmd/set/set_env_test.go index d5d73a5163a..f3d7c3338c0 100644 --- a/pkg/kubectl/cmd/set/set_env_test.go +++ b/pkg/kubectl/cmd/set/set_env_test.go @@ -45,7 +45,7 @@ import ( ) func TestSetEnvLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.Client = &fake.RESTClient{ @@ -56,7 +56,6 @@ func TestSetEnvLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} outputFormat := "name" @@ -83,7 +82,7 @@ func TestSetEnvLocal(t *testing.T) { } func TestSetMultiResourcesEnvLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.Client = &fake.RESTClient{ @@ -94,7 +93,6 @@ func TestSetMultiResourcesEnvLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} outputFormat := "name" @@ -447,16 +445,15 @@ func TestSetEnvRemote(t *testing.T) { t.Run(input.name, func(t *testing.T) { groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} testapi.Default = testapi.Groups[input.testAPIGroup] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} defer tf.Cleanup() - tf.Namespace = "test" tf.Client = &fake.RESTClient{ GroupVersion: groupVersion, NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) + resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", "test", input.args[1]) switch p, m := req.URL.Path, req.Method; { case p == resourcePath && m == http.MethodGet: return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil @@ -585,10 +582,9 @@ func TestSetEnvFromResource(t *testing.T) { }, } t.Run(input.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, diff --git a/pkg/kubectl/cmd/set/set_image.go b/pkg/kubectl/cmd/set/set_image.go index b1de0b7b71a..7efa5f2d1fd 100644 --- a/pkg/kubectl/cmd/set/set_image.go +++ b/pkg/kubectl/cmd/set/set_image.go @@ -150,7 +150,7 @@ func (o *SetImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [ o.PrintObj = printer.PrintObj - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/set/set_image_test.go b/pkg/kubectl/cmd/set/set_image_test.go index fb383be767d..bf731f066b2 100644 --- a/pkg/kubectl/cmd/set/set_image_test.go +++ b/pkg/kubectl/cmd/set/set_image_test.go @@ -46,7 +46,7 @@ import ( ) func TestImageLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.Client = &fake.RESTClient{ @@ -57,7 +57,6 @@ func TestImageLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} outputFormat := "name" @@ -159,7 +158,7 @@ func TestSetImageValidation(t *testing.T) { } func TestSetMultiResourcesImageLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.Client = &fake.RESTClient{ @@ -170,7 +169,6 @@ func TestSetMultiResourcesImageLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} outputFormat := "name" @@ -532,15 +530,14 @@ func TestSetImageRemote(t *testing.T) { t.Run(input.name, func(t *testing.T) { groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} testapi.Default = testapi.Groups[input.testAPIGroup] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.Client = &fake.RESTClient{ GroupVersion: groupVersion, NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) + resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", "test", input.args[1]) switch p, m := req.URL.Path, req.Method; { case p == resourcePath && m == http.MethodGet: return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil diff --git a/pkg/kubectl/cmd/set/set_resources.go b/pkg/kubectl/cmd/set/set_resources.go index 055068dd203..e773bb8137e 100644 --- a/pkg/kubectl/cmd/set/set_resources.go +++ b/pkg/kubectl/cmd/set/set_resources.go @@ -160,7 +160,7 @@ func (o *SetResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, ar } o.PrintObj = printer.PrintObj - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/set/set_resources_test.go b/pkg/kubectl/cmd/set/set_resources_test.go index fe630782649..9d286278f01 100644 --- a/pkg/kubectl/cmd/set/set_resources_test.go +++ b/pkg/kubectl/cmd/set/set_resources_test.go @@ -45,7 +45,7 @@ import ( ) func TestResourcesLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.Client = &fake.RESTClient{ @@ -56,7 +56,6 @@ func TestResourcesLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} outputFormat := "name" @@ -94,7 +93,7 @@ func TestResourcesLocal(t *testing.T) { } func TestSetMultiResourcesLimitsLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.Client = &fake.RESTClient{ @@ -105,7 +104,6 @@ func TestSetMultiResourcesLimitsLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} outputFormat := "name" @@ -455,15 +453,14 @@ func TestSetResourcesRemote(t *testing.T) { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} testapi.Default = testapi.Groups[input.testAPIGroup] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.Client = &fake.RESTClient{ GroupVersion: groupVersion, NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) + resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", "test", input.args[1]) switch p, m := req.URL.Path, req.Method; { case p == resourcePath && m == http.MethodGet: return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil diff --git a/pkg/kubectl/cmd/set/set_selector.go b/pkg/kubectl/cmd/set/set_selector.go index 54cfbacc1f7..70199c37679 100644 --- a/pkg/kubectl/cmd/set/set_selector.go +++ b/pkg/kubectl/cmd/set/set_selector.go @@ -23,7 +23,6 @@ import ( "github.com/spf13/cobra" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" @@ -40,26 +39,23 @@ import ( // SelectorOptions 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 { - fileOptions resource.FilenameOptions - - PrintFlags *genericclioptions.PrintFlags - RecordFlags *genericclioptions.RecordFlags - - local bool - dryrun bool - all bool - output string + // Bound + ResourceBuilderFlags *genericclioptions.ResourceBuilderFlags + PrintFlags *genericclioptions.PrintFlags + RecordFlags *genericclioptions.RecordFlags + dryrun bool + // set by args resources []string selector *metav1.LabelSelector - ClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error) - - PrintObj printers.ResourcePrinterFunc - Recorder genericclioptions.Recorder - - builder *resource.Builder + // computed + WriteToServer bool + PrintObj printers.ResourcePrinterFunc + Recorder genericclioptions.Recorder + ResourceFinder genericclioptions.ResourceFinder + // set at initialization genericclioptions.IOStreams } @@ -79,6 +75,12 @@ var ( func NewSelectorOptions(streams genericclioptions.IOStreams) *SetSelectorOptions { return &SetSelectorOptions{ + ResourceBuilderFlags: genericclioptions.NewResourceBuilderFlags(). + WithScheme(scheme.Scheme). + WithAll(false). + WithLocal(false). + WithUninitialized(false). + WithLatest(), PrintFlags: genericclioptions.NewPrintFlags("selector updated").WithTypeSetter(scheme.Scheme), RecordFlags: genericclioptions.NewRecordFlags(), @@ -105,16 +107,12 @@ func NewCmdSelector(f cmdutil.Factory, streams genericclioptions.IOStreams) *cob }, } + o.ResourceBuilderFlags.AddFlags(cmd.Flags()) o.PrintFlags.AddFlags(cmd) o.RecordFlags.AddFlags(cmd) - cmd.Flags().BoolVar(&o.all, "all", o.all, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") - cmd.Flags().BoolVar(&o.local, "local", o.local, "If true, set selector will NOT contact api-server but run locally.") cmd.Flags().String("resource-version", "", "If non-empty, the selectors update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.") - usage := "the resource to update the selectors" - cmdutil.AddFilenameOptionFlags(cmd, &o.fileOptions, usage) cmdutil.AddDryRunFlag(cmd) - cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } @@ -130,40 +128,14 @@ func (o *SetSelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg } o.dryrun = cmdutil.GetDryRunFlag(cmd) - o.output = cmdutil.GetFlagString(cmd, "output") - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } o.resources, o.selector, err = getResourcesAndSelector(args) if err != nil { return err } - includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) - o.builder = f.NewBuilder(). - WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). - LocalParam(o.local). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &o.fileOptions). - IncludeUninitialized(includeUninitialized). - Flatten() - - if !o.local { - o.builder. - ResourceTypeOrNameArgs(o.all, o.resources...). - Latest() - } else { - // if a --local flag was provided, and a resource was specified in the form - // /, fail immediately as --local cannot query the api server - // for the specified resource. - if len(o.resources) > 0 { - return resource.LocalResourceError - } - } + o.ResourceFinder = o.ResourceBuilderFlags.ToBuilder(f, o.resources) + o.WriteToServer = !(*o.ResourceBuilderFlags.Local || o.dryrun) if o.dryrun { o.PrintFlags.Complete("%s (dry run)") @@ -174,17 +146,11 @@ func (o *SetSelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg } o.PrintObj = printer.PrintObj - o.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) { - return f.ClientForMapping(mapping) - } return err } // Validate basic inputs func (o *SetSelectorOptions) Validate() error { - if len(o.resources) < 1 && cmdutil.IsFilenameSliceEmpty(o.fileOptions.Filenames) { - return fmt.Errorf("one or more resources must be specified as or /") - } if o.selector == nil { return fmt.Errorf("one selector is required") } @@ -193,11 +159,7 @@ func (o *SetSelectorOptions) Validate() error { // RunSelector executes the command. func (o *SetSelectorOptions) RunSelector() error { - r := o.builder.Do() - err := r.Err() - if err != nil { - return err - } + r := o.ResourceFinder.Do() return r.Visit(func(info *resource.Info, err error) error { patch := &Patch{Info: info} @@ -218,7 +180,7 @@ func (o *SetSelectorOptions) RunSelector() error { if patch.Err != nil { return patch.Err } - if o.local || o.dryrun { + if !o.WriteToServer { return o.PrintObj(info.Object, o.Out) } diff --git a/pkg/kubectl/cmd/set/set_selector_test.go b/pkg/kubectl/cmd/set/set_selector_test.go index 9c014f0c32d..e1924f32c56 100644 --- a/pkg/kubectl/cmd/set/set_selector_test.go +++ b/pkg/kubectl/cmd/set/set_selector_test.go @@ -17,7 +17,6 @@ limitations under the License. package set import ( - "net/http" "reflect" "strings" "testing" @@ -28,13 +27,9 @@ import ( extensionsv1beta1 "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/runtime/serializer" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/rest/fake" - cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" - "k8s.io/kubernetes/pkg/kubectl/scheme" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" ) func TestUpdateSelectorForObjectTypes(t *testing.T) { @@ -317,28 +312,30 @@ func TestGetResourcesAndSelector(t *testing.T) { } func TestSelectorTest(t *testing.T) { - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - tf.Client = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: ""}, - NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) - return nil, nil - }), + info := &resource.Info{ + Object: &v1.Service{ + TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Service"}, + ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "cassandra"}, + }, } - tf.Namespace = "test" - tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} - streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdSelector(tf, streams) - cmd.Flags().Set("output", "name") - cmd.Flags().Set("local", "true") - cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/statefulset/cassandra/service.yaml") + labelToSet, err := metav1.ParseToLabelSelector("environment=qa") + if err != nil { + t.Fatal(err) + } - cmd.Run(cmd, []string{"environment=qa"}) + iostreams, _, buf, _ := genericclioptions.NewTestIOStreams() + o := &SetSelectorOptions{ + selector: labelToSet, + ResourceFinder: genericclioptions.NewSimpleFakeResourceFinder(info), + Recorder: genericclioptions.NoopRecorder{}, + PrintObj: (&printers.NamePrinter{}).PrintObj, + IOStreams: iostreams, + } + if err := o.RunSelector(); err != nil { + t.Fatal(err) + } if !strings.Contains(buf.String(), "service/cassandra") { t.Errorf("did not set selector: %s", buf.String()) } diff --git a/pkg/kubectl/cmd/set/set_serviceaccount.go b/pkg/kubectl/cmd/set/set_serviceaccount.go index ab4e843a619..6faf727801a 100644 --- a/pkg/kubectl/cmd/set/set_serviceaccount.go +++ b/pkg/kubectl/cmd/set/set_serviceaccount.go @@ -141,7 +141,7 @@ func (o *SetServiceAccountOptions) Complete(f cmdutil.Factory, cmd *cobra.Comman } o.PrintObj = printer.PrintObj - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/set/set_serviceaccount_test.go b/pkg/kubectl/cmd/set/set_serviceaccount_test.go index f2e06bd7bb6..7239bf1c587 100644 --- a/pkg/kubectl/cmd/set/set_serviceaccount_test.go +++ b/pkg/kubectl/cmd/set/set_serviceaccount_test.go @@ -68,7 +68,7 @@ func TestSetServiceAccountLocal(t *testing.T) { for i, input := range inputs { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.Client = &fake.RESTClient{ @@ -81,7 +81,6 @@ func TestSetServiceAccountLocal(t *testing.T) { outputFormat := "yaml" - tf.Namespace = "test" streams, _, buf, _ := genericclioptions.NewTestIOStreams() cmd := NewCmdServiceAccount(tf, streams) cmd.Flags().Set("output", outputFormat) @@ -105,7 +104,7 @@ func TestSetServiceAccountLocal(t *testing.T) { func TestSetServiceAccountMultiLocal(t *testing.T) { testapi.Default = testapi.Groups[""] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.Client = &fake.RESTClient{ @@ -116,7 +115,6 @@ func TestSetServiceAccountMultiLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} outputFormat := "name" @@ -326,15 +324,14 @@ func TestSetServiceAccountRemote(t *testing.T) { t.Run(input.apiPrefix, func(t *testing.T) { groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} testapi.Default = testapi.Groups[input.testAPIGroup] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.Client = &fake.RESTClient{ GroupVersion: groupVersion, NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) + resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", "test", input.args[1]) switch p, m := req.URL.Path, req.Method; { case p == resourcePath && m == http.MethodGet: return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil @@ -387,7 +384,7 @@ func TestServiceAccountValidation(t *testing.T) { } for _, input := range inputs { t.Run(input.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.Client = &fake.RESTClient{ @@ -400,7 +397,6 @@ func TestServiceAccountValidation(t *testing.T) { outputFormat := "" - tf.Namespace = "test" streams := genericclioptions.NewTestIOStreamsDiscard() cmd := NewCmdServiceAccount(tf, streams) diff --git a/pkg/kubectl/cmd/set/set_subject.go b/pkg/kubectl/cmd/set/set_subject.go index c745abfc3a4..4b395b31d3c 100644 --- a/pkg/kubectl/cmd/set/set_subject.go +++ b/pkg/kubectl/cmd/set/set_subject.go @@ -131,7 +131,7 @@ func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [] o.PrintObj = printer.PrintObj var enforceNamespace bool - o.namespace, enforceNamespace, err = f.DefaultNamespace() + o.namespace, enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/set/set_subject_test.go b/pkg/kubectl/cmd/set/set_subject_test.go index 05c82082c83..33fd75cd739 100644 --- a/pkg/kubectl/cmd/set/set_subject_test.go +++ b/pkg/kubectl/cmd/set/set_subject_test.go @@ -28,11 +28,9 @@ import ( ) func TestValidate(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" - tests := map[string]struct { options *SubjectOptions expectErr bool diff --git a/pkg/kubectl/cmd/taint.go b/pkg/kubectl/cmd/taint.go index e4c68dd4340..45b6ab0e7bf 100644 --- a/pkg/kubectl/cmd/taint.go +++ b/pkg/kubectl/cmd/taint.go @@ -124,7 +124,7 @@ func NewCmdTaint(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra. // Complete adapts from the command line args and factory to the data required. func (o *TaintOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) (err error) { - namespace, _, err := f.DefaultNamespace() + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/testing/BUILD b/pkg/kubectl/cmd/testing/BUILD index 8c615c2cf7f..e6b59fa7f0e 100644 --- a/pkg/kubectl/cmd/testing/BUILD +++ b/pkg/kubectl/cmd/testing/BUILD @@ -18,7 +18,6 @@ go_library( "//pkg/kubectl/genericclioptions:go_default_library", "//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/validation:go_default_library", - "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/pkg/kubectl/cmd/testing/fake.go b/pkg/kubectl/cmd/testing/fake.go index 839ee29dbea..12d876626d7 100644 --- a/pkg/kubectl/cmd/testing/fake.go +++ b/pkg/kubectl/cmd/testing/fake.go @@ -25,8 +25,6 @@ import ( "path/filepath" "time" - "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta/testrestmapper" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -234,12 +232,12 @@ func (d *fakeCachedDiscoveryClient) ServerResources() ([]*metav1.APIResourceList type TestFactory struct { cmdutil.Factory + kubeConfigFlags *genericclioptions.TestConfigFlags + Client kubectl.RESTClient ScaleGetter scaleclient.ScalesGetter UnstructuredClient kubectl.RESTClient - Namespace string ClientConfigVal *restclient.Config - CommandVal string FakeDynamicClient *fakedynamic.FakeDynamicClient tempConfigFile *os.File @@ -276,6 +274,7 @@ func NewTestFactory() *TestFactory { return &TestFactory{ Factory: cmdutil.NewFactory(configFlags), + kubeConfigFlags: configFlags, FakeDynamicClient: fakedynamic.NewSimpleDynamicClient(legacyscheme.Scheme), tempConfigFile: tmpFile, @@ -283,6 +282,11 @@ func NewTestFactory() *TestFactory { } } +func (f *TestFactory) WithNamespace(ns string) *TestFactory { + f.kubeConfigFlags.WithNamespace(ns) + return f +} + func (f *TestFactory) Cleanup() { if f.tempConfigFile == nil { return @@ -295,10 +299,6 @@ func (f *TestFactory) ToRESTConfig() (*restclient.Config, error) { return f.ClientConfigVal, nil } -func (f *TestFactory) BareClientConfig() (*restclient.Config, error) { - return f.ClientConfigVal, nil -} - func (f *TestFactory) ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { return f.Client, nil } @@ -314,10 +314,6 @@ func (f *TestFactory) Validator(validate bool) (validation.Schema, error) { return validation.NullSchema{}, nil } -func (f *TestFactory) DefaultNamespace() (string, bool, error) { - return f.Namespace, false, nil -} - func (f *TestFactory) OpenAPISchema() (openapi.Resources, error) { if f.OpenAPISchemaFunc != nil { return f.OpenAPISchemaFunc() @@ -325,10 +321,6 @@ func (f *TestFactory) OpenAPISchema() (openapi.Resources, error) { return openapitesting.EmptyResources{}, nil } -func (f *TestFactory) Command(*cobra.Command, bool) string { - return f.CommandVal -} - func (f *TestFactory) NewBuilder() *resource.Builder { mapper, err := f.ToRESTMapper() @@ -425,10 +417,6 @@ func (f *TestFactory) DiscoveryClient() (discovery.CachedDiscoveryInterface, err return cachedClient, nil } -func (f *TestFactory) ClientSetForVersion(requiredVersion *schema.GroupVersion) (internalclientset.Interface, error) { - return f.ClientSet() -} - func testRESTMapper() meta.RESTMapper { groupResources := testDynamicResources() mapper := restmapper.NewDiscoveryRESTMapper(groupResources) diff --git a/pkg/kubectl/cmd/top_node_test.go b/pkg/kubectl/cmd/top_node_test.go index 6857355fb1a..ab387fbfc83 100644 --- a/pkg/kubectl/cmd/top_node_test.go +++ b/pkg/kubectl/cmd/top_node_test.go @@ -50,7 +50,7 @@ func TestTopNodeAllMetrics(t *testing.T) { expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsApiVersion) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -78,7 +78,6 @@ func TestTopNodeAllMetrics(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -103,7 +102,7 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) { expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", customBaseMetricsAddress, metricsApiVersion) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -131,7 +130,6 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -167,7 +165,7 @@ func TestTopNodeWithNameMetrics(t *testing.T) { 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() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -195,7 +193,6 @@ func TestTopNodeWithNameMetrics(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -234,7 +231,7 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) { expectedQuery := fmt.Sprintf("labelSelector=%s", url.QueryEscape(label)) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -262,7 +259,6 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -289,7 +285,7 @@ func TestTopNodeAllMetricsFromMetricsServer(t *testing.T) { expectedMetrics, nodes := testNodeV1beta1MetricsData() expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -315,7 +311,6 @@ func TestTopNodeAllMetricsFromMetricsServer(t *testing.T) { fakemetricsClientset.AddReactor("list", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, expectedMetrics, nil }) - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -357,7 +352,7 @@ func TestTopNodeWithNameMetricsFromMetricsServer(t *testing.T) { } expectedNodePath := fmt.Sprintf("/%s/%s/nodes/%s", apiPrefix, apiVersion, expectedMetrics.Name) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -383,7 +378,6 @@ func TestTopNodeWithNameMetricsFromMetricsServer(t *testing.T) { fakemetricsClientset.AddReactor("get", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, &expectedMetrics, nil }) - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -435,7 +429,7 @@ func TestTopNodeWithLabelSelectorMetricsFromMetricsServer(t *testing.T) { label := "key=value" expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) @@ -462,7 +456,6 @@ func TestTopNodeWithLabelSelectorMetricsFromMetricsServer(t *testing.T) { fakemetricsClientset.AddReactor("list", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, expectedMetrics, nil }) - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() diff --git a/pkg/kubectl/cmd/top_pod.go b/pkg/kubectl/cmd/top_pod.go index e90ac689882..b63dde44ebf 100644 --- a/pkg/kubectl/cmd/top_pod.go +++ b/pkg/kubectl/cmd/top_pod.go @@ -121,7 +121,7 @@ func (o *TopPodOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []s return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/top_pod_test.go b/pkg/kubectl/cmd/top_pod_test.go index 494e08efa6c..1cba8d692eb 100644 --- a/pkg/kubectl/cmd/top_pod_test.go +++ b/pkg/kubectl/cmd/top_pod_test.go @@ -164,7 +164,7 @@ func TestTopPod(t *testing.T) { } } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace(testNS) defer tf.Cleanup() ns := legacyscheme.Codecs @@ -190,7 +190,6 @@ func TestTopPod(t *testing.T) { } }), } - tf.Namespace = testNS tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -309,7 +308,7 @@ func TestTopPodWithMetricsServer(t *testing.T) { }) } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace(testNS) defer tf.Cleanup() ns := legacyscheme.Codecs @@ -329,7 +328,6 @@ func TestTopPodWithMetricsServer(t *testing.T) { } }), } - tf.Namespace = testNS tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() @@ -508,7 +506,7 @@ func TestTopPodCustomDefaults(t *testing.T) { } } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace(testNS) defer tf.Cleanup() ns := legacyscheme.Codecs @@ -534,7 +532,6 @@ func TestTopPodCustomDefaults(t *testing.T) { } }), } - tf.Namespace = testNS tf.ClientConfigVal = defaultClientConfig() streams, _, buf, _ := genericclioptions.NewTestIOStreams() diff --git a/pkg/kubectl/cmd/util/BUILD b/pkg/kubectl/cmd/util/BUILD index fa44ccc6917..7ed95e5050b 100644 --- a/pkg/kubectl/cmd/util/BUILD +++ b/pkg/kubectl/cmd/util/BUILD @@ -6,6 +6,7 @@ go_library( "conversion.go", "factory.go", "factory_client_access.go", + "generator.go", "helpers.go", "kubectl_match_version.go", "printing.go", @@ -57,10 +58,7 @@ go_library( go_test( name = "go_default_test", - srcs = [ - "factory_test.go", - "helpers_test.go", - ], + srcs = ["helpers_test.go"], embed = [":go_default_library"], deps = [ "//pkg/api/testapi:go_default_library", @@ -89,8 +87,6 @@ filegroup( srcs = [ ":package-srcs", "//pkg/kubectl/cmd/util/editor:all-srcs", - "//pkg/kubectl/cmd/util/env:all-srcs", - "//pkg/kubectl/cmd/util/jsonmerge:all-srcs", "//pkg/kubectl/cmd/util/openapi:all-srcs", "//pkg/kubectl/cmd/util/sanity:all-srcs", ], diff --git a/pkg/kubectl/cmd/util/editor/BUILD b/pkg/kubectl/cmd/util/editor/BUILD index 06cf3472f53..379bdcc5c95 100644 --- a/pkg/kubectl/cmd/util/editor/BUILD +++ b/pkg/kubectl/cmd/util/editor/BUILD @@ -18,11 +18,11 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/kubectl:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", + "//pkg/kubectl/cmd/util/editor/crlf:go_default_library", "//pkg/kubectl/genericclioptions:go_default_library", "//pkg/kubectl/genericclioptions/printers:go_default_library", "//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/scheme:go_default_library", - "//pkg/kubectl/util/crlf:go_default_library", "//pkg/kubectl/util/term:go_default_library", "//vendor/github.com/evanphx/json-patch:go_default_library", "//vendor/github.com/golang/glog:go_default_library", @@ -57,7 +57,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//pkg/kubectl/cmd/util/editor/crlf:all-srcs", + ], tags = ["automanaged"], visibility = [ "//build/visible_to:pkg_kubectl_cmd_util_editor_CONSUMERS", diff --git a/pkg/kubectl/util/crlf/BUILD b/pkg/kubectl/cmd/util/editor/crlf/BUILD similarity index 85% rename from pkg/kubectl/util/crlf/BUILD rename to pkg/kubectl/cmd/util/editor/crlf/BUILD index fad33187461..ebf46c7e204 100644 --- a/pkg/kubectl/util/crlf/BUILD +++ b/pkg/kubectl/cmd/util/editor/crlf/BUILD @@ -8,7 +8,7 @@ load( go_library( name = "go_default_library", srcs = ["crlf.go"], - importpath = "k8s.io/kubernetes/pkg/kubectl/util/crlf", + importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf", ) filegroup( diff --git a/pkg/kubectl/util/crlf/crlf.go b/pkg/kubectl/cmd/util/editor/crlf/crlf.go similarity index 98% rename from pkg/kubectl/util/crlf/crlf.go rename to pkg/kubectl/cmd/util/editor/crlf/crlf.go index c08fe6f3108..524a81f3e73 100644 --- a/pkg/kubectl/util/crlf/crlf.go +++ b/pkg/kubectl/cmd/util/editor/crlf/crlf.go @@ -51,7 +51,7 @@ func (w crlfWriter) Write(b []byte) (n int, err error) { } return written + n, err } - written += 1 + written++ i = next + 1 } } diff --git a/pkg/kubectl/cmd/util/editor/editoptions.go b/pkg/kubectl/cmd/util/editor/editoptions.go index abf1e7ef2a3..f2d2920b98a 100644 --- a/pkg/kubectl/cmd/util/editor/editoptions.go +++ b/pkg/kubectl/cmd/util/editor/editoptions.go @@ -45,11 +45,11 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" - "k8s.io/kubernetes/pkg/kubectl/util/crlf" ) // EditOptions contains all the options for running edit cli command. @@ -129,7 +129,7 @@ func (o *EditOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Comm return fmt.Errorf("the edit mode doesn't support output the patch") } - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index 0e7f0724797..3a0fc5d97cf 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -17,18 +17,11 @@ limitations under the License. package util import ( - "fmt" - "strconv" - "strings" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - scaleclient "k8s.io/client-go/scale" - api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" @@ -64,13 +57,6 @@ type Factory interface { // and which implements the common patterns for CLI interactions with generic resources. NewBuilder() *resource.Builder - // Returns the default namespace to use in cases where no - // other namespace is specified and whether the namespace was - // overridden. - DefaultNamespace() (string, bool, error) - // Generators returns the generators for the provided command - Generators(cmdName string) map[string]kubectl.Generator - // Returns a RESTClient for working with the specified RESTMapping or an error. This is intended // for working with arbitrary resources and is not guaranteed to point to a Kubernetes APIServer. ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) @@ -81,30 +67,4 @@ type Factory interface { Validator(validate bool) (validation.Schema, error) // OpenAPISchema returns the schema openapi schema definition OpenAPISchema() (openapi.Resources, error) - - // ScaleClient gives you back scale getter - ScaleClient() (scaleclient.ScalesGetter, error) -} - -func makePortsString(ports []api.ServicePort, useNodePort bool) string { - pieces := make([]string, len(ports)) - for ix := range ports { - var port int32 - if useNodePort { - port = ports[ix].NodePort - } else { - port = ports[ix].Port - } - pieces[ix] = fmt.Sprintf("%s:%d", strings.ToLower(string(ports[ix].Protocol)), port) - } - return strings.Join(pieces, ",") -} - -// Extracts the protocols exposed by a service from the given service spec. -func getServiceProtocols(spec api.ServiceSpec) map[string]string { - result := make(map[string]string) - for _, servicePort := range spec.Ports { - result[strconv.Itoa(int(servicePort.Port))] = string(servicePort.Protocol) - } - return result } diff --git a/pkg/kubectl/cmd/util/factory_client_access.go b/pkg/kubectl/cmd/util/factory_client_access.go index c9cbda6bdde..43b4a1a9b08 100644 --- a/pkg/kubectl/cmd/util/factory_client_access.go +++ b/pkg/kubectl/cmd/util/factory_client_access.go @@ -19,32 +19,19 @@ limitations under the License. package util import ( - "fmt" - "io" "sync" - appsv1 "k8s.io/api/apps/v1" - appsv1beta1 "k8s.io/api/apps/v1beta1" - batchv1 "k8s.io/api/batch/v1" - batchv1beta1 "k8s.io/api/batch/v1beta1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" - extensionsv1beta1 "k8s.io/api/extensions/v1beta1" - apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - scaleclient "k8s.io/client-go/scale" "k8s.io/client-go/tools/clientcmd" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" openapivalidation "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" @@ -130,10 +117,6 @@ func (f *factoryImpl) RESTClient() (*restclient.RESTClient, error) { return restclient.RESTClientFor(clientConfig) } -func (f *factoryImpl) DefaultNamespace() (string, bool, error) { - return f.clientGetter.ToRawKubeConfigLoader().Namespace() -} - func (f *factoryImpl) ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { cfg, err := f.clientGetter.ToRESTConfig() if err != nil { @@ -205,234 +188,6 @@ func (f *factoryImpl) OpenAPISchema() (openapi.Resources, error) { return f.openAPIGetter.getter.Get() } -func (f *factoryImpl) ScaleClient() (scaleclient.ScalesGetter, error) { - discoClient, err := f.clientGetter.ToDiscoveryClient() - if err != nil { - return nil, err - } - restClient, err := f.RESTClient() - if err != nil { - return nil, err - } - resolver := scaleclient.NewDiscoveryScaleKindResolver(discoClient) - mapper, err := f.clientGetter.ToRESTMapper() - if err != nil { - return nil, err - } - - return scaleclient.New(restClient, mapper, dynamic.LegacyAPIPathResolverFunc, resolver), nil -} - -const ( - // TODO(sig-cli): Enforce consistent naming for generators here. - // See discussion in https://github.com/kubernetes/kubernetes/issues/46237 - // before you add any more. - RunV1GeneratorName = "run/v1" - RunPodV1GeneratorName = "run-pod/v1" - ServiceV1GeneratorName = "service/v1" - ServiceV2GeneratorName = "service/v2" - ServiceNodePortGeneratorV1Name = "service-nodeport/v1" - ServiceClusterIPGeneratorV1Name = "service-clusterip/v1" - ServiceLoadBalancerGeneratorV1Name = "service-loadbalancer/v1" - ServiceExternalNameGeneratorV1Name = "service-externalname/v1" - ServiceAccountV1GeneratorName = "serviceaccount/v1" - HorizontalPodAutoscalerV1GeneratorName = "horizontalpodautoscaler/v1" - DeploymentV1Beta1GeneratorName = "deployment/v1beta1" - DeploymentAppsV1Beta1GeneratorName = "deployment/apps.v1beta1" - DeploymentBasicV1Beta1GeneratorName = "deployment-basic/v1beta1" - DeploymentBasicAppsV1Beta1GeneratorName = "deployment-basic/apps.v1beta1" - DeploymentBasicAppsV1GeneratorName = "deployment-basic/apps.v1" - JobV1GeneratorName = "job/v1" - CronJobV2Alpha1GeneratorName = "cronjob/v2alpha1" - CronJobV1Beta1GeneratorName = "cronjob/v1beta1" - NamespaceV1GeneratorName = "namespace/v1" - ResourceQuotaV1GeneratorName = "resourcequotas/v1" - SecretV1GeneratorName = "secret/v1" - SecretForDockerRegistryV1GeneratorName = "secret-for-docker-registry/v1" - SecretForTLSV1GeneratorName = "secret-for-tls/v1" - ConfigMapV1GeneratorName = "configmap/v1" - ClusterRoleBindingV1GeneratorName = "clusterrolebinding.rbac.authorization.k8s.io/v1alpha1" - RoleBindingV1GeneratorName = "rolebinding.rbac.authorization.k8s.io/v1alpha1" - ClusterV1Beta1GeneratorName = "cluster/v1beta1" - PodDisruptionBudgetV1GeneratorName = "poddisruptionbudget/v1beta1" - PodDisruptionBudgetV2GeneratorName = "poddisruptionbudget/v1beta1/v2" - PriorityClassV1Alpha1GeneratorName = "priorityclass/v1alpha1" -) - -// DefaultGenerators returns the set of default generators for use in Factory instances -func DefaultGenerators(cmdName string) map[string]kubectl.Generator { - var generator map[string]kubectl.Generator - switch cmdName { - case "expose": - generator = map[string]kubectl.Generator{ - ServiceV1GeneratorName: kubectl.ServiceGeneratorV1{}, - ServiceV2GeneratorName: kubectl.ServiceGeneratorV2{}, - } - case "service-clusterip": - generator = map[string]kubectl.Generator{ - ServiceClusterIPGeneratorV1Name: kubectl.ServiceClusterIPGeneratorV1{}, - } - case "service-nodeport": - generator = map[string]kubectl.Generator{ - ServiceNodePortGeneratorV1Name: kubectl.ServiceNodePortGeneratorV1{}, - } - case "service-loadbalancer": - generator = map[string]kubectl.Generator{ - ServiceLoadBalancerGeneratorV1Name: kubectl.ServiceLoadBalancerGeneratorV1{}, - } - case "deployment": - // Create Deployment has only StructuredGenerators and no - // param-based Generators. - // The StructuredGenerators are as follows (as of 2018-03-16): - // DeploymentBasicV1Beta1GeneratorName -> kubectl.DeploymentBasicGeneratorV1 - // DeploymentBasicAppsV1Beta1GeneratorName -> kubectl.DeploymentBasicAppsGeneratorV1Beta1 - // DeploymentBasicAppsV1GeneratorName -> kubectl.DeploymentBasicAppsGeneratorV1 - generator = map[string]kubectl.Generator{} - case "run": - generator = map[string]kubectl.Generator{ - RunV1GeneratorName: kubectl.BasicReplicationController{}, - RunPodV1GeneratorName: kubectl.BasicPod{}, - DeploymentV1Beta1GeneratorName: kubectl.DeploymentV1Beta1{}, - DeploymentAppsV1Beta1GeneratorName: kubectl.DeploymentAppsV1Beta1{}, - JobV1GeneratorName: kubectl.JobV1{}, - CronJobV2Alpha1GeneratorName: kubectl.CronJobV2Alpha1{}, - CronJobV1Beta1GeneratorName: kubectl.CronJobV1Beta1{}, - } - case "namespace": - generator = map[string]kubectl.Generator{ - NamespaceV1GeneratorName: kubectl.NamespaceGeneratorV1{}, - } - case "quota": - generator = map[string]kubectl.Generator{ - ResourceQuotaV1GeneratorName: kubectl.ResourceQuotaGeneratorV1{}, - } - case "secret": - generator = map[string]kubectl.Generator{ - SecretV1GeneratorName: kubectl.SecretGeneratorV1{}, - } - case "secret-for-docker-registry": - generator = map[string]kubectl.Generator{ - SecretForDockerRegistryV1GeneratorName: kubectl.SecretForDockerRegistryGeneratorV1{}, - } - case "secret-for-tls": - generator = map[string]kubectl.Generator{ - SecretForTLSV1GeneratorName: kubectl.SecretForTLSGeneratorV1{}, - } - } - - return generator -} - -// fallbackGeneratorNameIfNecessary returns the name of the old generator -// if server does not support new generator. Otherwise, the -// generator string is returned unchanged. -// -// If the generator name is changed, print a warning message to let the user -// know. -func FallbackGeneratorNameIfNecessary( - generatorName string, - discoveryClient discovery.DiscoveryInterface, - cmdErr io.Writer, -) (string, error) { - switch generatorName { - case DeploymentAppsV1Beta1GeneratorName: - hasResource, err := HasResource(discoveryClient, appsv1beta1.SchemeGroupVersion.WithResource("deployments")) - if err != nil { - return "", err - } - if !hasResource { - return FallbackGeneratorNameIfNecessary(DeploymentV1Beta1GeneratorName, discoveryClient, cmdErr) - } - case DeploymentV1Beta1GeneratorName: - hasResource, err := HasResource(discoveryClient, extensionsv1beta1.SchemeGroupVersion.WithResource("deployments")) - if err != nil { - return "", err - } - if !hasResource { - return RunV1GeneratorName, nil - } - case DeploymentBasicAppsV1GeneratorName: - hasResource, err := HasResource(discoveryClient, appsv1.SchemeGroupVersion.WithResource("deployments")) - if err != nil { - return "", err - } - if !hasResource { - return FallbackGeneratorNameIfNecessary(DeploymentBasicAppsV1Beta1GeneratorName, discoveryClient, cmdErr) - } - case DeploymentBasicAppsV1Beta1GeneratorName: - hasResource, err := HasResource(discoveryClient, appsv1beta1.SchemeGroupVersion.WithResource("deployments")) - if err != nil { - return "", err - } - if !hasResource { - return DeploymentBasicV1Beta1GeneratorName, nil - } - case JobV1GeneratorName: - hasResource, err := HasResource(discoveryClient, batchv1.SchemeGroupVersion.WithResource("jobs")) - if err != nil { - return "", err - } - if !hasResource { - return RunPodV1GeneratorName, nil - } - case CronJobV1Beta1GeneratorName: - hasResource, err := HasResource(discoveryClient, batchv1beta1.SchemeGroupVersion.WithResource("cronjobs")) - if err != nil { - return "", err - } - if !hasResource { - return FallbackGeneratorNameIfNecessary(CronJobV2Alpha1GeneratorName, discoveryClient, cmdErr) - } - case CronJobV2Alpha1GeneratorName: - hasResource, err := HasResource(discoveryClient, batchv2alpha1.SchemeGroupVersion.WithResource("cronjobs")) - if err != nil { - return "", err - } - if !hasResource { - return JobV1GeneratorName, nil - } - } - return generatorName, nil -} - -func Warning(cmdErr io.Writer, newGeneratorName, oldGeneratorName string) { - fmt.Fprintf(cmdErr, "WARNING: New generator %q specified, "+ - "but it isn't available. "+ - "Falling back to %q.\n", - newGeneratorName, - oldGeneratorName, - ) -} - -func HasResource(client discovery.DiscoveryInterface, resource schema.GroupVersionResource) (bool, error) { - resources, err := client.ServerResourcesForGroupVersion(resource.GroupVersion().String()) - if apierrors.IsNotFound(err) { - // entire group is missing - return false, nil - } - if err != nil { - // other errors error - return false, fmt.Errorf("failed to discover supported resources: %v", err) - } - for _, serverResource := range resources.APIResources { - if serverResource.Name == resource.Resource { - return true, nil - } - } - return false, nil -} - -func Contains(resourcesList []*metav1.APIResourceList, resource schema.GroupVersionResource) bool { - resources := discovery.FilteredBy(discovery.ResourcePredicateFunc(func(gv string, r *metav1.APIResource) bool { - return resource.GroupVersion().String() == gv && resource.Resource == r.Name - }), resourcesList) - return len(resources) != 0 -} - -func (f *factoryImpl) Generators(cmdName string) map[string]kubectl.Generator { - return DefaultGenerators(cmdName) -} - // this method exists to help us find the points still relying on internal types. func InternalVersionDecoder() runtime.Decoder { return legacyscheme.Codecs.UniversalDecoder() diff --git a/pkg/kubectl/cmd/util/factory_test.go b/pkg/kubectl/cmd/util/factory_test.go deleted file mode 100644 index 06d9ac87062..00000000000 --- a/pkg/kubectl/cmd/util/factory_test.go +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT 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 ( - "testing" - - api "k8s.io/kubernetes/pkg/apis/core" -) - -func TestMakePortsString(t *testing.T) { - tests := []struct { - ports []api.ServicePort - useNodePort bool - expectedOutput string - }{ - {ports: nil, expectedOutput: ""}, - {ports: []api.ServicePort{}, expectedOutput: ""}, - {ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - }, - }, - expectedOutput: "tcp:80", - }, - {ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - }, - { - Port: 8080, - Protocol: "UDP", - }, - { - Port: 9000, - Protocol: "TCP", - }, - }, - expectedOutput: "tcp:80,udp:8080,tcp:9000", - }, - {ports: []api.ServicePort{ - { - Port: 80, - NodePort: 9090, - Protocol: "TCP", - }, - { - Port: 8080, - NodePort: 80, - Protocol: "UDP", - }, - }, - useNodePort: true, - expectedOutput: "tcp:9090,udp:80", - }, - } - for _, test := range tests { - output := makePortsString(test.ports, test.useNodePort) - if output != test.expectedOutput { - t.Errorf("expected: %s, saw: %s.", test.expectedOutput, output) - } - } -} diff --git a/pkg/kubectl/cmd/util/generator.go b/pkg/kubectl/cmd/util/generator.go new file mode 100644 index 00000000000..7d02669bee8 --- /dev/null +++ b/pkg/kubectl/cmd/util/generator.go @@ -0,0 +1,237 @@ +/* +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" + "io" + + appsv1 "k8s.io/api/apps/v1" + appsv1beta1 "k8s.io/api/apps/v1beta1" + batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" + batchv2alpha1 "k8s.io/api/batch/v2alpha1" + extensionsv1beta1 "k8s.io/api/extensions/v1beta1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" + "k8s.io/kubernetes/pkg/kubectl" +) + +const ( + // TODO(sig-cli): Enforce consistent naming for generators here. + // See discussion in https://github.com/kubernetes/kubernetes/issues/46237 + // before you add any more. + RunV1GeneratorName = "run/v1" + RunPodV1GeneratorName = "run-pod/v1" + ServiceV1GeneratorName = "service/v1" + ServiceV2GeneratorName = "service/v2" + ServiceNodePortGeneratorV1Name = "service-nodeport/v1" + ServiceClusterIPGeneratorV1Name = "service-clusterip/v1" + ServiceLoadBalancerGeneratorV1Name = "service-loadbalancer/v1" + ServiceExternalNameGeneratorV1Name = "service-externalname/v1" + ServiceAccountV1GeneratorName = "serviceaccount/v1" + HorizontalPodAutoscalerV1GeneratorName = "horizontalpodautoscaler/v1" + DeploymentV1Beta1GeneratorName = "deployment/v1beta1" + DeploymentAppsV1Beta1GeneratorName = "deployment/apps.v1beta1" + DeploymentBasicV1Beta1GeneratorName = "deployment-basic/v1beta1" + DeploymentBasicAppsV1Beta1GeneratorName = "deployment-basic/apps.v1beta1" + DeploymentBasicAppsV1GeneratorName = "deployment-basic/apps.v1" + JobV1GeneratorName = "job/v1" + CronJobV2Alpha1GeneratorName = "cronjob/v2alpha1" + CronJobV1Beta1GeneratorName = "cronjob/v1beta1" + NamespaceV1GeneratorName = "namespace/v1" + ResourceQuotaV1GeneratorName = "resourcequotas/v1" + SecretV1GeneratorName = "secret/v1" + SecretForDockerRegistryV1GeneratorName = "secret-for-docker-registry/v1" + SecretForTLSV1GeneratorName = "secret-for-tls/v1" + ConfigMapV1GeneratorName = "configmap/v1" + ClusterRoleBindingV1GeneratorName = "clusterrolebinding.rbac.authorization.k8s.io/v1alpha1" + RoleBindingV1GeneratorName = "rolebinding.rbac.authorization.k8s.io/v1alpha1" + PodDisruptionBudgetV1GeneratorName = "poddisruptionbudget/v1beta1" + PodDisruptionBudgetV2GeneratorName = "poddisruptionbudget/v1beta1/v2" + PriorityClassV1Alpha1GeneratorName = "priorityclass/v1alpha1" +) + +// GeneratorFunc returns the generators for the provided command +type GeneratorFunc func(cmdName string) map[string]kubectl.Generator + +// GeneratorFn gives a way to easily override the function for unit testing if needed +var GeneratorFn GeneratorFunc = defaultGenerators + +// defaultGenerators returns the set of default generators for use in Factory instances +func defaultGenerators(cmdName string) map[string]kubectl.Generator { + var generator map[string]kubectl.Generator + switch cmdName { + case "expose": + generator = map[string]kubectl.Generator{ + ServiceV1GeneratorName: kubectl.ServiceGeneratorV1{}, + ServiceV2GeneratorName: kubectl.ServiceGeneratorV2{}, + } + case "service-clusterip": + generator = map[string]kubectl.Generator{ + ServiceClusterIPGeneratorV1Name: kubectl.ServiceClusterIPGeneratorV1{}, + } + case "service-nodeport": + generator = map[string]kubectl.Generator{ + ServiceNodePortGeneratorV1Name: kubectl.ServiceNodePortGeneratorV1{}, + } + case "service-loadbalancer": + generator = map[string]kubectl.Generator{ + ServiceLoadBalancerGeneratorV1Name: kubectl.ServiceLoadBalancerGeneratorV1{}, + } + case "deployment": + // Create Deployment has only StructuredGenerators and no + // param-based Generators. + // The StructuredGenerators are as follows (as of 2018-03-16): + // DeploymentBasicV1Beta1GeneratorName -> kubectl.DeploymentBasicGeneratorV1 + // DeploymentBasicAppsV1Beta1GeneratorName -> kubectl.DeploymentBasicAppsGeneratorV1Beta1 + // DeploymentBasicAppsV1GeneratorName -> kubectl.DeploymentBasicAppsGeneratorV1 + generator = map[string]kubectl.Generator{} + case "run": + generator = map[string]kubectl.Generator{ + RunV1GeneratorName: kubectl.BasicReplicationController{}, + RunPodV1GeneratorName: kubectl.BasicPod{}, + DeploymentV1Beta1GeneratorName: kubectl.DeploymentV1Beta1{}, + DeploymentAppsV1Beta1GeneratorName: kubectl.DeploymentAppsV1Beta1{}, + JobV1GeneratorName: kubectl.JobV1{}, + CronJobV2Alpha1GeneratorName: kubectl.CronJobV2Alpha1{}, + CronJobV1Beta1GeneratorName: kubectl.CronJobV1Beta1{}, + } + case "namespace": + generator = map[string]kubectl.Generator{ + NamespaceV1GeneratorName: kubectl.NamespaceGeneratorV1{}, + } + case "quota": + generator = map[string]kubectl.Generator{ + ResourceQuotaV1GeneratorName: kubectl.ResourceQuotaGeneratorV1{}, + } + case "secret": + generator = map[string]kubectl.Generator{ + SecretV1GeneratorName: kubectl.SecretGeneratorV1{}, + } + case "secret-for-docker-registry": + generator = map[string]kubectl.Generator{ + SecretForDockerRegistryV1GeneratorName: kubectl.SecretForDockerRegistryGeneratorV1{}, + } + case "secret-for-tls": + generator = map[string]kubectl.Generator{ + SecretForTLSV1GeneratorName: kubectl.SecretForTLSGeneratorV1{}, + } + } + + return generator +} + +// FallbackGeneratorNameIfNecessary returns the name of the old generator +// if server does not support new generator. Otherwise, the +// generator string is returned unchanged. +// +// If the generator name is changed, print a warning message to let the user +// know. +func FallbackGeneratorNameIfNecessary( + generatorName string, + discoveryClient discovery.DiscoveryInterface, + cmdErr io.Writer, +) (string, error) { + switch generatorName { + case DeploymentAppsV1Beta1GeneratorName: + hasResource, err := HasResource(discoveryClient, appsv1beta1.SchemeGroupVersion.WithResource("deployments")) + if err != nil { + return "", err + } + if !hasResource { + return FallbackGeneratorNameIfNecessary(DeploymentV1Beta1GeneratorName, discoveryClient, cmdErr) + } + case DeploymentV1Beta1GeneratorName: + hasResource, err := HasResource(discoveryClient, extensionsv1beta1.SchemeGroupVersion.WithResource("deployments")) + if err != nil { + return "", err + } + if !hasResource { + return RunV1GeneratorName, nil + } + case DeploymentBasicAppsV1GeneratorName: + hasResource, err := HasResource(discoveryClient, appsv1.SchemeGroupVersion.WithResource("deployments")) + if err != nil { + return "", err + } + if !hasResource { + return FallbackGeneratorNameIfNecessary(DeploymentBasicAppsV1Beta1GeneratorName, discoveryClient, cmdErr) + } + case DeploymentBasicAppsV1Beta1GeneratorName: + hasResource, err := HasResource(discoveryClient, appsv1beta1.SchemeGroupVersion.WithResource("deployments")) + if err != nil { + return "", err + } + if !hasResource { + return DeploymentBasicV1Beta1GeneratorName, nil + } + case JobV1GeneratorName: + hasResource, err := HasResource(discoveryClient, batchv1.SchemeGroupVersion.WithResource("jobs")) + if err != nil { + return "", err + } + if !hasResource { + return RunPodV1GeneratorName, nil + } + case CronJobV1Beta1GeneratorName: + hasResource, err := HasResource(discoveryClient, batchv1beta1.SchemeGroupVersion.WithResource("cronjobs")) + if err != nil { + return "", err + } + if !hasResource { + return FallbackGeneratorNameIfNecessary(CronJobV2Alpha1GeneratorName, discoveryClient, cmdErr) + } + case CronJobV2Alpha1GeneratorName: + hasResource, err := HasResource(discoveryClient, batchv2alpha1.SchemeGroupVersion.WithResource("cronjobs")) + if err != nil { + return "", err + } + if !hasResource { + return JobV1GeneratorName, nil + } + } + return generatorName, nil +} + +func HasResource(client discovery.DiscoveryInterface, resource schema.GroupVersionResource) (bool, error) { + resources, err := client.ServerResourcesForGroupVersion(resource.GroupVersion().String()) + if apierrors.IsNotFound(err) { + // entire group is missing + return false, nil + } + if err != nil { + // other errors error + return false, fmt.Errorf("failed to discover supported resources: %v", err) + } + for _, serverResource := range resources.APIResources { + if serverResource.Name == resource.Resource { + return true, nil + } + } + return false, nil +} + +func Warning(cmdErr io.Writer, newGeneratorName, oldGeneratorName string) { + fmt.Fprintf(cmdErr, "WARNING: New generator %q specified, "+ + "but it isn't available. "+ + "Falling back to %q.\n", + newGeneratorName, + oldGeneratorName, + ) +} diff --git a/pkg/kubectl/cmd/util/helpers.go b/pkg/kubectl/cmd/util/helpers.go index b4640f67b25..aa2224652b8 100644 --- a/pkg/kubectl/cmd/util/helpers.go +++ b/pkg/kubectl/cmd/util/helpers.go @@ -29,6 +29,7 @@ import ( "github.com/evanphx/json-patch" "github.com/golang/glog" "github.com/spf13/cobra" + "github.com/spf13/pflag" kerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" @@ -38,9 +39,10 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/yaml" "k8s.io/client-go/dynamic" + "k8s.io/client-go/rest" + "k8s.io/client-go/scale" "k8s.io/client-go/tools/clientcmd" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/printers" @@ -298,16 +300,6 @@ func IsFilenameSliceEmpty(filenames []string) bool { return len(filenames) == 0 } -// Whether this cmd need watching objects. -func isWatch(cmd *cobra.Command) bool { - if w, err := cmd.Flags().GetBool("watch"); err == nil && w { - return true - } - - wo, err := cmd.Flags().GetBool("watch-only") - return err == nil && wo -} - func GetFlagString(cmd *cobra.Command, flag string) string { s, err := cmd.Flags().GetString(flag) if err != nil { @@ -334,15 +326,6 @@ func GetFlagStringArray(cmd *cobra.Command, flag string) []string { return s } -// GetWideFlag is used to determine if "-o wide" is used -func GetWideFlag(cmd *cobra.Command) bool { - f := cmd.Flags().Lookup("output") - if f != nil && f.Value != nil && f.Value.String() == "wide" { - return true - } - return false -} - func GetFlagBool(cmd *cobra.Command, flag string) bool { b, err := cmd.Flags().GetBool(flag) if err != nil { @@ -403,10 +386,19 @@ func AddValidateOptionFlags(cmd *cobra.Command, options *ValidateOptions) { } func AddFilenameOptionFlags(cmd *cobra.Command, options *resource.FilenameOptions, usage string) { - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, "Filename, directory, or URL to files "+usage) + AddJsonFilenameFlag(cmd.Flags(), &options.Filenames, "Filename, directory, or URL to files "+usage) cmd.Flags().BoolVarP(&options.Recursive, "recursive", "R", options.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") } +func AddJsonFilenameFlag(flags *pflag.FlagSet, value *[]string, usage string) { + flags.StringSliceVarP(value, "filename", "f", *value, usage) + annotations := make([]string, 0, len(resource.FileExtensions)) + for _, ext := range resource.FileExtensions { + annotations = append(annotations, strings.TrimLeft(ext, ".")) + } + flags.SetAnnotation("filename", cobra.BashCompFilenameExt, annotations) +} + // AddDryRunFlag adds dry-run flag to a command. Usually used by mutations. func AddDryRunFlag(cmd *cobra.Command) { cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.") @@ -673,3 +665,35 @@ func genericDescriber(restClientGetter genericclioptions.RESTClientGetter, mappi eventsClient := clientSet.Core() return printersinternal.GenericDescriberFor(mapping, dynamicClient, eventsClient), nil } + +// ScaleClientFunc provides a ScalesGetter +type ScaleClientFunc func(genericclioptions.RESTClientGetter) (scale.ScalesGetter, error) + +// ScaleClientFn gives a way to easily override the function for unit testing if needed. +var ScaleClientFn ScaleClientFunc = scaleClient + +// scaleClient gives you back scale getter +func scaleClient(restClientGetter genericclioptions.RESTClientGetter) (scale.ScalesGetter, error) { + discoveryClient, err := restClientGetter.ToDiscoveryClient() + if err != nil { + return nil, err + } + + clientConfig, err := restClientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + + setKubernetesDefaults(clientConfig) + restClient, err := rest.RESTClientFor(clientConfig) + if err != nil { + return nil, err + } + resolver := scale.NewDiscoveryScaleKindResolver(discoveryClient) + mapper, err := restClientGetter.ToRESTMapper() + if err != nil { + return nil, err + } + + return scale.New(restClient, mapper, dynamic.LegacyAPIPathResolverFunc, resolver), nil +} diff --git a/pkg/kubectl/cmd/util/jsonmerge/BUILD b/pkg/kubectl/cmd/util/jsonmerge/BUILD deleted file mode 100644 index 08551294bbd..00000000000 --- a/pkg/kubectl/cmd/util/jsonmerge/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["jsonmerge.go"], - importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge", - visibility = ["//visibility:public"], - deps = [ - "//vendor/github.com/evanphx/json-patch:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/mergepatch:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = [ - "//build/visible_to:pkg_kubectl_cmd_util_jsonmerge_CONSUMERS", - ], -) diff --git a/pkg/kubectl/cmd/util/jsonmerge/jsonmerge.go b/pkg/kubectl/cmd/util/jsonmerge/jsonmerge.go deleted file mode 100644 index beebc7f052a..00000000000 --- a/pkg/kubectl/cmd/util/jsonmerge/jsonmerge.go +++ /dev/null @@ -1,193 +0,0 @@ -/* -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 jsonmerge - -import ( - "encoding/json" - "fmt" - - "github.com/evanphx/json-patch" - "github.com/golang/glog" - - "k8s.io/apimachinery/pkg/util/mergepatch" - "k8s.io/apimachinery/pkg/util/yaml" -) - -// Delta represents a change between two JSON documents. -type Delta struct { - original []byte - edit []byte - - preconditions []PreconditionFunc -} - -// PreconditionFunc is a test to verify that an incompatible change -// has occurred before an Apply can be successful. -type PreconditionFunc func(interface{}) (hold bool, message string) - -// AddPreconditions adds precondition checks to a change which must -// be satisfied before an Apply is considered successful. If a -// precondition returns false, the Apply is failed with -// ErrPreconditionFailed. -func (d *Delta) AddPreconditions(fns ...PreconditionFunc) { - d.preconditions = append(d.preconditions, fns...) -} - -// RequireKeyUnchanged creates a precondition function that fails -// if the provided key is present in the diff (indicating its value -// has changed). -func RequireKeyUnchanged(key string) PreconditionFunc { - return func(diff interface{}) (bool, string) { - m, ok := diff.(map[string]interface{}) - if !ok { - return true, "" - } - // the presence of key in a diff means that its value has been changed, therefore - // we should fail the precondition. - _, ok = m[key] - if ok { - return false, key + " should not be changed\n" - } else { - return true, "" - } - } -} - -// RequireMetadataKeyUnchanged creates a precondition function that fails -// if the metadata.key is present in the diff (indicating its value -// has changed). -func RequireMetadataKeyUnchanged(key string) PreconditionFunc { - return func(diff interface{}) (bool, string) { - m, ok := diff.(map[string]interface{}) - if !ok { - return true, "" - } - m1, ok := m["metadata"] - if !ok { - return true, "" - } - m2, ok := m1.(map[string]interface{}) - if !ok { - return true, "" - } - _, ok = m2[key] - if ok { - return false, "metadata." + key + " should not be changed\n" - } else { - return true, "" - } - } -} - -// TestPreconditions test if preconditions hold given the edit -func TestPreconditionsHold(edit []byte, preconditions []PreconditionFunc) (bool, string) { - diff := make(map[string]interface{}) - if err := json.Unmarshal(edit, &diff); err != nil { - return false, err.Error() - } - for _, fn := range preconditions { - if hold, msg := fn(diff); !hold { - return false, msg - } - } - return true, "" -} - -// NewDelta accepts two JSON or YAML documents and calculates the difference -// between them. It returns a Delta object which can be used to resolve -// conflicts against a third version with a common parent, or an error -// if either document is in error. -func NewDelta(from, to []byte) (*Delta, error) { - d := &Delta{} - before, err := yaml.ToJSON(from) - if err != nil { - return nil, err - } - after, err := yaml.ToJSON(to) - if err != nil { - return nil, err - } - diff, err := jsonpatch.CreateMergePatch(before, after) - if err != nil { - return nil, err - } - glog.V(6).Infof("Patch created from:\n%s\n%s\n%s", string(before), string(after), string(diff)) - d.original = before - d.edit = diff - return d, nil -} - -// Apply attempts to apply the changes described by Delta onto latest, -// returning an error if the changes cannot be applied cleanly. -// IsConflicting will be true if the changes overlap, otherwise a -// generic error will be returned. -func (d *Delta) Apply(latest []byte) ([]byte, error) { - base, err := yaml.ToJSON(latest) - if err != nil { - return nil, err - } - changes, err := jsonpatch.CreateMergePatch(d.original, base) - if err != nil { - return nil, err - } - diff1 := make(map[string]interface{}) - if err := json.Unmarshal(d.edit, &diff1); err != nil { - return nil, err - } - diff2 := make(map[string]interface{}) - if err := json.Unmarshal(changes, &diff2); err != nil { - return nil, err - } - for _, fn := range d.preconditions { - hold1, _ := fn(diff1) - hold2, _ := fn(diff2) - if !hold1 || !hold2 { - return nil, ErrPreconditionFailed - } - } - - glog.V(6).Infof("Testing for conflict between:\n%s\n%s", string(d.edit), string(changes)) - hasConflicts, err := mergepatch.HasConflicts(diff1, diff2) - if err != nil { - return nil, err - } - if hasConflicts { - return nil, ErrConflict - } - - return jsonpatch.MergePatch(base, d.edit) -} - -// IsConflicting returns true if the provided error indicates a -// conflict exists between the original changes and the applied -// changes. -func IsConflicting(err error) bool { - return err == ErrConflict -} - -// IsPreconditionFailed returns true if the provided error indicates -// a Delta precondition did not succeed. -func IsPreconditionFailed(err error) bool { - return err == ErrPreconditionFailed -} - -var ErrPreconditionFailed = fmt.Errorf("a precondition failed") -var ErrConflict = fmt.Errorf("changes are in conflict") - -func (d *Delta) Edit() []byte { - return d.edit -} diff --git a/pkg/kubectl/cmd/util/openapi/BUILD b/pkg/kubectl/cmd/util/openapi/BUILD index bb6b3e24048..22f8f9c737e 100644 --- a/pkg/kubectl/cmd/util/openapi/BUILD +++ b/pkg/kubectl/cmd/util/openapi/BUILD @@ -35,13 +35,14 @@ go_test( data = ["//api/openapi-spec:swagger-spec"], deps = [ ":go_default_library", - "//pkg/kubectl/cmd/util/openapi/testing:go_default_library", + "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/ginkgo/config:go_default_library", "//vendor/github.com/onsi/ginkgo/types:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library", ], ) diff --git a/pkg/kubectl/cmd/util/openapi/openapi_getter_test.go b/pkg/kubectl/cmd/util/openapi/openapi_getter_test.go index 004d27e1b2b..9239fe2bc75 100644 --- a/pkg/kubectl/cmd/util/openapi/openapi_getter_test.go +++ b/pkg/kubectl/cmd/util/openapi/openapi_getter_test.go @@ -19,27 +19,36 @@ package openapi_test import ( "fmt" + openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" ) +// FakeCounter returns a "null" document and the specified error. It +// also counts how many times the OpenAPISchema method has been called. +type FakeCounter struct { + Calls int + Err error +} + +func (f *FakeCounter) OpenAPISchema() (*openapi_v2.Document, error) { + f.Calls = f.Calls + 1 + return nil, f.Err +} + var _ = Describe("Getting the Resources", func() { - var client *tst.FakeClient - var expectedData openapi.Resources + var client FakeCounter var instance openapi.Getter + var expectedData openapi.Resources BeforeEach(func() { - client = tst.NewFakeClient(&fakeSchema) - d, err := fakeSchema.OpenAPISchema() + client = FakeCounter{} + instance = openapi.NewOpenAPIGetter(&client) + var err error + expectedData, err = openapi.NewOpenAPIData(nil) Expect(err).To(BeNil()) - - expectedData, err = openapi.NewOpenAPIData(d) - Expect(err).To(BeNil()) - - instance = openapi.NewOpenAPIGetter(client) }) Context("when the server returns a successful result", func() { diff --git a/pkg/kubectl/cmd/util/openapi/openapi_test.go b/pkg/kubectl/cmd/util/openapi/openapi_test.go index 5ee7302f1bc..d996a533823 100644 --- a/pkg/kubectl/cmd/util/openapi/openapi_test.go +++ b/pkg/kubectl/cmd/util/openapi/openapi_test.go @@ -24,11 +24,11 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kube-openapi/pkg/util/proto" + "k8s.io/kube-openapi/pkg/util/proto/testing" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" ) -var fakeSchema = tst.Fake{Path: filepath.Join("..", "..", "..", "..", "..", "api", "openapi-spec", "swagger.json")} +var fakeSchema = testing.Fake{Path: filepath.Join("..", "..", "..", "..", "..", "api", "openapi-spec", "swagger.json")} var _ = Describe("Reading apps/v1beta1/Deployment from openAPIData", func() { var resources openapi.Resources diff --git a/pkg/kubectl/cmd/util/openapi/testing/BUILD b/pkg/kubectl/cmd/util/openapi/testing/BUILD index 26a7b346737..ce6ffc739b3 100644 --- a/pkg/kubectl/cmd/util/openapi/testing/BUILD +++ b/pkg/kubectl/cmd/util/openapi/testing/BUILD @@ -11,11 +11,9 @@ go_library( importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing", deps = [ "//pkg/kubectl/cmd/util/openapi:go_default_library", - "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", - "//vendor/github.com/googleapis/gnostic/compiler:go_default_library", - "//vendor/gopkg.in/yaml.v2:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library", ], ) diff --git a/pkg/kubectl/cmd/util/openapi/testing/openapi.go b/pkg/kubectl/cmd/util/openapi/testing/openapi.go index 1ccf47c25a5..e59e6d3d390 100644 --- a/pkg/kubectl/cmd/util/openapi/testing/openapi.go +++ b/pkg/kubectl/cmd/util/openapi/testing/openapi.go @@ -17,86 +17,17 @@ limitations under the License. package testing import ( - "io/ioutil" - "os" - "sync" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kube-openapi/pkg/util/proto" + "k8s.io/kube-openapi/pkg/util/proto/testing" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - - yaml "gopkg.in/yaml.v2" - - "github.com/googleapis/gnostic/OpenAPIv2" - "github.com/googleapis/gnostic/compiler" ) -// Fake opens and returns a openapi swagger from a file Path. It will -// parse only once and then return the same copy everytime. -type Fake struct { - Path string - - once sync.Once - document *openapi_v2.Document - err error -} - -// OpenAPISchema returns the openapi document and a potential error. -func (f *Fake) OpenAPISchema() (*openapi_v2.Document, error) { - f.once.Do(func() { - _, err := os.Stat(f.Path) - if err != nil { - f.err = err - return - } - spec, err := ioutil.ReadFile(f.Path) - if err != nil { - f.err = err - return - } - var info yaml.MapSlice - err = yaml.Unmarshal(spec, &info) - if err != nil { - f.err = err - return - } - f.document, f.err = openapi_v2.NewDocument(info, compiler.NewContext("$root", nil)) - }) - return f.document, f.err -} - -// FakeClient implements a dummy OpenAPISchemaInterface that uses the -// fake OpenAPI schema given as a parameter, and count the number of -// call to the function. -type FakeClient struct { - Calls int - Err error - - fake *Fake -} - -// NewFakeClient creates a new FakeClient from the given Fake. -func NewFakeClient(f *Fake) *FakeClient { - return &FakeClient{fake: f} -} - -// OpenAPISchema returns a OpenAPI Document as returned by the fake, but -// it also counts the number of calls. -func (f *FakeClient) OpenAPISchema() (*openapi_v2.Document, error) { - f.Calls = f.Calls + 1 - - if f.Err != nil { - return nil, f.Err - } - - return f.fake.OpenAPISchema() -} - // FakeResources is a wrapper to directly load the openapi schema from a // file, and get the schema for given GVK. This is only for test since // it's assuming that the file is there and everything will go fine. type FakeResources struct { - fake Fake + fake testing.Fake } var _ openapi.Resources = &FakeResources{} @@ -104,7 +35,7 @@ var _ openapi.Resources = &FakeResources{} // NewFakeResources creates a new FakeResources. func NewFakeResources(path string) *FakeResources { return &FakeResources{ - fake: Fake{Path: path}, + fake: testing.Fake{Path: path}, } } diff --git a/pkg/kubectl/cmd/util/openapi/validation/BUILD b/pkg/kubectl/cmd/util/openapi/validation/BUILD index b1fa6fb0ae0..1d1ebb302d4 100644 --- a/pkg/kubectl/cmd/util/openapi/validation/BUILD +++ b/pkg/kubectl/cmd/util/openapi/validation/BUILD @@ -31,12 +31,12 @@ go_test( deps = [ "//pkg/api/testapi:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library", - "//pkg/kubectl/cmd/util/openapi/testing:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/ginkgo/config:go_default_library", "//vendor/github.com/onsi/ginkgo/types:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library", "//vendor/k8s.io/kube-openapi/pkg/util/proto/validation:go_default_library", ], ) diff --git a/pkg/kubectl/cmd/util/openapi/validation/validation_test.go b/pkg/kubectl/cmd/util/openapi/validation/validation_test.go index 67aad17174b..2fb8b528e43 100644 --- a/pkg/kubectl/cmd/util/openapi/validation/validation_test.go +++ b/pkg/kubectl/cmd/util/openapi/validation/validation_test.go @@ -25,12 +25,12 @@ 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/api/testapi" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" ) -var fakeSchema = tst.Fake{Path: filepath.Join("..", "..", "..", "..", "..", "..", "api", "openapi-spec", "swagger.json")} +var fakeSchema = testing.Fake{Path: filepath.Join("..", "..", "..", "..", "..", "..", "api", "openapi-spec", "swagger.json")} var _ = Describe("resource validation using OpenAPI Schema", func() { var validator *SchemaValidation diff --git a/pkg/kubectl/cmd/wait/BUILD b/pkg/kubectl/cmd/wait/BUILD index ce1253f61eb..0f13739b86c 100644 --- a/pkg/kubectl/cmd/wait/BUILD +++ b/pkg/kubectl/cmd/wait/BUILD @@ -2,11 +2,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", - srcs = [ - "fakeresourcefinder.go", - "flags.go", - "wait.go", - ], + srcs = ["wait.go"], importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/wait", visibility = ["//visibility:public"], deps = [ @@ -15,7 +11,6 @@ go_library( "//pkg/kubectl/genericclioptions/printers:go_default_library", "//pkg/kubectl/genericclioptions/resource:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", - "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", diff --git a/pkg/kubectl/cmd/wait/flags.go b/pkg/kubectl/cmd/wait/flags.go deleted file mode 100644 index 824a8af8db6..00000000000 --- a/pkg/kubectl/cmd/wait/flags.go +++ /dev/null @@ -1,114 +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 wait - -import ( - "strings" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "k8s.io/kubernetes/pkg/kubectl/genericclioptions" - "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" -) - -// ResourceBuilderFlags are flags for finding resources -type ResourceBuilderFlags struct { - FilenameOptions resource.FilenameOptions - - LabelSelector string - FieldSelector string - AllNamespaces bool - Namespace string - ExplicitNamespace bool - - // TODO add conditional support. These are false for now. - All bool - Local bool -} - -// NewResourceBuilderFlags returns a default ResourceBuilderFlags -func NewResourceBuilderFlags() *ResourceBuilderFlags { - return &ResourceBuilderFlags{ - FilenameOptions: resource.FilenameOptions{ - Recursive: true, - }, - } -} - -// AddFlags registers flags for finding resources -func (o *ResourceBuilderFlags) AddFlags(flagset *pflag.FlagSet) { - flagset.StringSliceVarP(&o.FilenameOptions.Filenames, "filename", "f", o.FilenameOptions.Filenames, "Filename, directory, or URL to files identifying the resource.") - annotations := make([]string, 0, len(resource.FileExtensions)) - for _, ext := range resource.FileExtensions { - annotations = append(annotations, strings.TrimLeft(ext, ".")) - } - flagset.SetAnnotation("filename", cobra.BashCompFilenameExt, annotations) - flagset.BoolVar(&o.FilenameOptions.Recursive, "recursive", o.FilenameOptions.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") - - flagset.StringVarP(&o.LabelSelector, "selector", "l", o.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - 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.") - 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.") -} - -// ToBuilder gives you back a resource finder to visit resources that are located -func (o *ResourceBuilderFlags) ToBuilder(restClientGetter genericclioptions.RESTClientGetter, resources []string) ResourceFinder { - namespace, enforceNamespace, namespaceErr := restClientGetter.ToRawKubeConfigLoader().Namespace() - - return &ResourceFindBuilderWrapper{ - builder: resource.NewBuilder(restClientGetter). - Unstructured(). - NamespaceParam(namespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &o.FilenameOptions). - LabelSelectorParam(o.LabelSelector). - FieldSelectorParam(o.FieldSelector). - ResourceTypeOrNameArgs(o.All, resources...). - Latest(). - Flatten(). - AddError(namespaceErr), - } -} - -// ResourceFindBuilderWrapper wraps a builder in an interface -type ResourceFindBuilderWrapper struct { - builder *resource.Builder -} - -// Do finds you resources to check -func (b *ResourceFindBuilderWrapper) Do() resource.Visitor { - return b.builder.Do() -} - -// ResourceFinder allows mocking the resource builder -// TODO resource builders needs to become more interfacey -type ResourceFinder interface { - Do() resource.Visitor -} - -// ResourceFinderFunc is a handy way to make a ResourceFinder -type ResourceFinderFunc func() resource.Visitor - -// Do implements ResourceFinder -func (fn ResourceFinderFunc) Do() resource.Visitor { - return fn() -} - -// ResourceFinderForResult skins a visitor for re-use as a ResourceFinder -func ResourceFinderForResult(result resource.Visitor) ResourceFinder { - return ResourceFinderFunc(func() resource.Visitor { - return result - }) -} diff --git a/pkg/kubectl/cmd/wait/wait.go b/pkg/kubectl/cmd/wait/wait.go index e75d5f418dc..503a4bf08c6 100644 --- a/pkg/kubectl/cmd/wait/wait.go +++ b/pkg/kubectl/cmd/wait/wait.go @@ -42,7 +42,7 @@ import ( type WaitFlags struct { RESTClientGetter genericclioptions.RESTClientGetter PrintFlags *genericclioptions.PrintFlags - ResourceBuilderFlags *ResourceBuilderFlags + ResourceBuilderFlags *genericclioptions.ResourceBuilderFlags Timeout time.Duration ForCondition string @@ -53,9 +53,12 @@ type WaitFlags struct { // NewWaitFlags returns a default WaitFlags func NewWaitFlags(restClientGetter genericclioptions.RESTClientGetter, streams genericclioptions.IOStreams) *WaitFlags { return &WaitFlags{ - RESTClientGetter: restClientGetter, - PrintFlags: genericclioptions.NewPrintFlags("condition met"), - ResourceBuilderFlags: NewResourceBuilderFlags(), + RESTClientGetter: restClientGetter, + PrintFlags: genericclioptions.NewPrintFlags("condition met"), + ResourceBuilderFlags: genericclioptions.NewResourceBuilderFlags(). + WithLabelSelector(""). + WithAllNamespaces(false). + WithLatest(), Timeout: 30 * time.Second, @@ -70,7 +73,7 @@ func NewCmdWait(restClientGetter genericclioptions.RESTClientGetter, streams gen cmd := &cobra.Command{ Use: "wait resource.group/name [--for=delete|--for condition=available]", DisableFlagsInUseLine: true, - Short: "Wait for one condition on one or many resources", + Short: "Experimental: Wait for one condition on one or many resources", Run: func(cmd *cobra.Command, args []string) { o, err := flags.ToOptions(args) cmdutil.CheckErr(err) @@ -151,7 +154,7 @@ func conditionFuncFor(condition string) (ConditionFunc, error) { // WaitOptions is a set of options that allows you to wait. This is the object reflects the runtime needs of a wait // command, making the logic itself easy to unit test with our existing mocks. type WaitOptions struct { - ResourceFinder ResourceFinder + ResourceFinder genericclioptions.ResourceFinder DynamicClient dynamic.Interface Timeout time.Duration diff --git a/pkg/kubectl/cmd/wait/wait_test.go b/pkg/kubectl/cmd/wait/wait_test.go index 6ef63357bd5..27446e840f6 100644 --- a/pkg/kubectl/cmd/wait/wait_test.go +++ b/pkg/kubectl/cmd/wait/wait_test.go @@ -219,7 +219,7 @@ func TestWaitForDeletion(t *testing.T) { t.Run(test.name, func(t *testing.T) { fakeClient := test.fakeClient() o := &WaitOptions{ - ResourceFinder: NewSimpleResourceFinder(test.info), + ResourceFinder: genericclioptions.NewSimpleFakeResourceFinder(test.info), DynamicClient: fakeClient, Timeout: test.timeout, @@ -451,7 +451,7 @@ func TestWaitForCondition(t *testing.T) { t.Run(test.name, func(t *testing.T) { fakeClient := test.fakeClient() o := &WaitOptions{ - ResourceFinder: NewSimpleResourceFinder(test.info), + ResourceFinder: genericclioptions.NewSimpleFakeResourceFinder(test.info), DynamicClient: fakeClient, Timeout: test.timeout, diff --git a/pkg/kubectl/genericclioptions/BUILD b/pkg/kubectl/genericclioptions/BUILD index 66867c87ec5..0a04b54eeac 100644 --- a/pkg/kubectl/genericclioptions/BUILD +++ b/pkg/kubectl/genericclioptions/BUILD @@ -3,9 +3,12 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "builder_flags.go", + "builder_flags_fake.go", "config_flags.go", "config_flags_fake.go", "doc.go", + "filename_flags.go", "io_options.go", "json_yaml_flags.go", "name_flags.go", @@ -16,6 +19,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", "//vendor/github.com/evanphx/json-patch:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", @@ -26,6 +30,7 @@ go_library( "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/restmapper:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", "//vendor/k8s.io/client-go/util/homedir:go_default_library", ], ) diff --git a/pkg/kubectl/genericclioptions/builder_flags.go b/pkg/kubectl/genericclioptions/builder_flags.go new file mode 100644 index 00000000000..43ca43b3b6e --- /dev/null +++ b/pkg/kubectl/genericclioptions/builder_flags.go @@ -0,0 +1,233 @@ +/* +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 genericclioptions + +import ( + "github.com/spf13/pflag" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" +) + +// ResourceBuilderFlags are flags for finding resources +// TODO(juanvallejo): wire --local flag from commands through +type ResourceBuilderFlags struct { + FileNameFlags *FileNameFlags + + LabelSelector *string + FieldSelector *string + AllNamespaces *bool + All *bool + Local *bool + IncludeUninitialized *bool + + Scheme *runtime.Scheme + Latest bool + StopOnFirstError bool +} + +// NewResourceBuilderFlags returns a default ResourceBuilderFlags +func NewResourceBuilderFlags() *ResourceBuilderFlags { + filenames := []string{} + + return &ResourceBuilderFlags{ + FileNameFlags: &FileNameFlags{ + Usage: "identifying the resource.", + Filenames: &filenames, + Recursive: boolPtr(true), + }, + } +} + +func (o *ResourceBuilderFlags) WithFile(recurse bool, files ...string) *ResourceBuilderFlags { + o.FileNameFlags = &FileNameFlags{ + Usage: "identifying the resource.", + Filenames: &files, + Recursive: boolPtr(recurse), + } + + return o +} + +func (o *ResourceBuilderFlags) WithLabelSelector(selector string) *ResourceBuilderFlags { + o.LabelSelector = &selector + return o +} + +func (o *ResourceBuilderFlags) WithFieldSelector(selector string) *ResourceBuilderFlags { + o.FieldSelector = &selector + return o +} + +func (o *ResourceBuilderFlags) WithAllNamespaces(defaultVal bool) *ResourceBuilderFlags { + o.AllNamespaces = &defaultVal + return o +} + +func (o *ResourceBuilderFlags) WithAll(defaultVal bool) *ResourceBuilderFlags { + o.All = &defaultVal + return o +} + +func (o *ResourceBuilderFlags) WithLocal(defaultVal bool) *ResourceBuilderFlags { + o.Local = &defaultVal + return o +} + +// WithUninitialized is using an alpha feature and may be dropped +func (o *ResourceBuilderFlags) WithUninitialized(defaultVal bool) *ResourceBuilderFlags { + o.IncludeUninitialized = &defaultVal + return o +} + +func (o *ResourceBuilderFlags) WithScheme(scheme *runtime.Scheme) *ResourceBuilderFlags { + o.Scheme = scheme + return o +} + +func (o *ResourceBuilderFlags) WithLatest() *ResourceBuilderFlags { + o.Latest = true + return o +} + +func (o *ResourceBuilderFlags) StopOnError() *ResourceBuilderFlags { + o.StopOnFirstError = true + return o +} + +// AddFlags registers flags for finding resources +func (o *ResourceBuilderFlags) AddFlags(flagset *pflag.FlagSet) { + o.FileNameFlags.AddFlags(flagset) + + if o.LabelSelector != nil { + flagset.StringVarP(o.LabelSelector, "selector", "l", *o.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + } + if o.FieldSelector != nil { + 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.") + } + if o.All != nil { + flagset.BoolVar(o.All, "all", *o.All, "Select all resources in the namespace of the specified resource types") + } + if o.Local != nil { + flagset.BoolVar(o.Local, "local", *o.Local, "If true, annotation will NOT contact api-server but run locally.") + } + if o.IncludeUninitialized != nil { + flagset.BoolVar(o.IncludeUninitialized, "include-uninitialized", *o.IncludeUninitialized, `If true, the kubectl command applies to uninitialized objects. If explicitly set to false, this flag overrides other flags that make the kubectl commands apply to uninitialized objects, e.g., "--all". Objects with empty metadata.initializers are regarded as initialized.`) + } +} + +// ToBuilder gives you back a resource finder to visit resources that are located +func (o *ResourceBuilderFlags) ToBuilder(restClientGetter RESTClientGetter, resources []string) ResourceFinder { + namespace, enforceNamespace, namespaceErr := restClientGetter.ToRawKubeConfigLoader().Namespace() + + builder := resource.NewBuilder(restClientGetter). + NamespaceParam(namespace).DefaultNamespace() + + if o.Scheme != nil { + builder.WithScheme(o.Scheme, o.Scheme.PrioritizedVersionsAllGroups()...) + } else { + builder.Unstructured() + } + + if o.FileNameFlags != nil { + opts := o.FileNameFlags.ToOptions() + builder.FilenameParam(enforceNamespace, &opts) + } + + if o.Local == nil || !*o.Local { + // resource type/name tuples only work non-local + if o.All != nil { + builder.ResourceTypeOrNameArgs(*o.All, resources...) + } else { + builder.ResourceTypeOrNameArgs(false, resources...) + } + // label selectors only work non-local (for now) + if o.LabelSelector != nil { + builder.LabelSelectorParam(*o.LabelSelector) + } + // field selectors only work non-local (forever) + if o.FieldSelector != nil { + builder.FieldSelectorParam(*o.FieldSelector) + } + // latest only works non-local (forever) + if o.Latest { + builder.Latest() + } + + } else { + builder.Local() + + if len(resources) > 0 { + builder.AddError(resource.LocalResourceError) + } + } + + if o.IncludeUninitialized != nil { + builder.IncludeUninitialized(*o.IncludeUninitialized) + } + + if !o.StopOnFirstError { + builder.ContinueOnError() + } + + return &ResourceFindBuilderWrapper{ + builder: builder. + Flatten(). // I think we're going to recommend this everywhere + AddError(namespaceErr), + } +} + +// ResourceFindBuilderWrapper wraps a builder in an interface +type ResourceFindBuilderWrapper struct { + builder *resource.Builder +} + +// Do finds you resources to check +func (b *ResourceFindBuilderWrapper) Do() resource.Visitor { + return b.builder.Do() +} + +// ResourceFinder allows mocking the resource builder +// TODO resource builders needs to become more interfacey +type ResourceFinder interface { + Do() resource.Visitor +} + +// ResourceFinderFunc is a handy way to make a ResourceFinder +type ResourceFinderFunc func() resource.Visitor + +// Do implements ResourceFinder +func (fn ResourceFinderFunc) Do() resource.Visitor { + return fn() +} + +// ResourceFinderForResult skins a visitor for re-use as a ResourceFinder +func ResourceFinderForResult(result resource.Visitor) ResourceFinder { + return ResourceFinderFunc(func() resource.Visitor { + return result + }) +} + +func strPtr(val string) *string { + return &val +} + +func boolPtr(val bool) *bool { + return &val +} diff --git a/pkg/kubectl/cmd/wait/fakeresourcefinder.go b/pkg/kubectl/genericclioptions/builder_flags_fake.go similarity index 92% rename from pkg/kubectl/cmd/wait/fakeresourcefinder.go rename to pkg/kubectl/genericclioptions/builder_flags_fake.go index 591dea27ef4..de968d8e5d7 100644 --- a/pkg/kubectl/cmd/wait/fakeresourcefinder.go +++ b/pkg/kubectl/genericclioptions/builder_flags_fake.go @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package wait +package genericclioptions import ( "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" ) // NewSimpleResourceFinder builds a super simple ResourceFinder that just iterates over the objects you provided -func NewSimpleResourceFinder(infos ...*resource.Info) ResourceFinder { +func NewSimpleFakeResourceFinder(infos ...*resource.Info) ResourceFinder { return &fakeResourceFinder{ Infos: infos, } diff --git a/pkg/kubectl/genericclioptions/config_flags_fake.go b/pkg/kubectl/genericclioptions/config_flags_fake.go index d019b8c93a2..64e9a688330 100644 --- a/pkg/kubectl/genericclioptions/config_flags_fake.go +++ b/pkg/kubectl/genericclioptions/config_flags_fake.go @@ -24,6 +24,7 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/restmapper" "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) type TestConfigFlags struct { @@ -74,6 +75,36 @@ func (f *TestConfigFlags) WithDiscoveryClient(c discovery.CachedDiscoveryInterfa return f } +func (f *TestConfigFlags) WithNamespace(ns string) *TestConfigFlags { + if f.clientConfig == nil { + panic("attempt to obtain a test RawKubeConfigLoader with no clientConfig specified") + } + f.clientConfig = &namespacedClientConfig{ + delegate: f.clientConfig, + namespace: ns, + } + return f +} + func NewTestConfigFlags() *TestConfigFlags { return &TestConfigFlags{} } + +type namespacedClientConfig struct { + delegate clientcmd.ClientConfig + namespace string +} + +func (c *namespacedClientConfig) Namespace() (string, bool, error) { + return c.namespace, false, nil +} + +func (c *namespacedClientConfig) RawConfig() (clientcmdapi.Config, error) { + return c.delegate.RawConfig() +} +func (c *namespacedClientConfig) ClientConfig() (*rest.Config, error) { + return c.delegate.ClientConfig() +} +func (c *namespacedClientConfig) ConfigAccess() clientcmd.ConfigAccess { + return c.delegate.ConfigAccess() +} diff --git a/pkg/kubectl/genericclioptions/filename_flags.go b/pkg/kubectl/genericclioptions/filename_flags.go new file mode 100644 index 00000000000..9fc0b60709c --- /dev/null +++ b/pkg/kubectl/genericclioptions/filename_flags.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 genericclioptions + +import ( + "strings" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" +) + +// Usage of this struct by itself is discouraged. +// These flags are composed by ResourceBuilderFlags +// which should be used instead. +type FileNameFlags struct { + Usage string + + Filenames *[]string + Recursive *bool +} + +func (o *FileNameFlags) ToOptions() resource.FilenameOptions { + options := resource.FilenameOptions{} + + if o == nil { + return options + } + + if o.Recursive != nil { + options.Recursive = *o.Recursive + } + if o.Filenames != nil { + options.Filenames = *o.Filenames + } + + return options +} + +func (o *FileNameFlags) AddFlags(flags *pflag.FlagSet) { + if o == nil { + return + } + + if o.Recursive != nil { + flags.BoolVarP(o.Recursive, "recursive", "R", *o.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") + } + if o.Filenames != nil { + flags.StringSliceVarP(o.Filenames, "filename", "f", *o.Filenames, o.Usage) + annotations := make([]string, 0, len(resource.FileExtensions)) + for _, ext := range resource.FileExtensions { + annotations = append(annotations, strings.TrimLeft(ext, ".")) + } + flags.SetAnnotation("filename", cobra.BashCompFilenameExt, annotations) + } +} diff --git a/pkg/kubectl/genericclioptions/json_yaml_flags.go b/pkg/kubectl/genericclioptions/json_yaml_flags.go index 91a86e43e9c..8205f5191d1 100644 --- a/pkg/kubectl/genericclioptions/json_yaml_flags.go +++ b/pkg/kubectl/genericclioptions/json_yaml_flags.go @@ -24,6 +24,10 @@ import ( "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" ) +func (f *JSONYamlPrintFlags) AllowedFormats() []string { + return []string{"json", "yaml"} +} + // JSONYamlPrintFlags provides default flags necessary for json/yaml printing. // Given the following flag values, a printer can be requested that knows // how to handle printing based on these values. @@ -44,7 +48,7 @@ func (f *JSONYamlPrintFlags) ToPrinter(outputFormat string) (printers.ResourcePr case "yaml": printer = &printers.YAMLPrinter{} default: - return nil, NoCompatiblePrinterError{Options: f, OutputFormat: &outputFormat} + return nil, NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()} } return printer, nil diff --git a/pkg/kubectl/genericclioptions/name_flags.go b/pkg/kubectl/genericclioptions/name_flags.go index 5b103e73dd7..13c714554f8 100644 --- a/pkg/kubectl/genericclioptions/name_flags.go +++ b/pkg/kubectl/genericclioptions/name_flags.go @@ -40,6 +40,10 @@ func (f *NamePrintFlags) Complete(successTemplate string) error { return nil } +func (f *NamePrintFlags) AllowedFormats() []string { + return []string{"name"} +} + // ToPrinter receives an outputFormat and returns a printer capable of // handling --output=name printing. // Returns false if the specified outputFormat does not match a supported format. @@ -57,7 +61,7 @@ func (f *NamePrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinte case "": return namePrinter, nil default: - return nil, NoCompatiblePrinterError{Options: f, OutputFormat: &outputFormat} + return nil, NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()} } } diff --git a/pkg/kubectl/genericclioptions/print_flags.go b/pkg/kubectl/genericclioptions/print_flags.go index 981f3697f07..453b913e78b 100644 --- a/pkg/kubectl/genericclioptions/print_flags.go +++ b/pkg/kubectl/genericclioptions/print_flags.go @@ -18,6 +18,8 @@ package genericclioptions import ( "fmt" + "sort" + "strings" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/runtime" @@ -25,8 +27,9 @@ import ( ) type NoCompatiblePrinterError struct { - OutputFormat *string - Options interface{} + OutputFormat *string + AllowedFormats []string + Options interface{} } func (e NoCompatiblePrinterError) Error() string { @@ -35,7 +38,8 @@ func (e NoCompatiblePrinterError) Error() string { output = *e.OutputFormat } - return fmt.Sprintf("unable to match a printer suitable for the output format %q and the options specified: %#v", output, e.Options) + sort.Strings(e.AllowedFormats) + return fmt.Sprintf("unable to match a printer suitable for the output format %q, allowed formats are: %s", output, strings.Join(e.AllowedFormats, ",")) } func IsNoCompatiblePrinterError(err error) bool { @@ -63,6 +67,10 @@ func (f *PrintFlags) Complete(successTemplate string) error { return f.NamePrintFlags.Complete(successTemplate) } +func (f *PrintFlags) AllowedFormats() []string { + return append(f.JSONYamlPrintFlags.AllowedFormats(), f.NamePrintFlags.AllowedFormats()...) +} + func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) { outputFormat := "" if f.OutputFormat != nil { @@ -81,7 +89,7 @@ func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) { } } - return nil, NoCompatiblePrinterError{Options: f, OutputFormat: f.OutputFormat} + return nil, NoCompatiblePrinterError{OutputFormat: f.OutputFormat, AllowedFormats: f.AllowedFormats()} } func (f *PrintFlags) AddFlags(cmd *cobra.Command) { diff --git a/pkg/kubectl/genericclioptions/resource/builder.go b/pkg/kubectl/genericclioptions/resource/builder.go index 9f4e02d02b2..09e21827f7e 100644 --- a/pkg/kubectl/genericclioptions/resource/builder.go +++ b/pkg/kubectl/genericclioptions/resource/builder.go @@ -49,9 +49,7 @@ type Builder struct { categoryExpander restmapper.CategoryExpander // mapper is set explicitly by resource builders - mapper *mapper - internal *mapper - unstructured *mapper + mapper *mapper // clientConfigFn is a function to produce a client, *if* you need one clientConfigFn ClientConfigFunc @@ -829,7 +827,6 @@ func (b *Builder) visitBySelector() *Result { result.err = err return result } - client = NewClientWithOptions(client, b.requestTransforms...) selectorNamespace := b.namespace if mapping.Scope.Name() != meta.RESTScopeNameNamespace { selectorNamespace = "" @@ -846,15 +843,25 @@ func (b *Builder) visitBySelector() *Result { } func (b *Builder) getClient(gv schema.GroupVersion) (RESTClient, error) { - if b.fakeClientFn != nil { - return b.fakeClientFn(gv) + var ( + client RESTClient + err error + ) + + switch { + case b.fakeClientFn != nil: + client, err = b.fakeClientFn(gv) + case b.negotiatedSerializer != nil: + client, err = b.clientConfigFn.clientForGroupVersion(gv, b.negotiatedSerializer) + default: + client, err = b.clientConfigFn.unstructuredClientForGroupVersion(gv) } - if b.negotiatedSerializer != nil { - return b.clientConfigFn.clientForGroupVersion(gv, b.negotiatedSerializer) + if err != nil { + return nil, err } - return b.clientConfigFn.unstructuredClientForGroupVersion(gv) + return NewClientWithOptions(client, b.requestTransforms...), nil } func (b *Builder) visitByResource() *Result { @@ -891,7 +898,6 @@ func (b *Builder) visitByResource() *Result { result.err = err return result } - client = NewClientWithOptions(client, b.requestTransforms...) clients[s] = client } diff --git a/pkg/kubectl/genericclioptions/resource/builder_test.go b/pkg/kubectl/genericclioptions/resource/builder_test.go index e6308a56687..ecf12529a19 100644 --- a/pkg/kubectl/genericclioptions/resource/builder_test.go +++ b/pkg/kubectl/genericclioptions/resource/builder_test.go @@ -655,22 +655,50 @@ func TestMultipleResourceByTheSameName(t *testing.T) { } func TestRequestModifier(t *testing.T) { - var got *rest.Request - b := newDefaultBuilderWith(fakeClientWith("test", t, nil)). - NamespaceParam("foo"). - TransformRequests(func(req *rest.Request) { - got = req - }). - ResourceNames("", "services/baz"). - RequireObject(false) - - i, err := b.Do().Infos() - if err != nil { - t.Fatal(err) - } - req := i[0].Client.Get() - if got != req { - t.Fatalf("request was not received by modifier: %#v", req) + for _, tc := range []struct { + name string + f func(t *testing.T, got **rest.Request) *Builder + }{ + { + name: "simple", + f: func(t *testing.T, got **rest.Request) *Builder { + return newDefaultBuilderWith(fakeClientWith(t.Name(), t, nil)). + NamespaceParam("foo"). + TransformRequests(func(req *rest.Request) { + *got = req + }). + ResourceNames("", "services/baz"). + RequireObject(false) + }, + }, + { + name: "flatten", + f: func(t *testing.T, got **rest.Request) *Builder { + pods, _ := testData() + return newDefaultBuilderWith(fakeClientWith(t.Name(), t, map[string]string{ + "/namespaces/foo/pods": runtime.EncodeOrDie(corev1Codec, pods), + })). + NamespaceParam("foo"). + TransformRequests(func(req *rest.Request) { + *got = req + }). + ResourceTypeOrNameArgs(true, "pods"). + Flatten() + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + var got *rest.Request + b := tc.f(t, &got) + i, err := b.Do().Infos() + if err != nil { + t.Fatal(err) + } + req := i[0].Client.Get() + if got != req { + t.Fatalf("request was not received by modifier: %#v", req) + } + }) } } diff --git a/pkg/kubectl/genericclioptions/resource/interfaces.go b/pkg/kubectl/genericclioptions/resource/interfaces.go index 6179481a5d8..508d4d6b5e4 100644 --- a/pkg/kubectl/genericclioptions/resource/interfaces.go +++ b/pkg/kubectl/genericclioptions/resource/interfaces.go @@ -47,6 +47,9 @@ type RequestTransform func(*rest.Request) // NewClientWithOptions wraps the provided RESTClient and invokes each transform on each // newly created request. func NewClientWithOptions(c RESTClient, transforms ...RequestTransform) RESTClient { + if len(transforms) == 0 { + return c + } return &clientOptions{c: c, transforms: transforms} } diff --git a/pkg/kubectl/rollout_status.go b/pkg/kubectl/rollout_status.go index b65b91fd4eb..714d364fd83 100644 --- a/pkg/kubectl/rollout_status.go +++ b/pkg/kubectl/rollout_status.go @@ -83,13 +83,13 @@ func (s *DeploymentStatusViewer) Status(namespace, name string, revision int64) return "", false, fmt.Errorf("deployment %q exceeded its progress deadline", name) } if deployment.Spec.Replicas != nil && deployment.Status.UpdatedReplicas < *deployment.Spec.Replicas { - return fmt.Sprintf("Waiting for rollout to finish: %d out of %d new replicas have been updated...\n", deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas), false, nil + return fmt.Sprintf("Waiting for deployment %q rollout to finish: %d out of %d new replicas have been updated...\n", name, deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas), false, nil } if deployment.Status.Replicas > deployment.Status.UpdatedReplicas { - return fmt.Sprintf("Waiting for rollout to finish: %d old replicas are pending termination...\n", deployment.Status.Replicas-deployment.Status.UpdatedReplicas), false, nil + return fmt.Sprintf("Waiting for deployment %q rollout to finish: %d old replicas are pending termination...\n", name, deployment.Status.Replicas-deployment.Status.UpdatedReplicas), false, nil } if deployment.Status.AvailableReplicas < deployment.Status.UpdatedReplicas { - return fmt.Sprintf("Waiting for rollout to finish: %d of %d updated replicas are available...\n", deployment.Status.AvailableReplicas, deployment.Status.UpdatedReplicas), false, nil + return fmt.Sprintf("Waiting for deployment %q rollout to finish: %d of %d updated replicas are available...\n", name, deployment.Status.AvailableReplicas, deployment.Status.UpdatedReplicas), false, nil } return fmt.Sprintf("deployment %q successfully rolled out\n", name), true, nil } @@ -109,10 +109,10 @@ func (s *DaemonSetStatusViewer) Status(namespace, name string, revision int64) ( } if daemon.Generation <= daemon.Status.ObservedGeneration { if daemon.Status.UpdatedNumberScheduled < daemon.Status.DesiredNumberScheduled { - return fmt.Sprintf("Waiting for rollout to finish: %d out of %d new pods have been updated...\n", daemon.Status.UpdatedNumberScheduled, daemon.Status.DesiredNumberScheduled), false, nil + return fmt.Sprintf("Waiting for daemon set %q rollout to finish: %d out of %d new pods have been updated...\n", name, daemon.Status.UpdatedNumberScheduled, daemon.Status.DesiredNumberScheduled), false, nil } if daemon.Status.NumberAvailable < daemon.Status.DesiredNumberScheduled { - return fmt.Sprintf("Waiting for rollout to finish: %d of %d updated pods are available...\n", daemon.Status.NumberAvailable, daemon.Status.DesiredNumberScheduled), false, nil + return fmt.Sprintf("Waiting for daemon set %q rollout to finish: %d of %d updated pods are available...\n", name, daemon.Status.NumberAvailable, daemon.Status.DesiredNumberScheduled), false, nil } return fmt.Sprintf("daemon set %q successfully rolled out\n", name), true, nil } diff --git a/pkg/kubectl/rollout_status_test.go b/pkg/kubectl/rollout_status_test.go index 729709a7af3..ae346f116bc 100644 --- a/pkg/kubectl/rollout_status_test.go +++ b/pkg/kubectl/rollout_status_test.go @@ -45,7 +45,7 @@ func TestDeploymentStatusViewerStatus(t *testing.T) { UnavailableReplicas: 0, }, - msg: "Waiting for rollout to finish: 0 out of 1 new replicas have been updated...\n", + msg: "Waiting for deployment \"foo\" rollout to finish: 0 out of 1 new replicas have been updated...\n", done: false, }, { @@ -59,7 +59,7 @@ func TestDeploymentStatusViewerStatus(t *testing.T) { UnavailableReplicas: 0, }, - msg: "Waiting for rollout to finish: 1 old replicas are pending termination...\n", + msg: "Waiting for deployment \"foo\" rollout to finish: 1 old replicas are pending termination...\n", done: false, }, { @@ -73,7 +73,7 @@ func TestDeploymentStatusViewerStatus(t *testing.T) { UnavailableReplicas: 1, }, - msg: "Waiting for rollout to finish: 1 of 2 updated replicas are available...\n", + msg: "Waiting for deployment \"foo\" rollout to finish: 1 of 2 updated replicas are available...\n", done: false, }, { @@ -155,7 +155,7 @@ func TestDaemonSetStatusViewerStatus(t *testing.T) { NumberAvailable: 0, }, - msg: "Waiting for rollout to finish: 0 out of 1 new pods have been updated...\n", + msg: "Waiting for daemon set \"foo\" rollout to finish: 0 out of 1 new pods have been updated...\n", done: false, }, { @@ -167,7 +167,7 @@ func TestDaemonSetStatusViewerStatus(t *testing.T) { NumberAvailable: 1, }, - msg: "Waiting for rollout to finish: 1 of 2 updated pods are available...\n", + msg: "Waiting for daemon set \"foo\" rollout to finish: 1 of 2 updated pods are available...\n", done: false, }, { diff --git a/pkg/kubectl/scale.go b/pkg/kubectl/scale.go index 590b600fd49..f1d46b7a110 100644 --- a/pkg/kubectl/scale.go +++ b/pkg/kubectl/scale.go @@ -149,14 +149,7 @@ func (s *genericScaler) Scale(namespace, resourceName string, newSize uint, prec return err } if waitForReplicas != nil { - err := wait.PollImmediate( - waitForReplicas.Interval, - waitForReplicas.Timeout, - scaleHasDesiredReplicas(s.scaleNamespacer, gr, resourceName, namespace, int32(newSize))) - if err == wait.ErrWaitTimeout { - return fmt.Errorf("timed out waiting for %q to be synced", resourceName) - } - return err + return WaitForScaleHasDesiredReplicas(s.scaleNamespacer, gr, resourceName, namespace, newSize, waitForReplicas) } return nil } @@ -177,3 +170,19 @@ func scaleHasDesiredReplicas(sClient scaleclient.ScalesGetter, gr schema.GroupRe desiredReplicas == actualScale.Status.Replicas, nil } } + +// WaitForScaleHasDesiredReplicas waits until condition scaleHasDesiredReplicas is satisfied +// or returns error when timeout happens +func WaitForScaleHasDesiredReplicas(sClient scaleclient.ScalesGetter, gr schema.GroupResource, resourceName string, namespace string, newSize uint, waitForReplicas *RetryParams) error { + if waitForReplicas == nil { + return fmt.Errorf("waitForReplicas parameter cannot be nil!") + } + err := wait.PollImmediate( + waitForReplicas.Interval, + waitForReplicas.Timeout, + scaleHasDesiredReplicas(sClient, gr, resourceName, namespace, int32(newSize))) + if err == wait.ErrWaitTimeout { + return fmt.Errorf("timed out waiting for %q to be synced", resourceName) + } + return err +} diff --git a/pkg/kubectl/util/BUILD b/pkg/kubectl/util/BUILD index ad3c1b73130..73dfd3a1932 100644 --- a/pkg/kubectl/util/BUILD +++ b/pkg/kubectl/util/BUILD @@ -98,7 +98,6 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", - "//pkg/kubectl/util/crlf:all-srcs", "//pkg/kubectl/util/hash:all-srcs", "//pkg/kubectl/util/i18n:all-srcs", "//pkg/kubectl/util/logs:all-srcs", diff --git a/pkg/kubelet/BUILD b/pkg/kubelet/BUILD index b4d6d166fa9..d6c52d725ad 100644 --- a/pkg/kubelet/BUILD +++ b/pkg/kubelet/BUILD @@ -80,16 +80,19 @@ go_library( "//pkg/kubelet/stats:go_default_library", "//pkg/kubelet/status:go_default_library", "//pkg/kubelet/sysctl:go_default_library", + "//pkg/kubelet/token:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util:go_default_library", "//pkg/kubelet/util/format:go_default_library", "//pkg/kubelet/util/manager:go_default_library", + "//pkg/kubelet/util/pluginwatcher:go_default_library", "//pkg/kubelet/util/queue:go_default_library", "//pkg/kubelet/util/sliceutils:go_default_library", "//pkg/kubelet/volumemanager:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/security/apparmor:go_default_library", + "//pkg/security/podsecuritypolicy/sysctl:go_default_library", "//pkg/securitycontext:go_default_library", "//pkg/util/dbus:go_default_library", "//pkg/util/file:go_default_library", @@ -101,6 +104,7 @@ go_library( "//pkg/util/removeall:go_default_library", "//pkg/version:go_default_library", "//pkg/volume:go_default_library", + "//pkg/volume/csi:go_default_library", "//pkg/volume/util:go_default_library", "//pkg/volume/util/types:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library", @@ -111,6 +115,7 @@ go_library( "//vendor/github.com/google/cadvisor/events:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library", "//vendor/github.com/google/cadvisor/info/v2:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -131,7 +136,6 @@ go_library( "//vendor/k8s.io/client-go/listers/core/v1:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/client-go/tools/record:go_default_library", - "//vendor/k8s.io/client-go/tools/remotecommand:go_default_library", "//vendor/k8s.io/client-go/util/certificate:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", "//vendor/k8s.io/client-go/util/integer:go_default_library", @@ -190,14 +194,18 @@ go_test( "//pkg/kubelet/stats:go_default_library", "//pkg/kubelet/status:go_default_library", "//pkg/kubelet/status/testing:go_default_library", + "//pkg/kubelet/token:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util/queue:go_default_library", "//pkg/kubelet/util/sliceutils:go_default_library", "//pkg/kubelet/volumemanager:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/version:go_default_library", "//pkg/volume:go_default_library", + "//pkg/volume/aws_ebs:go_default_library", + "//pkg/volume/azure_dd:go_default_library", + "//pkg/volume/gce_pd:go_default_library", "//pkg/volume/host_path:go_default_library", "//pkg/volume/testing:go_default_library", "//pkg/volume/util:go_default_library", @@ -278,6 +286,7 @@ filegroup( "//pkg/kubelet/stats:all-srcs", "//pkg/kubelet/status:all-srcs", "//pkg/kubelet/sysctl:all-srcs", + "//pkg/kubelet/token:all-srcs", "//pkg/kubelet/types:all-srcs", "//pkg/kubelet/util:all-srcs", "//pkg/kubelet/volumemanager:all-srcs", diff --git a/pkg/kubelet/apis/BUILD b/pkg/kubelet/apis/BUILD index 47cb8184ccb..2a22e48121a 100644 --- a/pkg/kubelet/apis/BUILD +++ b/pkg/kubelet/apis/BUILD @@ -41,6 +41,7 @@ filegroup( "//pkg/kubelet/apis/deviceplugin/v1alpha:all-srcs", "//pkg/kubelet/apis/deviceplugin/v1beta1:all-srcs", "//pkg/kubelet/apis/kubeletconfig:all-srcs", + "//pkg/kubelet/apis/pluginregistration/v1alpha1:all-srcs", "//pkg/kubelet/apis/stats/v1alpha1:all-srcs", ], tags = ["automanaged"], diff --git a/pkg/kubelet/apis/cri/runtime/v1alpha2/api.pb.go b/pkg/kubelet/apis/cri/runtime/v1alpha2/api.pb.go index f627e948a2a..c17a8e0daa2 100644 --- a/pkg/kubelet/apis/cri/runtime/v1alpha2/api.pb.go +++ b/pkg/kubelet/apis/cri/runtime/v1alpha2/api.pb.go @@ -60,6 +60,7 @@ limitations under the License. Capability LinuxContainerSecurityContext LinuxContainerConfig + WindowsContainerSecurityContext WindowsContainerConfig WindowsContainerResources ContainerMetadata @@ -1615,16 +1616,39 @@ func (m *LinuxContainerConfig) GetSecurityContext() *LinuxContainerSecurityConte return nil } +// WindowsContainerSecurityContext holds windows security configuration that will be applied to a container. +type WindowsContainerSecurityContext struct { + // User name to run the container process as. If specified, the user MUST + // exist in the container image and be resolved there by the runtime; + // otherwise, the runtime MUST return error. + RunAsUsername string `protobuf:"bytes,1,opt,name=run_as_username,json=runAsUsername,proto3" json:"run_as_username,omitempty"` +} + +func (m *WindowsContainerSecurityContext) Reset() { *m = WindowsContainerSecurityContext{} } +func (*WindowsContainerSecurityContext) ProtoMessage() {} +func (*WindowsContainerSecurityContext) Descriptor() ([]byte, []int) { + return fileDescriptorApi, []int{35} +} + +func (m *WindowsContainerSecurityContext) GetRunAsUsername() string { + if m != nil { + return m.RunAsUsername + } + return "" +} + // WindowsContainerConfig contains platform-specific configuration for // Windows-based containers. type WindowsContainerConfig struct { // Resources specification for the container. Resources *WindowsContainerResources `protobuf:"bytes,1,opt,name=resources" json:"resources,omitempty"` + // WindowsContainerSecurityContext configuration for the container. + SecurityContext *WindowsContainerSecurityContext `protobuf:"bytes,2,opt,name=security_context,json=securityContext" json:"security_context,omitempty"` } func (m *WindowsContainerConfig) Reset() { *m = WindowsContainerConfig{} } func (*WindowsContainerConfig) ProtoMessage() {} -func (*WindowsContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{35} } +func (*WindowsContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{36} } func (m *WindowsContainerConfig) GetResources() *WindowsContainerResources { if m != nil { @@ -1633,6 +1657,13 @@ func (m *WindowsContainerConfig) GetResources() *WindowsContainerResources { return nil } +func (m *WindowsContainerConfig) GetSecurityContext() *WindowsContainerSecurityContext { + if m != nil { + return m.SecurityContext + } + return nil +} + // WindowsContainerResources specifies Windows specific configuration for // resources. type WindowsContainerResources struct { @@ -1648,7 +1679,7 @@ type WindowsContainerResources struct { func (m *WindowsContainerResources) Reset() { *m = WindowsContainerResources{} } func (*WindowsContainerResources) ProtoMessage() {} -func (*WindowsContainerResources) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{36} } +func (*WindowsContainerResources) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{37} } func (m *WindowsContainerResources) GetCpuShares() int64 { if m != nil { @@ -1692,7 +1723,7 @@ type ContainerMetadata struct { func (m *ContainerMetadata) Reset() { *m = ContainerMetadata{} } func (*ContainerMetadata) ProtoMessage() {} -func (*ContainerMetadata) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{37} } +func (*ContainerMetadata) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{38} } func (m *ContainerMetadata) GetName() string { if m != nil { @@ -1723,7 +1754,7 @@ type Device struct { func (m *Device) Reset() { *m = Device{} } func (*Device) ProtoMessage() {} -func (*Device) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{38} } +func (*Device) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{39} } func (m *Device) GetContainerPath() string { if m != nil { @@ -1812,7 +1843,7 @@ type ContainerConfig struct { func (m *ContainerConfig) Reset() { *m = ContainerConfig{} } func (*ContainerConfig) ProtoMessage() {} -func (*ContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{39} } +func (*ContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{40} } func (m *ContainerConfig) GetMetadata() *ContainerMetadata { if m != nil { @@ -1940,7 +1971,7 @@ type CreateContainerRequest struct { func (m *CreateContainerRequest) Reset() { *m = CreateContainerRequest{} } func (*CreateContainerRequest) ProtoMessage() {} -func (*CreateContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{40} } +func (*CreateContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{41} } func (m *CreateContainerRequest) GetPodSandboxId() string { if m != nil { @@ -1970,7 +2001,7 @@ type CreateContainerResponse struct { func (m *CreateContainerResponse) Reset() { *m = CreateContainerResponse{} } func (*CreateContainerResponse) ProtoMessage() {} -func (*CreateContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{41} } +func (*CreateContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{42} } func (m *CreateContainerResponse) GetContainerId() string { if m != nil { @@ -1986,7 +2017,7 @@ type StartContainerRequest struct { func (m *StartContainerRequest) Reset() { *m = StartContainerRequest{} } func (*StartContainerRequest) ProtoMessage() {} -func (*StartContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{42} } +func (*StartContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{43} } func (m *StartContainerRequest) GetContainerId() string { if m != nil { @@ -2000,7 +2031,7 @@ type StartContainerResponse struct { func (m *StartContainerResponse) Reset() { *m = StartContainerResponse{} } func (*StartContainerResponse) ProtoMessage() {} -func (*StartContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{43} } +func (*StartContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{44} } type StopContainerRequest struct { // ID of the container to stop. @@ -2012,7 +2043,7 @@ type StopContainerRequest struct { func (m *StopContainerRequest) Reset() { *m = StopContainerRequest{} } func (*StopContainerRequest) ProtoMessage() {} -func (*StopContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{44} } +func (*StopContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{45} } func (m *StopContainerRequest) GetContainerId() string { if m != nil { @@ -2033,7 +2064,7 @@ type StopContainerResponse struct { func (m *StopContainerResponse) Reset() { *m = StopContainerResponse{} } func (*StopContainerResponse) ProtoMessage() {} -func (*StopContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{45} } +func (*StopContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{46} } type RemoveContainerRequest struct { // ID of the container to remove. @@ -2042,7 +2073,7 @@ type RemoveContainerRequest struct { func (m *RemoveContainerRequest) Reset() { *m = RemoveContainerRequest{} } func (*RemoveContainerRequest) ProtoMessage() {} -func (*RemoveContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{46} } +func (*RemoveContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{47} } func (m *RemoveContainerRequest) GetContainerId() string { if m != nil { @@ -2056,7 +2087,7 @@ type RemoveContainerResponse struct { func (m *RemoveContainerResponse) Reset() { *m = RemoveContainerResponse{} } func (*RemoveContainerResponse) ProtoMessage() {} -func (*RemoveContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{47} } +func (*RemoveContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{48} } // ContainerStateValue is the wrapper of ContainerState. type ContainerStateValue struct { @@ -2066,7 +2097,7 @@ type ContainerStateValue struct { func (m *ContainerStateValue) Reset() { *m = ContainerStateValue{} } func (*ContainerStateValue) ProtoMessage() {} -func (*ContainerStateValue) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{48} } +func (*ContainerStateValue) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{49} } func (m *ContainerStateValue) GetState() ContainerState { if m != nil { @@ -2092,7 +2123,7 @@ type ContainerFilter struct { func (m *ContainerFilter) Reset() { *m = ContainerFilter{} } func (*ContainerFilter) ProtoMessage() {} -func (*ContainerFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{49} } +func (*ContainerFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{50} } func (m *ContainerFilter) GetId() string { if m != nil { @@ -2128,7 +2159,7 @@ type ListContainersRequest struct { func (m *ListContainersRequest) Reset() { *m = ListContainersRequest{} } func (*ListContainersRequest) ProtoMessage() {} -func (*ListContainersRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{50} } +func (*ListContainersRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{51} } func (m *ListContainersRequest) GetFilter() *ContainerFilter { if m != nil { @@ -2167,7 +2198,7 @@ type Container struct { func (m *Container) Reset() { *m = Container{} } func (*Container) ProtoMessage() {} -func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{51} } +func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{52} } func (m *Container) GetId() string { if m != nil { @@ -2239,7 +2270,7 @@ type ListContainersResponse struct { func (m *ListContainersResponse) Reset() { *m = ListContainersResponse{} } func (*ListContainersResponse) ProtoMessage() {} -func (*ListContainersResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{52} } +func (*ListContainersResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{53} } func (m *ListContainersResponse) GetContainers() []*Container { if m != nil { @@ -2257,7 +2288,7 @@ type ContainerStatusRequest struct { func (m *ContainerStatusRequest) Reset() { *m = ContainerStatusRequest{} } func (*ContainerStatusRequest) ProtoMessage() {} -func (*ContainerStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{53} } +func (*ContainerStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{54} } func (m *ContainerStatusRequest) GetContainerId() string { if m != nil { @@ -2314,7 +2345,7 @@ type ContainerStatus struct { func (m *ContainerStatus) Reset() { *m = ContainerStatus{} } func (*ContainerStatus) ProtoMessage() {} -func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{54} } +func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{55} } func (m *ContainerStatus) GetId() string { if m != nil { @@ -2433,7 +2464,7 @@ type ContainerStatusResponse struct { func (m *ContainerStatusResponse) Reset() { *m = ContainerStatusResponse{} } func (*ContainerStatusResponse) ProtoMessage() {} -func (*ContainerStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{55} } +func (*ContainerStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{56} } func (m *ContainerStatusResponse) GetStatus() *ContainerStatus { if m != nil { @@ -2459,7 +2490,7 @@ type UpdateContainerResourcesRequest struct { func (m *UpdateContainerResourcesRequest) Reset() { *m = UpdateContainerResourcesRequest{} } func (*UpdateContainerResourcesRequest) ProtoMessage() {} func (*UpdateContainerResourcesRequest) Descriptor() ([]byte, []int) { - return fileDescriptorApi, []int{56} + return fileDescriptorApi, []int{57} } func (m *UpdateContainerResourcesRequest) GetContainerId() string { @@ -2482,7 +2513,7 @@ type UpdateContainerResourcesResponse struct { func (m *UpdateContainerResourcesResponse) Reset() { *m = UpdateContainerResourcesResponse{} } func (*UpdateContainerResourcesResponse) ProtoMessage() {} func (*UpdateContainerResourcesResponse) Descriptor() ([]byte, []int) { - return fileDescriptorApi, []int{57} + return fileDescriptorApi, []int{58} } type ExecSyncRequest struct { @@ -2496,7 +2527,7 @@ type ExecSyncRequest struct { func (m *ExecSyncRequest) Reset() { *m = ExecSyncRequest{} } func (*ExecSyncRequest) ProtoMessage() {} -func (*ExecSyncRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{58} } +func (*ExecSyncRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{59} } func (m *ExecSyncRequest) GetContainerId() string { if m != nil { @@ -2530,7 +2561,7 @@ type ExecSyncResponse struct { func (m *ExecSyncResponse) Reset() { *m = ExecSyncResponse{} } func (*ExecSyncResponse) ProtoMessage() {} -func (*ExecSyncResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{59} } +func (*ExecSyncResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{60} } func (m *ExecSyncResponse) GetStdout() []byte { if m != nil { @@ -2576,7 +2607,7 @@ type ExecRequest struct { func (m *ExecRequest) Reset() { *m = ExecRequest{} } func (*ExecRequest) ProtoMessage() {} -func (*ExecRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{60} } +func (*ExecRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{61} } func (m *ExecRequest) GetContainerId() string { if m != nil { @@ -2627,7 +2658,7 @@ type ExecResponse struct { func (m *ExecResponse) Reset() { *m = ExecResponse{} } func (*ExecResponse) ProtoMessage() {} -func (*ExecResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{61} } +func (*ExecResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{62} } func (m *ExecResponse) GetUrl() string { if m != nil { @@ -2658,7 +2689,7 @@ type AttachRequest struct { func (m *AttachRequest) Reset() { *m = AttachRequest{} } func (*AttachRequest) ProtoMessage() {} -func (*AttachRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{62} } +func (*AttachRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{63} } func (m *AttachRequest) GetContainerId() string { if m != nil { @@ -2702,7 +2733,7 @@ type AttachResponse struct { func (m *AttachResponse) Reset() { *m = AttachResponse{} } func (*AttachResponse) ProtoMessage() {} -func (*AttachResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{63} } +func (*AttachResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{64} } func (m *AttachResponse) GetUrl() string { if m != nil { @@ -2720,7 +2751,7 @@ type PortForwardRequest struct { func (m *PortForwardRequest) Reset() { *m = PortForwardRequest{} } func (*PortForwardRequest) ProtoMessage() {} -func (*PortForwardRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{64} } +func (*PortForwardRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{65} } func (m *PortForwardRequest) GetPodSandboxId() string { if m != nil { @@ -2743,7 +2774,7 @@ type PortForwardResponse struct { func (m *PortForwardResponse) Reset() { *m = PortForwardResponse{} } func (*PortForwardResponse) ProtoMessage() {} -func (*PortForwardResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{65} } +func (*PortForwardResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{66} } func (m *PortForwardResponse) GetUrl() string { if m != nil { @@ -2759,7 +2790,7 @@ type ImageFilter struct { func (m *ImageFilter) Reset() { *m = ImageFilter{} } func (*ImageFilter) ProtoMessage() {} -func (*ImageFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{66} } +func (*ImageFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{67} } func (m *ImageFilter) GetImage() *ImageSpec { if m != nil { @@ -2775,7 +2806,7 @@ type ListImagesRequest struct { func (m *ListImagesRequest) Reset() { *m = ListImagesRequest{} } func (*ListImagesRequest) ProtoMessage() {} -func (*ListImagesRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{67} } +func (*ListImagesRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{68} } func (m *ListImagesRequest) GetFilter() *ImageFilter { if m != nil { @@ -2805,7 +2836,7 @@ type Image struct { func (m *Image) Reset() { *m = Image{} } func (*Image) ProtoMessage() {} -func (*Image) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{68} } +func (*Image) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{69} } func (m *Image) GetId() string { if m != nil { @@ -2856,7 +2887,7 @@ type ListImagesResponse struct { func (m *ListImagesResponse) Reset() { *m = ListImagesResponse{} } func (*ListImagesResponse) ProtoMessage() {} -func (*ListImagesResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{69} } +func (*ListImagesResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{70} } func (m *ListImagesResponse) GetImages() []*Image { if m != nil { @@ -2874,7 +2905,7 @@ type ImageStatusRequest struct { func (m *ImageStatusRequest) Reset() { *m = ImageStatusRequest{} } func (*ImageStatusRequest) ProtoMessage() {} -func (*ImageStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{70} } +func (*ImageStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{71} } func (m *ImageStatusRequest) GetImage() *ImageSpec { if m != nil { @@ -2902,7 +2933,7 @@ type ImageStatusResponse struct { func (m *ImageStatusResponse) Reset() { *m = ImageStatusResponse{} } func (*ImageStatusResponse) ProtoMessage() {} -func (*ImageStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{71} } +func (*ImageStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{72} } func (m *ImageStatusResponse) GetImage() *Image { if m != nil { @@ -2933,7 +2964,7 @@ type AuthConfig struct { func (m *AuthConfig) Reset() { *m = AuthConfig{} } func (*AuthConfig) ProtoMessage() {} -func (*AuthConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{72} } +func (*AuthConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{73} } func (m *AuthConfig) GetUsername() string { if m != nil { @@ -2988,7 +3019,7 @@ type PullImageRequest struct { func (m *PullImageRequest) Reset() { *m = PullImageRequest{} } func (*PullImageRequest) ProtoMessage() {} -func (*PullImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{73} } +func (*PullImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{74} } func (m *PullImageRequest) GetImage() *ImageSpec { if m != nil { @@ -3019,7 +3050,7 @@ type PullImageResponse struct { func (m *PullImageResponse) Reset() { *m = PullImageResponse{} } func (*PullImageResponse) ProtoMessage() {} -func (*PullImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{74} } +func (*PullImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{75} } func (m *PullImageResponse) GetImageRef() string { if m != nil { @@ -3035,7 +3066,7 @@ type RemoveImageRequest struct { func (m *RemoveImageRequest) Reset() { *m = RemoveImageRequest{} } func (*RemoveImageRequest) ProtoMessage() {} -func (*RemoveImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{75} } +func (*RemoveImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{76} } func (m *RemoveImageRequest) GetImage() *ImageSpec { if m != nil { @@ -3049,7 +3080,7 @@ type RemoveImageResponse struct { func (m *RemoveImageResponse) Reset() { *m = RemoveImageResponse{} } func (*RemoveImageResponse) ProtoMessage() {} -func (*RemoveImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{76} } +func (*RemoveImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{77} } type NetworkConfig struct { // CIDR to use for pod IP addresses. If the CIDR is empty, runtimes @@ -3059,7 +3090,7 @@ type NetworkConfig struct { func (m *NetworkConfig) Reset() { *m = NetworkConfig{} } func (*NetworkConfig) ProtoMessage() {} -func (*NetworkConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{77} } +func (*NetworkConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{78} } func (m *NetworkConfig) GetPodCidr() string { if m != nil { @@ -3074,7 +3105,7 @@ type RuntimeConfig struct { func (m *RuntimeConfig) Reset() { *m = RuntimeConfig{} } func (*RuntimeConfig) ProtoMessage() {} -func (*RuntimeConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{78} } +func (*RuntimeConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{79} } func (m *RuntimeConfig) GetNetworkConfig() *NetworkConfig { if m != nil { @@ -3089,7 +3120,7 @@ type UpdateRuntimeConfigRequest struct { func (m *UpdateRuntimeConfigRequest) Reset() { *m = UpdateRuntimeConfigRequest{} } func (*UpdateRuntimeConfigRequest) ProtoMessage() {} -func (*UpdateRuntimeConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{79} } +func (*UpdateRuntimeConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{80} } func (m *UpdateRuntimeConfigRequest) GetRuntimeConfig() *RuntimeConfig { if m != nil { @@ -3103,7 +3134,7 @@ type UpdateRuntimeConfigResponse struct { func (m *UpdateRuntimeConfigResponse) Reset() { *m = UpdateRuntimeConfigResponse{} } func (*UpdateRuntimeConfigResponse) ProtoMessage() {} -func (*UpdateRuntimeConfigResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{80} } +func (*UpdateRuntimeConfigResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{81} } // RuntimeCondition contains condition information for the runtime. // There are 2 kinds of runtime conditions: @@ -3131,7 +3162,7 @@ type RuntimeCondition struct { func (m *RuntimeCondition) Reset() { *m = RuntimeCondition{} } func (*RuntimeCondition) ProtoMessage() {} -func (*RuntimeCondition) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{81} } +func (*RuntimeCondition) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{82} } func (m *RuntimeCondition) GetType() string { if m != nil { @@ -3169,7 +3200,7 @@ type RuntimeStatus struct { func (m *RuntimeStatus) Reset() { *m = RuntimeStatus{} } func (*RuntimeStatus) ProtoMessage() {} -func (*RuntimeStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{82} } +func (*RuntimeStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{83} } func (m *RuntimeStatus) GetConditions() []*RuntimeCondition { if m != nil { @@ -3185,7 +3216,7 @@ type StatusRequest struct { func (m *StatusRequest) Reset() { *m = StatusRequest{} } func (*StatusRequest) ProtoMessage() {} -func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{83} } +func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{84} } func (m *StatusRequest) GetVerbose() bool { if m != nil { @@ -3206,7 +3237,7 @@ type StatusResponse struct { func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (*StatusResponse) ProtoMessage() {} -func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{84} } +func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{85} } func (m *StatusResponse) GetStatus() *RuntimeStatus { if m != nil { @@ -3227,7 +3258,7 @@ type ImageFsInfoRequest struct { func (m *ImageFsInfoRequest) Reset() { *m = ImageFsInfoRequest{} } func (*ImageFsInfoRequest) ProtoMessage() {} -func (*ImageFsInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{85} } +func (*ImageFsInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{86} } // UInt64Value is the wrapper of uint64. type UInt64Value struct { @@ -3237,7 +3268,7 @@ type UInt64Value struct { func (m *UInt64Value) Reset() { *m = UInt64Value{} } func (*UInt64Value) ProtoMessage() {} -func (*UInt64Value) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{86} } +func (*UInt64Value) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{87} } func (m *UInt64Value) GetValue() uint64 { if m != nil { @@ -3254,7 +3285,7 @@ type FilesystemIdentifier struct { func (m *FilesystemIdentifier) Reset() { *m = FilesystemIdentifier{} } func (*FilesystemIdentifier) ProtoMessage() {} -func (*FilesystemIdentifier) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{87} } +func (*FilesystemIdentifier) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{88} } func (m *FilesystemIdentifier) GetMountpoint() string { if m != nil { @@ -3281,7 +3312,7 @@ type FilesystemUsage struct { func (m *FilesystemUsage) Reset() { *m = FilesystemUsage{} } func (*FilesystemUsage) ProtoMessage() {} -func (*FilesystemUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{88} } +func (*FilesystemUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{89} } func (m *FilesystemUsage) GetTimestamp() int64 { if m != nil { @@ -3318,7 +3349,7 @@ type ImageFsInfoResponse struct { func (m *ImageFsInfoResponse) Reset() { *m = ImageFsInfoResponse{} } func (*ImageFsInfoResponse) ProtoMessage() {} -func (*ImageFsInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{89} } +func (*ImageFsInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{90} } func (m *ImageFsInfoResponse) GetImageFilesystems() []*FilesystemUsage { if m != nil { @@ -3334,7 +3365,7 @@ type ContainerStatsRequest struct { func (m *ContainerStatsRequest) Reset() { *m = ContainerStatsRequest{} } func (*ContainerStatsRequest) ProtoMessage() {} -func (*ContainerStatsRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{90} } +func (*ContainerStatsRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{91} } func (m *ContainerStatsRequest) GetContainerId() string { if m != nil { @@ -3350,7 +3381,7 @@ type ContainerStatsResponse struct { func (m *ContainerStatsResponse) Reset() { *m = ContainerStatsResponse{} } func (*ContainerStatsResponse) ProtoMessage() {} -func (*ContainerStatsResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{91} } +func (*ContainerStatsResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{92} } func (m *ContainerStatsResponse) GetStats() *ContainerStats { if m != nil { @@ -3366,7 +3397,7 @@ type ListContainerStatsRequest struct { func (m *ListContainerStatsRequest) Reset() { *m = ListContainerStatsRequest{} } func (*ListContainerStatsRequest) ProtoMessage() {} -func (*ListContainerStatsRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{92} } +func (*ListContainerStatsRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{93} } func (m *ListContainerStatsRequest) GetFilter() *ContainerStatsFilter { if m != nil { @@ -3390,7 +3421,7 @@ type ContainerStatsFilter struct { func (m *ContainerStatsFilter) Reset() { *m = ContainerStatsFilter{} } func (*ContainerStatsFilter) ProtoMessage() {} -func (*ContainerStatsFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{93} } +func (*ContainerStatsFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{94} } func (m *ContainerStatsFilter) GetId() string { if m != nil { @@ -3420,7 +3451,7 @@ type ListContainerStatsResponse struct { func (m *ListContainerStatsResponse) Reset() { *m = ListContainerStatsResponse{} } func (*ListContainerStatsResponse) ProtoMessage() {} -func (*ListContainerStatsResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{94} } +func (*ListContainerStatsResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{95} } func (m *ListContainerStatsResponse) GetStats() []*ContainerStats { if m != nil { @@ -3446,7 +3477,7 @@ type ContainerAttributes struct { func (m *ContainerAttributes) Reset() { *m = ContainerAttributes{} } func (*ContainerAttributes) ProtoMessage() {} -func (*ContainerAttributes) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{95} } +func (*ContainerAttributes) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{96} } func (m *ContainerAttributes) GetId() string { if m != nil { @@ -3490,7 +3521,7 @@ type ContainerStats struct { func (m *ContainerStats) Reset() { *m = ContainerStats{} } func (*ContainerStats) ProtoMessage() {} -func (*ContainerStats) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{96} } +func (*ContainerStats) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{97} } func (m *ContainerStats) GetAttributes() *ContainerAttributes { if m != nil { @@ -3530,7 +3561,7 @@ type CpuUsage struct { func (m *CpuUsage) Reset() { *m = CpuUsage{} } func (*CpuUsage) ProtoMessage() {} -func (*CpuUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{97} } +func (*CpuUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{98} } func (m *CpuUsage) GetTimestamp() int64 { if m != nil { @@ -3556,7 +3587,7 @@ type MemoryUsage struct { func (m *MemoryUsage) Reset() { *m = MemoryUsage{} } func (*MemoryUsage) ProtoMessage() {} -func (*MemoryUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{98} } +func (*MemoryUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{99} } func (m *MemoryUsage) GetTimestamp() int64 { if m != nil { @@ -3579,7 +3610,7 @@ type ReopenContainerLogRequest struct { func (m *ReopenContainerLogRequest) Reset() { *m = ReopenContainerLogRequest{} } func (*ReopenContainerLogRequest) ProtoMessage() {} -func (*ReopenContainerLogRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{99} } +func (*ReopenContainerLogRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{100} } func (m *ReopenContainerLogRequest) GetContainerId() string { if m != nil { @@ -3593,7 +3624,7 @@ type ReopenContainerLogResponse struct { func (m *ReopenContainerLogResponse) Reset() { *m = ReopenContainerLogResponse{} } func (*ReopenContainerLogResponse) ProtoMessage() {} -func (*ReopenContainerLogResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{100} } +func (*ReopenContainerLogResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{101} } func init() { proto.RegisterType((*VersionRequest)(nil), "runtime.v1alpha2.VersionRequest") @@ -3631,6 +3662,7 @@ func init() { proto.RegisterType((*Capability)(nil), "runtime.v1alpha2.Capability") proto.RegisterType((*LinuxContainerSecurityContext)(nil), "runtime.v1alpha2.LinuxContainerSecurityContext") proto.RegisterType((*LinuxContainerConfig)(nil), "runtime.v1alpha2.LinuxContainerConfig") + proto.RegisterType((*WindowsContainerSecurityContext)(nil), "runtime.v1alpha2.WindowsContainerSecurityContext") proto.RegisterType((*WindowsContainerConfig)(nil), "runtime.v1alpha2.WindowsContainerConfig") proto.RegisterType((*WindowsContainerResources)(nil), "runtime.v1alpha2.WindowsContainerResources") proto.RegisterType((*ContainerMetadata)(nil), "runtime.v1alpha2.ContainerMetadata") @@ -6330,6 +6362,30 @@ func (m *LinuxContainerConfig) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *WindowsContainerSecurityContext) 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 *WindowsContainerSecurityContext) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.RunAsUsername) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.RunAsUsername))) + i += copy(dAtA[i:], m.RunAsUsername) + } + return i, nil +} + func (m *WindowsContainerConfig) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -6355,6 +6411,16 @@ func (m *WindowsContainerConfig) MarshalTo(dAtA []byte) (int, error) { } i += n30 } + if m.SecurityContext != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintApi(dAtA, i, uint64(m.SecurityContext.Size())) + n31, err := m.SecurityContext.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n31 + } return i, nil } @@ -6480,21 +6546,21 @@ func (m *ContainerConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Metadata.Size())) - n31, err := m.Metadata.MarshalTo(dAtA[i:]) + n32, err := m.Metadata.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n31 + i += n32 } if m.Image != nil { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n32, err := m.Image.MarshalTo(dAtA[i:]) + n33, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n32 + i += n33 } if len(m.Command) > 0 { for _, s := range m.Command { @@ -6642,11 +6708,11 @@ func (m *ContainerConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x7a i++ i = encodeVarintApi(dAtA, i, uint64(m.Linux.Size())) - n33, err := m.Linux.MarshalTo(dAtA[i:]) + n34, err := m.Linux.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n33 + i += n34 } if m.Windows != nil { dAtA[i] = 0x82 @@ -6654,11 +6720,11 @@ func (m *ContainerConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintApi(dAtA, i, uint64(m.Windows.Size())) - n34, err := m.Windows.MarshalTo(dAtA[i:]) + n35, err := m.Windows.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n34 + i += n35 } return i, nil } @@ -6688,21 +6754,21 @@ func (m *CreateContainerRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Config.Size())) - n35, err := m.Config.MarshalTo(dAtA[i:]) + n36, err := m.Config.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n35 + i += n36 } if m.SandboxConfig != nil { dAtA[i] = 0x1a i++ i = encodeVarintApi(dAtA, i, uint64(m.SandboxConfig.Size())) - n36, err := m.SandboxConfig.MarshalTo(dAtA[i:]) + n37, err := m.SandboxConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n36 + i += n37 } return i, nil } @@ -6910,11 +6976,11 @@ func (m *ContainerFilter) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.State.Size())) - n37, err := m.State.MarshalTo(dAtA[i:]) + n38, err := m.State.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n37 + i += n38 } if len(m.PodSandboxId) > 0 { dAtA[i] = 0x1a @@ -6961,11 +7027,11 @@ func (m *ListContainersRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Filter.Size())) - n38, err := m.Filter.MarshalTo(dAtA[i:]) + n39, err := m.Filter.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n38 + i += n39 } return i, nil } @@ -7001,21 +7067,21 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintApi(dAtA, i, uint64(m.Metadata.Size())) - n39, err := m.Metadata.MarshalTo(dAtA[i:]) + n40, err := m.Metadata.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n39 + i += n40 } if m.Image != nil { dAtA[i] = 0x22 i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n40, err := m.Image.MarshalTo(dAtA[i:]) + n41, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n40 + i += n41 } if len(m.ImageRef) > 0 { dAtA[i] = 0x2a @@ -7159,11 +7225,11 @@ func (m *ContainerStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Metadata.Size())) - n41, err := m.Metadata.MarshalTo(dAtA[i:]) + n42, err := m.Metadata.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n41 + i += n42 } if m.State != 0 { dAtA[i] = 0x18 @@ -7194,11 +7260,11 @@ func (m *ContainerStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x42 i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n42, err := m.Image.MarshalTo(dAtA[i:]) + n43, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n42 + i += n43 } if len(m.ImageRef) > 0 { dAtA[i] = 0x4a @@ -7292,11 +7358,11 @@ func (m *ContainerStatusResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Status.Size())) - n43, err := m.Status.MarshalTo(dAtA[i:]) + n44, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n43 + i += n44 } if len(m.Info) > 0 { for k := range m.Info { @@ -7343,11 +7409,11 @@ func (m *UpdateContainerResourcesRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Linux.Size())) - n44, err := m.Linux.MarshalTo(dAtA[i:]) + n45, err := m.Linux.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n44 + i += n45 } return i, nil } @@ -7662,22 +7728,22 @@ func (m *PortForwardRequest) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], m.PodSandboxId) } if len(m.Port) > 0 { - dAtA46 := make([]byte, len(m.Port)*10) - var j45 int + dAtA47 := make([]byte, len(m.Port)*10) + var j46 int for _, num1 := range m.Port { num := uint64(num1) for num >= 1<<7 { - dAtA46[j45] = uint8(uint64(num)&0x7f | 0x80) + dAtA47[j46] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j45++ + j46++ } - dAtA46[j45] = uint8(num) - j45++ + dAtA47[j46] = uint8(num) + j46++ } dAtA[i] = 0x12 i++ - i = encodeVarintApi(dAtA, i, uint64(j45)) - i += copy(dAtA[i:], dAtA46[:j45]) + i = encodeVarintApi(dAtA, i, uint64(j46)) + i += copy(dAtA[i:], dAtA47[:j46]) } return i, nil } @@ -7725,11 +7791,11 @@ func (m *ImageFilter) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n47, err := m.Image.MarshalTo(dAtA[i:]) + n48, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n47 + i += n48 } return i, nil } @@ -7753,11 +7819,11 @@ func (m *ListImagesRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Filter.Size())) - n48, err := m.Filter.MarshalTo(dAtA[i:]) + n49, err := m.Filter.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n48 + i += n49 } return i, nil } @@ -7822,11 +7888,11 @@ func (m *Image) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintApi(dAtA, i, uint64(m.Uid.Size())) - n49, err := m.Uid.MarshalTo(dAtA[i:]) + n50, err := m.Uid.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n49 + i += n50 } if len(m.Username) > 0 { dAtA[i] = 0x32 @@ -7886,11 +7952,11 @@ func (m *ImageStatusRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n50, err := m.Image.MarshalTo(dAtA[i:]) + n51, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n50 + i += n51 } if m.Verbose { dAtA[i] = 0x10 @@ -7924,11 +7990,11 @@ func (m *ImageStatusResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n51, err := m.Image.MarshalTo(dAtA[i:]) + n52, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n51 + i += n52 } if len(m.Info) > 0 { for k := range m.Info { @@ -8023,32 +8089,32 @@ func (m *PullImageRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n52, err := m.Image.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n52 - } - if m.Auth != nil { - dAtA[i] = 0x12 - i++ - i = encodeVarintApi(dAtA, i, uint64(m.Auth.Size())) - n53, err := m.Auth.MarshalTo(dAtA[i:]) + n53, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n53 } - if m.SandboxConfig != nil { - dAtA[i] = 0x1a + if m.Auth != nil { + dAtA[i] = 0x12 i++ - i = encodeVarintApi(dAtA, i, uint64(m.SandboxConfig.Size())) - n54, err := m.SandboxConfig.MarshalTo(dAtA[i:]) + i = encodeVarintApi(dAtA, i, uint64(m.Auth.Size())) + n54, err := m.Auth.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n54 } + if m.SandboxConfig != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintApi(dAtA, i, uint64(m.SandboxConfig.Size())) + n55, err := m.SandboxConfig.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n55 + } return i, nil } @@ -8095,11 +8161,11 @@ func (m *RemoveImageRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n55, err := m.Image.MarshalTo(dAtA[i:]) + n56, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n55 + i += n56 } return i, nil } @@ -8165,11 +8231,11 @@ func (m *RuntimeConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.NetworkConfig.Size())) - n56, err := m.NetworkConfig.MarshalTo(dAtA[i:]) + n57, err := m.NetworkConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n56 + i += n57 } return i, nil } @@ -8193,11 +8259,11 @@ func (m *UpdateRuntimeConfigRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.RuntimeConfig.Size())) - n57, err := m.RuntimeConfig.MarshalTo(dAtA[i:]) + n58, err := m.RuntimeConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n57 + i += n58 } return i, nil } @@ -8343,11 +8409,11 @@ func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Status.Size())) - n58, err := m.Status.MarshalTo(dAtA[i:]) + n59, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n58 + i += n59 } if len(m.Info) > 0 { for k := range m.Info { @@ -8458,32 +8524,32 @@ func (m *FilesystemUsage) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.FsId.Size())) - n59, err := m.FsId.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n59 - } - if m.UsedBytes != nil { - dAtA[i] = 0x1a - i++ - i = encodeVarintApi(dAtA, i, uint64(m.UsedBytes.Size())) - n60, err := m.UsedBytes.MarshalTo(dAtA[i:]) + n60, err := m.FsId.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n60 } - if m.InodesUsed != nil { - dAtA[i] = 0x22 + if m.UsedBytes != nil { + dAtA[i] = 0x1a i++ - i = encodeVarintApi(dAtA, i, uint64(m.InodesUsed.Size())) - n61, err := m.InodesUsed.MarshalTo(dAtA[i:]) + i = encodeVarintApi(dAtA, i, uint64(m.UsedBytes.Size())) + n61, err := m.UsedBytes.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n61 } + if m.InodesUsed != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintApi(dAtA, i, uint64(m.InodesUsed.Size())) + n62, err := m.InodesUsed.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n62 + } return i, nil } @@ -8560,11 +8626,11 @@ func (m *ContainerStatsResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Stats.Size())) - n62, err := m.Stats.MarshalTo(dAtA[i:]) + n63, err := m.Stats.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n62 + i += n63 } return i, nil } @@ -8588,11 +8654,11 @@ func (m *ListContainerStatsRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Filter.Size())) - n63, err := m.Filter.MarshalTo(dAtA[i:]) + n64, err := m.Filter.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n63 + i += n64 } return i, nil } @@ -8699,11 +8765,11 @@ func (m *ContainerAttributes) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Metadata.Size())) - n64, err := m.Metadata.MarshalTo(dAtA[i:]) + n65, err := m.Metadata.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n64 + i += n65 } if len(m.Labels) > 0 { for k := range m.Labels { @@ -8761,42 +8827,42 @@ func (m *ContainerStats) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Attributes.Size())) - n65, err := m.Attributes.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n65 - } - if m.Cpu != nil { - dAtA[i] = 0x12 - i++ - i = encodeVarintApi(dAtA, i, uint64(m.Cpu.Size())) - n66, err := m.Cpu.MarshalTo(dAtA[i:]) + n66, err := m.Attributes.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n66 } - if m.Memory != nil { - dAtA[i] = 0x1a + if m.Cpu != nil { + dAtA[i] = 0x12 i++ - i = encodeVarintApi(dAtA, i, uint64(m.Memory.Size())) - n67, err := m.Memory.MarshalTo(dAtA[i:]) + i = encodeVarintApi(dAtA, i, uint64(m.Cpu.Size())) + n67, err := m.Cpu.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n67 } - if m.WritableLayer != nil { - dAtA[i] = 0x22 + if m.Memory != nil { + dAtA[i] = 0x1a i++ - i = encodeVarintApi(dAtA, i, uint64(m.WritableLayer.Size())) - n68, err := m.WritableLayer.MarshalTo(dAtA[i:]) + i = encodeVarintApi(dAtA, i, uint64(m.Memory.Size())) + n68, err := m.Memory.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n68 } + if m.WritableLayer != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintApi(dAtA, i, uint64(m.WritableLayer.Size())) + n69, err := m.WritableLayer.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n69 + } return i, nil } @@ -8824,11 +8890,11 @@ func (m *CpuUsage) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.UsageCoreNanoSeconds.Size())) - n69, err := m.UsageCoreNanoSeconds.MarshalTo(dAtA[i:]) + n70, err := m.UsageCoreNanoSeconds.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n69 + i += n70 } return i, nil } @@ -8857,11 +8923,11 @@ func (m *MemoryUsage) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.WorkingSetBytes.Size())) - n70, err := m.WorkingSetBytes.MarshalTo(dAtA[i:]) + n71, err := m.WorkingSetBytes.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n70 + i += n71 } return i, nil } @@ -9594,6 +9660,16 @@ func (m *LinuxContainerConfig) Size() (n int) { return n } +func (m *WindowsContainerSecurityContext) Size() (n int) { + var l int + _ = l + l = len(m.RunAsUsername) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + func (m *WindowsContainerConfig) Size() (n int) { var l int _ = l @@ -9601,6 +9677,10 @@ func (m *WindowsContainerConfig) Size() (n int) { l = m.Resources.Size() n += 1 + l + sovApi(uint64(l)) } + if m.SecurityContext != nil { + l = m.SecurityContext.Size() + n += 1 + l + sovApi(uint64(l)) + } return n } @@ -11182,12 +11262,23 @@ func (this *LinuxContainerConfig) String() string { }, "") return s } +func (this *WindowsContainerSecurityContext) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&WindowsContainerSecurityContext{`, + `RunAsUsername:` + fmt.Sprintf("%v", this.RunAsUsername) + `,`, + `}`, + }, "") + return s +} func (this *WindowsContainerConfig) String() string { if this == nil { return "nil" } s := strings.Join([]string{`&WindowsContainerConfig{`, `Resources:` + strings.Replace(fmt.Sprintf("%v", this.Resources), "WindowsContainerResources", "WindowsContainerResources", 1) + `,`, + `SecurityContext:` + strings.Replace(fmt.Sprintf("%v", this.SecurityContext), "WindowsContainerSecurityContext", "WindowsContainerSecurityContext", 1) + `,`, `}`, }, "") return s @@ -17555,6 +17646,85 @@ func (m *LinuxContainerConfig) Unmarshal(dAtA []byte) error { } return nil } +func (m *WindowsContainerSecurityContext) 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 ErrIntOverflowApi + } + 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: WindowsContainerSecurityContext: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WindowsContainerSecurityContext: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RunAsUsername", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RunAsUsername = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *WindowsContainerConfig) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -17617,6 +17787,39 @@ func (m *WindowsContainerConfig) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecurityContext", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SecurityContext == nil { + m.SecurityContext = &WindowsContainerSecurityContext{} + } + if err := m.SecurityContext.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipApi(dAtA[iNdEx:]) @@ -26455,294 +26658,296 @@ var ( func init() { proto.RegisterFile("api.proto", fileDescriptorApi) } var fileDescriptorApi = []byte{ - // 4623 bytes of a gzipped FileDescriptorProto + // 4649 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5c, 0xcd, 0x6f, 0x1b, 0x49, - 0x76, 0x17, 0x49, 0x7d, 0x90, 0x8f, 0xa2, 0x44, 0x95, 0x65, 0x8b, 0xa6, 0x6d, 0x8d, 0xd5, 0x1e, + 0x76, 0x57, 0x93, 0xfa, 0x20, 0x1f, 0x45, 0x89, 0x2a, 0xcb, 0x16, 0x4d, 0xdb, 0xb2, 0xd5, 0x1e, 0x7f, 0xce, 0x58, 0x1e, 0x6b, 0x76, 0x3d, 0xb1, 0x3d, 0x6b, 0x9b, 0x96, 0x64, 0x9b, 0x59, 0x9b, - 0x52, 0x9a, 0xd2, 0x7c, 0xec, 0x2c, 0xd0, 0xdb, 0x62, 0x97, 0xa8, 0x5e, 0x93, 0x5d, 0x3d, 0xdd, + 0x52, 0x9a, 0xd2, 0x7c, 0xec, 0x0c, 0xd0, 0xdb, 0x62, 0x97, 0xa8, 0x5e, 0x93, 0x5d, 0x3d, 0xdd, 0x4d, 0xdb, 0xca, 0x21, 0x58, 0x20, 0xc8, 0x1e, 0x02, 0x04, 0xc8, 0x79, 0x8f, 0x9b, 0x43, 0x0e, - 0xb9, 0x05, 0x08, 0x72, 0xc8, 0x29, 0xc1, 0x1e, 0xf6, 0x12, 0x20, 0xa7, 0x45, 0x3e, 0x2e, 0x99, - 0x09, 0x72, 0xc9, 0x21, 0xc8, 0x1f, 0x90, 0x43, 0x50, 0x5f, 0xfd, 0xdd, 0xfc, 0xd0, 0x78, 0x77, - 0x26, 0x27, 0x75, 0xbd, 0x7a, 0xef, 0xd5, 0xab, 0xaa, 0x57, 0xaf, 0x5e, 0xfd, 0xaa, 0x28, 0x28, - 0xe9, 0xb6, 0xb9, 0x6e, 0x3b, 0xc4, 0x23, 0xa8, 0xea, 0x0c, 0x2c, 0xcf, 0xec, 0xe3, 0xf5, 0x57, - 0xb7, 0xf5, 0x9e, 0x7d, 0xa4, 0x6f, 0xd4, 0x6f, 0x76, 0x4d, 0xef, 0x68, 0x70, 0xb0, 0xde, 0x21, - 0xfd, 0x5b, 0x5d, 0xd2, 0x25, 0xb7, 0x18, 0xe3, 0xc1, 0xe0, 0x90, 0x95, 0x58, 0x81, 0x7d, 0x71, - 0x05, 0xca, 0x0d, 0x58, 0xf8, 0x04, 0x3b, 0xae, 0x49, 0x2c, 0x15, 0x7f, 0x39, 0xc0, 0xae, 0x87, - 0x6a, 0x30, 0xf7, 0x8a, 0x53, 0x6a, 0xb9, 0x8b, 0xb9, 0x6b, 0x25, 0x55, 0x16, 0x95, 0xbf, 0xcc, - 0xc1, 0xa2, 0xcf, 0xec, 0xda, 0xc4, 0x72, 0x71, 0x36, 0x37, 0x5a, 0x83, 0x79, 0x61, 0x9c, 0x66, - 0xe9, 0x7d, 0x5c, 0xcb, 0xb3, 0xea, 0xb2, 0xa0, 0xb5, 0xf4, 0x3e, 0x46, 0x57, 0x61, 0x51, 0xb2, - 0x48, 0x25, 0x05, 0xc6, 0xb5, 0x20, 0xc8, 0xa2, 0x35, 0xb4, 0x0e, 0xa7, 0x24, 0xa3, 0x6e, 0x9b, - 0x3e, 0xf3, 0x34, 0x63, 0x5e, 0x12, 0x55, 0x0d, 0xdb, 0x14, 0xfc, 0xca, 0x17, 0x50, 0xda, 0x6a, - 0xb5, 0x37, 0x89, 0x75, 0x68, 0x76, 0xa9, 0x89, 0x2e, 0x76, 0xa8, 0x4c, 0x2d, 0x77, 0xb1, 0x40, - 0x4d, 0x14, 0x45, 0x54, 0x87, 0xa2, 0x8b, 0x75, 0xa7, 0x73, 0x84, 0xdd, 0x5a, 0x9e, 0x55, 0xf9, - 0x65, 0x2a, 0x45, 0x6c, 0xcf, 0x24, 0x96, 0x5b, 0x2b, 0x70, 0x29, 0x51, 0x54, 0x7e, 0x99, 0x83, - 0xf2, 0x2e, 0x71, 0xbc, 0x17, 0xba, 0x6d, 0x9b, 0x56, 0x17, 0xdd, 0x81, 0x22, 0x1b, 0xcb, 0x0e, - 0xe9, 0xb1, 0x31, 0x58, 0xd8, 0xa8, 0xaf, 0xc7, 0xa7, 0x65, 0x7d, 0x57, 0x70, 0xa8, 0x3e, 0x2f, - 0xba, 0x0c, 0x0b, 0x1d, 0x62, 0x79, 0xba, 0x69, 0x61, 0x47, 0xb3, 0x89, 0xe3, 0xb1, 0x21, 0x9a, - 0x51, 0x2b, 0x3e, 0x95, 0xb6, 0x82, 0xce, 0x41, 0xe9, 0x88, 0xb8, 0x1e, 0xe7, 0x28, 0x30, 0x8e, - 0x22, 0x25, 0xb0, 0xca, 0x15, 0x98, 0x63, 0x95, 0xa6, 0x2d, 0x06, 0x63, 0x96, 0x16, 0x9b, 0xb6, - 0xf2, 0x9b, 0x1c, 0xcc, 0xbc, 0x20, 0x03, 0xcb, 0x8b, 0x35, 0xa3, 0x7b, 0x47, 0x62, 0xa2, 0x42, - 0xcd, 0xe8, 0xde, 0x51, 0xd0, 0x0c, 0xe5, 0xe0, 0x73, 0xc5, 0x9b, 0xa1, 0x95, 0x75, 0x28, 0x3a, - 0x58, 0x37, 0x88, 0xd5, 0x3b, 0x66, 0x26, 0x14, 0x55, 0xbf, 0x4c, 0x27, 0xd1, 0xc5, 0x3d, 0xd3, - 0x1a, 0xbc, 0xd1, 0x1c, 0xdc, 0xd3, 0x0f, 0x70, 0x8f, 0x99, 0x52, 0x54, 0x17, 0x04, 0x59, 0xe5, - 0x54, 0xb4, 0x05, 0x65, 0xdb, 0x21, 0xb6, 0xde, 0xd5, 0xe9, 0x38, 0xd6, 0x66, 0xd8, 0x50, 0x29, - 0xc9, 0xa1, 0x62, 0x66, 0xef, 0x06, 0x9c, 0x6a, 0x58, 0x4c, 0xf9, 0xeb, 0x1c, 0x2c, 0x52, 0xe7, - 0x71, 0x6d, 0xbd, 0x83, 0x77, 0xd8, 0x94, 0xa0, 0xbb, 0x30, 0x67, 0x61, 0xef, 0x35, 0x71, 0x5e, - 0x8a, 0x09, 0x78, 0x27, 0xa9, 0xd5, 0x97, 0x79, 0x41, 0x0c, 0xac, 0x4a, 0x7e, 0x74, 0x1b, 0x0a, - 0xb6, 0x69, 0xb0, 0x0e, 0x8f, 0x21, 0x46, 0x79, 0xa9, 0x88, 0x69, 0x77, 0xd8, 0x38, 0x8c, 0x23, - 0x62, 0xda, 0x1d, 0x45, 0x01, 0x68, 0x5a, 0xde, 0x9d, 0xef, 0x7d, 0xa2, 0xf7, 0x06, 0x18, 0x2d, - 0xc3, 0xcc, 0x2b, 0xfa, 0xc1, 0x8c, 0x2d, 0xa8, 0xbc, 0xa0, 0x7c, 0x55, 0x80, 0x73, 0xcf, 0xe9, - 0x78, 0xb5, 0x75, 0xcb, 0x38, 0x20, 0x6f, 0xda, 0xb8, 0x33, 0x70, 0x4c, 0xef, 0x78, 0x93, 0x58, - 0x1e, 0x7e, 0xe3, 0xa1, 0x16, 0x2c, 0x59, 0x52, 0xb3, 0x26, 0x5d, 0x93, 0x6a, 0x28, 0x6f, 0xac, - 0x0d, 0x31, 0x82, 0x0f, 0x91, 0x5a, 0xb5, 0xa2, 0x04, 0x17, 0x3d, 0x0b, 0xe6, 0x4d, 0x6a, 0xcb, - 0x33, 0x6d, 0x29, 0x5d, 0x6a, 0x6f, 0x33, 0xcb, 0x84, 0x2e, 0x39, 0xb1, 0x52, 0xd3, 0xc7, 0x40, - 0x57, 0xb5, 0xa6, 0xbb, 0xda, 0xc0, 0xc5, 0x0e, 0x1b, 0x98, 0xf2, 0xc6, 0xf9, 0xa4, 0x96, 0x60, - 0x08, 0xd4, 0x92, 0x33, 0xb0, 0x1a, 0xee, 0xbe, 0x8b, 0x1d, 0x16, 0x04, 0x84, 0x2f, 0x69, 0x0e, - 0x21, 0xde, 0xa1, 0x2b, 0xfd, 0x47, 0x92, 0x55, 0x46, 0x45, 0xb7, 0xe0, 0x94, 0x3b, 0xb0, 0xed, - 0x1e, 0xee, 0x63, 0xcb, 0xd3, 0x7b, 0x5a, 0xd7, 0x21, 0x03, 0xdb, 0xad, 0xcd, 0x5c, 0x2c, 0x5c, - 0x2b, 0xa8, 0x28, 0x5c, 0xf5, 0x94, 0xd5, 0xa0, 0x55, 0x00, 0xdb, 0x31, 0x5f, 0x99, 0x3d, 0xdc, - 0xc5, 0x46, 0x6d, 0x96, 0x29, 0x0d, 0x51, 0xd0, 0x07, 0xb0, 0xec, 0xe2, 0x4e, 0x87, 0xf4, 0x6d, - 0xcd, 0x76, 0xc8, 0xa1, 0xd9, 0xc3, 0xdc, 0xfb, 0xe7, 0x98, 0xf7, 0x23, 0x51, 0xb7, 0xcb, 0xab, - 0xd8, 0x3a, 0x78, 0xc0, 0x62, 0x1a, 0xed, 0x29, 0x6b, 0xbc, 0x56, 0x1c, 0xa3, 0xab, 0xc0, 0xba, - 0xca, 0x4c, 0x52, 0x7e, 0x99, 0x87, 0xd3, 0x6c, 0x24, 0x77, 0x89, 0x21, 0xa6, 0x59, 0x04, 0xa9, - 0x4b, 0x50, 0xe9, 0x30, 0x9d, 0x9a, 0xad, 0x3b, 0xd8, 0xf2, 0xc4, 0x22, 0x9d, 0xe7, 0xc4, 0x5d, - 0x46, 0x43, 0x9f, 0x41, 0xd5, 0x15, 0x5e, 0xa1, 0x75, 0xb8, 0x5b, 0x88, 0x39, 0xbb, 0x99, 0x34, - 0x61, 0x88, 0x2f, 0xa9, 0x8b, 0x6e, 0xc2, 0xb9, 0xe6, 0xdc, 0x63, 0xb7, 0xe3, 0xf5, 0x78, 0xb4, - 0x2b, 0x6f, 0x7c, 0x2f, 0x43, 0x61, 0xdc, 0xf0, 0xf5, 0x36, 0x17, 0xdb, 0xb6, 0x3c, 0xe7, 0x58, - 0x95, 0x4a, 0xea, 0xf7, 0x60, 0x3e, 0x5c, 0x81, 0xaa, 0x50, 0x78, 0x89, 0x8f, 0x45, 0xa7, 0xe8, - 0x67, 0xb0, 0x08, 0x78, 0xac, 0xe1, 0x85, 0x7b, 0xf9, 0xdf, 0xcb, 0x29, 0x0e, 0xa0, 0xa0, 0x95, - 0x17, 0xd8, 0xd3, 0x0d, 0xdd, 0xd3, 0x11, 0x82, 0x69, 0xb6, 0x8d, 0x70, 0x15, 0xec, 0x9b, 0x6a, - 0x1d, 0x88, 0xc5, 0x5b, 0x52, 0xe9, 0x27, 0x3a, 0x0f, 0x25, 0xdf, 0xd1, 0xc5, 0x5e, 0x12, 0x10, - 0x68, 0x4c, 0xd7, 0x3d, 0x0f, 0xf7, 0x6d, 0x8f, 0xb9, 0x58, 0x45, 0x95, 0x45, 0xe5, 0xbf, 0xa7, - 0xa1, 0x9a, 0x98, 0x93, 0x47, 0x50, 0xec, 0x8b, 0xe6, 0xc5, 0x42, 0x7b, 0x37, 0x25, 0xb0, 0x27, - 0x4c, 0x55, 0x7d, 0x29, 0x1a, 0x37, 0x69, 0x0c, 0x0d, 0xed, 0x7f, 0x7e, 0x99, 0xce, 0x78, 0x8f, - 0x74, 0x35, 0xc3, 0x74, 0x70, 0xc7, 0x23, 0xce, 0xb1, 0x30, 0x77, 0xbe, 0x47, 0xba, 0x5b, 0x92, - 0x86, 0xee, 0x01, 0x18, 0x96, 0x4b, 0x27, 0xfb, 0xd0, 0xec, 0x32, 0xa3, 0xcb, 0x1b, 0xe7, 0x92, - 0x46, 0xf8, 0x9b, 0x9d, 0x5a, 0x32, 0x2c, 0x57, 0x98, 0xff, 0x18, 0x2a, 0x74, 0xcf, 0xd0, 0xfa, - 0x7c, 0x9f, 0xe2, 0x2b, 0xa5, 0xbc, 0x71, 0x21, 0xad, 0x0f, 0xfe, 0x6e, 0xa6, 0xce, 0xdb, 0x41, - 0xc1, 0x45, 0x4f, 0x60, 0x96, 0x05, 0x6f, 0xb7, 0x36, 0xcb, 0x84, 0xd7, 0x87, 0x0d, 0x80, 0xf0, - 0x88, 0xe7, 0x4c, 0x80, 0x3b, 0x84, 0x90, 0x46, 0xfb, 0x50, 0xd6, 0x2d, 0x8b, 0x78, 0x3a, 0x0f, - 0x34, 0x73, 0x4c, 0xd9, 0x87, 0x63, 0x28, 0x6b, 0x04, 0x52, 0x5c, 0x63, 0x58, 0x0f, 0xfa, 0x01, - 0xcc, 0xb0, 0x48, 0x24, 0x16, 0xe2, 0xd5, 0x31, 0x9d, 0x56, 0xe5, 0x52, 0xf5, 0xbb, 0x50, 0x0e, - 0x19, 0x3b, 0x89, 0x93, 0xd6, 0x1f, 0x40, 0x35, 0x6e, 0xda, 0x44, 0x4e, 0xae, 0xc2, 0xb2, 0x3a, - 0xb0, 0x02, 0xc3, 0x64, 0xf6, 0x75, 0x0f, 0x66, 0xc5, 0x64, 0x73, 0x8f, 0x53, 0x46, 0x8f, 0x91, - 0x2a, 0x24, 0x94, 0x1f, 0xc0, 0xe9, 0x98, 0x4e, 0x91, 0xa4, 0xbd, 0x0b, 0x0b, 0x36, 0x31, 0x34, - 0x97, 0x93, 0x35, 0xd3, 0x90, 0xd1, 0xc5, 0xf6, 0x79, 0x9b, 0x06, 0x15, 0x6f, 0x7b, 0xc4, 0x4e, - 0xda, 0x34, 0x9e, 0x78, 0x0d, 0xce, 0xc4, 0xc5, 0x79, 0xf3, 0xca, 0x43, 0x58, 0x51, 0x71, 0x9f, - 0xbc, 0xc2, 0x27, 0x55, 0x5d, 0x87, 0x5a, 0x52, 0x81, 0x50, 0xfe, 0x39, 0xac, 0x04, 0xd4, 0xb6, - 0xa7, 0x7b, 0x03, 0x77, 0x22, 0xe5, 0x22, 0x83, 0x3d, 0x20, 0x2e, 0x9f, 0xa5, 0xa2, 0x2a, 0x8b, - 0xca, 0xf5, 0xb0, 0xea, 0x16, 0x4f, 0x18, 0x78, 0x0b, 0x68, 0x01, 0xf2, 0xa6, 0x2d, 0xd4, 0xe5, - 0x4d, 0x5b, 0x79, 0x06, 0x25, 0x7f, 0xc7, 0x45, 0xf7, 0x83, 0xd4, 0x31, 0x3f, 0xee, 0xfe, 0xec, - 0x67, 0x97, 0x7b, 0x89, 0x1d, 0x42, 0x34, 0x79, 0x1f, 0xc0, 0x8f, 0x64, 0x72, 0xe3, 0x3f, 0x37, - 0x44, 0xb1, 0x1a, 0x62, 0x57, 0xfe, 0x35, 0x12, 0xdf, 0x42, 0x9d, 0x30, 0xfc, 0x4e, 0x18, 0x91, - 0x78, 0x97, 0x3f, 0x51, 0xbc, 0xfb, 0x08, 0x66, 0x5c, 0x4f, 0xf7, 0xb0, 0x48, 0x8e, 0xd6, 0x86, - 0x89, 0x53, 0x23, 0xb0, 0xca, 0xf9, 0xd1, 0x05, 0x80, 0x8e, 0x83, 0x75, 0x0f, 0x1b, 0x9a, 0xce, - 0x83, 0x73, 0x41, 0x2d, 0x09, 0x4a, 0xc3, 0x43, 0x9b, 0x41, 0x82, 0x37, 0xc3, 0x0c, 0xbb, 0x3e, - 0x4c, 0x73, 0x64, 0xaa, 0x82, 0x54, 0xcf, 0x0f, 0x16, 0xb3, 0x63, 0x06, 0x0b, 0xa1, 0x80, 0x4b, - 0x85, 0x42, 0xe1, 0xdc, 0xe8, 0x50, 0xc8, 0x45, 0xc7, 0x09, 0x85, 0xc5, 0xd1, 0xa1, 0x50, 0x28, - 0x1b, 0x1a, 0x0a, 0xbf, 0xcd, 0x58, 0xf6, 0x2f, 0x39, 0xa8, 0x25, 0xd7, 0xa0, 0x88, 0x3d, 0xf7, - 0x60, 0xd6, 0x65, 0x94, 0x71, 0x02, 0x9a, 0x90, 0x15, 0x12, 0xe8, 0x19, 0x4c, 0x9b, 0xd6, 0x21, - 0x61, 0x67, 0xb3, 0xd4, 0x94, 0x24, 0xab, 0xd5, 0xf5, 0xa6, 0x75, 0x48, 0xf8, 0x20, 0x31, 0x0d, - 0xf5, 0x8f, 0xa0, 0xe4, 0x93, 0x26, 0xea, 0xdb, 0x0e, 0x2c, 0xc7, 0x5c, 0x96, 0xe7, 0xf0, 0xbe, - 0xa7, 0xe7, 0x26, 0xf3, 0x74, 0xe5, 0x67, 0xf9, 0xf0, 0x4a, 0x7c, 0x62, 0xf6, 0x3c, 0xec, 0x24, - 0x56, 0xe2, 0xc7, 0x52, 0x3b, 0x5f, 0x86, 0x57, 0x46, 0x6a, 0xe7, 0xa9, 0xa6, 0x58, 0x4c, 0x3f, - 0x86, 0x05, 0xe6, 0x6b, 0x9a, 0x8b, 0x7b, 0x2c, 0x8f, 0x10, 0x39, 0xdd, 0xf7, 0x87, 0xa9, 0xe1, - 0x96, 0x70, 0x8f, 0x6d, 0x0b, 0x39, 0x3e, 0x82, 0x95, 0x5e, 0x98, 0x56, 0x7f, 0x04, 0x28, 0xc9, - 0x34, 0xd1, 0x98, 0xb6, 0x69, 0x88, 0xa3, 0x07, 0xd8, 0x94, 0xcd, 0xef, 0x90, 0x99, 0x31, 0x8e, - 0xaf, 0x70, 0x83, 0x55, 0x21, 0xa1, 0xfc, 0xaa, 0x00, 0x10, 0x54, 0xfe, 0x3f, 0x8a, 0x6d, 0x8f, - 0xfc, 0xb8, 0xc2, 0xf3, 0xb3, 0x6b, 0xc3, 0x14, 0xa7, 0x46, 0x94, 0x9d, 0x68, 0x44, 0xe1, 0x99, - 0xda, 0xcd, 0xa1, 0x6a, 0xbe, 0xb3, 0xb1, 0xe4, 0x39, 0x9c, 0x89, 0xfb, 0x86, 0x08, 0x24, 0x1b, - 0x30, 0x63, 0x7a, 0xb8, 0xcf, 0x41, 0x9c, 0xd4, 0x43, 0x57, 0x48, 0x88, 0xb3, 0x2a, 0x6b, 0x50, - 0x6a, 0xf6, 0xf5, 0x2e, 0x6e, 0xdb, 0xb8, 0x43, 0x1b, 0x35, 0x69, 0x41, 0x18, 0xc2, 0x0b, 0xca, - 0x06, 0x14, 0x7f, 0x88, 0x8f, 0xf9, 0xa2, 0x1e, 0xd3, 0x50, 0xe5, 0xcf, 0xf2, 0xb0, 0xc2, 0xf6, - 0x8a, 0x4d, 0x09, 0xa1, 0xa8, 0xd8, 0x25, 0x03, 0xa7, 0x83, 0x5d, 0x36, 0xdb, 0xf6, 0x40, 0xb3, - 0xb1, 0x63, 0x12, 0x43, 0x9c, 0xf0, 0x4b, 0x1d, 0x7b, 0xb0, 0xcb, 0x08, 0xe8, 0x1c, 0xd0, 0x82, - 0xf6, 0xe5, 0x80, 0x08, 0x47, 0x2c, 0xa8, 0xc5, 0x8e, 0x3d, 0xf8, 0x03, 0x5a, 0x96, 0xb2, 0xee, - 0x91, 0xee, 0x60, 0x97, 0xf9, 0x19, 0x97, 0x6d, 0x33, 0x02, 0xba, 0x0d, 0xa7, 0xfb, 0xb8, 0x4f, - 0x9c, 0x63, 0xad, 0x67, 0xf6, 0x4d, 0x4f, 0x33, 0x2d, 0xed, 0xe0, 0xd8, 0xc3, 0xae, 0xf0, 0x29, - 0xc4, 0x2b, 0x9f, 0xd3, 0xba, 0xa6, 0xf5, 0x98, 0xd6, 0x20, 0x05, 0x2a, 0x84, 0xf4, 0x35, 0xb7, - 0x43, 0x1c, 0xac, 0xe9, 0xc6, 0x4f, 0xd9, 0xf6, 0x59, 0x50, 0xcb, 0x84, 0xf4, 0xdb, 0x94, 0xd6, - 0x30, 0x7e, 0x8a, 0xde, 0x81, 0x72, 0xc7, 0x1e, 0xb8, 0xd8, 0xd3, 0xe8, 0x1f, 0xb6, 0x3b, 0x96, - 0x54, 0xe0, 0xa4, 0x4d, 0x7b, 0xe0, 0x86, 0x18, 0xfa, 0x74, 0xfc, 0xe7, 0xc2, 0x0c, 0x2f, 0xe8, - 0x30, 0xeb, 0x50, 0x89, 0x20, 0x04, 0xf4, 0xb0, 0xc6, 0xa0, 0x00, 0x71, 0x58, 0xa3, 0xdf, 0x94, - 0xe6, 0x90, 0x9e, 0x1c, 0x49, 0xf6, 0x4d, 0x69, 0xde, 0xb1, 0x2d, 0x4f, 0x6a, 0xec, 0x9b, 0x0e, - 0x79, 0x0f, 0xbf, 0x12, 0x28, 0x52, 0x49, 0xe5, 0x05, 0xc5, 0x00, 0xd8, 0xd4, 0x6d, 0xfd, 0xc0, - 0xec, 0x99, 0xde, 0x31, 0xba, 0x0e, 0x55, 0xdd, 0x30, 0xb4, 0x8e, 0xa4, 0x98, 0x58, 0x62, 0x7b, - 0x8b, 0xba, 0x61, 0x6c, 0x86, 0xc8, 0xe8, 0x3d, 0x58, 0x32, 0x1c, 0x62, 0x47, 0x79, 0x39, 0xd8, - 0x57, 0xa5, 0x15, 0x61, 0x66, 0xe5, 0x17, 0x33, 0x70, 0x21, 0x3a, 0xb1, 0x71, 0x14, 0xe6, 0x11, - 0xcc, 0xc7, 0x5a, 0xcd, 0x40, 0x00, 0x02, 0x6b, 0xd5, 0x88, 0x44, 0x0c, 0x95, 0xc8, 0x27, 0x50, - 0x89, 0x54, 0x9c, 0xa7, 0xf0, 0x56, 0x71, 0x9e, 0xe9, 0xb7, 0x82, 0xf3, 0xcc, 0x4c, 0x86, 0xf3, - 0x5c, 0x61, 0x60, 0xaf, 0x94, 0x66, 0x47, 0x62, 0xee, 0x6a, 0x15, 0x9f, 0xc7, 0x92, 0xa0, 0x70, - 0x0c, 0x0f, 0x9a, 0x9b, 0x04, 0x0f, 0x2a, 0x66, 0xe2, 0x41, 0xd4, 0x6b, 0x6c, 0x5b, 0x77, 0xfa, - 0xc4, 0x91, 0x80, 0x4f, 0xad, 0xc4, 0x4c, 0x58, 0x94, 0x74, 0x01, 0xf6, 0x64, 0x42, 0x43, 0x90, - 0x09, 0x0d, 0x5d, 0x84, 0x79, 0x8b, 0x68, 0x16, 0x7e, 0xad, 0xd1, 0xb9, 0x74, 0x6b, 0x65, 0x3e, - 0xb1, 0x16, 0x69, 0xe1, 0xd7, 0xbb, 0x94, 0x92, 0x00, 0x8f, 0xe6, 0x27, 0x04, 0x8f, 0xfe, 0x2e, - 0x07, 0xcb, 0x51, 0xe7, 0x14, 0x07, 0xfd, 0xa7, 0x50, 0x72, 0x64, 0xfc, 0x11, 0x0e, 0x79, 0x3d, - 0x23, 0xb9, 0x4d, 0x06, 0x2c, 0x35, 0x90, 0x45, 0x3f, 0xca, 0xc4, 0x97, 0x6e, 0x8d, 0xd2, 0x37, - 0x0a, 0x61, 0x52, 0x3a, 0x70, 0xe6, 0x53, 0xd3, 0x32, 0xc8, 0x6b, 0x37, 0x6e, 0x7e, 0x33, 0x69, - 0xfe, 0x7b, 0xc9, 0xe6, 0xe2, 0xc2, 0x69, 0x1d, 0x50, 0xfe, 0x2a, 0x07, 0x67, 0x33, 0x19, 0x63, - 0xe1, 0x35, 0x17, 0x0f, 0xaf, 0x22, 0x34, 0x77, 0xc8, 0xc0, 0xf2, 0x42, 0xa1, 0x79, 0x93, 0xa1, - 0xe8, 0x3c, 0x06, 0x6a, 0x7d, 0xfd, 0x8d, 0xd9, 0x1f, 0xf4, 0x45, 0x6c, 0xa6, 0xea, 0x5e, 0x70, - 0xca, 0x09, 0x82, 0xb3, 0xd2, 0x80, 0x25, 0xdf, 0xca, 0xa1, 0x38, 0x57, 0x08, 0xb7, 0xca, 0x47, - 0x71, 0x2b, 0x0b, 0x66, 0xb7, 0xf0, 0x2b, 0xb3, 0x83, 0xdf, 0x0a, 0xcc, 0x7f, 0x11, 0xca, 0x36, - 0x76, 0xfa, 0xa6, 0xeb, 0xfa, 0x41, 0xa7, 0xa4, 0x86, 0x49, 0xca, 0x7f, 0xce, 0xc2, 0x62, 0x7c, - 0xfe, 0x1e, 0x26, 0x60, 0xb2, 0x4b, 0x29, 0xe1, 0x30, 0xde, 0xd1, 0x50, 0x66, 0x75, 0x5b, 0x6e, - 0xcc, 0xf9, 0xac, 0x43, 0xad, 0xbf, 0x89, 0x8b, 0x5d, 0x9b, 0x8e, 0x48, 0x87, 0xf4, 0xfb, 0xba, - 0x65, 0xc8, 0xdb, 0x19, 0x51, 0xa4, 0xe3, 0xa7, 0x3b, 0x5d, 0x3a, 0xec, 0x94, 0xcc, 0xbe, 0xe9, - 0xe4, 0xd1, 0x13, 0xa0, 0x69, 0x31, 0xb8, 0x8d, 0x05, 0xae, 0x92, 0x0a, 0x82, 0xb4, 0x65, 0x3a, - 0x68, 0x1d, 0xa6, 0xb1, 0xf5, 0x4a, 0xa6, 0x4e, 0x29, 0xd7, 0x37, 0x32, 0x45, 0x50, 0x19, 0x1f, - 0xba, 0x05, 0xb3, 0x7d, 0xea, 0x16, 0xf2, 0x2c, 0xb8, 0x92, 0x71, 0x8b, 0xa1, 0x0a, 0x36, 0xb4, - 0x01, 0x73, 0x06, 0x9b, 0x27, 0x79, 0xe0, 0xab, 0xa5, 0x80, 0x78, 0x8c, 0x41, 0x95, 0x8c, 0x68, - 0xdb, 0x4f, 0x0c, 0x4b, 0x59, 0x19, 0x5d, 0x6c, 0x2a, 0x52, 0xb3, 0xc3, 0xbd, 0x68, 0x76, 0x08, - 0x4c, 0xd7, 0xc6, 0x68, 0x5d, 0xc3, 0x91, 0xb7, 0xb3, 0x50, 0xec, 0x91, 0x2e, 0x77, 0xa3, 0x32, - 0xbf, 0xf8, 0xeb, 0x91, 0x2e, 0xf3, 0xa2, 0x65, 0x9a, 0x28, 0x1b, 0xa6, 0xc5, 0x02, 0x5c, 0x51, - 0xe5, 0x05, 0xba, 0xf8, 0xd8, 0x87, 0x46, 0xac, 0x0e, 0xae, 0x55, 0x58, 0x55, 0x89, 0x51, 0x76, - 0xac, 0x0e, 0x4b, 0xbd, 0x3c, 0xef, 0xb8, 0xb6, 0xc0, 0xe8, 0xf4, 0x93, 0x9e, 0x81, 0xf8, 0x71, - 0x7d, 0x31, 0xeb, 0x0c, 0x94, 0x16, 0x0c, 0xe5, 0x69, 0xfd, 0x31, 0xcc, 0xbd, 0xe6, 0x81, 0xa0, - 0x56, 0x65, 0xf2, 0xd7, 0x46, 0x87, 0x14, 0xa1, 0x41, 0x0a, 0x7e, 0x9b, 0x69, 0xf0, 0xaf, 0x72, - 0x70, 0x66, 0x93, 0x1d, 0x11, 0x42, 0x71, 0x6c, 0x12, 0x54, 0xeb, 0xae, 0x8f, 0x23, 0x66, 0x42, - 0x50, 0xf1, 0x7e, 0x0b, 0x01, 0xd4, 0x84, 0x05, 0xa9, 0x5c, 0xa8, 0x28, 0x8c, 0x0d, 0x45, 0x56, - 0xdc, 0x70, 0x51, 0xf9, 0x18, 0x56, 0x12, 0xbd, 0x10, 0xe9, 0xfc, 0x1a, 0xcc, 0x07, 0xf1, 0xca, - 0xef, 0x44, 0xd9, 0xa7, 0x35, 0x0d, 0xe5, 0x1e, 0x9c, 0x6e, 0x7b, 0xba, 0xe3, 0x25, 0x86, 0x60, - 0x0c, 0x59, 0x86, 0x46, 0x46, 0x65, 0x05, 0x60, 0xd8, 0x86, 0xe5, 0xb6, 0x47, 0xec, 0x13, 0x28, - 0xa5, 0x51, 0x87, 0xf6, 0x9f, 0x0c, 0xe4, 0xfe, 0x20, 0x8b, 0xca, 0x0a, 0xc7, 0x4e, 0x93, 0xad, - 0xdd, 0x87, 0x33, 0x1c, 0xba, 0x3c, 0x49, 0x27, 0xce, 0x4a, 0xe0, 0x34, 0xa9, 0xf7, 0x05, 0x9c, - 0x0a, 0xf6, 0xde, 0x00, 0x96, 0xb8, 0x13, 0x85, 0x25, 0x2e, 0x0e, 0x99, 0xf5, 0x08, 0x2a, 0xf1, - 0x17, 0xf9, 0x50, 0x5c, 0xcf, 0x00, 0x25, 0xee, 0x47, 0x41, 0x89, 0xcb, 0xa3, 0x74, 0x47, 0x30, - 0x89, 0xa4, 0xd7, 0x16, 0x52, 0xbc, 0xf6, 0x8b, 0x04, 0x72, 0x31, 0x9d, 0x05, 0xfd, 0xc4, 0xac, - 0xfd, 0x9d, 0x00, 0x17, 0x2a, 0x07, 0x2e, 0xfc, 0xa6, 0x7d, 0xa4, 0xf9, 0x6e, 0x0c, 0xb8, 0x58, - 0x1b, 0x69, 0xaf, 0x8f, 0x5b, 0xfc, 0xcd, 0x34, 0x94, 0xfc, 0xba, 0xc4, 0x98, 0x27, 0x87, 0x2d, - 0x9f, 0x32, 0x6c, 0xe1, 0x1d, 0xb8, 0xf0, 0x8d, 0x76, 0xe0, 0xe9, 0xb1, 0x77, 0xe0, 0x73, 0x50, - 0x62, 0x1f, 0x9a, 0x83, 0x0f, 0xc5, 0x8e, 0x5a, 0x64, 0x04, 0x15, 0x1f, 0x06, 0x6e, 0x38, 0x3b, - 0x91, 0x1b, 0xc6, 0xa0, 0x92, 0xb9, 0x38, 0x54, 0xf2, 0xd0, 0xdf, 0x11, 0xf9, 0x26, 0x7a, 0x75, - 0x88, 0xde, 0xd4, 0xbd, 0xb0, 0x15, 0xdd, 0x0b, 0xf9, 0xbe, 0xfa, 0xfe, 0x30, 0x2d, 0xdf, 0x59, - 0xa0, 0x64, 0x9f, 0x03, 0x25, 0x61, 0x5f, 0x14, 0x91, 0xf5, 0x3e, 0x80, 0x1f, 0x44, 0x24, 0x5a, - 0x72, 0x6e, 0x48, 0x1f, 0xd5, 0x10, 0x3b, 0x55, 0x1b, 0x99, 0x9a, 0xe0, 0x36, 0x65, 0xbc, 0xf8, - 0x98, 0x71, 0x95, 0xf2, 0xbf, 0x33, 0xa1, 0xf8, 0x92, 0x71, 0xfd, 0xf0, 0x30, 0x01, 0xd1, 0x4d, - 0xe8, 0xc5, 0x77, 0xa2, 0x08, 0xdd, 0x09, 0xbd, 0x2e, 0x01, 0xd0, 0xb1, 0xcc, 0x45, 0x77, 0x44, - 0x35, 0x07, 0x50, 0x4a, 0x82, 0xd2, 0x60, 0x27, 0x83, 0x43, 0xd3, 0x32, 0xdd, 0x23, 0x5e, 0x3f, - 0xcb, 0x4f, 0x06, 0x92, 0xd4, 0x60, 0x0f, 0x78, 0xf0, 0x1b, 0xd3, 0xd3, 0x3a, 0xc4, 0xc0, 0xcc, - 0xa7, 0x67, 0xd4, 0x22, 0x25, 0x6c, 0x12, 0x03, 0x07, 0x2b, 0xaf, 0x78, 0xb2, 0x95, 0x57, 0x8a, - 0xad, 0xbc, 0x33, 0x30, 0xeb, 0x60, 0xdd, 0x25, 0x96, 0x38, 0xaa, 0x8a, 0x12, 0x9d, 0x9a, 0x3e, - 0x76, 0x5d, 0xda, 0x92, 0x48, 0xd7, 0x44, 0x31, 0x94, 0x66, 0xce, 0x8f, 0x4c, 0x33, 0x87, 0x5c, - 0x6b, 0xc4, 0xd2, 0xcc, 0xca, 0xc8, 0x34, 0x73, 0x9c, 0x5b, 0x8d, 0x50, 0xa2, 0xbd, 0x30, 0x5e, - 0xa2, 0x1d, 0xce, 0x4b, 0x17, 0x23, 0x79, 0xe9, 0xb7, 0xb9, 0x58, 0x7f, 0x93, 0x83, 0x95, 0xc4, - 0xb2, 0x12, 0xcb, 0xf5, 0x6e, 0xec, 0x82, 0x64, 0x6d, 0xe4, 0x98, 0xf9, 0xf7, 0x23, 0x4f, 0x23, - 0xf7, 0x23, 0x1f, 0x8e, 0x16, 0x7c, 0xeb, 0xd7, 0x23, 0x7f, 0x92, 0x83, 0x77, 0xf6, 0x6d, 0x23, - 0x96, 0xe1, 0x89, 0x83, 0xf9, 0xf8, 0x81, 0xe3, 0xa1, 0xcc, 0xf5, 0xf3, 0x93, 0xa2, 0x17, 0x5c, - 0x4e, 0x51, 0xe0, 0x62, 0xb6, 0x19, 0x22, 0x65, 0xfa, 0x09, 0x2c, 0x6e, 0xbf, 0xc1, 0x9d, 0xf6, - 0xb1, 0xd5, 0x99, 0xc0, 0xb4, 0x2a, 0x14, 0x3a, 0x7d, 0x43, 0x20, 0x86, 0xf4, 0x33, 0x9c, 0x05, - 0x16, 0xa2, 0x59, 0xa0, 0x06, 0xd5, 0xa0, 0x05, 0x31, 0xbd, 0x67, 0xe8, 0xf4, 0x1a, 0x94, 0x99, - 0x2a, 0x9f, 0x57, 0x45, 0x49, 0xd0, 0xb1, 0xe3, 0xb0, 0x3e, 0x73, 0x3a, 0x76, 0x9c, 0x68, 0xb4, - 0x28, 0x44, 0xa3, 0x85, 0xf2, 0x8b, 0x1c, 0x94, 0x69, 0x0b, 0xdf, 0xc8, 0x7e, 0x71, 0xd4, 0x2a, - 0x04, 0x47, 0x2d, 0xff, 0xc4, 0x36, 0x1d, 0x3e, 0xb1, 0x05, 0x96, 0xcf, 0x30, 0x72, 0xd2, 0xf2, - 0x59, 0x9f, 0x8e, 0x1d, 0x47, 0xb9, 0x08, 0xf3, 0xdc, 0x36, 0xd1, 0xf3, 0x2a, 0x14, 0x06, 0x4e, - 0x4f, 0xfa, 0xd1, 0xc0, 0xe9, 0x29, 0x7f, 0x9a, 0x83, 0x4a, 0xc3, 0xf3, 0xf4, 0xce, 0xd1, 0x04, - 0x1d, 0xf0, 0x8d, 0xcb, 0x87, 0x8d, 0x4b, 0x76, 0x22, 0x30, 0x77, 0x3a, 0xc3, 0xdc, 0x99, 0x88, - 0xb9, 0x0a, 0x2c, 0x48, 0x5b, 0x32, 0x0d, 0x6e, 0x01, 0xda, 0x25, 0x8e, 0xf7, 0x84, 0x38, 0xaf, - 0x75, 0xc7, 0x98, 0xec, 0x04, 0x86, 0x60, 0x5a, 0x3c, 0xea, 0x2c, 0x5c, 0x9b, 0x51, 0xd9, 0xb7, - 0x72, 0x15, 0x4e, 0x45, 0xf4, 0x65, 0x36, 0xfc, 0x08, 0xca, 0x2c, 0xee, 0x8b, 0x54, 0xfc, 0x76, - 0xf8, 0xea, 0x62, 0xac, 0x5d, 0x42, 0xf9, 0x7d, 0x58, 0xa2, 0xf9, 0x01, 0xa3, 0xfb, 0x4b, 0xf1, - 0xfb, 0xb1, 0x3c, 0xf5, 0x42, 0x86, 0xa2, 0x58, 0x8e, 0xfa, 0xb7, 0x39, 0x98, 0x61, 0xf4, 0xc4, - 0x9e, 0x7d, 0x0e, 0x4a, 0x0e, 0xb6, 0x89, 0xe6, 0xe9, 0x5d, 0xff, 0x09, 0x2d, 0x25, 0xec, 0xe9, - 0x5d, 0x97, 0xbd, 0x00, 0xa6, 0x95, 0x86, 0xd9, 0xc5, 0xae, 0x27, 0xdf, 0xd1, 0x96, 0x29, 0x6d, - 0x8b, 0x93, 0xe8, 0x20, 0xb9, 0xe6, 0x1f, 0xf2, 0xbc, 0x73, 0x5a, 0x65, 0xdf, 0x68, 0x9d, 0xbf, - 0xea, 0x1a, 0x07, 0x5e, 0x66, 0x6f, 0xbe, 0xea, 0x50, 0x8c, 0x21, 0xca, 0x7e, 0x59, 0xd9, 0x06, - 0x14, 0x1e, 0x05, 0x31, 0xde, 0xb7, 0x60, 0x96, 0x0d, 0x92, 0xcc, 0x8e, 0x56, 0x32, 0x86, 0x41, - 0x15, 0x6c, 0x8a, 0x0e, 0x88, 0x0f, 0x70, 0x24, 0x23, 0x9a, 0x7c, 0x56, 0x86, 0x64, 0x48, 0xff, - 0x90, 0x83, 0x53, 0x91, 0x36, 0x84, 0xad, 0x37, 0xa3, 0x8d, 0x64, 0x9a, 0x2a, 0x1a, 0xd8, 0x8c, - 0x6c, 0x09, 0xb7, 0xb2, 0x4c, 0xfa, 0x2d, 0x6d, 0x07, 0xff, 0x98, 0x03, 0x68, 0x0c, 0xbc, 0x23, - 0x81, 0x0c, 0x86, 0x67, 0x26, 0x17, 0x9d, 0x19, 0x5a, 0x67, 0xeb, 0xae, 0xfb, 0x9a, 0x38, 0xf2, - 0x4c, 0xe3, 0x97, 0x19, 0x86, 0x37, 0xf0, 0x8e, 0xe4, 0xb5, 0x10, 0xfd, 0x46, 0x97, 0x61, 0x81, - 0x3f, 0xdb, 0xd6, 0x74, 0xc3, 0x70, 0xb0, 0xeb, 0x8a, 0xfb, 0xa1, 0x0a, 0xa7, 0x36, 0x38, 0x91, - 0xb2, 0x99, 0x06, 0xb6, 0x3c, 0xd3, 0x3b, 0xd6, 0x3c, 0xf2, 0x12, 0x5b, 0xe2, 0x6c, 0x52, 0x91, - 0xd4, 0x3d, 0x4a, 0xa4, 0x6c, 0x0e, 0xee, 0x9a, 0xae, 0xe7, 0x48, 0x36, 0x79, 0x17, 0x21, 0xa8, - 0x8c, 0x8d, 0x4e, 0x4a, 0x75, 0x77, 0xd0, 0xeb, 0xf1, 0x21, 0x3e, 0xf9, 0xb4, 0x7f, 0x20, 0x3a, - 0x94, 0xcf, 0xf2, 0xe9, 0x60, 0xd0, 0x44, 0x77, 0xdf, 0x22, 0x08, 0xf3, 0x01, 0x2c, 0x85, 0xfa, - 0x20, 0xdc, 0x2a, 0x92, 0x44, 0xe6, 0xa2, 0x49, 0xa4, 0xf2, 0x14, 0x10, 0xc7, 0x1d, 0xbe, 0x61, - 0xbf, 0x95, 0xd3, 0x70, 0x2a, 0xa2, 0x48, 0xec, 0xc4, 0x37, 0xa0, 0x22, 0xde, 0xe8, 0x08, 0x47, - 0x39, 0x0b, 0x45, 0x1a, 0x51, 0x3b, 0xa6, 0x21, 0xef, 0x0c, 0xe7, 0x6c, 0x62, 0x6c, 0x9a, 0x86, - 0xa3, 0x7c, 0x0a, 0x15, 0x95, 0xb7, 0x23, 0x78, 0x9f, 0xc0, 0x82, 0x78, 0xd1, 0xa3, 0x45, 0x5e, - 0xca, 0xa5, 0xbd, 0xc4, 0x0e, 0x37, 0xa2, 0x56, 0xac, 0x70, 0x51, 0x31, 0xa0, 0xce, 0x53, 0x86, - 0x88, 0x7a, 0xd9, 0xd9, 0x27, 0x20, 0x7f, 0x83, 0x30, 0xb2, 0x95, 0xa8, 0x7c, 0xc5, 0x09, 0x17, - 0x95, 0x0b, 0x70, 0x2e, 0xb5, 0x15, 0x31, 0x12, 0x36, 0x54, 0x83, 0x0a, 0xc3, 0x94, 0x97, 0xa7, - 0xec, 0x52, 0x34, 0x17, 0xba, 0x14, 0x3d, 0xe3, 0x27, 0x89, 0x79, 0xb9, 0x89, 0xb1, 0x0c, 0x30, - 0x48, 0xf7, 0x0b, 0x59, 0xe9, 0xfe, 0x74, 0x24, 0xdd, 0x57, 0xda, 0xfe, 0x78, 0x8a, 0x63, 0xd8, - 0x63, 0x76, 0x5c, 0xe4, 0x6d, 0xcb, 0x80, 0xa8, 0x0c, 0xeb, 0x25, 0x67, 0x55, 0x43, 0x52, 0xca, - 0x75, 0xa8, 0x44, 0x43, 0x63, 0x28, 0xce, 0xe5, 0x12, 0x71, 0x6e, 0x21, 0x16, 0xe2, 0x3e, 0x8a, - 0x65, 0xc0, 0xd9, 0x63, 0x1c, 0xcb, 0x7f, 0x1f, 0x44, 0x82, 0xdd, 0x8d, 0x94, 0xfb, 0xcc, 0xdf, - 0x52, 0x9c, 0x5b, 0x16, 0xfb, 0xc1, 0x13, 0x97, 0xca, 0x8b, 0x4e, 0x2b, 0x97, 0xa0, 0xbc, 0x9f, - 0xf5, 0xcc, 0x7f, 0x5a, 0xbe, 0x1d, 0xb8, 0x03, 0xcb, 0x4f, 0xcc, 0x1e, 0x76, 0x8f, 0x5d, 0x0f, - 0xf7, 0x9b, 0x2c, 0x28, 0x1d, 0x9a, 0xd8, 0x41, 0xab, 0x00, 0xec, 0x08, 0x63, 0x13, 0xd3, 0x7f, - 0xfd, 0x1d, 0xa2, 0x28, 0xff, 0x95, 0x83, 0xc5, 0x40, 0x70, 0x9f, 0x1d, 0xdd, 0xce, 0x43, 0x89, - 0xf6, 0xd7, 0xf5, 0xf4, 0xbe, 0x2d, 0xef, 0xb3, 0x7c, 0x02, 0xba, 0x0f, 0x33, 0x87, 0xae, 0x84, - 0x8c, 0x52, 0x01, 0xf4, 0x34, 0x43, 0xd4, 0xe9, 0x43, 0xb7, 0x69, 0xa0, 0x8f, 0x01, 0x06, 0x2e, - 0x36, 0xc4, 0x1d, 0x56, 0x21, 0x2b, 0x5b, 0xd8, 0x0f, 0xdf, 0xf5, 0x52, 0x01, 0xfe, 0xec, 0xe0, - 0x01, 0x94, 0x4d, 0x8b, 0x18, 0x98, 0xdd, 0xf5, 0x1a, 0x02, 0x55, 0x1a, 0x21, 0x0e, 0x5c, 0x62, - 0xdf, 0xc5, 0x86, 0x82, 0xc5, 0x5e, 0x28, 0xc7, 0x57, 0x38, 0x4a, 0x0b, 0x96, 0x78, 0xd0, 0x3a, - 0xf4, 0x0d, 0x97, 0x1e, 0xbb, 0x36, 0xac, 0x77, 0x6c, 0xb4, 0xd4, 0xaa, 0x29, 0x52, 0x1b, 0x29, - 0xaa, 0xdc, 0x83, 0xd3, 0x91, 0x13, 0xd2, 0x04, 0x47, 0x16, 0x65, 0x37, 0x06, 0x94, 0x04, 0xee, - 0x2c, 0x60, 0x08, 0xe9, 0xcd, 0xa3, 0x60, 0x08, 0x97, 0xc3, 0x10, 0xae, 0xf2, 0x05, 0x9c, 0x8d, - 0x20, 0x3a, 0x11, 0x8b, 0x1e, 0xc4, 0x32, 0xb7, 0x2b, 0xa3, 0xb4, 0xc6, 0x52, 0xb8, 0xff, 0xc9, - 0xc1, 0x72, 0x1a, 0xc3, 0x09, 0x11, 0xc7, 0x9f, 0x64, 0x3c, 0x31, 0xbb, 0x3b, 0x9e, 0x59, 0xbf, - 0x13, 0xb4, 0x76, 0x0f, 0xea, 0x69, 0xe3, 0x99, 0x9c, 0xa5, 0xc2, 0x24, 0xb3, 0xf4, 0xf3, 0x42, - 0x08, 0x79, 0x6f, 0x78, 0x9e, 0x63, 0x1e, 0x0c, 0xa8, 0xcb, 0xbf, 0x75, 0x34, 0xab, 0xe9, 0xe3, - 0x32, 0x7c, 0x68, 0x6f, 0x0f, 0x11, 0x0f, 0xec, 0x48, 0xc5, 0x66, 0x3e, 0x8b, 0x62, 0x33, 0x1c, - 0x53, 0xbf, 0x33, 0x9e, 0xbe, 0xef, 0x2c, 0x00, 0xfa, 0xf3, 0x3c, 0x2c, 0x44, 0xa7, 0x08, 0x6d, - 0x03, 0xe8, 0xbe, 0xe5, 0x62, 0xa1, 0x5c, 0x1e, 0xab, 0x9b, 0x6a, 0x48, 0x10, 0xbd, 0x0f, 0x85, - 0x8e, 0x3d, 0x10, 0xb3, 0x96, 0x72, 0x19, 0xbc, 0x69, 0x0f, 0x78, 0x44, 0xa1, 0x6c, 0xf4, 0x4c, - 0xc5, 0xef, 0xf6, 0xb3, 0xa3, 0xe4, 0x0b, 0x56, 0xcf, 0x65, 0x04, 0x33, 0x7a, 0x06, 0x0b, 0xaf, - 0x1d, 0xd3, 0xd3, 0x0f, 0x7a, 0x58, 0xeb, 0xe9, 0xc7, 0xd8, 0x11, 0x51, 0x72, 0x8c, 0x40, 0x56, - 0x91, 0x82, 0xcf, 0xa9, 0x9c, 0xf2, 0x47, 0x50, 0x94, 0x16, 0x8d, 0xd8, 0x11, 0xf6, 0x60, 0x65, - 0x40, 0xd9, 0x34, 0xf6, 0x1c, 0xcc, 0xd2, 0x2d, 0xa2, 0xb9, 0x98, 0x6e, 0xe3, 0xf2, 0xa1, 0xfa, - 0x88, 0x10, 0xbd, 0xcc, 0xa4, 0x37, 0x89, 0x83, 0x5b, 0xba, 0x45, 0xda, 0x5c, 0x54, 0x79, 0x05, - 0xe5, 0x50, 0x07, 0x47, 0x98, 0xd0, 0x84, 0x25, 0x79, 0x15, 0xef, 0x62, 0x4f, 0x6c, 0x2f, 0x63, - 0x35, 0xbe, 0x28, 0xe4, 0xda, 0xd8, 0xe3, 0xcf, 0x27, 0x1e, 0xc0, 0x59, 0x15, 0x13, 0x1b, 0x5b, - 0xfe, 0x7c, 0x3e, 0x27, 0xdd, 0x09, 0x22, 0xf8, 0x79, 0xa8, 0xa7, 0xc9, 0xf3, 0xf8, 0x70, 0xe3, - 0x3c, 0x14, 0xe5, 0x6f, 0x36, 0xd1, 0x1c, 0x14, 0xf6, 0x36, 0x77, 0xab, 0x53, 0xf4, 0x63, 0x7f, - 0x6b, 0xb7, 0x9a, 0xbb, 0xd1, 0x87, 0x6a, 0xfc, 0x67, 0x8a, 0x68, 0x05, 0x4e, 0xed, 0xaa, 0x3b, - 0xbb, 0x8d, 0xa7, 0x8d, 0xbd, 0xe6, 0x4e, 0x4b, 0xdb, 0x55, 0x9b, 0x9f, 0x34, 0xf6, 0xb6, 0xab, - 0x53, 0x68, 0x0d, 0x2e, 0x84, 0x2b, 0x9e, 0xed, 0xb4, 0xf7, 0xb4, 0xbd, 0x1d, 0x6d, 0x73, 0xa7, - 0xb5, 0xd7, 0x68, 0xb6, 0xb6, 0xd5, 0x6a, 0x0e, 0x5d, 0x80, 0xb3, 0x61, 0x96, 0xc7, 0xcd, 0xad, - 0xa6, 0xba, 0xbd, 0x49, 0xbf, 0x1b, 0xcf, 0xab, 0xf9, 0x1b, 0xb7, 0xa1, 0x12, 0xf9, 0x55, 0x21, - 0x35, 0x64, 0x77, 0x67, 0xab, 0x3a, 0x85, 0x2a, 0x50, 0x0a, 0xeb, 0x29, 0xc2, 0x74, 0x6b, 0x67, - 0x6b, 0xbb, 0x9a, 0xbf, 0x71, 0x0f, 0x16, 0x63, 0xef, 0x51, 0xd1, 0x12, 0x54, 0xda, 0x8d, 0xd6, - 0xd6, 0xe3, 0x9d, 0xcf, 0x34, 0x75, 0xbb, 0xb1, 0xf5, 0x79, 0x75, 0x0a, 0x2d, 0x43, 0x55, 0x92, - 0x5a, 0x3b, 0x7b, 0x9c, 0x9a, 0xbb, 0xf1, 0x32, 0xb6, 0xb2, 0x30, 0x3a, 0x0d, 0x4b, 0x7e, 0x33, - 0xda, 0xa6, 0xba, 0xdd, 0xd8, 0xdb, 0xa6, 0xad, 0x47, 0xc8, 0xea, 0x7e, 0xab, 0xd5, 0x6c, 0x3d, - 0xad, 0xe6, 0xa8, 0xd6, 0x80, 0xbc, 0xfd, 0x59, 0x93, 0x32, 0xe7, 0xa3, 0xcc, 0xfb, 0xad, 0x1f, - 0xb6, 0x76, 0x3e, 0x6d, 0x55, 0x0b, 0x1b, 0x7f, 0xbf, 0x04, 0x0b, 0x32, 0xbd, 0xc3, 0x0e, 0x7b, - 0xcb, 0xb2, 0x0b, 0x73, 0xf2, 0x97, 0xbf, 0x29, 0x71, 0x39, 0xfa, 0x7b, 0xe5, 0xfa, 0xda, 0x10, - 0x0e, 0x91, 0x65, 0x4f, 0xa1, 0x03, 0x96, 0xf5, 0x86, 0xde, 0x07, 0x5f, 0x49, 0xcd, 0x31, 0x13, - 0x4f, 0x92, 0xeb, 0x57, 0x47, 0xf2, 0xf9, 0x6d, 0x60, 0x9a, 0xd8, 0x86, 0x7f, 0x00, 0x83, 0xae, - 0xa6, 0x65, 0xa4, 0x29, 0xbf, 0xb0, 0xa9, 0x5f, 0x1b, 0xcd, 0xe8, 0x37, 0xf3, 0x12, 0xaa, 0xf1, - 0x1f, 0xc3, 0xa0, 0x14, 0xc0, 0x34, 0xe3, 0x17, 0x37, 0xf5, 0x1b, 0xe3, 0xb0, 0x86, 0x1b, 0x4b, - 0xfc, 0x6c, 0xe4, 0xfa, 0x38, 0xef, 0xf0, 0x33, 0x1b, 0xcb, 0x7a, 0xb2, 0xcf, 0x07, 0x30, 0xfa, - 0xf6, 0x17, 0xa5, 0xfe, 0x46, 0x23, 0xe5, 0xe5, 0x78, 0xda, 0x00, 0xa6, 0x3f, 0x23, 0x56, 0xa6, - 0xd0, 0x11, 0x2c, 0xc6, 0x1e, 0x25, 0xa0, 0x14, 0xf1, 0xf4, 0xd7, 0x17, 0xf5, 0xeb, 0x63, 0x70, - 0x46, 0x3d, 0x22, 0xfc, 0x08, 0x21, 0xdd, 0x23, 0x52, 0x9e, 0x38, 0xa4, 0x7b, 0x44, 0xea, 0x7b, - 0x06, 0xe6, 0xdc, 0x91, 0xc7, 0x07, 0x69, 0xce, 0x9d, 0xf6, 0xe4, 0xa1, 0x7e, 0x75, 0x24, 0x5f, - 0x78, 0xd0, 0x62, 0x4f, 0x11, 0xd2, 0x06, 0x2d, 0xfd, 0xa9, 0x43, 0xfd, 0xfa, 0x18, 0x9c, 0x71, - 0x2f, 0x08, 0x2e, 0x36, 0xb3, 0xbc, 0x20, 0x71, 0x0d, 0x9f, 0xe5, 0x05, 0xc9, 0x3b, 0x52, 0xe1, - 0x05, 0xb1, 0x0b, 0xc9, 0x6b, 0x63, 0x5c, 0xa0, 0x64, 0x7b, 0x41, 0xfa, 0x55, 0x8b, 0x32, 0x85, - 0xfe, 0x38, 0x07, 0xb5, 0xac, 0xcb, 0x09, 0x94, 0x92, 0xd5, 0x8d, 0xb8, 0x4f, 0xa9, 0x6f, 0x4c, - 0x22, 0xe2, 0x5b, 0xf1, 0x25, 0xa0, 0xe4, 0x6e, 0x87, 0xde, 0x4b, 0x9b, 0x99, 0x8c, 0x3d, 0xb5, - 0xfe, 0xfe, 0x78, 0xcc, 0x7e, 0x93, 0x6d, 0x28, 0xca, 0xeb, 0x10, 0x94, 0x12, 0xa5, 0x63, 0x97, - 0x31, 0x75, 0x65, 0x18, 0x8b, 0xaf, 0xf4, 0x29, 0x4c, 0x53, 0x2a, 0xba, 0x90, 0xce, 0x2d, 0x95, - 0xad, 0x66, 0x55, 0xfb, 0x8a, 0x5e, 0xc0, 0x2c, 0xc7, 0xff, 0x51, 0x0a, 0xde, 0x10, 0xb9, 0xa5, - 0xa8, 0x5f, 0xcc, 0x66, 0xf0, 0xd5, 0xfd, 0x98, 0xff, 0x53, 0x08, 0x01, 0xed, 0xa3, 0x77, 0xd3, - 0x7f, 0x65, 0x1b, 0xbd, 0x49, 0xa8, 0x5f, 0x1e, 0xc1, 0x15, 0x5e, 0x14, 0xb1, 0x5c, 0xf7, 0xea, - 0xc8, 0x03, 0x4b, 0xf6, 0xa2, 0x48, 0x3f, 0x12, 0x71, 0x27, 0x49, 0x1e, 0x99, 0xd2, 0x9c, 0x24, - 0xf3, 0xa0, 0x9a, 0xe6, 0x24, 0xd9, 0xa7, 0x30, 0x65, 0x0a, 0x79, 0x70, 0x2a, 0x05, 0x20, 0x43, - 0xef, 0x67, 0x39, 0x79, 0x1a, 0x5a, 0x57, 0xbf, 0x39, 0x26, 0x77, 0x78, 0xf2, 0xc5, 0xa2, 0x7f, - 0x27, 0x1b, 0x35, 0xca, 0x9c, 0xfc, 0xf8, 0x12, 0xdf, 0xf8, 0xb7, 0x02, 0xcc, 0x73, 0xf0, 0x53, - 0x64, 0x30, 0x9f, 0x03, 0x04, 0xf7, 0x0e, 0xe8, 0x52, 0xfa, 0x98, 0x44, 0xee, 0x66, 0xea, 0xef, - 0x0e, 0x67, 0x0a, 0x3b, 0x5a, 0x08, 0xc3, 0x4f, 0x73, 0xb4, 0xe4, 0x55, 0x45, 0x9a, 0xa3, 0xa5, - 0x5c, 0x04, 0x28, 0x53, 0xe8, 0x13, 0x28, 0xf9, 0x60, 0x31, 0x4a, 0x03, 0x9b, 0x63, 0x68, 0x78, - 0xfd, 0xd2, 0x50, 0x9e, 0xb0, 0xd5, 0x21, 0x24, 0x38, 0xcd, 0xea, 0x24, 0xe2, 0x9c, 0x66, 0x75, - 0x1a, 0x9c, 0x1c, 0x8c, 0x09, 0xc7, 0x8b, 0x32, 0xc7, 0x24, 0x02, 0xd7, 0x65, 0x8e, 0x49, 0x14, - 0x74, 0x52, 0xa6, 0x1e, 0x5f, 0xf9, 0xf5, 0x57, 0xab, 0xb9, 0x7f, 0xfe, 0x6a, 0x75, 0xea, 0x67, - 0x5f, 0xaf, 0xe6, 0x7e, 0xfd, 0xf5, 0x6a, 0xee, 0x9f, 0xbe, 0x5e, 0xcd, 0xfd, 0xfb, 0xd7, 0xab, - 0xb9, 0x3f, 0xff, 0x8f, 0xd5, 0xa9, 0x1f, 0x15, 0xa5, 0xf4, 0xc1, 0x2c, 0xfb, 0xd7, 0x2e, 0x1f, - 0xfe, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x44, 0x4e, 0x61, 0x00, 0xa0, 0x47, 0x00, 0x00, + 0xb9, 0x05, 0x08, 0x72, 0xc8, 0x69, 0x83, 0x3d, 0xec, 0x25, 0x40, 0x4e, 0x8b, 0x7c, 0x5c, 0x32, + 0x13, 0xe4, 0x92, 0x43, 0x90, 0x3f, 0x20, 0x87, 0xa0, 0xbe, 0x9a, 0xfd, 0xc9, 0x0f, 0x8f, 0x77, + 0x67, 0xf6, 0xa4, 0xae, 0xd7, 0xef, 0xbd, 0x7a, 0xf5, 0xea, 0xf5, 0xab, 0x57, 0xbf, 0x2a, 0x0a, + 0x8a, 0x86, 0x63, 0xad, 0x3b, 0x2e, 0xf1, 0x09, 0xaa, 0xb8, 0x7d, 0xdb, 0xb7, 0x7a, 0x78, 0xfd, + 0xe5, 0x2d, 0xa3, 0xeb, 0x1c, 0x19, 0x1b, 0xb5, 0x1b, 0x1d, 0xcb, 0x3f, 0xea, 0x1f, 0xac, 0xb7, + 0x49, 0xef, 0x66, 0x87, 0x74, 0xc8, 0x4d, 0xc6, 0x78, 0xd0, 0x3f, 0x64, 0x2d, 0xd6, 0x60, 0x4f, + 0x5c, 0x81, 0x7a, 0x1d, 0x16, 0x3e, 0xc6, 0xae, 0x67, 0x11, 0x5b, 0xc3, 0x5f, 0xf6, 0xb1, 0xe7, + 0xa3, 0x2a, 0xcc, 0xbd, 0xe4, 0x94, 0xaa, 0x72, 0x41, 0xb9, 0x5a, 0xd4, 0x64, 0x53, 0xfd, 0x6b, + 0x05, 0x16, 0x03, 0x66, 0xcf, 0x21, 0xb6, 0x87, 0xb3, 0xb9, 0xd1, 0x1a, 0xcc, 0x0b, 0xe3, 0x74, + 0xdb, 0xe8, 0xe1, 0x6a, 0x8e, 0xbd, 0x2e, 0x09, 0x5a, 0xd3, 0xe8, 0x61, 0x74, 0x05, 0x16, 0x25, + 0x8b, 0x54, 0x92, 0x67, 0x5c, 0x0b, 0x82, 0x2c, 0x7a, 0x43, 0xeb, 0x70, 0x42, 0x32, 0x1a, 0x8e, + 0x15, 0x30, 0x4f, 0x33, 0xe6, 0x25, 0xf1, 0xaa, 0xee, 0x58, 0x82, 0x5f, 0xfd, 0x1c, 0x8a, 0x5b, + 0xcd, 0xd6, 0x26, 0xb1, 0x0f, 0xad, 0x0e, 0x35, 0xd1, 0xc3, 0x2e, 0x95, 0xa9, 0x2a, 0x17, 0xf2, + 0xd4, 0x44, 0xd1, 0x44, 0x35, 0x28, 0x78, 0xd8, 0x70, 0xdb, 0x47, 0xd8, 0xab, 0xe6, 0xd8, 0xab, + 0xa0, 0x4d, 0xa5, 0x88, 0xe3, 0x5b, 0xc4, 0xf6, 0xaa, 0x79, 0x2e, 0x25, 0x9a, 0xea, 0x2f, 0x14, + 0x28, 0xed, 0x12, 0xd7, 0x7f, 0x6e, 0x38, 0x8e, 0x65, 0x77, 0xd0, 0x6d, 0x28, 0x30, 0x5f, 0xb6, + 0x49, 0x97, 0xf9, 0x60, 0x61, 0xa3, 0xb6, 0x1e, 0x9f, 0x96, 0xf5, 0x5d, 0xc1, 0xa1, 0x05, 0xbc, + 0xe8, 0x12, 0x2c, 0xb4, 0x89, 0xed, 0x1b, 0x96, 0x8d, 0x5d, 0xdd, 0x21, 0xae, 0xcf, 0x5c, 0x34, + 0xa3, 0x95, 0x03, 0x2a, 0xed, 0x05, 0x9d, 0x81, 0xe2, 0x11, 0xf1, 0x7c, 0xce, 0x91, 0x67, 0x1c, + 0x05, 0x4a, 0x60, 0x2f, 0x57, 0x60, 0x8e, 0xbd, 0xb4, 0x1c, 0xe1, 0x8c, 0x59, 0xda, 0x6c, 0x38, + 0xea, 0x6f, 0x14, 0x98, 0x79, 0x4e, 0xfa, 0xb6, 0x1f, 0xeb, 0xc6, 0xf0, 0x8f, 0xc4, 0x44, 0x85, + 0xba, 0x31, 0xfc, 0xa3, 0x41, 0x37, 0x94, 0x83, 0xcf, 0x15, 0xef, 0x86, 0xbe, 0xac, 0x41, 0xc1, + 0xc5, 0x86, 0x49, 0xec, 0xee, 0x31, 0x33, 0xa1, 0xa0, 0x05, 0x6d, 0x3a, 0x89, 0x1e, 0xee, 0x5a, + 0x76, 0xff, 0xb5, 0xee, 0xe2, 0xae, 0x71, 0x80, 0xbb, 0xcc, 0x94, 0x82, 0xb6, 0x20, 0xc8, 0x1a, + 0xa7, 0xa2, 0x2d, 0x28, 0x39, 0x2e, 0x71, 0x8c, 0x8e, 0x41, 0xfd, 0x58, 0x9d, 0x61, 0xae, 0x52, + 0x93, 0xae, 0x62, 0x66, 0xef, 0x0e, 0x38, 0xb5, 0xb0, 0x98, 0xfa, 0xb7, 0x0a, 0x2c, 0xd2, 0xe0, + 0xf1, 0x1c, 0xa3, 0x8d, 0x77, 0xd8, 0x94, 0xa0, 0x3b, 0x30, 0x67, 0x63, 0xff, 0x15, 0x71, 0x5f, + 0x88, 0x09, 0x38, 0x9f, 0xd4, 0x1a, 0xc8, 0x3c, 0x27, 0x26, 0xd6, 0x24, 0x3f, 0xba, 0x05, 0x79, + 0xc7, 0x32, 0xd9, 0x80, 0xc7, 0x10, 0xa3, 0xbc, 0x54, 0xc4, 0x72, 0xda, 0xcc, 0x0f, 0xe3, 0x88, + 0x58, 0x4e, 0x5b, 0x55, 0x01, 0x1a, 0xb6, 0x7f, 0xfb, 0x7b, 0x1f, 0x1b, 0xdd, 0x3e, 0x46, 0xcb, + 0x30, 0xf3, 0x92, 0x3e, 0x30, 0x63, 0xf3, 0x1a, 0x6f, 0xa8, 0x5f, 0xe5, 0xe1, 0xcc, 0x33, 0xea, + 0xaf, 0x96, 0x61, 0x9b, 0x07, 0xe4, 0x75, 0x0b, 0xb7, 0xfb, 0xae, 0xe5, 0x1f, 0x6f, 0x12, 0xdb, + 0xc7, 0xaf, 0x7d, 0xd4, 0x84, 0x25, 0x5b, 0x6a, 0xd6, 0x65, 0x68, 0x52, 0x0d, 0xa5, 0x8d, 0xb5, + 0x21, 0x46, 0x70, 0x17, 0x69, 0x15, 0x3b, 0x4a, 0xf0, 0xd0, 0xd3, 0xc1, 0xbc, 0x49, 0x6d, 0x39, + 0xa6, 0x2d, 0x65, 0x48, 0xad, 0x6d, 0x66, 0x99, 0xd0, 0x25, 0x27, 0x56, 0x6a, 0xfa, 0x08, 0xe8, + 0x57, 0xad, 0x1b, 0x9e, 0xde, 0xf7, 0xb0, 0xcb, 0x1c, 0x53, 0xda, 0x38, 0x9b, 0xd4, 0x32, 0x70, + 0x81, 0x56, 0x74, 0xfb, 0x76, 0xdd, 0xdb, 0xf7, 0xb0, 0xcb, 0x92, 0x80, 0x88, 0x25, 0xdd, 0x25, + 0xc4, 0x3f, 0xf4, 0x64, 0xfc, 0x48, 0xb2, 0xc6, 0xa8, 0xe8, 0x26, 0x9c, 0xf0, 0xfa, 0x8e, 0xd3, + 0xc5, 0x3d, 0x6c, 0xfb, 0x46, 0x57, 0xef, 0xb8, 0xa4, 0xef, 0x78, 0xd5, 0x99, 0x0b, 0xf9, 0xab, + 0x79, 0x0d, 0x85, 0x5f, 0x3d, 0x61, 0x6f, 0xd0, 0x2a, 0x80, 0xe3, 0x5a, 0x2f, 0xad, 0x2e, 0xee, + 0x60, 0xb3, 0x3a, 0xcb, 0x94, 0x86, 0x28, 0xe8, 0x7d, 0x58, 0xf6, 0x70, 0xbb, 0x4d, 0x7a, 0x8e, + 0xee, 0xb8, 0xe4, 0xd0, 0xea, 0x62, 0x1e, 0xfd, 0x73, 0x2c, 0xfa, 0x91, 0x78, 0xb7, 0xcb, 0x5f, + 0xb1, 0xef, 0xe0, 0x3e, 0xcb, 0x69, 0x74, 0xa4, 0xac, 0xf3, 0x6a, 0x61, 0x8c, 0xa1, 0x02, 0x1b, + 0x2a, 0x33, 0x49, 0xfd, 0x45, 0x0e, 0x4e, 0x32, 0x4f, 0xee, 0x12, 0x53, 0x4c, 0xb3, 0x48, 0x52, + 0x17, 0xa1, 0xdc, 0x66, 0x3a, 0x75, 0xc7, 0x70, 0xb1, 0xed, 0x8b, 0x8f, 0x74, 0x9e, 0x13, 0x77, + 0x19, 0x0d, 0x7d, 0x0a, 0x15, 0x4f, 0x44, 0x85, 0xde, 0xe6, 0x61, 0x21, 0xe6, 0xec, 0x46, 0xd2, + 0x84, 0x21, 0xb1, 0xa4, 0x2d, 0x7a, 0x89, 0xe0, 0x9a, 0xf3, 0x8e, 0xbd, 0xb6, 0xdf, 0xe5, 0xd9, + 0xae, 0xb4, 0xf1, 0xbd, 0x0c, 0x85, 0x71, 0xc3, 0xd7, 0x5b, 0x5c, 0x6c, 0xdb, 0xf6, 0xdd, 0x63, + 0x4d, 0x2a, 0xa9, 0xdd, 0x85, 0xf9, 0xf0, 0x0b, 0x54, 0x81, 0xfc, 0x0b, 0x7c, 0x2c, 0x06, 0x45, + 0x1f, 0x07, 0x1f, 0x01, 0xcf, 0x35, 0xbc, 0x71, 0x37, 0xf7, 0x07, 0x8a, 0xea, 0x02, 0x1a, 0xf4, + 0xf2, 0x1c, 0xfb, 0x86, 0x69, 0xf8, 0x06, 0x42, 0x30, 0xcd, 0x96, 0x11, 0xae, 0x82, 0x3d, 0x53, + 0xad, 0x7d, 0xf1, 0xf1, 0x16, 0x35, 0xfa, 0x88, 0xce, 0x42, 0x31, 0x08, 0x74, 0xb1, 0x96, 0x0c, + 0x08, 0x34, 0xa7, 0x1b, 0xbe, 0x8f, 0x7b, 0x8e, 0xcf, 0x42, 0xac, 0xac, 0xc9, 0xa6, 0xfa, 0x3f, + 0xd3, 0x50, 0x49, 0xcc, 0xc9, 0x43, 0x28, 0xf4, 0x44, 0xf7, 0xe2, 0x43, 0x7b, 0x27, 0x25, 0xb1, + 0x27, 0x4c, 0xd5, 0x02, 0x29, 0x9a, 0x37, 0x69, 0x0e, 0x0d, 0xad, 0x7f, 0x41, 0x9b, 0xce, 0x78, + 0x97, 0x74, 0x74, 0xd3, 0x72, 0x71, 0xdb, 0x27, 0xee, 0xb1, 0x30, 0x77, 0xbe, 0x4b, 0x3a, 0x5b, + 0x92, 0x86, 0xee, 0x02, 0x98, 0xb6, 0x47, 0x27, 0xfb, 0xd0, 0xea, 0x30, 0xa3, 0x4b, 0x1b, 0x67, + 0x92, 0x46, 0x04, 0x8b, 0x9d, 0x56, 0x34, 0x6d, 0x4f, 0x98, 0xff, 0x08, 0xca, 0x74, 0xcd, 0xd0, + 0x7b, 0x7c, 0x9d, 0xe2, 0x5f, 0x4a, 0x69, 0xe3, 0x5c, 0xda, 0x18, 0x82, 0xd5, 0x4c, 0x9b, 0x77, + 0x06, 0x0d, 0x0f, 0x3d, 0x86, 0x59, 0x96, 0xbc, 0xbd, 0xea, 0x2c, 0x13, 0x5e, 0x1f, 0xe6, 0x00, + 0x11, 0x11, 0xcf, 0x98, 0x00, 0x0f, 0x08, 0x21, 0x8d, 0xf6, 0xa1, 0x64, 0xd8, 0x36, 0xf1, 0x0d, + 0x9e, 0x68, 0xe6, 0x98, 0xb2, 0x0f, 0xc6, 0x50, 0x56, 0x1f, 0x48, 0x71, 0x8d, 0x61, 0x3d, 0xe8, + 0x07, 0x30, 0xc3, 0x32, 0x91, 0xf8, 0x10, 0xaf, 0x8c, 0x19, 0xb4, 0x1a, 0x97, 0xaa, 0xdd, 0x81, + 0x52, 0xc8, 0xd8, 0x49, 0x82, 0xb4, 0x76, 0x1f, 0x2a, 0x71, 0xd3, 0x26, 0x0a, 0x72, 0x0d, 0x96, + 0xb5, 0xbe, 0x3d, 0x30, 0x4c, 0x56, 0x5f, 0x77, 0x61, 0x56, 0x4c, 0x36, 0x8f, 0x38, 0x75, 0xb4, + 0x8f, 0x34, 0x21, 0xa1, 0xfe, 0x00, 0x4e, 0xc6, 0x74, 0x8a, 0x22, 0xed, 0x1d, 0x58, 0x70, 0x88, + 0xa9, 0x7b, 0x9c, 0xac, 0x5b, 0xa6, 0xcc, 0x2e, 0x4e, 0xc0, 0xdb, 0x30, 0xa9, 0x78, 0xcb, 0x27, + 0x4e, 0xd2, 0xa6, 0xf1, 0xc4, 0xab, 0x70, 0x2a, 0x2e, 0xce, 0xbb, 0x57, 0x1f, 0xc0, 0x8a, 0x86, + 0x7b, 0xe4, 0x25, 0x7e, 0x53, 0xd5, 0x35, 0xa8, 0x26, 0x15, 0x08, 0xe5, 0x9f, 0xc1, 0xca, 0x80, + 0xda, 0xf2, 0x0d, 0xbf, 0xef, 0x4d, 0xa4, 0x5c, 0x54, 0xb0, 0x07, 0xc4, 0xe3, 0xb3, 0x54, 0xd0, + 0x64, 0x53, 0xbd, 0x16, 0x56, 0xdd, 0xe4, 0x05, 0x03, 0xef, 0x01, 0x2d, 0x40, 0xce, 0x72, 0x84, + 0xba, 0x9c, 0xe5, 0xa8, 0x4f, 0xa1, 0x18, 0xac, 0xb8, 0xe8, 0xde, 0xa0, 0x74, 0xcc, 0x8d, 0xbb, + 0x3e, 0x07, 0xd5, 0xe5, 0x5e, 0x62, 0x85, 0x10, 0x5d, 0xde, 0x03, 0x08, 0x32, 0x99, 0x5c, 0xf8, + 0xcf, 0x0c, 0x51, 0xac, 0x85, 0xd8, 0xd5, 0x7f, 0x8b, 0xe4, 0xb7, 0xd0, 0x20, 0xcc, 0x60, 0x10, + 0x66, 0x24, 0xdf, 0xe5, 0xde, 0x28, 0xdf, 0x7d, 0x08, 0x33, 0x9e, 0x6f, 0xf8, 0x58, 0x14, 0x47, + 0x6b, 0xc3, 0xc4, 0xa9, 0x11, 0x58, 0xe3, 0xfc, 0xe8, 0x1c, 0x40, 0xdb, 0xc5, 0x86, 0x8f, 0x4d, + 0xdd, 0xe0, 0xc9, 0x39, 0xaf, 0x15, 0x05, 0xa5, 0xee, 0xa3, 0xcd, 0x41, 0x81, 0x37, 0xc3, 0x0c, + 0xbb, 0x36, 0x4c, 0x73, 0x64, 0xaa, 0x06, 0xa5, 0x5e, 0x90, 0x2c, 0x66, 0xc7, 0x4c, 0x16, 0x42, + 0x01, 0x97, 0x0a, 0xa5, 0xc2, 0xb9, 0xd1, 0xa9, 0x90, 0x8b, 0x8e, 0x93, 0x0a, 0x0b, 0xa3, 0x53, + 0xa1, 0x50, 0x36, 0x34, 0x15, 0x7e, 0x9b, 0xb9, 0xec, 0x5f, 0x15, 0xa8, 0x26, 0xbf, 0x41, 0x91, + 0x7b, 0xee, 0xc2, 0xac, 0xc7, 0x28, 0xe3, 0x24, 0x34, 0x21, 0x2b, 0x24, 0xd0, 0x53, 0x98, 0xb6, + 0xec, 0x43, 0xc2, 0xf6, 0x66, 0xa9, 0x25, 0x49, 0x56, 0xaf, 0xeb, 0x0d, 0xfb, 0x90, 0x70, 0x27, + 0x31, 0x0d, 0xb5, 0x0f, 0xa1, 0x18, 0x90, 0x26, 0x1a, 0xdb, 0x0e, 0x2c, 0xc7, 0x42, 0x96, 0xd7, + 0xf0, 0x41, 0xa4, 0x2b, 0x93, 0x45, 0xba, 0xfa, 0xd3, 0x5c, 0xf8, 0x4b, 0x7c, 0x6c, 0x75, 0x7d, + 0xec, 0x26, 0xbe, 0xc4, 0x8f, 0xa4, 0x76, 0xfe, 0x19, 0x5e, 0x1e, 0xa9, 0x9d, 0x97, 0x9a, 0xe2, + 0x63, 0xfa, 0x02, 0x16, 0x58, 0xac, 0xe9, 0x1e, 0xee, 0xb2, 0x3a, 0x42, 0xd4, 0x74, 0xdf, 0x1f, + 0xa6, 0x86, 0x5b, 0xc2, 0x23, 0xb6, 0x25, 0xe4, 0xb8, 0x07, 0xcb, 0xdd, 0x30, 0xad, 0xf6, 0x10, + 0x50, 0x92, 0x69, 0x22, 0x9f, 0xb6, 0x68, 0x8a, 0xa3, 0x1b, 0xd8, 0x94, 0xc5, 0xef, 0x90, 0x99, + 0x31, 0x4e, 0xac, 0x70, 0x83, 0x35, 0x21, 0xa1, 0xfe, 0x2a, 0x0f, 0x30, 0x78, 0xf9, 0x7b, 0x94, + 0xdb, 0x1e, 0x06, 0x79, 0x85, 0xd7, 0x67, 0x57, 0x87, 0x29, 0x4e, 0xcd, 0x28, 0x3b, 0xd1, 0x8c, + 0xc2, 0x2b, 0xb5, 0x1b, 0x43, 0xd5, 0x7c, 0x67, 0x73, 0xc9, 0x33, 0x38, 0x15, 0x8f, 0x0d, 0x91, + 0x48, 0x36, 0x60, 0xc6, 0xf2, 0x71, 0x8f, 0x83, 0x38, 0xa9, 0x9b, 0xae, 0x90, 0x10, 0x67, 0x55, + 0xd7, 0xa0, 0xd8, 0xe8, 0x19, 0x1d, 0xdc, 0x72, 0x70, 0x9b, 0x76, 0x6a, 0xd1, 0x86, 0x30, 0x84, + 0x37, 0xd4, 0x0d, 0x28, 0xfc, 0x10, 0x1f, 0xf3, 0x8f, 0x7a, 0x4c, 0x43, 0xd5, 0xbf, 0xc8, 0xc1, + 0x0a, 0x5b, 0x2b, 0x36, 0x25, 0x84, 0xa2, 0x61, 0x8f, 0xf4, 0xdd, 0x36, 0xf6, 0xd8, 0x6c, 0x3b, + 0x7d, 0xdd, 0xc1, 0xae, 0x45, 0x4c, 0xb1, 0xc3, 0x2f, 0xb6, 0x9d, 0xfe, 0x2e, 0x23, 0xa0, 0x33, + 0x40, 0x1b, 0xfa, 0x97, 0x7d, 0x22, 0x02, 0x31, 0xaf, 0x15, 0xda, 0x4e, 0xff, 0x8f, 0x68, 0x5b, + 0xca, 0x7a, 0x47, 0x86, 0x8b, 0x3d, 0x16, 0x67, 0x5c, 0xb6, 0xc5, 0x08, 0xe8, 0x16, 0x9c, 0xec, + 0xe1, 0x1e, 0x71, 0x8f, 0xf5, 0xae, 0xd5, 0xb3, 0x7c, 0xdd, 0xb2, 0xf5, 0x83, 0x63, 0x1f, 0x7b, + 0x22, 0xa6, 0x10, 0x7f, 0xf9, 0x8c, 0xbe, 0x6b, 0xd8, 0x8f, 0xe8, 0x1b, 0xa4, 0x42, 0x99, 0x90, + 0x9e, 0xee, 0xb5, 0x89, 0x8b, 0x75, 0xc3, 0xfc, 0x09, 0x5b, 0x3e, 0xf3, 0x5a, 0x89, 0x90, 0x5e, + 0x8b, 0xd2, 0xea, 0xe6, 0x4f, 0xd0, 0x79, 0x28, 0xb5, 0x9d, 0xbe, 0x87, 0x7d, 0x9d, 0xfe, 0x61, + 0xab, 0x63, 0x51, 0x03, 0x4e, 0xda, 0x74, 0xfa, 0x5e, 0x88, 0xa1, 0x47, 0xfd, 0x3f, 0x17, 0x66, + 0x78, 0x4e, 0xdd, 0x6c, 0x40, 0x39, 0x82, 0x10, 0xd0, 0xcd, 0x1a, 0x83, 0x02, 0xc4, 0x66, 0x8d, + 0x3e, 0x53, 0x9a, 0x4b, 0xba, 0xd2, 0x93, 0xec, 0x99, 0xd2, 0xfc, 0x63, 0x47, 0xee, 0xd4, 0xd8, + 0x33, 0x75, 0x79, 0x17, 0xbf, 0x14, 0x28, 0x52, 0x51, 0xe3, 0x0d, 0xd5, 0x04, 0xd8, 0x34, 0x1c, + 0xe3, 0xc0, 0xea, 0x5a, 0xfe, 0x31, 0xba, 0x06, 0x15, 0xc3, 0x34, 0xf5, 0xb6, 0xa4, 0x58, 0x58, + 0x62, 0x7b, 0x8b, 0x86, 0x69, 0x6e, 0x86, 0xc8, 0xe8, 0x5d, 0x58, 0x32, 0x5d, 0xe2, 0x44, 0x79, + 0x39, 0xd8, 0x57, 0xa1, 0x2f, 0xc2, 0xcc, 0xea, 0xcf, 0x67, 0xe0, 0x5c, 0x74, 0x62, 0xe3, 0x28, + 0xcc, 0x43, 0x98, 0x8f, 0xf5, 0x9a, 0x81, 0x00, 0x0c, 0xac, 0xd5, 0x22, 0x12, 0x31, 0x54, 0x22, + 0x97, 0x40, 0x25, 0x52, 0x71, 0x9e, 0xfc, 0x5b, 0xc5, 0x79, 0xa6, 0xdf, 0x0a, 0xce, 0x33, 0x33, + 0x19, 0xce, 0x73, 0x99, 0x81, 0xbd, 0x52, 0x9a, 0x6d, 0x89, 0x79, 0xa8, 0x95, 0x03, 0x1e, 0x5b, + 0x82, 0xc2, 0x31, 0x3c, 0x68, 0x6e, 0x12, 0x3c, 0xa8, 0x90, 0x89, 0x07, 0xd1, 0xa8, 0x71, 0x1c, + 0xc3, 0xed, 0x11, 0x57, 0x02, 0x3e, 0xd5, 0x22, 0x33, 0x61, 0x51, 0xd2, 0x05, 0xd8, 0x93, 0x09, + 0x0d, 0x41, 0x26, 0x34, 0x74, 0x01, 0xe6, 0x6d, 0xa2, 0xdb, 0xf8, 0x95, 0x4e, 0xe7, 0xd2, 0xab, + 0x96, 0xf8, 0xc4, 0xda, 0xa4, 0x89, 0x5f, 0xed, 0x52, 0x4a, 0x02, 0x3c, 0x9a, 0x9f, 0x10, 0x3c, + 0xfa, 0x07, 0x05, 0x96, 0xa3, 0xc1, 0x29, 0x36, 0xfa, 0x4f, 0xa0, 0xe8, 0xca, 0xfc, 0x23, 0x02, + 0xf2, 0x5a, 0x46, 0x71, 0x9b, 0x4c, 0x58, 0xda, 0x40, 0x16, 0xfd, 0x28, 0x13, 0x5f, 0xba, 0x39, + 0x4a, 0xdf, 0x28, 0x84, 0x49, 0x6d, 0xc0, 0xf9, 0x4f, 0x2c, 0xdb, 0x24, 0xaf, 0xbc, 0xcc, 0x6f, + 0x2b, 0x25, 0x42, 0x94, 0x94, 0x08, 0x51, 0x7f, 0xa9, 0xc0, 0xa9, 0xb8, 0x2e, 0xe1, 0x8a, 0x46, + 0xd2, 0x15, 0xef, 0x26, 0x4d, 0x8f, 0x0b, 0xa7, 0x3a, 0xe3, 0x8b, 0x4c, 0x67, 0xdc, 0x1a, 0xad, + 0x71, 0xa4, 0x3b, 0xfe, 0x46, 0x81, 0xd3, 0x99, 0x66, 0xc4, 0x16, 0x02, 0x25, 0xbe, 0x10, 0x88, + 0x45, 0xa4, 0x4d, 0xfa, 0xb6, 0x1f, 0x5a, 0x44, 0x36, 0x19, 0xde, 0xcf, 0xb3, 0xb5, 0xde, 0x33, + 0x5e, 0x5b, 0xbd, 0x7e, 0x4f, 0xac, 0x22, 0x54, 0xdd, 0x73, 0x4e, 0x79, 0x83, 0x65, 0x44, 0xad, + 0xc3, 0x52, 0x60, 0xe5, 0x50, 0x44, 0x2e, 0x84, 0xb0, 0xe5, 0xa2, 0x08, 0x9b, 0x0d, 0xb3, 0x5b, + 0xf8, 0xa5, 0xd5, 0xc6, 0x6f, 0xe5, 0x40, 0xe2, 0x02, 0x94, 0x1c, 0xec, 0xf6, 0x2c, 0xcf, 0x0b, + 0xd2, 0x63, 0x51, 0x0b, 0x93, 0xd4, 0xff, 0x9a, 0x85, 0xc5, 0x78, 0x74, 0x3c, 0x48, 0x00, 0x7a, + 0x17, 0x53, 0x12, 0x77, 0x7c, 0xa0, 0xa1, 0x1a, 0xf0, 0x96, 0x2c, 0x21, 0x72, 0x59, 0xdb, 0xef, + 0xa0, 0xdc, 0x10, 0xf5, 0x05, 0xf5, 0x48, 0x9b, 0xf4, 0x7a, 0x86, 0x6d, 0xca, 0x73, 0x24, 0xd1, + 0xa4, 0xfe, 0x33, 0xdc, 0x0e, 0x75, 0x3b, 0x25, 0xb3, 0x67, 0x3a, 0x79, 0x74, 0xaf, 0x6a, 0xd9, + 0x0c, 0x18, 0x64, 0x29, 0xb6, 0xa8, 0x81, 0x20, 0x6d, 0x59, 0x2e, 0x5a, 0x87, 0x69, 0x6c, 0xbf, + 0x94, 0x45, 0x5e, 0xca, 0x41, 0x93, 0x2c, 0x66, 0x34, 0xc6, 0x87, 0x6e, 0xc2, 0x6c, 0x8f, 0x86, + 0x85, 0xdc, 0xb5, 0xae, 0x64, 0x9c, 0xb7, 0x68, 0x82, 0x0d, 0x6d, 0xc0, 0x9c, 0xc9, 0xe6, 0x49, + 0x6e, 0x4d, 0xab, 0x29, 0x70, 0x23, 0x63, 0xd0, 0x24, 0x23, 0xda, 0x0e, 0x4a, 0xd8, 0x62, 0x56, + 0xed, 0x19, 0x9b, 0x8a, 0xd4, 0x3a, 0x76, 0x2f, 0x5a, 0xc7, 0x02, 0xd3, 0xb5, 0x31, 0x5a, 0xd7, + 0x70, 0x8c, 0xf0, 0x34, 0x14, 0xba, 0xa4, 0xc3, 0xc3, 0xa8, 0xc4, 0x8f, 0x28, 0xbb, 0xa4, 0xc3, + 0xa2, 0x68, 0x99, 0x96, 0xf4, 0xa6, 0x65, 0xb3, 0x54, 0x5c, 0xd0, 0x78, 0x83, 0x7e, 0x7c, 0xec, + 0x41, 0x27, 0x76, 0x1b, 0x57, 0xcb, 0xec, 0x55, 0x91, 0x51, 0x76, 0xec, 0x36, 0x2b, 0x12, 0x7d, + 0xff, 0xb8, 0xba, 0xc0, 0xe8, 0xf4, 0x91, 0xee, 0xd6, 0x38, 0xb0, 0xb0, 0x98, 0xb5, 0x5b, 0x4b, + 0x4b, 0xdb, 0x12, 0x57, 0x78, 0x04, 0x73, 0xaf, 0x78, 0x22, 0xa8, 0x56, 0x98, 0xfc, 0xd5, 0xd1, + 0xe9, 0x45, 0x68, 0x90, 0x82, 0xdf, 0x66, 0xc1, 0xfe, 0x2b, 0x05, 0x4e, 0x6d, 0xb2, 0xcd, 0x4c, + 0x28, 0x8f, 0x4d, 0x82, 0xbf, 0xdd, 0x09, 0x10, 0xcf, 0x4c, 0xb0, 0x2c, 0x3e, 0x6e, 0x21, 0x80, + 0x1a, 0xb0, 0x20, 0x95, 0x0b, 0x15, 0xf9, 0xb1, 0x41, 0xd3, 0xb2, 0x17, 0x6e, 0xaa, 0x1f, 0xc1, + 0x4a, 0x62, 0x14, 0x62, 0xe3, 0xb1, 0x06, 0xf3, 0x83, 0x7c, 0x15, 0x0c, 0xa2, 0x14, 0xd0, 0x1a, + 0xa6, 0x7a, 0x17, 0x4e, 0xb6, 0x7c, 0xc3, 0xf5, 0x13, 0x2e, 0x18, 0x43, 0x96, 0xe1, 0xa6, 0x51, + 0x59, 0x01, 0x6d, 0xb6, 0x60, 0xb9, 0xe5, 0x13, 0xe7, 0x0d, 0x94, 0xd2, 0xac, 0x43, 0xc7, 0x4f, + 0xfa, 0x72, 0x7d, 0x90, 0x4d, 0x75, 0x85, 0xa3, 0xbc, 0xc9, 0xde, 0xee, 0xc1, 0x29, 0x0e, 0xb2, + 0xbe, 0xc9, 0x20, 0x4e, 0x4b, 0x88, 0x37, 0xa9, 0xf7, 0x39, 0x9c, 0x18, 0x2c, 0x8b, 0x03, 0x00, + 0xe5, 0x76, 0x14, 0x40, 0xb9, 0x30, 0x64, 0xd6, 0x23, 0xf8, 0xc9, 0x5f, 0xe5, 0x42, 0x79, 0x3d, + 0x03, 0x3e, 0xb9, 0x17, 0x85, 0x4f, 0x2e, 0x8d, 0xd2, 0x1d, 0x41, 0x4f, 0x92, 0x51, 0x9b, 0x4f, + 0x89, 0xda, 0xcf, 0x13, 0x18, 0xcb, 0x74, 0x16, 0x48, 0x15, 0xb3, 0xf6, 0x77, 0x02, 0xb1, 0x68, + 0x1c, 0x62, 0x09, 0xba, 0x0e, 0x30, 0xf1, 0x3b, 0x31, 0x88, 0x65, 0x6d, 0xa4, 0xbd, 0x01, 0xc2, + 0xf2, 0x77, 0xd3, 0x50, 0x0c, 0xde, 0x25, 0x7c, 0x9e, 0x74, 0x5b, 0x2e, 0xc5, 0x6d, 0xe1, 0x15, + 0x38, 0xff, 0x8d, 0x56, 0xe0, 0xe9, 0xb1, 0x57, 0xe0, 0x33, 0x50, 0x64, 0x0f, 0xba, 0x8b, 0x0f, + 0xc5, 0x8a, 0x5a, 0x60, 0x04, 0x0d, 0x1f, 0x0e, 0xc2, 0x70, 0x76, 0xa2, 0x30, 0x8c, 0x81, 0x3a, + 0x73, 0x71, 0x50, 0xe7, 0x41, 0xb0, 0x22, 0xf2, 0x45, 0xf4, 0xca, 0x10, 0xbd, 0xa9, 0x6b, 0x61, + 0x33, 0xba, 0x16, 0xf2, 0x75, 0xf5, 0xbd, 0x61, 0x5a, 0xbe, 0xb3, 0x90, 0xce, 0x3e, 0x87, 0x74, + 0xc2, 0xb1, 0x28, 0x32, 0xeb, 0x3d, 0x80, 0x20, 0x89, 0x48, 0x5c, 0xe7, 0xcc, 0x90, 0x31, 0x6a, + 0x21, 0x76, 0xaa, 0x36, 0x32, 0x35, 0x83, 0x73, 0x9f, 0xf1, 0xf2, 0x63, 0xc6, 0xa1, 0xcf, 0xff, + 0xcd, 0x84, 0xf2, 0x4b, 0xc6, 0x41, 0xc9, 0x83, 0x04, 0x98, 0x38, 0x61, 0x14, 0xdf, 0x8e, 0x62, + 0x89, 0x6f, 0x18, 0x75, 0x09, 0x28, 0x91, 0x55, 0x2e, 0x86, 0x2b, 0x5e, 0x73, 0xa8, 0xa7, 0x28, + 0x28, 0x75, 0xb6, 0x33, 0x38, 0xb4, 0x6c, 0xcb, 0x3b, 0xe2, 0xef, 0x67, 0xf9, 0xce, 0x40, 0x92, + 0xea, 0xec, 0xaa, 0x11, 0x7e, 0x6d, 0xf9, 0x7a, 0x9b, 0x98, 0x98, 0xc5, 0xf4, 0x8c, 0x56, 0xa0, + 0x84, 0x4d, 0x62, 0xe2, 0xc1, 0x97, 0x57, 0x78, 0xb3, 0x2f, 0xaf, 0x18, 0xfb, 0xf2, 0x4e, 0xc1, + 0xac, 0x8b, 0x0d, 0x8f, 0xd8, 0x62, 0x53, 0x2d, 0x5a, 0x74, 0x6a, 0x7a, 0xd8, 0xf3, 0x68, 0x4f, + 0xa2, 0x5c, 0x13, 0xcd, 0x50, 0x99, 0x39, 0x3f, 0xb2, 0xcc, 0x1c, 0x72, 0x00, 0x13, 0x2b, 0x33, + 0xcb, 0x23, 0xcb, 0xcc, 0x71, 0xce, 0x5f, 0x42, 0x85, 0xf6, 0xc2, 0x78, 0x85, 0x76, 0xb8, 0x2e, + 0x5d, 0x8c, 0xd4, 0xa5, 0xdf, 0xe6, 0xc7, 0xfa, 0x1b, 0x05, 0x56, 0x12, 0x9f, 0x95, 0xf8, 0x5c, + 0xef, 0xc4, 0x8e, 0x72, 0xd6, 0x46, 0xfa, 0x2c, 0x38, 0xc9, 0x79, 0x12, 0x39, 0xc9, 0xf9, 0x60, + 0xb4, 0xe0, 0x5b, 0x3f, 0xc8, 0xf9, 0x33, 0x05, 0xce, 0xef, 0x3b, 0x66, 0xac, 0xc2, 0x13, 0xdb, + 0xfe, 0xf1, 0x13, 0xc7, 0x03, 0x59, 0xeb, 0xe7, 0x26, 0xc5, 0x59, 0xb8, 0x9c, 0xaa, 0xc2, 0x85, + 0x6c, 0x33, 0x44, 0xc9, 0xf4, 0x63, 0x58, 0xdc, 0x7e, 0x8d, 0xdb, 0xad, 0x63, 0xbb, 0x3d, 0x81, + 0x69, 0x15, 0xc8, 0xb7, 0x7b, 0xa6, 0xc0, 0x36, 0xe9, 0x63, 0xb8, 0x0a, 0xcc, 0x47, 0xab, 0x40, + 0x1d, 0x2a, 0x83, 0x1e, 0xc4, 0xf4, 0x9e, 0xa2, 0xd3, 0x6b, 0x52, 0x66, 0xaa, 0x7c, 0x5e, 0x13, + 0x2d, 0x41, 0xc7, 0xae, 0xcb, 0xc6, 0xcc, 0xe9, 0xd8, 0x75, 0xa3, 0xd9, 0x22, 0x1f, 0xcd, 0x16, + 0xea, 0xcf, 0x15, 0x28, 0xd1, 0x1e, 0xbe, 0x91, 0xfd, 0x62, 0xab, 0x95, 0x1f, 0x6c, 0xb5, 0x82, + 0x1d, 0xdb, 0x74, 0x78, 0xc7, 0x36, 0xb0, 0x7c, 0x86, 0x91, 0x93, 0x96, 0xcf, 0x06, 0x74, 0xec, + 0xba, 0xea, 0x05, 0x98, 0xe7, 0xb6, 0x89, 0x91, 0x57, 0x20, 0xdf, 0x77, 0xbb, 0x32, 0x8e, 0xfa, + 0x6e, 0x57, 0xfd, 0x73, 0x05, 0xca, 0x75, 0xdf, 0x37, 0xda, 0x47, 0x13, 0x0c, 0x20, 0x30, 0x2e, + 0x17, 0x36, 0x2e, 0x39, 0x88, 0x81, 0xb9, 0xd3, 0x19, 0xe6, 0xce, 0x44, 0xcc, 0x55, 0x61, 0x41, + 0xda, 0x92, 0x69, 0x70, 0x13, 0xd0, 0x2e, 0x71, 0xfd, 0xc7, 0xc4, 0x7d, 0x65, 0xb8, 0xe6, 0x64, + 0x3b, 0x30, 0x04, 0xd3, 0xe2, 0xfa, 0x69, 0xfe, 0xea, 0x8c, 0xc6, 0x9e, 0xd5, 0x2b, 0x70, 0x22, + 0xa2, 0x2f, 0xb3, 0xe3, 0x87, 0x50, 0x62, 0x79, 0x5f, 0x94, 0xe2, 0xb7, 0xc2, 0x87, 0x2c, 0x63, + 0xad, 0x12, 0xea, 0x1f, 0xc2, 0x12, 0xad, 0x0f, 0x18, 0x3d, 0xf8, 0x14, 0xbf, 0x1f, 0xab, 0x53, + 0xcf, 0x65, 0x28, 0x8a, 0xd5, 0xa8, 0x7f, 0xaf, 0xc0, 0x0c, 0xa3, 0x27, 0xd6, 0xec, 0x33, 0x50, + 0x74, 0xb1, 0x43, 0x74, 0xdf, 0xe8, 0x04, 0x97, 0x7d, 0x29, 0x61, 0xcf, 0xe8, 0x78, 0xec, 0xae, + 0x32, 0x7d, 0x69, 0x5a, 0x1d, 0xec, 0xf9, 0xf2, 0xc6, 0x6f, 0x89, 0xd2, 0xb6, 0x38, 0x89, 0x3a, + 0xc9, 0xb3, 0xfe, 0x98, 0xd7, 0x9d, 0xd3, 0x1a, 0x7b, 0x46, 0xeb, 0xfc, 0xfe, 0xd9, 0x38, 0x40, + 0x38, 0xbb, 0x9d, 0x56, 0x83, 0x42, 0x0c, 0xfb, 0x0e, 0xda, 0xea, 0x36, 0xa0, 0xb0, 0x17, 0x84, + 0xbf, 0x6f, 0xc2, 0x2c, 0x73, 0x92, 0xac, 0x8e, 0x56, 0x32, 0xdc, 0xa0, 0x09, 0x36, 0xd5, 0x00, + 0xc4, 0x1d, 0x1c, 0xa9, 0x88, 0x26, 0x9f, 0x95, 0x21, 0x15, 0xd2, 0x3f, 0x2a, 0x70, 0x22, 0xd2, + 0x87, 0xb0, 0xf5, 0x46, 0xb4, 0x93, 0x4c, 0x53, 0x45, 0x07, 0x9b, 0x91, 0x25, 0xe1, 0x66, 0x96, + 0x49, 0xbf, 0xa5, 0xe5, 0xe0, 0x9f, 0x14, 0x80, 0x7a, 0xdf, 0x3f, 0x12, 0xc8, 0x60, 0x78, 0x66, + 0x94, 0xe8, 0xcc, 0xd0, 0x77, 0x8e, 0xe1, 0x79, 0xaf, 0x88, 0x2b, 0xf7, 0x34, 0x41, 0x9b, 0x61, + 0x78, 0x7d, 0xff, 0x48, 0x1e, 0x60, 0xd1, 0x67, 0x74, 0x09, 0x16, 0xf8, 0x05, 0x73, 0xdd, 0x30, + 0x4d, 0x17, 0x7b, 0x9e, 0x38, 0xc9, 0x2a, 0x73, 0x6a, 0x9d, 0x13, 0x29, 0x9b, 0x65, 0x62, 0xdb, + 0xb7, 0xfc, 0x63, 0xdd, 0x27, 0x2f, 0xb0, 0x2d, 0xf6, 0x26, 0x65, 0x49, 0xdd, 0xa3, 0x44, 0xca, + 0xe6, 0xe2, 0x8e, 0xe5, 0xf9, 0xae, 0x64, 0x93, 0xa7, 0x26, 0x82, 0xca, 0xd8, 0xe8, 0xa4, 0x54, + 0x76, 0xfb, 0xdd, 0x2e, 0x77, 0xf1, 0x9b, 0x4f, 0xfb, 0xfb, 0x62, 0x40, 0xb9, 0xac, 0x98, 0x1e, + 0x38, 0x4d, 0x0c, 0xf7, 0x2d, 0x82, 0x30, 0xef, 0xc3, 0x52, 0x68, 0x0c, 0x22, 0xac, 0x22, 0x45, + 0xa4, 0x12, 0x2d, 0x22, 0xd5, 0x27, 0x80, 0x38, 0xee, 0xf0, 0x0d, 0xc7, 0xad, 0x9e, 0x84, 0x13, + 0x11, 0x45, 0x62, 0x25, 0xbe, 0x0e, 0x65, 0x71, 0x9b, 0x48, 0x04, 0xca, 0x69, 0x28, 0xd0, 0x8c, + 0xda, 0xb6, 0x4c, 0x79, 0xba, 0x39, 0xe7, 0x10, 0x73, 0xd3, 0x32, 0x5d, 0xf5, 0x13, 0x28, 0x6b, + 0xbc, 0x1f, 0xc1, 0xfb, 0x18, 0x16, 0xc4, 0xdd, 0x23, 0x3d, 0x72, 0xa7, 0x2f, 0xed, 0xce, 0x78, + 0xb8, 0x13, 0xad, 0x6c, 0x87, 0x9b, 0xaa, 0x09, 0x35, 0x5e, 0x32, 0x44, 0xd4, 0xcb, 0xc1, 0x3e, + 0x06, 0xf9, 0x6b, 0x89, 0x91, 0xbd, 0x44, 0xe5, 0xcb, 0x6e, 0xb8, 0xa9, 0x9e, 0x83, 0x33, 0xa9, + 0xbd, 0x08, 0x4f, 0x38, 0x50, 0x19, 0xbc, 0x30, 0x2d, 0x79, 0xcc, 0xcb, 0x8e, 0x6f, 0x95, 0xd0, + 0xf1, 0xed, 0xa9, 0xa0, 0x48, 0xcc, 0xc9, 0x45, 0x8c, 0x55, 0x80, 0x83, 0x72, 0x3f, 0x9f, 0x55, + 0xee, 0x4f, 0x47, 0xca, 0x7d, 0xb5, 0x15, 0xf8, 0x53, 0x6c, 0xc3, 0x1e, 0xb1, 0xed, 0x22, 0xef, + 0x5b, 0x26, 0x44, 0x75, 0xd8, 0x28, 0x39, 0xab, 0x16, 0x92, 0x52, 0xaf, 0x41, 0x39, 0x9a, 0x1a, + 0x43, 0x79, 0x4e, 0x49, 0xe4, 0xb9, 0x85, 0x58, 0x8a, 0xfb, 0x30, 0x56, 0x01, 0x67, 0xfb, 0x38, + 0x56, 0xff, 0xde, 0x8f, 0x24, 0xbb, 0xeb, 0x29, 0x27, 0xaf, 0xbf, 0xa5, 0x3c, 0xb7, 0x2c, 0xd6, + 0x83, 0xc7, 0x1e, 0x95, 0x17, 0x83, 0x56, 0x2f, 0x42, 0x69, 0x3f, 0xeb, 0x07, 0x09, 0xd3, 0xf2, + 0x96, 0xc3, 0x6d, 0x58, 0x7e, 0x6c, 0x75, 0xb1, 0x77, 0xec, 0xf9, 0xb8, 0xd7, 0x60, 0x49, 0xe9, + 0xd0, 0xc2, 0x2e, 0x5a, 0x05, 0x60, 0x5b, 0x18, 0x87, 0x58, 0xc1, 0x3d, 0xf5, 0x10, 0x45, 0xfd, + 0x6f, 0x05, 0x16, 0x07, 0x82, 0xfb, 0x6c, 0xeb, 0x76, 0x16, 0x8a, 0x74, 0xbc, 0x9e, 0x6f, 0xf4, + 0x1c, 0x79, 0x9e, 0x15, 0x10, 0xd0, 0x3d, 0x98, 0x39, 0xf4, 0x24, 0x64, 0x94, 0x0a, 0xa0, 0xa7, + 0x19, 0xa2, 0x4d, 0x1f, 0x7a, 0x0d, 0x13, 0x7d, 0x04, 0xd0, 0xf7, 0xb0, 0x29, 0xce, 0xb0, 0xf2, + 0x59, 0xd5, 0xc2, 0x7e, 0xf8, 0x54, 0x9a, 0x0a, 0xf0, 0x0b, 0x12, 0xf7, 0xa1, 0x64, 0xd9, 0xc4, + 0xc4, 0xec, 0xcc, 0xd1, 0x14, 0xa8, 0xd2, 0x08, 0x71, 0xe0, 0x12, 0xfb, 0x1e, 0x36, 0x55, 0x2c, + 0xd6, 0x42, 0xe9, 0x5f, 0x11, 0x28, 0x4d, 0x58, 0xe2, 0x49, 0xeb, 0x30, 0x30, 0x5c, 0x46, 0xec, + 0xda, 0xb0, 0xd1, 0x31, 0x6f, 0x69, 0x15, 0x4b, 0x94, 0x36, 0x52, 0x54, 0xbd, 0x0b, 0x27, 0x23, + 0x3b, 0xa4, 0x09, 0xb6, 0x2c, 0xea, 0x6e, 0x0c, 0x28, 0x19, 0x84, 0xb3, 0x80, 0x21, 0x64, 0x34, + 0x8f, 0x82, 0x21, 0x3c, 0x0e, 0x43, 0x78, 0xea, 0xe7, 0x70, 0x3a, 0x82, 0xe8, 0x44, 0x2c, 0xba, + 0x1f, 0xab, 0xdc, 0x2e, 0x8f, 0xd2, 0x1a, 0x2b, 0xe1, 0xfe, 0x57, 0x81, 0xe5, 0x34, 0x86, 0x37, + 0x44, 0x1c, 0x7f, 0x9c, 0x71, 0x19, 0xee, 0xce, 0x78, 0x66, 0xfd, 0x4e, 0xd0, 0xda, 0x3d, 0xa8, + 0xa5, 0xf9, 0x33, 0x39, 0x4b, 0xf9, 0x49, 0x66, 0xe9, 0x67, 0xf9, 0x10, 0xf2, 0x5e, 0xf7, 0x7d, + 0xd7, 0x3a, 0xe8, 0xd3, 0x90, 0x7f, 0xeb, 0x68, 0x56, 0x23, 0xc0, 0x65, 0xb8, 0x6b, 0x6f, 0x0d, + 0x11, 0x1f, 0xd8, 0x91, 0x8a, 0xcd, 0x7c, 0x1a, 0xc5, 0x66, 0x38, 0xa6, 0x7e, 0x7b, 0x3c, 0x7d, + 0xdf, 0x59, 0x00, 0xf4, 0x67, 0x39, 0x58, 0x88, 0x4e, 0x11, 0xda, 0x06, 0x30, 0x02, 0xcb, 0xc5, + 0x87, 0x72, 0x69, 0xac, 0x61, 0x6a, 0x21, 0x41, 0xf4, 0x1e, 0xe4, 0xdb, 0x4e, 0x5f, 0xcc, 0x5a, + 0xca, 0x61, 0xf0, 0xa6, 0xd3, 0xe7, 0x19, 0x85, 0xb2, 0xd1, 0x3d, 0x15, 0x3f, 0xdb, 0xcf, 0xce, + 0x92, 0xcf, 0xd9, 0x7b, 0x2e, 0x23, 0x98, 0xd1, 0x53, 0x58, 0x78, 0xe5, 0x5a, 0xbe, 0x71, 0xd0, + 0xc5, 0x7a, 0xd7, 0x38, 0xc6, 0xae, 0xc8, 0x92, 0x63, 0x24, 0xb2, 0xb2, 0x14, 0x7c, 0x46, 0xe5, + 0xd4, 0x3f, 0x81, 0x82, 0xb4, 0x68, 0xc4, 0x8a, 0xb0, 0x07, 0x2b, 0x7d, 0xca, 0xa6, 0xb3, 0x8b, + 0x6b, 0xb6, 0x61, 0x13, 0xdd, 0xc3, 0x74, 0x19, 0x97, 0x57, 0xea, 0x47, 0xa4, 0xe8, 0x65, 0x26, + 0xbd, 0x49, 0x5c, 0xdc, 0x34, 0x6c, 0xd2, 0xe2, 0xa2, 0xea, 0x4b, 0x28, 0x85, 0x06, 0x38, 0xc2, + 0x84, 0x06, 0x2c, 0xc9, 0xa3, 0x78, 0x0f, 0xfb, 0x62, 0x79, 0x19, 0xab, 0xf3, 0x45, 0x21, 0xd7, + 0xc2, 0x3e, 0xbf, 0x3e, 0x71, 0x1f, 0x4e, 0x6b, 0x98, 0x38, 0xd8, 0x0e, 0xe6, 0xf3, 0x19, 0xe9, + 0x4c, 0x90, 0xc1, 0xcf, 0x42, 0x2d, 0x4d, 0x9e, 0xe7, 0x87, 0xeb, 0x67, 0xa1, 0x20, 0x7f, 0x5d, + 0x8a, 0xe6, 0x20, 0xbf, 0xb7, 0xb9, 0x5b, 0x99, 0xa2, 0x0f, 0xfb, 0x5b, 0xbb, 0x15, 0xe5, 0x7a, + 0x0f, 0x2a, 0xf1, 0x1f, 0x54, 0xa2, 0x15, 0x38, 0xb1, 0xab, 0xed, 0xec, 0xd6, 0x9f, 0xd4, 0xf7, + 0x1a, 0x3b, 0x4d, 0x7d, 0x57, 0x6b, 0x7c, 0x5c, 0xdf, 0xdb, 0xae, 0x4c, 0xa1, 0x35, 0x38, 0x17, + 0x7e, 0xf1, 0x74, 0xa7, 0xb5, 0xa7, 0xef, 0xed, 0xe8, 0x9b, 0x3b, 0xcd, 0xbd, 0x7a, 0xa3, 0xb9, + 0xad, 0x55, 0x14, 0x74, 0x0e, 0x4e, 0x87, 0x59, 0x1e, 0x35, 0xb6, 0x1a, 0xda, 0xf6, 0x26, 0x7d, + 0xae, 0x3f, 0xab, 0xe4, 0xae, 0xdf, 0x82, 0x72, 0xe4, 0xf7, 0x8f, 0xd4, 0x90, 0xdd, 0x9d, 0xad, + 0xca, 0x14, 0x2a, 0x43, 0x31, 0xac, 0xa7, 0x00, 0xd3, 0xcd, 0x9d, 0xad, 0xed, 0x4a, 0xee, 0xfa, + 0x5d, 0x58, 0x8c, 0xdd, 0x9c, 0x45, 0x4b, 0x50, 0x6e, 0xd5, 0x9b, 0x5b, 0x8f, 0x76, 0x3e, 0xd5, + 0xb5, 0xed, 0xfa, 0xd6, 0x67, 0x95, 0x29, 0xb4, 0x0c, 0x15, 0x49, 0x6a, 0xee, 0xec, 0x71, 0xaa, + 0x72, 0xfd, 0x45, 0xec, 0xcb, 0xc2, 0xe8, 0x24, 0x2c, 0x05, 0xdd, 0xe8, 0x9b, 0xda, 0x76, 0x7d, + 0x6f, 0x9b, 0xf6, 0x1e, 0x21, 0x6b, 0xfb, 0xcd, 0x66, 0xa3, 0xf9, 0xa4, 0xa2, 0x50, 0xad, 0x03, + 0xf2, 0xf6, 0xa7, 0x0d, 0xca, 0x9c, 0x8b, 0x32, 0xef, 0x37, 0x7f, 0xd8, 0xdc, 0xf9, 0xa4, 0x59, + 0xc9, 0x6f, 0xfc, 0x72, 0x09, 0x16, 0x64, 0x79, 0x87, 0x5d, 0x76, 0x97, 0x65, 0x17, 0xe6, 0xe4, + 0x6f, 0x94, 0x53, 0xf2, 0x72, 0xf4, 0x97, 0xd5, 0xb5, 0xb5, 0x21, 0x1c, 0xa2, 0xca, 0x9e, 0x42, + 0x07, 0xac, 0xea, 0x0d, 0xdd, 0x64, 0xbe, 0x9c, 0x5a, 0x63, 0x26, 0x2e, 0x4f, 0xd7, 0xae, 0x8c, + 0xe4, 0x0b, 0xfa, 0xc0, 0xb4, 0xb0, 0x0d, 0xff, 0x54, 0x07, 0x5d, 0x49, 0xab, 0x48, 0x53, 0x7e, + 0x0b, 0x54, 0xbb, 0x3a, 0x9a, 0x31, 0xe8, 0xe6, 0x05, 0x54, 0xe2, 0x3f, 0xdb, 0x41, 0x29, 0x80, + 0x69, 0xc6, 0x6f, 0x83, 0x6a, 0xd7, 0xc7, 0x61, 0x0d, 0x77, 0x96, 0xf8, 0x81, 0xcb, 0xb5, 0x71, + 0x7e, 0x31, 0x90, 0xd9, 0x59, 0xd6, 0x8f, 0x0b, 0xb8, 0x03, 0xa3, 0xb7, 0x94, 0x51, 0xea, 0xaf, + 0x49, 0x52, 0xee, 0xb8, 0xa7, 0x39, 0x30, 0xfd, 0xc2, 0xb3, 0x3a, 0x85, 0x8e, 0x60, 0x31, 0x76, + 0x29, 0x01, 0xa5, 0x88, 0xa7, 0xdf, 0xbe, 0xa8, 0x5d, 0x1b, 0x83, 0x33, 0x1a, 0x11, 0xe1, 0x4b, + 0x08, 0xe9, 0x11, 0x91, 0x72, 0xc5, 0x21, 0x3d, 0x22, 0x52, 0xef, 0x33, 0xb0, 0xe0, 0x8e, 0x5c, + 0x3e, 0x48, 0x0b, 0xee, 0xb4, 0x2b, 0x0f, 0xb5, 0x2b, 0x23, 0xf9, 0xc2, 0x4e, 0x8b, 0x5d, 0x45, + 0x48, 0x73, 0x5a, 0xfa, 0x55, 0x87, 0xda, 0xb5, 0x31, 0x38, 0xe3, 0x51, 0x30, 0x38, 0xd8, 0xcc, + 0x8a, 0x82, 0xc4, 0x31, 0x7c, 0x56, 0x14, 0x24, 0xcf, 0x48, 0x45, 0x14, 0xc4, 0x0e, 0x24, 0xaf, + 0x8e, 0x71, 0x80, 0x92, 0x1d, 0x05, 0xe9, 0x47, 0x2d, 0xea, 0x14, 0xfa, 0x53, 0x05, 0xaa, 0x59, + 0x87, 0x13, 0x28, 0xa5, 0xaa, 0x1b, 0x71, 0x9e, 0x52, 0xdb, 0x98, 0x44, 0x24, 0xb0, 0xe2, 0x4b, + 0x40, 0xc9, 0xd5, 0x0e, 0xbd, 0x9b, 0x36, 0x33, 0x19, 0x6b, 0x6a, 0xed, 0xbd, 0xf1, 0x98, 0x83, + 0x2e, 0x5b, 0x50, 0x90, 0xc7, 0x21, 0x28, 0x25, 0x4b, 0xc7, 0x0e, 0x63, 0x6a, 0xea, 0x30, 0x96, + 0x40, 0xe9, 0x13, 0x98, 0xa6, 0x54, 0x74, 0x2e, 0x9d, 0x5b, 0x2a, 0x5b, 0xcd, 0x7a, 0x1d, 0x28, + 0x7a, 0x0e, 0xb3, 0x1c, 0xff, 0x47, 0x29, 0x78, 0x43, 0xe4, 0x94, 0xa2, 0x76, 0x21, 0x9b, 0x21, + 0x50, 0xf7, 0x05, 0xff, 0xf7, 0x15, 0x02, 0xda, 0x47, 0xef, 0xa4, 0xff, 0x1e, 0x38, 0x7a, 0x92, + 0x50, 0xbb, 0x34, 0x82, 0x2b, 0xfc, 0x51, 0xc4, 0x6a, 0xdd, 0x2b, 0x23, 0x37, 0x2c, 0xd9, 0x1f, + 0x45, 0xfa, 0x96, 0x88, 0x07, 0x49, 0x72, 0xcb, 0x94, 0x16, 0x24, 0x99, 0x1b, 0xd5, 0xb4, 0x20, + 0xc9, 0xde, 0x85, 0xa9, 0x53, 0xc8, 0x87, 0x13, 0x29, 0x00, 0x19, 0x7a, 0x2f, 0x2b, 0xc8, 0xd3, + 0xd0, 0xba, 0xda, 0x8d, 0x31, 0xb9, 0xc3, 0x93, 0x2f, 0x3e, 0xfa, 0xf3, 0xd9, 0xa8, 0x51, 0xe6, + 0xe4, 0xc7, 0x3f, 0xf1, 0x8d, 0x7f, 0xcf, 0xc3, 0x3c, 0x07, 0x3f, 0x45, 0x05, 0xf3, 0x19, 0xc0, + 0xe0, 0xdc, 0x01, 0x5d, 0x4c, 0xf7, 0x49, 0xe4, 0x6c, 0xa6, 0xf6, 0xce, 0x70, 0xa6, 0x70, 0xa0, + 0x85, 0x30, 0xfc, 0xb4, 0x40, 0x4b, 0x1e, 0x55, 0xa4, 0x05, 0x5a, 0xca, 0x41, 0x80, 0x3a, 0x85, + 0x3e, 0x86, 0x62, 0x00, 0x16, 0xa3, 0x34, 0xb0, 0x39, 0x86, 0x86, 0xd7, 0x2e, 0x0e, 0xe5, 0x09, + 0x5b, 0x1d, 0x42, 0x82, 0xd3, 0xac, 0x4e, 0x22, 0xce, 0x69, 0x56, 0xa7, 0xc1, 0xc9, 0x03, 0x9f, + 0x70, 0xbc, 0x28, 0xd3, 0x27, 0x11, 0xb8, 0x2e, 0xd3, 0x27, 0x51, 0xd0, 0x49, 0x9d, 0x7a, 0x74, + 0xf9, 0xd7, 0x5f, 0xad, 0x2a, 0xff, 0xf2, 0xd5, 0xea, 0xd4, 0x4f, 0xbf, 0x5e, 0x55, 0x7e, 0xfd, + 0xf5, 0xaa, 0xf2, 0xcf, 0x5f, 0xaf, 0x2a, 0xff, 0xf1, 0xf5, 0xaa, 0xf2, 0x97, 0xff, 0xb9, 0x3a, + 0xf5, 0xa3, 0x82, 0x94, 0x3e, 0x98, 0x65, 0xff, 0x84, 0xe6, 0x83, 0xff, 0x0f, 0x00, 0x00, 0xff, + 0xff, 0xb5, 0x80, 0xdd, 0xf4, 0x4a, 0x48, 0x00, 0x00, } diff --git a/pkg/kubelet/apis/cri/runtime/v1alpha2/api.proto b/pkg/kubelet/apis/cri/runtime/v1alpha2/api.proto index 854b8f61282..ab4351374b3 100644 --- a/pkg/kubelet/apis/cri/runtime/v1alpha2/api.proto +++ b/pkg/kubelet/apis/cri/runtime/v1alpha2/api.proto @@ -597,11 +597,21 @@ message LinuxContainerConfig { LinuxContainerSecurityContext security_context = 2; } +// WindowsContainerSecurityContext holds windows security configuration that will be applied to a container. +message WindowsContainerSecurityContext { + // User name to run the container process as. If specified, the user MUST + // exist in the container image and be resolved there by the runtime; + // otherwise, the runtime MUST return error. + string run_as_username = 1; +} + // WindowsContainerConfig contains platform-specific configuration for // Windows-based containers. message WindowsContainerConfig { // Resources specification for the container. WindowsContainerResources resources = 1; + // WindowsContainerSecurityContext configuration for the container. + WindowsContainerSecurityContext security_context = 2; } // WindowsContainerResources specifies Windows specific configuration for diff --git a/pkg/kubelet/apis/kubeletconfig/types.go b/pkg/kubelet/apis/kubeletconfig/types.go index 7a2c75055b0..4b220981f36 100644 --- a/pkg/kubelet/apis/kubeletconfig/types.go +++ b/pkg/kubelet/apis/kubeletconfig/types.go @@ -260,7 +260,7 @@ type KubeletConfiguration struct { // Maximum number of container log files that can be present for a container. ContainerLogMaxFiles int32 - /* following flags are meant for Node Allocatable */ + /* the following fields are meant for Node Allocatable */ // A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=150G) pairs // that describe resources reserved for non-kubernetes components. diff --git a/pkg/kubelet/apis/kubeletconfig/v1beta1/types.go b/pkg/kubelet/apis/kubeletconfig/v1beta1/types.go index 00b3a837e9b..2ec949efe4f 100644 --- a/pkg/kubelet/apis/kubeletconfig/v1beta1/types.go +++ b/pkg/kubelet/apis/kubeletconfig/v1beta1/types.go @@ -47,64 +47,96 @@ type KubeletConfiguration struct { // staticPodPath is the path to the directory containing local (static) pods to // run, or the path to a single static pod file. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // the set of static pods specified at the new path may be different than the + // ones the Kubelet initially started with, and this may disrupt your node. // Default: "" // +optional StaticPodPath string `json:"staticPodPath,omitempty"` // syncFrequency is the max period between synchronizing running // containers and config. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // shortening this duration may have a negative performance impact, especially + // as the number of Pods on the node increases. Alternatively, increasing this + // duration will result in longer refresh times for ConfigMaps and Secrets. // Default: "1m" // +optional SyncFrequency metav1.Duration `json:"syncFrequency,omitempty"` // fileCheckFrequency is the duration between checking config files for // new data + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // shortening the duration will cause the Kubelet to reload local Static Pod + // configurations more frequently, which may have a negative performance impact. // Default: "20s" // +optional FileCheckFrequency metav1.Duration `json:"fileCheckFrequency,omitempty"` // httpCheckFrequency is the duration between checking http for new data + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // shortening the duration will cause the Kubelet to poll staticPodURL more + // frequently, which may have a negative performance impact. // Default: "20s" // +optional HTTPCheckFrequency metav1.Duration `json:"httpCheckFrequency,omitempty"` // staticPodURL is the URL for accessing static pods to run + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // the set of static pods specified at the new URL may be different than the + // ones the Kubelet initially started with, and this may disrupt your node. // Default: "" // +optional StaticPodURL string `json:"staticPodURL,omitempty"` // staticPodURLHeader is a map of slices with HTTP headers to use when accessing the podURL + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt the ability to read the latest set of static pods from StaticPodURL. // Default: nil // +optional StaticPodURLHeader map[string][]string `json:"staticPodURLHeader,omitempty"` // address is the IP address for the Kubelet to serve on (set to 0.0.0.0 // for all interfaces). + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: "0.0.0.0" // +optional Address string `json:"address,omitempty"` // port is the port for the Kubelet to serve on. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: 10250 // +optional Port int32 `json:"port,omitempty"` // readOnlyPort is the read-only port for the Kubelet to serve on with // no authentication/authorization. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: 0 (disabled) // +optional ReadOnlyPort int32 `json:"readOnlyPort,omitempty"` - // tlsCertFile is the file containing x509 Certificate for HTTPS. (CA cert, + // tlsCertFile is the file containing x509 Certificate for HTTPS. (CA cert, // if any, concatenated after server cert). If tlsCertFile and // tlsPrivateKeyFile are not provided, a self-signed certificate // and key are generated for the public address and saved to the directory // passed to the Kubelet's --cert-dir flag. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: "" // +optional TLSCertFile string `json:"tlsCertFile,omitempty"` // tlsPrivateKeyFile is the file containing x509 private key matching tlsCertFile + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: "" // +optional TLSPrivateKeyFile string `json:"tlsPrivateKeyFile,omitempty"` // TLSCipherSuites is the list of allowed cipher suites for the server. // Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: nil // +optional TLSCipherSuites []string `json:"tlsCipherSuites,omitempty"` // TLSMinVersion is the minimum TLS version supported. // Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: "" // +optional TLSMinVersion string `json:"tlsMinVersion,omitempty"` @@ -112,6 +144,9 @@ type KubeletConfiguration struct { // new certificate from the certificates.k8s.io API. This requires an approver to approve the // certificate signing requests. The RotateKubeletClientCertificate feature // must be enabled. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // disabling it may disrupt the Kubelet's ability to authenticate with the API server + // after the current certificate expires. // Default: false // +optional RotateCertificates bool `json:"rotateCertificates,omitempty"` @@ -120,10 +155,16 @@ type KubeletConfiguration struct { // the certificates.k8s.io API. This requires an approver to approve the // certificate signing requests. The RotateKubeletServerCertificate feature // must be enabled. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // disabling it will stop the renewal of Kubelet server certificates, which can + // disrupt components that interact with the Kubelet server in the long term, + // due to certificate expiration. // Default: false // +optional ServerTLSBootstrap bool `json:"serverTLSBootstrap,omitempty"` // authentication specifies how requests to the Kubelet's server are authenticated + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Defaults: // anonymous: // enabled: false @@ -133,6 +174,8 @@ type KubeletConfiguration struct { // +optional Authentication KubeletAuthentication `json:"authentication"` // authorization specifies how requests to the Kubelet's server are authorized + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Defaults: // mode: Webhook // webhook: @@ -142,136 +185,202 @@ type KubeletConfiguration struct { Authorization KubeletAuthorization `json:"authorization"` // registryPullQPS is the limit of registry pulls per second. // Set to 0 for no limit. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic produced + // by image pulls. // Default: 5 // +optional RegistryPullQPS *int32 `json:"registryPullQPS,omitempty"` // registryBurst is the maximum size of bursty pulls, temporarily allows // pulls to burst to this number, while still not exceeding registryPullQPS. // Only used if registryPullQPS > 0. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic produced + // by image pulls. // Default: 10 // +optional RegistryBurst int32 `json:"registryBurst,omitempty"` // eventRecordQPS is the maximum event creations per second. If 0, there // is no limit enforced. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic produced by + // event creations. // Default: 5 // +optional EventRecordQPS *int32 `json:"eventRecordQPS,omitempty"` // eventBurst is the maximum size of a burst of event creations, temporarily // allows event creations to burst to this number, while still not exceeding // eventRecordQPS. Only used if eventRecordQPS > 0. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic produced by + // event creations. // Default: 10 // +optional EventBurst int32 `json:"eventBurst,omitempty"` - // enableDebuggingHandlers enables server endpoints for log collection - // and local running of containers and commands + // enableDebuggingHandlers enables server endpoints for log access + // and local running of containers and commands, including the exec, + // attach, logs, and portforward features. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // disabling it may disrupt components that interact with the Kubelet server. // Default: true // +optional EnableDebuggingHandlers *bool `json:"enableDebuggingHandlers,omitempty"` // enableContentionProfiling enables lock contention profiling, if enableDebuggingHandlers is true. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // enabling it may carry a performance impact. // Default: false // +optional EnableContentionProfiling bool `json:"enableContentionProfiling,omitempty"` // healthzPort is the port of the localhost healthz endpoint (set to 0 to disable) + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that monitor Kubelet health. // Default: 10248 // +optional HealthzPort *int32 `json:"healthzPort,omitempty"` // healthzBindAddress is the IP address for the healthz server to serve on + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that monitor Kubelet health. // Default: "127.0.0.1" // +optional HealthzBindAddress string `json:"healthzBindAddress,omitempty"` // oomScoreAdj is The oom-score-adj value for kubelet process. Values // must be within the range [-1000, 1000]. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact the stability of nodes under memory pressure. // Default: -999 // +optional OOMScoreAdj *int32 `json:"oomScoreAdj,omitempty"` // clusterDomain is the DNS domain for this cluster. If set, kubelet will // configure all containers to search this domain in addition to the // host's search domains. + // Dynamic Kubelet Config (beta): Dynamically updating this field is not recommended, + // as it should be kept in sync with the rest of the cluster. // Default: "" // +optional ClusterDomain string `json:"clusterDomain,omitempty"` // clusterDNS is a list of IP addresses for the cluster DNS server. If set, // kubelet will configure all containers to use this for DNS resolution // instead of the host's DNS servers. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // changes will only take effect on Pods created after the update. Draining + // the node is recommended before changing this field. // Default: nil // +optional ClusterDNS []string `json:"clusterDNS,omitempty"` // streamingConnectionIdleTimeout is the maximum time a streaming connection // can be idle before the connection is automatically closed. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact components that rely on infrequent updates over streaming + // connections to the Kubelet server. // Default: "4h" // +optional StreamingConnectionIdleTimeout metav1.Duration `json:"streamingConnectionIdleTimeout,omitempty"` // nodeStatusUpdateFrequency is the frequency that kubelet posts node // status to master. Note: be cautious when changing the constant, it // must work with nodeMonitorGracePeriod in nodecontroller. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact node scalability, and also that the node controller's + // nodeMonitorGracePeriod must be set to N*NodeStatusUpdateFrequency, + // where N is the number of retries before the node controller marks + // the node unhealthy. // Default: "10s" // +optional NodeStatusUpdateFrequency metav1.Duration `json:"nodeStatusUpdateFrequency,omitempty"` // imageMinimumGCAge is the minimum age for an unused image before it is // garbage collected. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay garbage collection, and may change the image overhead + // on the node. // Default: "2m" // +optional ImageMinimumGCAge metav1.Duration `json:"imageMinimumGCAge,omitempty"` // imageGCHighThresholdPercent is the percent of disk usage after which // image garbage collection is always run. The percent is calculated as // this field value out of 100. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay garbage collection, and may change the image overhead + // on the node. // Default: 85 // +optional ImageGCHighThresholdPercent *int32 `json:"imageGCHighThresholdPercent,omitempty"` // imageGCLowThresholdPercent is the percent of disk usage before which // image garbage collection is never run. Lowest disk usage to garbage // collect to. The percent is calculated as this field value out of 100. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay garbage collection, and may change the image overhead + // on the node. // Default: 80 // +optional ImageGCLowThresholdPercent *int32 `json:"imageGCLowThresholdPercent,omitempty"` // How frequently to calculate and cache volume disk usage for all pods + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // shortening the period may carry a performance impact. // Default: "1m" // +optional VolumeStatsAggPeriod metav1.Duration `json:"volumeStatsAggPeriod,omitempty"` // kubeletCgroups is the absolute name of cgroups to isolate the kubelet in + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "" // +optional KubeletCgroups string `json:"kubeletCgroups,omitempty"` // systemCgroups is absolute name of cgroups in which to place // all non-kernel processes that are not already in a container. Empty // for no container. Rolling back the flag requires a reboot. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "" // +optional SystemCgroups string `json:"systemCgroups,omitempty"` // cgroupRoot is the root cgroup to use for pods. This is handled by the // container runtime on a best effort basis. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "" // +optional CgroupRoot string `json:"cgroupRoot,omitempty"` // Enable QoS based Cgroup hierarchy: top level cgroups for QoS Classes // And all Burstable and BestEffort pods are brought up under their // specific top level QoS cgroup. - // +optional + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: true // +optional CgroupsPerQOS *bool `json:"cgroupsPerQOS,omitempty"` // driver that the kubelet uses to manipulate cgroups on the host (cgroupfs or systemd) - // +optional + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "cgroupfs" // +optional CgroupDriver string `json:"cgroupDriver,omitempty"` // CPUManagerPolicy is the name of the policy to use. // Requires the CPUManager feature gate to be enabled. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "none" // +optional CPUManagerPolicy string `json:"cpuManagerPolicy,omitempty"` // CPU Manager reconciliation period. // Requires the CPUManager feature gate to be enabled. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // shortening the period may carry a performance impact. // Default: "10s" // +optional CPUManagerReconcilePeriod metav1.Duration `json:"cpuManagerReconcilePeriod,omitempty"` - // Map of QoS resource reservation percentages (memory only for now). + // qosReserved is a set of resource name to percentage pairs that specify + // the minimum percentage of a resource reserved for exclusive use by the + // guaranteed QoS tier. + // Currently supported resources: "memory" // Requires the QOSReserved feature gate to be enabled. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: nil // +optional QOSReserved map[string]string `json:"qosReserved,omitempty"` // runtimeRequestTimeout is the timeout for all runtime requests except long running // requests - pull, logs, exec and attach. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: "2m" // +optional RuntimeRequestTimeout metav1.Duration `json:"runtimeRequestTimeout,omitempty"` @@ -284,46 +393,74 @@ type KubeletConfiguration struct { // "none": do nothing. // Generally, one must set --hairpin-mode=hairpin-veth to achieve hairpin NAT, // because promiscuous-bridge assumes the existence of a container bridge named cbr0. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may require a node reboot, depending on the network plugin. // Default: "promiscuous-bridge" // +optional HairpinMode string `json:"hairpinMode,omitempty"` // maxPods is the number of pods that can run on this Kubelet. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // changes may cause Pods to fail admission on Kubelet restart, and may change + // the value reported in Node.Status.Capacity[v1.ResourcePods], thus affecting + // future scheduling decisions. Increasing this value may also decrease performance, + // as more Pods can be packed into a single node. // Default: 110 // +optional MaxPods int32 `json:"maxPods,omitempty"` // The CIDR to use for pod IP addresses, only used in standalone mode. // In cluster mode, this is obtained from the master. + // Dynamic Kubelet Config (beta): This field should always be set to the empty default. + // It should only set for standalone Kubelets, which cannot use Dynamic Kubelet Config. // Default: "" // +optional PodCIDR string `json:"podCIDR,omitempty"` // PodPidsLimit is the maximum number of pids in any pod. // Requires the SupportPodPidsLimit feature gate to be enabled. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // lowering it may prevent container processes from forking after the change. // Default: -1 // +optional PodPidsLimit *int64 `json:"podPidsLimit,omitempty"` // ResolverConfig is the resolver configuration file used as the basis // for the container DNS resolution configuration. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // changes will only take effect on Pods created after the update. Draining + // the node is recommended before changing this field. // Default: "/etc/resolv.conf" // +optional ResolverConfig string `json:"resolvConf,omitempty"` // cpuCFSQuota enables CPU CFS quota enforcement for containers that // specify CPU limits. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // disabling it may reduce node stability. // Default: true // +optional CPUCFSQuota *bool `json:"cpuCFSQuota,omitempty"` // maxOpenFiles is Number of files that can be opened by Kubelet process. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact the ability of the Kubelet to interact with the node's filesystem. // Default: 1000000 // +optional MaxOpenFiles int64 `json:"maxOpenFiles,omitempty"` // contentType is contentType of requests sent to apiserver. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact the ability for the Kubelet to communicate with the API server. + // If the Kubelet loses contact with the API server due to a change to this field, + // the change cannot be reverted via dynamic Kubelet config. // Default: "application/vnd.kubernetes.protobuf" // +optional ContentType string `json:"contentType,omitempty"` // kubeAPIQPS is the QPS to use while talking with kubernetes apiserver + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic the Kubelet + // sends to the API server. // Default: 5 // +optional KubeAPIQPS *int32 `json:"kubeAPIQPS,omitempty"` // kubeAPIBurst is the burst to allow while talking with kubernetes apiserver + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic the Kubelet + // sends to the API server. // Default: 10 // +optional KubeAPIBurst int32 `json:"kubeAPIBurst,omitempty"` @@ -331,11 +468,15 @@ type KubeletConfiguration struct { // at a time. We recommend *not* changing the default value on nodes that // run docker daemon with version < 1.9 or an Aufs storage backend. // Issue #10959 has more details. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact the performance of image pulls. // Default: true // +optional SerializeImagePulls *bool `json:"serializeImagePulls,omitempty"` // Map of signal names to quantities that defines hard eviction thresholds. For example: {"memory.available": "300Mi"}. // To explicitly disable, pass a 0% or 100% threshold on an arbitrary resource. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay Pod evictions. // Default: // memory.available: "100Mi" // nodefs.available: "10%" @@ -343,49 +484,83 @@ type KubeletConfiguration struct { // imagefs.available: "15%" // +optional EvictionHard map[string]string `json:"evictionHard,omitempty"` - // Map of signal names to quantities that defines soft eviction thresholds. For example: {"memory.available": "300Mi"}. + // Map of signal names to quantities that defines soft eviction thresholds. + // For example: {"memory.available": "300Mi"}. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay Pod evictions, and may change the allocatable reported + // by the node. // Default: nil // +optional EvictionSoft map[string]string `json:"evictionSoft,omitempty"` - // Map of signal names to quantities that defines grace periods for each soft eviction signal. For example: {"memory.available": "30s"}. + // Map of signal names to quantities that defines grace periods for each soft eviction signal. + // For example: {"memory.available": "30s"}. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay Pod evictions. // Default: nil // +optional EvictionSoftGracePeriod map[string]string `json:"evictionSoftGracePeriod,omitempty"` // Duration for which the kubelet has to wait before transitioning out of an eviction pressure condition. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // lowering it may decrease the stability of the node when the node is overcommitted. // Default: "5m" // +optional EvictionPressureTransitionPeriod metav1.Duration `json:"evictionPressureTransitionPeriod,omitempty"` - // Maximum allowed grace period (in seconds) to use when terminating pods in response to a soft eviction threshold being met. + // Maximum allowed grace period (in seconds) to use when terminating pods in + // response to a soft eviction threshold being met. This value effectively caps + // the Pod's TerminationGracePeriodSeconds value during soft evictions. + // Note: Due to issue #64530, the behavior has a bug where this value currently just + // overrides the grace period during soft eviction, which can increase the grace + // period from what is set on the Pod. This bug will be fixed in a future release. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // lowering it decreases the amount of time Pods will have to gracefully clean + // up before being killed during a soft eviction. // Default: 0 // +optional EvictionMaxPodGracePeriod int32 `json:"evictionMaxPodGracePeriod,omitempty"` // Map of signal names to quantities that defines minimum reclaims, which describe the minimum // amount of a given resource the kubelet will reclaim when performing a pod eviction while // that resource is under pressure. For example: {"imagefs.available": "2Gi"} - // +optional + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may change how well eviction can manage resource pressure. // Default: nil // +optional EvictionMinimumReclaim map[string]string `json:"evictionMinimumReclaim,omitempty"` // podsPerCore is the maximum number of pods per core. Cannot exceed MaxPods. // If 0, this field is ignored. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // changes may cause Pods to fail admission on Kubelet restart, and may change + // the value reported in Node.Status.Capacity[v1.ResourcePods], thus affecting + // future scheduling decisions. Increasing this value may also decrease performance, + // as more Pods can be packed into a single node. // Default: 0 // +optional PodsPerCore int32 `json:"podsPerCore,omitempty"` // enableControllerAttachDetach enables the Attach/Detach controller to // manage attachment/detachment of volumes scheduled to this node, and // disables kubelet from executing any attach/detach operations + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // changing which component is responsible for volume management on a live node + // may result in volumes refusing to detach if the node is not drained prior to + // the update, and if Pods are scheduled to the node before the + // volumes.kubernetes.io/controller-managed-attach-detach annotation is updated by the + // Kubelet. In general, it is safest to leave this value set the same as local config. // Default: true // +optional EnableControllerAttachDetach *bool `json:"enableControllerAttachDetach,omitempty"` // protectKernelDefaults, if true, causes the Kubelet to error if kernel // flags are not as it expects. Otherwise the Kubelet will attempt to modify // kernel flags to match its expectation. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // enabling it may cause the Kubelet to crash-loop if the Kernel is not configured as + // Kubelet expects. // Default: false // +optional ProtectKernelDefaults bool `json:"protectKernelDefaults,omitempty"` // If true, Kubelet ensures a set of iptables rules are present on host. // These rules will serve as utility rules for various components, e.g. KubeProxy. // The rules will be created based on IPTablesMasqueradeBit and IPTablesDropBit. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // disabling it will prevent the Kubelet from healing locally misconfigured iptables rules. // Default: true // +optional MakeIPTablesUtilChains *bool `json:"makeIPTablesUtilChains,omitempty"` @@ -393,39 +568,61 @@ type KubeletConfiguration struct { // Values must be within the range [0, 31]. Must be different from other mark bits. // Warning: Please match the value of the corresponding parameter in kube-proxy. // TODO: clean up IPTablesMasqueradeBit in kube-proxy + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it needs to be coordinated with other components, like kube-proxy, and the update + // will only be effective if MakeIPTablesUtilChains is enabled. // Default: 14 // +optional IPTablesMasqueradeBit *int32 `json:"iptablesMasqueradeBit,omitempty"` // iptablesDropBit is the bit of the iptables fwmark space to mark for dropping packets. // Values must be within the range [0, 31]. Must be different from other mark bits. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it needs to be coordinated with other components, like kube-proxy, and the update + // will only be effective if MakeIPTablesUtilChains is enabled. // Default: 15 // +optional IPTablesDropBit *int32 `json:"iptablesDropBit,omitempty"` // featureGates is a map of feature names to bools that enable or disable alpha/experimental // features. This field modifies piecemeal the built-in default values from // "k8s.io/kubernetes/pkg/features/kube_features.go". + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider the + // documentation for the features you are enabling or disabling. While we + // encourage feature developers to make it possible to dynamically enable + // and disable features, some changes may require node reboots, and some + // features may require careful coordination to retroactively disable. // Default: nil // +optional FeatureGates map[string]bool `json:"featureGates,omitempty"` // failSwapOn tells the Kubelet to fail to start if swap is enabled on the node. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // setting it to true will cause the Kubelet to crash-loop if swap is enabled. // Default: true // +optional FailSwapOn *bool `json:"failSwapOn,omitempty"` - // A quantity defines the maximum size of the container log file before it is rotated. For example: "5Mi" or "256Ki". + // A quantity defines the maximum size of the container log file before it is rotated. + // For example: "5Mi" or "256Ki". + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger log rotation. // Default: "10Mi" // +optional ContainerLogMaxSize string `json:"containerLogMaxSize,omitempty"` // Maximum number of container log files that can be present for a container. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // lowering it may cause log files to be deleted. // Default: 5 // +optional ContainerLogMaxFiles *int32 `json:"containerLogMaxFiles,omitempty"` - /* following flags are meant for Node Allocatable */ + /* the following fields are meant for Node Allocatable */ - // A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=150G) pairs - // that describe resources reserved for non-kubernetes components. + // systemReserved is a set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=150G) + // pairs that describe resources reserved for non-kubernetes components. // Currently only cpu and memory are supported. // See http://kubernetes.io/docs/user-guide/compute-resources for more detail. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may not be possible to increase the reserved resources, because this + // requires resizing cgroups. Always look for a NodeAllocatableEnforced event + // after updating this field to ensure that the update was successful. // Default: nil // +optional SystemReserved map[string]string `json:"systemReserved,omitempty"` @@ -433,16 +630,24 @@ type KubeletConfiguration struct { // that describe resources reserved for kubernetes system components. // Currently cpu, memory and local storage for root file system are supported. // See http://kubernetes.io/docs/user-guide/compute-resources for more detail. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may not be possible to increase the reserved resources, because this + // requires resizing cgroups. Always look for a NodeAllocatableEnforced event + // after updating this field to ensure that the update was successful. // Default: nil // +optional KubeReserved map[string]string `json:"kubeReserved,omitempty"` // This flag helps kubelet identify absolute name of top level cgroup used to enforce `SystemReserved` compute resource reservation for OS system daemons. // Refer to [Node Allocatable](https://git.k8s.io/community/contributors/design-proposals/node/node-allocatable.md) doc for more information. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "" // +optional SystemReservedCgroup string `json:"systemReservedCgroup,omitempty"` // This flag helps kubelet identify absolute name of top level cgroup used to enforce `KubeReserved` compute resource reservation for Kubernetes node system daemons. // Refer to [Node Allocatable](https://git.k8s.io/community/contributors/design-proposals/node/node-allocatable.md) doc for more information. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "" // +optional KubeReservedCgroup string `json:"kubeReservedCgroup,omitempty"` @@ -450,6 +655,12 @@ type KubeletConfiguration struct { // This flag accepts a list of options. Acceptable options are `none`, `pods`, `system-reserved` & `kube-reserved`. // If `none` is specified, no other options may be specified. // Refer to [Node Allocatable](https://git.k8s.io/community/contributors/design-proposals/node/node-allocatable.md) doc for more information. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // removing enforcements may reduce the stability of the node. Alternatively, adding + // enforcements may reduce the stability of components which were using more than + // the reserved amount of resources; for example, enforcing kube-reserved may cause + // Kubelets to OOM if it uses more than the reserved resources, and enforcing system-reserved + // may cause system daemons to OOM if they use more than the reserved resources. // Default: ["pods"] // +optional EnforceNodeAllocatable []string `json:"enforceNodeAllocatable,omitempty"` diff --git a/pkg/kubelet/apis/pluginregistration/v1alpha1/BUILD b/pkg/kubelet/apis/pluginregistration/v1alpha1/BUILD new file mode 100644 index 00000000000..f51668500bb --- /dev/null +++ b/pkg/kubelet/apis/pluginregistration/v1alpha1/BUILD @@ -0,0 +1,40 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "api.pb.go", + "constants.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1", + deps = [ + "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library", + "//vendor/github.com/gogo/protobuf/proto:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) + +filegroup( + name = "go_default_library_protos", + srcs = ["api.proto"], + visibility = ["//visibility:public"], +) diff --git a/pkg/kubelet/apis/pluginregistration/v1alpha1/api.pb.go b/pkg/kubelet/apis/pluginregistration/v1alpha1/api.pb.go new file mode 100644 index 00000000000..96e1d571dba --- /dev/null +++ b/pkg/kubelet/apis/pluginregistration/v1alpha1/api.pb.go @@ -0,0 +1,1027 @@ +/* +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. +// source: api.proto +// DO NOT EDIT! + +/* + Package pluginregistration is a generated protocol buffer package. + + It is generated from these files: + api.proto + + It has these top-level messages: + PluginInfo + RegistrationStatus + RegistrationStatusResponse + InfoRequest +*/ +package pluginregistration + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +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 + +// PluginInfo is the message sent from a plugin to the Kubelet pluginwatcher for plugin registration +type PluginInfo struct { + // Type of the Plugin. CSIPlugin or DevicePlugin + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + // Plugin name that uniquely identifies the plugin for the given plugin type. + // For DevicePlugin, this is the resource name that the plugin manages and + // should follow the extended resource name convention. + // For CSI, this is the CSI driver registrar name. + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // Optional endpoint location. If found set by Kubelet component, + // Kubelet component will use this endpoint for specific requests. + // This allows the plugin to register using one endpoint and possibly use + // a different socket for control operations. CSI uses this model to delegate + // its registration external from the plugin. + Endpoint string `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint,omitempty"` + // Plugin service API versions the plugin supports. + // For DevicePlugin, this maps to the deviceplugin API versions the + // plugin supports at the given socket. + // The Kubelet component communicating with the plugin should be able + // to choose any preferred version from this list, or returns an error + // if none of the listed versions is supported. + SupportedVersions []string `protobuf:"bytes,4,rep,name=supported_versions,json=supportedVersions" json:"supported_versions,omitempty"` +} + +func (m *PluginInfo) Reset() { *m = PluginInfo{} } +func (*PluginInfo) ProtoMessage() {} +func (*PluginInfo) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{0} } + +func (m *PluginInfo) GetType() string { + if m != nil { + return m.Type + } + return "" +} + +func (m *PluginInfo) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *PluginInfo) GetEndpoint() string { + if m != nil { + return m.Endpoint + } + return "" +} + +func (m *PluginInfo) GetSupportedVersions() []string { + if m != nil { + return m.SupportedVersions + } + return nil +} + +// RegistrationStatus is the message sent from Kubelet pluginwatcher to the plugin for notification on registration status +type RegistrationStatus struct { + // True if plugin gets registered successfully at Kubelet + PluginRegistered bool `protobuf:"varint,1,opt,name=plugin_registered,json=pluginRegistered,proto3" json:"plugin_registered,omitempty"` + // Error message in case plugin fails to register, empty string otherwise + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *RegistrationStatus) Reset() { *m = RegistrationStatus{} } +func (*RegistrationStatus) ProtoMessage() {} +func (*RegistrationStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{1} } + +func (m *RegistrationStatus) GetPluginRegistered() bool { + if m != nil { + return m.PluginRegistered + } + return false +} + +func (m *RegistrationStatus) GetError() string { + if m != nil { + return m.Error + } + return "" +} + +// RegistrationStatusResponse is sent by plugin to kubelet in response to RegistrationStatus RPC +type RegistrationStatusResponse struct { +} + +func (m *RegistrationStatusResponse) Reset() { *m = RegistrationStatusResponse{} } +func (*RegistrationStatusResponse) ProtoMessage() {} +func (*RegistrationStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{2} } + +// InfoRequest is the empty request message from Kubelet +type InfoRequest struct { +} + +func (m *InfoRequest) Reset() { *m = InfoRequest{} } +func (*InfoRequest) ProtoMessage() {} +func (*InfoRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{3} } + +func init() { + proto.RegisterType((*PluginInfo)(nil), "pluginregistration.PluginInfo") + proto.RegisterType((*RegistrationStatus)(nil), "pluginregistration.RegistrationStatus") + proto.RegisterType((*RegistrationStatusResponse)(nil), "pluginregistration.RegistrationStatusResponse") + proto.RegisterType((*InfoRequest)(nil), "pluginregistration.InfoRequest") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Registration service + +type RegistrationClient interface { + GetInfo(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*PluginInfo, error) + NotifyRegistrationStatus(ctx context.Context, in *RegistrationStatus, opts ...grpc.CallOption) (*RegistrationStatusResponse, error) +} + +type registrationClient struct { + cc *grpc.ClientConn +} + +func NewRegistrationClient(cc *grpc.ClientConn) RegistrationClient { + return ®istrationClient{cc} +} + +func (c *registrationClient) GetInfo(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*PluginInfo, error) { + out := new(PluginInfo) + err := grpc.Invoke(ctx, "/pluginregistration.Registration/GetInfo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *registrationClient) NotifyRegistrationStatus(ctx context.Context, in *RegistrationStatus, opts ...grpc.CallOption) (*RegistrationStatusResponse, error) { + out := new(RegistrationStatusResponse) + err := grpc.Invoke(ctx, "/pluginregistration.Registration/NotifyRegistrationStatus", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Registration service + +type RegistrationServer interface { + GetInfo(context.Context, *InfoRequest) (*PluginInfo, error) + NotifyRegistrationStatus(context.Context, *RegistrationStatus) (*RegistrationStatusResponse, error) +} + +func RegisterRegistrationServer(s *grpc.Server, srv RegistrationServer) { + s.RegisterService(&_Registration_serviceDesc, srv) +} + +func _Registration_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistrationServer).GetInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pluginregistration.Registration/GetInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistrationServer).GetInfo(ctx, req.(*InfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Registration_NotifyRegistrationStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RegistrationStatus) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistrationServer).NotifyRegistrationStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pluginregistration.Registration/NotifyRegistrationStatus", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistrationServer).NotifyRegistrationStatus(ctx, req.(*RegistrationStatus)) + } + return interceptor(ctx, in, info, handler) +} + +var _Registration_serviceDesc = grpc.ServiceDesc{ + ServiceName: "pluginregistration.Registration", + HandlerType: (*RegistrationServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetInfo", + Handler: _Registration_GetInfo_Handler, + }, + { + MethodName: "NotifyRegistrationStatus", + Handler: _Registration_NotifyRegistrationStatus_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "api.proto", +} + +func (m *PluginInfo) 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 *PluginInfo) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Type) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Type))) + i += copy(dAtA[i:], m.Type) + } + if len(m.Name) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + } + if len(m.Endpoint) > 0 { + dAtA[i] = 0x1a + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Endpoint))) + i += copy(dAtA[i:], m.Endpoint) + } + if len(m.SupportedVersions) > 0 { + for _, s := range m.SupportedVersions { + dAtA[i] = 0x22 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + return i, nil +} + +func (m *RegistrationStatus) 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 *RegistrationStatus) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.PluginRegistered { + dAtA[i] = 0x8 + i++ + if m.PluginRegistered { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } + if len(m.Error) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Error))) + i += copy(dAtA[i:], m.Error) + } + return i, nil +} + +func (m *RegistrationStatusResponse) 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 *RegistrationStatusResponse) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func (m *InfoRequest) 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 *InfoRequest) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func encodeFixed64Api(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Api(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintApi(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 *PluginInfo) Size() (n int) { + var l int + _ = l + l = len(m.Type) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.Name) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.Endpoint) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + if len(m.SupportedVersions) > 0 { + for _, s := range m.SupportedVersions { + l = len(s) + n += 1 + l + sovApi(uint64(l)) + } + } + return n +} + +func (m *RegistrationStatus) Size() (n int) { + var l int + _ = l + if m.PluginRegistered { + n += 2 + } + l = len(m.Error) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *RegistrationStatusResponse) Size() (n int) { + var l int + _ = l + return n +} + +func (m *InfoRequest) Size() (n int) { + var l int + _ = l + return n +} + +func sovApi(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozApi(x uint64) (n int) { + return sovApi(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *PluginInfo) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PluginInfo{`, + `Type:` + fmt.Sprintf("%v", this.Type) + `,`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Endpoint:` + fmt.Sprintf("%v", this.Endpoint) + `,`, + `SupportedVersions:` + fmt.Sprintf("%v", this.SupportedVersions) + `,`, + `}`, + }, "") + return s +} +func (this *RegistrationStatus) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RegistrationStatus{`, + `PluginRegistered:` + fmt.Sprintf("%v", this.PluginRegistered) + `,`, + `Error:` + fmt.Sprintf("%v", this.Error) + `,`, + `}`, + }, "") + return s +} +func (this *RegistrationStatusResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RegistrationStatusResponse{`, + `}`, + }, "") + return s +} +func (this *InfoRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&InfoRequest{`, + `}`, + }, "") + return s +} +func valueToStringApi(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *PluginInfo) 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 ErrIntOverflowApi + } + 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: PluginInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PluginInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Type = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Endpoint", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Endpoint = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SupportedVersions", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SupportedVersions = append(m.SupportedVersions, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RegistrationStatus) 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 ErrIntOverflowApi + } + 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: RegistrationStatus: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RegistrationStatus: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PluginRegistered", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.PluginRegistered = bool(v != 0) + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RegistrationStatusResponse) 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 ErrIntOverflowApi + } + 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: RegistrationStatusResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RegistrationStatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *InfoRequest) 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 ErrIntOverflowApi + } + 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: InfoRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: InfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipApi(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, ErrIntOverflowApi + } + 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, ErrIntOverflowApi + } + 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, ErrIntOverflowApi + } + 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, ErrInvalidLengthApi + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + 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 := skipApi(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 ( + ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowApi = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("api.proto", fileDescriptorApi) } + +var fileDescriptorApi = []byte{ + // 337 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x41, 0x4b, 0x33, 0x31, + 0x14, 0xdc, 0x7c, 0xed, 0xa7, 0xed, 0x53, 0xc1, 0x06, 0x0f, 0xcb, 0x52, 0x62, 0xd9, 0x83, 0x14, + 0xa4, 0x5b, 0xd0, 0x7f, 0xe0, 0x45, 0x04, 0x11, 0x89, 0xa0, 0xc7, 0xb2, 0xb5, 0xaf, 0x6b, 0xc0, + 0x26, 0x31, 0xc9, 0x0a, 0x3d, 0xe9, 0x4f, 0xf0, 0x67, 0xf5, 0x28, 0x9e, 0x3c, 0xda, 0xf5, 0x8f, + 0x48, 0xb3, 0x65, 0x2d, 0xb4, 0x07, 0x6f, 0x6f, 0xe6, 0x4d, 0x1e, 0x33, 0x43, 0xa0, 0x99, 0x6a, + 0x91, 0x68, 0xa3, 0x9c, 0xa2, 0x54, 0x3f, 0xe6, 0x99, 0x90, 0x06, 0x33, 0x61, 0x9d, 0x49, 0x9d, + 0x50, 0x32, 0xea, 0x65, 0xc2, 0x3d, 0xe4, 0xc3, 0xe4, 0x5e, 0x4d, 0xfa, 0x99, 0xca, 0x54, 0xdf, + 0x4b, 0x87, 0xf9, 0xd8, 0x23, 0x0f, 0xfc, 0x54, 0x9e, 0x88, 0x5f, 0x00, 0xae, 0xfd, 0x91, 0x0b, + 0x39, 0x56, 0x94, 0x42, 0xdd, 0x4d, 0x35, 0x86, 0xa4, 0x43, 0xba, 0x4d, 0xee, 0xe7, 0x05, 0x27, + 0xd3, 0x09, 0x86, 0xff, 0x4a, 0x6e, 0x31, 0xd3, 0x08, 0x1a, 0x28, 0x47, 0x5a, 0x09, 0xe9, 0xc2, + 0x9a, 0xe7, 0x2b, 0x4c, 0x7b, 0x40, 0x6d, 0xae, 0xb5, 0x32, 0x0e, 0x47, 0x83, 0x67, 0x34, 0x56, + 0x28, 0x69, 0xc3, 0x7a, 0xa7, 0xd6, 0x6d, 0xf2, 0x56, 0xb5, 0xb9, 0x5d, 0x2e, 0xe2, 0x3b, 0xa0, + 0x7c, 0xc5, 0xff, 0x8d, 0x4b, 0x5d, 0x6e, 0xe9, 0x31, 0xb4, 0xca, 0x6c, 0x83, 0x32, 0x1c, 0x1a, + 0x1c, 0x79, 0x57, 0x0d, 0xbe, 0x5f, 0x2e, 0x78, 0xc5, 0xd3, 0x03, 0xf8, 0x8f, 0xc6, 0x28, 0xb3, + 0xb4, 0x58, 0x82, 0xb8, 0x0d, 0xd1, 0xfa, 0x61, 0x8e, 0x56, 0x2b, 0x69, 0x31, 0xde, 0x83, 0x9d, + 0x45, 0x62, 0x8e, 0x4f, 0x39, 0x5a, 0x77, 0xf2, 0x41, 0x60, 0x77, 0x55, 0x4d, 0x2f, 0x61, 0xfb, + 0x1c, 0x9d, 0x2f, 0xe5, 0x30, 0x59, 0xaf, 0x39, 0x59, 0x79, 0x1c, 0xb1, 0x4d, 0x82, 0xdf, 0x56, + 0xe3, 0x80, 0x3a, 0x08, 0xaf, 0x94, 0x13, 0xe3, 0xe9, 0x86, 0xa8, 0x47, 0x9b, 0x5e, 0xaf, 0xeb, + 0xa2, 0xe4, 0x6f, 0xba, 0x2a, 0x61, 0x70, 0xd6, 0x9e, 0xcd, 0x19, 0xf9, 0x9c, 0xb3, 0xe0, 0xb5, + 0x60, 0x64, 0x56, 0x30, 0xf2, 0x5e, 0x30, 0xf2, 0x55, 0x30, 0xf2, 0xf6, 0xcd, 0x82, 0xe1, 0x96, + 0xff, 0x00, 0xa7, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe4, 0xc0, 0xe3, 0x42, 0x50, 0x02, 0x00, + 0x00, +} diff --git a/pkg/kubelet/apis/pluginregistration/v1alpha1/api.proto b/pkg/kubelet/apis/pluginregistration/v1alpha1/api.proto new file mode 100644 index 00000000000..319b3f19fb7 --- /dev/null +++ b/pkg/kubelet/apis/pluginregistration/v1alpha1/api.proto @@ -0,0 +1,60 @@ +// To regenerate api.pb.go run hack/update-generated-kubelet-plugin-registration.sh +syntax = 'proto3'; + +package pluginregistration; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +option (gogoproto.goproto_stringer_all) = false; +option (gogoproto.stringer_all) = true; +option (gogoproto.goproto_getters_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.goproto_unrecognized_all) = false; + +// PluginInfo is the message sent from a plugin to the Kubelet pluginwatcher for plugin registration +message PluginInfo { + // Type of the Plugin. CSIPlugin or DevicePlugin + string type = 1; + // Plugin name that uniquely identifies the plugin for the given plugin type. + // For DevicePlugin, this is the resource name that the plugin manages and + // should follow the extended resource name convention. + // For CSI, this is the CSI driver registrar name. + string name = 2; + // Optional endpoint location. If found set by Kubelet component, + // Kubelet component will use this endpoint for specific requests. + // This allows the plugin to register using one endpoint and possibly use + // a different socket for control operations. CSI uses this model to delegate + // its registration external from the plugin. + string endpoint = 3; + // Plugin service API versions the plugin supports. + // For DevicePlugin, this maps to the deviceplugin API versions the + // plugin supports at the given socket. + // The Kubelet component communicating with the plugin should be able + // to choose any preferred version from this list, or returns an error + // if none of the listed versions is supported. + repeated string supported_versions = 4; +} + +// RegistrationStatus is the message sent from Kubelet pluginwatcher to the plugin for notification on registration status +message RegistrationStatus { + // True if plugin gets registered successfully at Kubelet + bool plugin_registered = 1; + // Error message in case plugin fails to register, empty string otherwise + string error = 2; +} + +// RegistrationStatusResponse is sent by plugin to kubelet in response to RegistrationStatus RPC +message RegistrationStatusResponse { +} + +// InfoRequest is the empty request message from Kubelet +message InfoRequest { +} + +// Registration is the service advertised by the Plugins. +service Registration { + rpc GetInfo(InfoRequest) returns (PluginInfo) {} + rpc NotifyRegistrationStatus(RegistrationStatus) returns (RegistrationStatusResponse) {} +} diff --git a/pkg/kubelet/apis/pluginregistration/v1alpha1/constants.go b/pkg/kubelet/apis/pluginregistration/v1alpha1/constants.go new file mode 100644 index 00000000000..cfc1b7c6d7c --- /dev/null +++ b/pkg/kubelet/apis/pluginregistration/v1alpha1/constants.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. +*/ + +package pluginregistration + +const ( + CSIPlugin = "CSIPlugin" + DevicePlugin = "DevicePlugin" +) diff --git a/pkg/kubelet/cadvisor/cadvisor_linux.go b/pkg/kubelet/cadvisor/cadvisor_linux.go index ffc2b0417be..6418beb1877 100644 --- a/pkg/kubelet/cadvisor/cadvisor_linux.go +++ b/pkg/kubelet/cadvisor/cadvisor_linux.go @@ -109,9 +109,10 @@ func New(address string, port uint, imageFsInfoProvider ImageFsInfoProvider, roo sysFs := sysfs.NewRealSysFs() ignoreMetrics := cadvisormetrics.MetricSet{ - cadvisormetrics.NetworkTcpUsageMetrics: struct{}{}, - cadvisormetrics.NetworkUdpUsageMetrics: struct{}{}, - cadvisormetrics.PerCpuUsageMetrics: struct{}{}, + cadvisormetrics.NetworkTcpUsageMetrics: struct{}{}, + cadvisormetrics.NetworkUdpUsageMetrics: struct{}{}, + cadvisormetrics.PerCpuUsageMetrics: struct{}{}, + cadvisormetrics.ProcessSchedulerMetrics: struct{}{}, } if !usingLegacyStats { ignoreMetrics[cadvisormetrics.DiskUsageMetrics] = struct{}{} diff --git a/pkg/kubelet/cadvisor/cadvisor_windows.go b/pkg/kubelet/cadvisor/cadvisor_windows.go index 597721cd176..eb416a141d9 100644 --- a/pkg/kubelet/cadvisor/cadvisor_windows.go +++ b/pkg/kubelet/cadvisor/cadvisor_windows.go @@ -26,6 +26,7 @@ import ( ) type cadvisorClient struct { + rootPath string winStatsClient winstats.Client } @@ -34,7 +35,10 @@ var _ Interface = new(cadvisorClient) // New creates a cAdvisor and exports its API on the specified port if port > 0. func New(address string, port uint, imageFsInfoProvider ImageFsInfoProvider, rootPath string, usingLegacyStats bool) (Interface, error) { client, err := winstats.NewPerfCounterClient() - return &cadvisorClient{winStatsClient: client}, err + return &cadvisorClient{ + rootPath: rootPath, + winStatsClient: client, + }, err } func (cu *cadvisorClient) Start() error { @@ -70,7 +74,7 @@ func (cu *cadvisorClient) ImagesFsInfo() (cadvisorapiv2.FsInfo, error) { } func (cu *cadvisorClient) RootFsInfo() (cadvisorapiv2.FsInfo, error) { - return cadvisorapiv2.FsInfo{}, nil + return cu.GetDirFsInfo(cu.rootPath) } func (cu *cadvisorClient) WatchEvents(request *events.Request) (*events.EventChannel, error) { diff --git a/pkg/kubelet/certificate/bootstrap/bootstrap.go b/pkg/kubelet/certificate/bootstrap/bootstrap.go index 9b7b9b3bff5..350e4ed212b 100644 --- a/pkg/kubelet/certificate/bootstrap/bootstrap.go +++ b/pkg/kubelet/certificate/bootstrap/bootstrap.go @@ -19,6 +19,7 @@ package bootstrap import ( "fmt" "os" + "path/filepath" "time" "github.com/golang/glog" @@ -35,6 +36,8 @@ import ( "k8s.io/client-go/util/certificate/csr" ) +const tmpPrivateKeyFile = "kubelet-client.key.tmp" + // 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. @@ -75,9 +78,15 @@ func LoadClientCert(kubeconfigPath string, bootstrapPath string, certDir string, } } } + // Cache the private key in a separate file until CSR succeeds. This has to + // be a separate file because store.CurrentPath() points to a symlink + // managed by the store. + privKeyPath := filepath.Join(certDir, tmpPrivateKeyFile) if !verifyKeyData(keyData) { - glog.V(2).Infof("No valid private key found for bootstrapping, creating a new one") - keyData, err = certutil.MakeEllipticPrivateKeyPEM() + glog.V(2).Infof("No valid private key and/or certificate found, reusing existing private key or creating a new one") + // Note: always call LoadOrGenerateKeyFile so that private key is + // reused on next startup if CSR request fails. + keyData, _, err = certutil.LoadOrGenerateKeyFile(privKeyPath) if err != nil { return err } @@ -90,6 +99,9 @@ func LoadClientCert(kubeconfigPath string, bootstrapPath string, certDir string, if _, err := store.Update(certData, keyData); err != nil { return err } + if err := os.Remove(privKeyPath); err != nil && !os.IsNotExist(err) { + glog.V(2).Infof("failed cleaning up private key file %q: %v", privKeyPath, err) + } pemPath := store.CurrentPath() @@ -192,8 +204,6 @@ func verifyKeyData(data []byte) bool { if len(data) == 0 { return false } - if _, err := certutil.ParsePrivateKeyPEM(data); err != nil { - return false - } - return true + _, err := certutil.ParsePrivateKeyPEM(data) + return err == nil } diff --git a/pkg/kubelet/cm/BUILD b/pkg/kubelet/cm/BUILD index d932de56460..8bfdd017dc5 100644 --- a/pkg/kubelet/cm/BUILD +++ b/pkg/kubelet/cm/BUILD @@ -91,7 +91,7 @@ go_library( "//pkg/kubelet/eviction/api:go_default_library", "//pkg/kubelet/lifecycle:go_default_library", "//pkg/kubelet/status:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", diff --git a/pkg/kubelet/cm/container_manager.go b/pkg/kubelet/cm/container_manager.go index 2e863581707..14a17396ab6 100644 --- a/pkg/kubelet/cm/container_manager.go +++ b/pkg/kubelet/cm/container_manager.go @@ -28,7 +28,7 @@ import ( evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/status" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "fmt" "strconv" diff --git a/pkg/kubelet/cm/container_manager_linux.go b/pkg/kubelet/cm/container_manager_linux.go index cf642a65f57..974986deabd 100644 --- a/pkg/kubelet/cm/container_manager_linux.go +++ b/pkg/kubelet/cm/container_manager_linux.go @@ -52,7 +52,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/qos" "k8s.io/kubernetes/pkg/kubelet/status" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" utilfile "k8s.io/kubernetes/pkg/util/file" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/oom" diff --git a/pkg/kubelet/cm/container_manager_linux_test.go b/pkg/kubelet/cm/container_manager_linux_test.go index cd4b0460c6f..882a3ea7bd4 100644 --- a/pkg/kubelet/cm/container_manager_linux_test.go +++ b/pkg/kubelet/cm/container_manager_linux_test.go @@ -19,8 +19,6 @@ limitations under the License. package cm import ( - "errors" - "fmt" "io/ioutil" "os" "path" @@ -32,97 +30,9 @@ import ( "k8s.io/kubernetes/pkg/util/mount" ) -type fakeMountInterface struct { - mountPoints []mount.MountPoint -} - -func (mi *fakeMountInterface) Mount(source string, target string, fstype string, options []string) error { - return fmt.Errorf("unsupported") -} - -func (mi *fakeMountInterface) Unmount(target string) error { - return fmt.Errorf("unsupported") -} - -func (mi *fakeMountInterface) List() ([]mount.MountPoint, error) { - return mi.mountPoints, nil -} - -func (mi *fakeMountInterface) IsMountPointMatch(mp mount.MountPoint, dir string) bool { - return (mp.Path == dir) -} - -func (mi *fakeMountInterface) IsNotMountPoint(dir string) (bool, error) { - return false, fmt.Errorf("unsupported") -} - -func (mi *fakeMountInterface) IsLikelyNotMountPoint(file string) (bool, error) { - return false, fmt.Errorf("unsupported") -} -func (mi *fakeMountInterface) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { - return "", nil -} - -func (mi *fakeMountInterface) DeviceOpened(pathname string) (bool, error) { - for _, mp := range mi.mountPoints { - if mp.Device == pathname { - return true, nil - } - } - return false, nil -} - -func (mi *fakeMountInterface) PathIsDevice(pathname string) (bool, error) { - return true, nil -} - -func (mi *fakeMountInterface) MakeRShared(path string) error { - return nil -} - -func (mi *fakeMountInterface) GetFileType(pathname string) (mount.FileType, error) { - return mount.FileType("fake"), nil -} - -func (mi *fakeMountInterface) MakeDir(pathname string) error { - return nil -} - -func (mi *fakeMountInterface) MakeFile(pathname string) error { - return nil -} - -func (mi *fakeMountInterface) ExistsPath(pathname string) bool { - return true -} - -func (mi *fakeMountInterface) PrepareSafeSubpath(subPath mount.Subpath) (newHostPath string, cleanupAction func(), err error) { - return "", nil, nil -} - -func (mi *fakeMountInterface) CleanSubPaths(_, _ string) error { - return nil -} - -func (mi *fakeMountInterface) SafeMakeDir(_, _ string, _ os.FileMode) error { - return nil -} - -func (mi *fakeMountInterface) GetMountRefs(pathname string) ([]string, error) { - return nil, errors.New("not implemented") -} - -func (mi *fakeMountInterface) GetFSGroup(pathname string) (int64, error) { - return -1, errors.New("not implemented") -} - -func (mi *fakeMountInterface) GetSELinuxSupport(pathname string) (bool, error) { - return false, errors.New("not implemented") -} - func fakeContainerMgrMountInt() mount.Interface { - return &fakeMountInterface{ - []mount.MountPoint{ + return &mount.FakeMounter{ + MountPoints: []mount.MountPoint{ { Device: "cgroup", Type: "cgroup", @@ -154,8 +64,8 @@ func TestCgroupMountValidationSuccess(t *testing.T) { } func TestCgroupMountValidationMemoryMissing(t *testing.T) { - mountInt := &fakeMountInterface{ - []mount.MountPoint{ + mountInt := &mount.FakeMounter{ + MountPoints: []mount.MountPoint{ { Device: "cgroup", Type: "cgroup", @@ -178,8 +88,8 @@ func TestCgroupMountValidationMemoryMissing(t *testing.T) { } func TestCgroupMountValidationMultipleSubsystem(t *testing.T) { - mountInt := &fakeMountInterface{ - []mount.MountPoint{ + mountInt := &mount.FakeMounter{ + MountPoints: []mount.MountPoint{ { Device: "cgroup", Type: "cgroup", @@ -208,8 +118,8 @@ func TestSoftRequirementsValidationSuccess(t *testing.T) { defer os.RemoveAll(tempDir) req.NoError(ioutil.WriteFile(path.Join(tempDir, "cpu.cfs_period_us"), []byte("0"), os.ModePerm)) req.NoError(ioutil.WriteFile(path.Join(tempDir, "cpu.cfs_quota_us"), []byte("0"), os.ModePerm)) - mountInt := &fakeMountInterface{ - []mount.MountPoint{ + mountInt := &mount.FakeMounter{ + MountPoints: []mount.MountPoint{ { Device: "cgroup", Type: "cgroup", diff --git a/pkg/kubelet/cm/container_manager_stub.go b/pkg/kubelet/cm/container_manager_stub.go index 261552da700..8a464adc0db 100644 --- a/pkg/kubelet/cm/container_manager_stub.go +++ b/pkg/kubelet/cm/container_manager_stub.go @@ -27,7 +27,7 @@ import ( kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/status" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) type containerManagerStub struct{} diff --git a/pkg/kubelet/cm/devicemanager/BUILD b/pkg/kubelet/cm/devicemanager/BUILD index ac2643dbb07..d2e467cca3b 100644 --- a/pkg/kubelet/cm/devicemanager/BUILD +++ b/pkg/kubelet/cm/devicemanager/BUILD @@ -22,7 +22,7 @@ go_library( "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/lifecycle:go_default_library", "//pkg/kubelet/metrics:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", @@ -42,7 +42,7 @@ go_test( "//pkg/kubelet/apis/deviceplugin/v1beta1:go_default_library", "//pkg/kubelet/checkpointmanager:go_default_library", "//pkg/kubelet/lifecycle:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", diff --git a/pkg/kubelet/cm/devicemanager/manager.go b/pkg/kubelet/cm/devicemanager/manager.go index 576164fc8a5..90ae034c619 100644 --- a/pkg/kubelet/cm/devicemanager/manager.go +++ b/pkg/kubelet/cm/devicemanager/manager.go @@ -39,7 +39,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/config" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/metrics" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // ActivePodsFunc is a function that returns a list of pods to reconcile. @@ -259,7 +259,6 @@ func (m *ManagerImpl) Devices() map[string][]pluginapi.Device { func (m *ManagerImpl) Allocate(node *schedulercache.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error { pod := attrs.Pod devicesToReuse := make(map[string]sets.String) - // TODO: Reuse devices between init containers and regular containers. for _, container := range pod.Spec.InitContainers { if err := m.allocateContainerResources(pod, &container, devicesToReuse); err != nil { return err diff --git a/pkg/kubelet/cm/devicemanager/manager_stub.go b/pkg/kubelet/cm/devicemanager/manager_stub.go index a0f14257fdd..b42c1b3eab1 100644 --- a/pkg/kubelet/cm/devicemanager/manager_stub.go +++ b/pkg/kubelet/cm/devicemanager/manager_stub.go @@ -21,7 +21,7 @@ import ( pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1" "k8s.io/kubernetes/pkg/kubelet/config" "k8s.io/kubernetes/pkg/kubelet/lifecycle" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // ManagerStub provides a simple stub implementation for the Device Manager. diff --git a/pkg/kubelet/cm/devicemanager/manager_test.go b/pkg/kubelet/cm/devicemanager/manager_test.go index 4f37cb191c2..d27f6b5f568 100644 --- a/pkg/kubelet/cm/devicemanager/manager_test.go +++ b/pkg/kubelet/cm/devicemanager/manager_test.go @@ -35,7 +35,7 @@ import ( pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1" "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" "k8s.io/kubernetes/pkg/kubelet/lifecycle" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) const ( diff --git a/pkg/kubelet/cm/devicemanager/types.go b/pkg/kubelet/cm/devicemanager/types.go index ab9fdbf12ec..4e34749b670 100644 --- a/pkg/kubelet/cm/devicemanager/types.go +++ b/pkg/kubelet/cm/devicemanager/types.go @@ -24,7 +24,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/config" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/lifecycle" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // Manager manages all the Device Plugins running on a node. diff --git a/pkg/kubelet/config/config_test.go b/pkg/kubelet/config/config_test.go index f41542a9a6c..9ebf5a66044 100644 --- a/pkg/kubelet/config/config_test.go +++ b/pkg/kubelet/config/config_test.go @@ -451,4 +451,10 @@ func TestPodRestore(t *testing.T) { t.Fatalf("Restore returned error: %v", err) } expectPodUpdate(t, ch, CreatePodUpdate(kubetypes.RESTORE, kubetypes.ApiserverSource, pod)) + + // Verify Restore only happen once + if err := config.Restore(tmpDir, channel); err != nil { + t.Fatalf("The second restore returned error: %v", err) + } + expectNoPodUpdate(t, ch) } diff --git a/pkg/kubelet/config/flags.go b/pkg/kubelet/config/flags.go index c51b4de8444..7710580794f 100644 --- a/pkg/kubelet/config/flags.go +++ b/pkg/kubelet/config/flags.go @@ -31,6 +31,15 @@ type ContainerRuntimeOptions struct { ContainerRuntime string // RuntimeCgroups that container runtime is expected to be isolated in. RuntimeCgroups string + // RedirectContainerStreaming enables container streaming redirect. + // When RedirectContainerStreaming is false, kubelet will proxy container streaming data + // between apiserver and container runtime. This approach is more secure, but the proxy + // introduces some overhead. + // When RedirectContainerStreaming is true, kubelet will return an http redirect to apiserver, + // and apiserver will access container runtime directly. This approach is more performant, + // but less secure because the connection between apiserver and container runtime is not + // authenticated. + RedirectContainerStreaming bool // Docker-specific options. @@ -77,6 +86,7 @@ func (s *ContainerRuntimeOptions) AddFlags(fs *pflag.FlagSet) { // General settings. fs.StringVar(&s.ContainerRuntime, "container-runtime", s.ContainerRuntime, "The container runtime to use. Possible values: 'docker', 'remote', 'rkt (deprecated)'.") fs.StringVar(&s.RuntimeCgroups, "runtime-cgroups", s.RuntimeCgroups, "Optional absolute name of cgroups to create and run the runtime in.") + fs.BoolVar(&s.RedirectContainerStreaming, "redirect-container-streaming", s.RedirectContainerStreaming, "Enables container streaming redirect. If false, kubelet will proxy container streaming data between apiserver and container runtime; if true, kubelet will return an http redirect to apiserver, and apiserver will access container runtime directly. The proxy approach is more secure, but introduces some overhead. The redirect approach is more performant, but less secure because the connection between apiserver and container runtime may not be authenticated.") // Docker-specific settings. fs.BoolVar(&s.ExperimentalDockershim, "experimental-dockershim", s.ExperimentalDockershim, "Enable dockershim only mode. In this mode, kubelet will only start dockershim without any other functionalities. This flag only serves test purpose, please do not use it unless you are conscious of what you are doing. [default=false]") diff --git a/pkg/kubelet/container/BUILD b/pkg/kubelet/container/BUILD index 0950b53b3da..287cd501367 100644 --- a/pkg/kubelet/container/BUILD +++ b/pkg/kubelet/container/BUILD @@ -21,7 +21,6 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", "//pkg/kubelet/util/format:go_default_library", - "//pkg/kubelet/util/ioutils:go_default_library", "//pkg/util/hash:go_default_library", "//pkg/volume:go_default_library", "//third_party/forked/golang/expansion:go_default_library", diff --git a/pkg/kubelet/container/helpers.go b/pkg/kubelet/container/helpers.go index 180a3e6df2d..01fe7129d38 100644 --- a/pkg/kubelet/container/helpers.go +++ b/pkg/kubelet/container/helpers.go @@ -17,11 +17,9 @@ limitations under the License. package container import ( - "bytes" "fmt" "hash/fnv" "strings" - "time" "github.com/golang/glog" @@ -32,7 +30,6 @@ import ( "k8s.io/client-go/tools/record" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" "k8s.io/kubernetes/pkg/kubelet/util/format" - "k8s.io/kubernetes/pkg/kubelet/util/ioutils" hashutil "k8s.io/kubernetes/pkg/util/hash" "k8s.io/kubernetes/third_party/forked/golang/expansion" ) @@ -133,6 +130,11 @@ func ExpandContainerCommandOnlyStatic(containerCommand []string, envs []v1.EnvVa return command } +func ExpandContainerVolumeMounts(mount v1.VolumeMount, envs []EnvVar) (expandedSubpath string) { + mapping := expansion.MappingFuncFor(EnvVarsToMap(envs)) + return expansion.Expand(mount.SubPath, mapping) +} + func ExpandContainerCommandAndArgs(container *v1.Container, envs []EnvVar) (command []string, args []string) { mapping := expansion.MappingFuncFor(EnvVarsToMap(envs)) @@ -193,6 +195,13 @@ func (irecorder *innerEventRecorder) PastEventf(object runtime.Object, timestamp } } +func (irecorder *innerEventRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { + if ref, ok := irecorder.shouldRecordEvent(object); ok { + irecorder.recorder.AnnotatedEventf(ref, annotations, eventtype, reason, messageFmt, args...) + } + +} + // Pod must not be nil. func IsHostNetworkPod(pod *v1.Pod) bool { return pod.Spec.HostNetwork @@ -253,22 +262,6 @@ func FormatPod(pod *Pod) string { return fmt.Sprintf("%s_%s(%s)", pod.Name, pod.Namespace, pod.ID) } -type containerCommandRunnerWrapper struct { - DirectStreamingRuntime -} - -var _ ContainerCommandRunner = &containerCommandRunnerWrapper{} - -func (r *containerCommandRunnerWrapper) RunInContainer(id ContainerID, cmd []string, timeout time.Duration) ([]byte, error) { - var buffer bytes.Buffer - output := ioutils.WriteCloserWrapper(&buffer) - err := r.ExecInContainer(id, cmd, nil, output, output, false, nil, timeout) - // Even if err is non-nil, there still may be output (e.g. the exec wrote to stdout or stderr but - // the command returned a nonzero exit code). Therefore, always return the output along with the - // error. - return buffer.Bytes(), err -} - // GetContainerSpec gets the container spec by containerName. func GetContainerSpec(pod *v1.Pod, containerName string) *v1.Container { for i, c := range pod.Spec.Containers { diff --git a/pkg/kubelet/container/helpers_test.go b/pkg/kubelet/container/helpers_test.go index 14d9d6e6c8c..d6c2792c60b 100644 --- a/pkg/kubelet/container/helpers_test.go +++ b/pkg/kubelet/container/helpers_test.go @@ -138,6 +138,114 @@ func TestExpandCommandAndArgs(t *testing.T) { } } +func TestExpandVolumeMountsWithSubpath(t *testing.T) { + cases := []struct { + name string + container *v1.Container + envs []EnvVar + expectedSubPath string + expectedMountPath string + }{ + { + name: "subpath with no expansion", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{SubPath: "foo"}}, + }, + expectedSubPath: "foo", + expectedMountPath: "", + }, + { + name: "volumes with expanded subpath", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{SubPath: "foo/$(POD_NAME)"}}, + }, + envs: []EnvVar{ + { + Name: "POD_NAME", + Value: "bar", + }, + }, + expectedSubPath: "foo/bar", + expectedMountPath: "", + }, + { + name: "volumes expanded with empty subpath", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{SubPath: ""}}, + }, + envs: []EnvVar{ + { + Name: "POD_NAME", + Value: "bar", + }, + }, + expectedSubPath: "", + expectedMountPath: "", + }, + { + name: "volumes expanded with no envs subpath", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{SubPath: "/foo/$(POD_NAME)"}}, + }, + expectedSubPath: "/foo/$(POD_NAME)", + expectedMountPath: "", + }, + { + name: "volumes expanded with leading environment variable", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{SubPath: "$(POD_NAME)/bar"}}, + }, + envs: []EnvVar{ + { + Name: "POD_NAME", + Value: "foo", + }, + }, + expectedSubPath: "foo/bar", + expectedMountPath: "", + }, + { + name: "volumes with volume and subpath", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{MountPath: "/foo", SubPath: "$(POD_NAME)/bar"}}, + }, + envs: []EnvVar{ + { + Name: "POD_NAME", + Value: "foo", + }, + }, + expectedSubPath: "foo/bar", + expectedMountPath: "/foo", + }, + { + name: "volumes with volume and no subpath", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{MountPath: "/foo"}}, + }, + envs: []EnvVar{ + { + Name: "POD_NAME", + Value: "foo", + }, + }, + expectedSubPath: "", + expectedMountPath: "/foo", + }, + } + + for _, tc := range cases { + actualSubPath := ExpandContainerVolumeMounts(tc.container.VolumeMounts[0], tc.envs) + if e, a := tc.expectedSubPath, actualSubPath; !reflect.DeepEqual(e, a) { + t.Errorf("%v: unexpected subpath; expected %v, got %v", tc.name, e, a) + } + if e, a := tc.expectedMountPath, tc.container.VolumeMounts[0].MountPath; !reflect.DeepEqual(e, a) { + t.Errorf("%v: unexpected mountpath; expected %v, got %v", tc.name, e, a) + } + } + +} + func TestShouldContainerBeRestarted(t *testing.T) { pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/kubelet/container/os.go b/pkg/kubelet/container/os.go index 6126063b308..bd27ae9f079 100644 --- a/pkg/kubelet/container/os.go +++ b/pkg/kubelet/container/os.go @@ -43,7 +43,7 @@ type OSInterface interface { // RealOS is used to dispatch the real system level operations. type RealOS struct{} -// MkDir will will call os.Mkdir to create a directory. +// MkdirAll will call os.MkdirAll to create a directory. func (RealOS) MkdirAll(path string, perm os.FileMode) error { return os.MkdirAll(path, perm) } diff --git a/pkg/kubelet/container/runtime.go b/pkg/kubelet/container/runtime.go index 29852d435ed..70b72024c9c 100644 --- a/pkg/kubelet/container/runtime.go +++ b/pkg/kubelet/container/runtime.go @@ -124,22 +124,10 @@ type Runtime interface { UpdatePodCIDR(podCIDR string) error } -// DirectStreamingRuntime is the interface implemented by runtimes for which the streaming calls -// (exec/attach/port-forward) should be served directly by the Kubelet. -type DirectStreamingRuntime interface { - // Runs the command in the container of the specified pod. Attaches - // the processes stdin, stdout, and stderr. Optionally uses a tty. - ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error - // Forward the specified port from the specified pod to the stream. - PortForward(pod *Pod, port int32, stream io.ReadWriteCloser) error - // ContainerAttach encapsulates the attaching to containers for testability - ContainerAttacher -} - -// IndirectStreamingRuntime is the interface implemented by runtimes that handle the serving of the +// StreamingRuntime is the interface implemented by runtimes that handle the serving of the // streaming calls (exec/attach/port-forward) themselves. In this case, Kubelet should redirect to // the runtime server. -type IndirectStreamingRuntime interface { +type StreamingRuntime interface { GetExec(id ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error) GetAttach(id ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error) GetPortForward(podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error) diff --git a/pkg/kubelet/container/testing/fake_runtime.go b/pkg/kubelet/container/testing/fake_runtime.go index 3019d30094e..707ee1ac456 100644 --- a/pkg/kubelet/container/testing/fake_runtime.go +++ b/pkg/kubelet/container/testing/fake_runtime.go @@ -26,7 +26,6 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/tools/remotecommand" "k8s.io/client-go/util/flowcontrol" . "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/volume" @@ -59,34 +58,13 @@ type FakeRuntime struct { StatusErr error } -type FakeDirectStreamingRuntime struct { - *FakeRuntime - - // Arguments to streaming method calls. - Args struct { - // Attach / Exec args - ContainerID ContainerID - Cmd []string - Stdin io.Reader - Stdout io.WriteCloser - Stderr io.WriteCloser - TTY bool - // Port-forward args - Pod *Pod - Port int32 - Stream io.ReadWriteCloser - } -} - -var _ DirectStreamingRuntime = &FakeDirectStreamingRuntime{} - const FakeHost = "localhost:12345" -type FakeIndirectStreamingRuntime struct { +type FakeStreamingRuntime struct { *FakeRuntime } -var _ IndirectStreamingRuntime = &FakeIndirectStreamingRuntime{} +var _ StreamingRuntime = &FakeStreamingRuntime{} // FakeRuntime should implement Runtime. var _ Runtime = &FakeRuntime{} @@ -311,35 +289,6 @@ func (f *FakeRuntime) GetPodStatus(uid types.UID, name, namespace string) (*PodS return &status, f.Err } -func (f *FakeDirectStreamingRuntime) ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error { - f.Lock() - defer f.Unlock() - - f.CalledFunctions = append(f.CalledFunctions, "ExecInContainer") - f.Args.ContainerID = containerID - f.Args.Cmd = cmd - f.Args.Stdin = stdin - f.Args.Stdout = stdout - f.Args.Stderr = stderr - f.Args.TTY = tty - - return f.Err -} - -func (f *FakeDirectStreamingRuntime) AttachContainer(containerID ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - f.Lock() - defer f.Unlock() - - f.CalledFunctions = append(f.CalledFunctions, "AttachContainer") - f.Args.ContainerID = containerID - f.Args.Stdin = stdin - f.Args.Stdout = stdout - f.Args.Stderr = stderr - f.Args.TTY = tty - - return f.Err -} - func (f *FakeRuntime) GetContainerLogs(pod *v1.Pod, containerID ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) (err error) { f.Lock() defer f.Unlock() @@ -394,18 +343,6 @@ func (f *FakeRuntime) RemoveImage(image ImageSpec) error { return f.Err } -func (f *FakeDirectStreamingRuntime) PortForward(pod *Pod, port int32, stream io.ReadWriteCloser) error { - f.Lock() - defer f.Unlock() - - f.CalledFunctions = append(f.CalledFunctions, "PortForward") - f.Args.Pod = pod - f.Args.Port = port - f.Args.Stream = stream - - return f.Err -} - func (f *FakeRuntime) GetNetNS(containerID ContainerID) (string, error) { f.Lock() defer f.Unlock() @@ -455,7 +392,7 @@ func (f *FakeRuntime) ImageStats() (*ImageStats, error) { return nil, f.Err } -func (f *FakeIndirectStreamingRuntime) GetExec(id ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error) { +func (f *FakeStreamingRuntime) GetExec(id ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error) { f.Lock() defer f.Unlock() @@ -463,7 +400,7 @@ func (f *FakeIndirectStreamingRuntime) GetExec(id ContainerID, cmd []string, std return &url.URL{Host: FakeHost}, f.Err } -func (f *FakeIndirectStreamingRuntime) GetAttach(id ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error) { +func (f *FakeStreamingRuntime) GetAttach(id ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error) { f.Lock() defer f.Unlock() @@ -471,7 +408,7 @@ func (f *FakeIndirectStreamingRuntime) GetAttach(id ContainerID, stdin, stdout, return &url.URL{Host: FakeHost}, f.Err } -func (f *FakeIndirectStreamingRuntime) GetPortForward(podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error) { +func (f *FakeStreamingRuntime) GetPortForward(podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error) { f.Lock() defer f.Unlock() diff --git a/pkg/kubelet/dockershim/BUILD b/pkg/kubelet/dockershim/BUILD index 7ea91d85402..286b902d949 100644 --- a/pkg/kubelet/dockershim/BUILD +++ b/pkg/kubelet/dockershim/BUILD @@ -21,56 +21,67 @@ go_library( ] + select({ "@io_bazel_rules_go//go/platform:android": [ "docker_image_unsupported.go", + "docker_sandbox_others.go", "docker_stats_unsupported.go", "helpers_unsupported.go", ], "@io_bazel_rules_go//go/platform:darwin": [ "docker_image_unsupported.go", + "docker_sandbox_others.go", "docker_stats_unsupported.go", "helpers_unsupported.go", ], "@io_bazel_rules_go//go/platform:dragonfly": [ "docker_image_unsupported.go", + "docker_sandbox_others.go", "docker_stats_unsupported.go", "helpers_unsupported.go", ], "@io_bazel_rules_go//go/platform:freebsd": [ "docker_image_unsupported.go", + "docker_sandbox_others.go", "docker_stats_unsupported.go", "helpers_unsupported.go", ], "@io_bazel_rules_go//go/platform:linux": [ "docker_image_linux.go", + "docker_sandbox_others.go", "docker_stats_linux.go", "helpers_linux.go", ], "@io_bazel_rules_go//go/platform:nacl": [ "docker_image_unsupported.go", + "docker_sandbox_others.go", "docker_stats_unsupported.go", "helpers_unsupported.go", ], "@io_bazel_rules_go//go/platform:netbsd": [ "docker_image_unsupported.go", + "docker_sandbox_others.go", "docker_stats_unsupported.go", "helpers_unsupported.go", ], "@io_bazel_rules_go//go/platform:openbsd": [ "docker_image_unsupported.go", + "docker_sandbox_others.go", "docker_stats_unsupported.go", "helpers_unsupported.go", ], "@io_bazel_rules_go//go/platform:plan9": [ "docker_image_unsupported.go", + "docker_sandbox_others.go", "docker_stats_unsupported.go", "helpers_unsupported.go", ], "@io_bazel_rules_go//go/platform:solaris": [ "docker_image_unsupported.go", + "docker_sandbox_others.go", "docker_stats_unsupported.go", "helpers_unsupported.go", ], "@io_bazel_rules_go//go/platform:windows": [ "docker_image_windows.go", + "docker_sandbox_windows.go", "docker_stats_windows.go", "helpers_windows.go", ], diff --git a/pkg/kubelet/dockershim/docker_sandbox.go b/pkg/kubelet/dockershim/docker_sandbox.go index 13e9c42366e..c0a9ecfa9e2 100644 --- a/pkg/kubelet/dockershim/docker_sandbox.go +++ b/pkg/kubelet/dockershim/docker_sandbox.go @@ -538,21 +538,6 @@ func (ds *dockerService) ListPodSandbox(_ context.Context, r *runtimeapi.ListPod return &runtimeapi.ListPodSandboxResponse{Items: result}, nil } -// applySandboxLinuxOptions applies LinuxPodSandboxConfig to dockercontainer.HostConfig and dockercontainer.ContainerCreateConfig. -func (ds *dockerService) applySandboxLinuxOptions(hc *dockercontainer.HostConfig, lc *runtimeapi.LinuxPodSandboxConfig, createConfig *dockertypes.ContainerCreateConfig, image string, separator rune) error { - if lc == nil { - return nil - } - // Apply security context. - if err := applySandboxSecurityContext(lc, createConfig.Config, hc, ds.network, separator); err != nil { - return err - } - - // Set sysctls. - hc.Sysctls = lc.Sysctls - return nil -} - func (ds *dockerService) applySandboxResources(hc *dockercontainer.HostConfig, lc *runtimeapi.LinuxPodSandboxConfig) error { hc.Resources = dockercontainer.Resources{ MemorySwap: DefaultMemorySwap(), @@ -593,8 +578,8 @@ func (ds *dockerService) makeSandboxDockerConfig(c *runtimeapi.PodSandboxConfig, HostConfig: hc, } - // Apply linux-specific options. - if err := ds.applySandboxLinuxOptions(hc, c.GetLinux(), createConfig, image, securityOptSeparator); err != nil { + // Apply platform-specific options. + if err := ds.applySandboxPlatformOptions(hc, c, createConfig, image, securityOptSeparator); err != nil { return nil, err } diff --git a/pkg/kubelet/dockershim/docker_sandbox_others.go b/pkg/kubelet/dockershim/docker_sandbox_others.go new file mode 100644 index 00000000000..108f31ce506 --- /dev/null +++ b/pkg/kubelet/dockershim/docker_sandbox_others.go @@ -0,0 +1,42 @@ +// +build !windows + +/* +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 dockershim + +import ( + dockertypes "github.com/docker/docker/api/types" + dockercontainer "github.com/docker/docker/api/types/container" + runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" +) + +// applySandboxPlatformOptions applies platform specific options to dockercontainer.HostConfig and dockercontainer.ContainerCreateConfig. +func (ds *dockerService) applySandboxPlatformOptions(hc *dockercontainer.HostConfig, config *runtimeapi.PodSandboxConfig, createConfig *dockertypes.ContainerCreateConfig, image string, separator rune) error { + lc := config.GetLinux() + if lc == nil { + return nil + } + + // Apply security context. + if err := applySandboxSecurityContext(lc, createConfig.Config, hc, ds.network, separator); err != nil { + return err + } + + // Set sysctls. + hc.Sysctls = lc.Sysctls + return nil +} diff --git a/pkg/kubelet/dockershim/docker_sandbox_windows.go b/pkg/kubelet/dockershim/docker_sandbox_windows.go new file mode 100644 index 00000000000..d899e126bd3 --- /dev/null +++ b/pkg/kubelet/dockershim/docker_sandbox_windows.go @@ -0,0 +1,39 @@ +// +build windows + +/* +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 dockershim + +import ( + dockertypes "github.com/docker/docker/api/types" + dockercontainer "github.com/docker/docker/api/types/container" + runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" +) + +// applySandboxPlatformOptions applies platform specific options to dockercontainer.HostConfig and dockercontainer.ContainerCreateConfig. +func (ds *dockerService) applySandboxPlatformOptions(hc *dockercontainer.HostConfig, config *runtimeapi.PodSandboxConfig, createConfig *dockertypes.ContainerCreateConfig, image string, separator rune) error { + dnsConfig := config.GetDnsConfig() + if dnsConfig == nil { + return nil + } + + // Setup DNS. + hc.DNS = dnsConfig.GetServers() + hc.DNSSearch = dnsConfig.GetSearches() + hc.DNSOptions = dnsConfig.GetOptions() + return nil +} diff --git a/pkg/kubelet/dockershim/docker_service.go b/pkg/kubelet/dockershim/docker_service.go index 5399094cc3c..8201ab941f2 100644 --- a/pkg/kubelet/dockershim/docker_service.go +++ b/pkg/kubelet/dockershim/docker_service.go @@ -188,7 +188,8 @@ func NewDockerClientFromConfig(config *ClientConfig) libdocker.Interface { // NOTE: Anything passed to DockerService should be eventually handled in another way when we switch to running the shim as a different process. func NewDockerService(config *ClientConfig, podSandboxImage string, streamingConfig *streaming.Config, - pluginSettings *NetworkPluginSettings, cgroupsName string, kubeCgroupDriver string, dockershimRootDir string, disableSharedPID bool) (DockerService, error) { + pluginSettings *NetworkPluginSettings, cgroupsName string, kubeCgroupDriver string, dockershimRootDir string, + disableSharedPID, startLocalStreamingServer bool) (DockerService, error) { client := NewDockerClientFromConfig(config) @@ -207,10 +208,11 @@ func NewDockerService(config *ClientConfig, podSandboxImage string, streamingCon client: client, execHandler: &NativeExecHandler{}, }, - containerManager: cm.NewContainerManager(cgroupsName, client), - checkpointManager: checkpointManager, - disableSharedPID: disableSharedPID, - networkReady: make(map[string]bool), + containerManager: cm.NewContainerManager(cgroupsName, client), + checkpointManager: checkpointManager, + disableSharedPID: disableSharedPID, + startLocalStreamingServer: startLocalStreamingServer, + networkReady: make(map[string]bool), } // check docker version compatibility. @@ -307,6 +309,9 @@ type dockerService struct { // See proposals/pod-pid-namespace.md for details. // TODO: Remove once the escape hatch is no longer used (https://issues.k8s.io/41938) disableSharedPID bool + // startLocalStreamingServer indicates whether dockershim should start a + // streaming server on localhost. + startLocalStreamingServer bool } // TODO: handle context. @@ -397,11 +402,17 @@ func (ds *dockerService) GetPodPortMappings(podSandboxID string) ([]*hostport.Po // Start initializes and starts components in dockerService. func (ds *dockerService) Start() error { // Initialize the legacy cleanup flag. + if ds.startLocalStreamingServer { + go func() { + if err := ds.streamingServer.Start(true); err != nil { + glog.Fatalf("Streaming server stopped unexpectedly: %v", err) + } + }() + } return ds.containerManager.Start() } // Status returns the status of the runtime. -// TODO(random-liu): Set network condition accordingly here. func (ds *dockerService) Status(_ context.Context, r *runtimeapi.StatusRequest) (*runtimeapi.StatusResponse, error) { runtimeReady := &runtimeapi.RuntimeCondition{ Type: runtimeapi.RuntimeReady, diff --git a/pkg/kubelet/dockershim/docker_stats_windows.go b/pkg/kubelet/dockershim/docker_stats_windows.go index a67a0511a04..a690f883b68 100644 --- a/pkg/kubelet/dockershim/docker_stats_windows.go +++ b/pkg/kubelet/dockershim/docker_stats_windows.go @@ -64,6 +64,11 @@ func (ds *dockerService) ListContainerStats(ctx context.Context, r *runtimeapi.L } func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.ContainerStats, error) { + info, err := ds.client.Info() + if err != nil { + return nil, err + } + statsJSON, err := ds.client.GetContainerStats(containerID) if err != nil { return nil, err @@ -101,6 +106,7 @@ func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.Cont }, WritableLayer: &runtimeapi.FilesystemUsage{ Timestamp: timestamp, + FsId: &runtimeapi.FilesystemIdentifier{Mountpoint: info.DockerRootDir}, UsedBytes: &runtimeapi.UInt64Value{Value: uint64(*containerJSON.SizeRw)}, }, } diff --git a/pkg/kubelet/dockershim/helpers_windows.go b/pkg/kubelet/dockershim/helpers_windows.go index 0c54bea03d4..436701546c5 100644 --- a/pkg/kubelet/dockershim/helpers_windows.go +++ b/pkg/kubelet/dockershim/helpers_windows.go @@ -76,6 +76,9 @@ func (ds *dockerService) updateCreateConfig( CPUPercent: rOpts.CpuMaximum, } } + + // Apply security context. + applyWindowsContainerSecurityContext(wc.GetSecurityContext(), createConfig.Config, createConfig.HostConfig) } applyExperimentalCreateConfig(createConfig, sandboxConfig.Annotations) @@ -83,6 +86,17 @@ func (ds *dockerService) updateCreateConfig( return nil } +// applyWindowsContainerSecurityContext updates docker container options according to security context. +func applyWindowsContainerSecurityContext(wsc *runtimeapi.WindowsContainerSecurityContext, config *dockercontainer.Config, hc *dockercontainer.HostConfig) { + if wsc == nil { + return + } + + if wsc.GetRunAsUsername() != "" { + config.User = wsc.GetRunAsUsername() + } +} + func (ds *dockerService) determinePodIPBySandboxID(sandboxID string) string { opts := dockertypes.ContainerListOptions{ All: true, @@ -134,7 +148,11 @@ func (ds *dockerService) determinePodIPBySandboxID(sandboxID string) string { return containerIP } } else { - // Do not return any IP, so that we would continue and get the IP of the Sandbox + // Do not return any IP, so that we would continue and get the IP of the Sandbox. + // Windows 1709 and 1803 doesn't have the Namespace support, so getIP() is called + // to replicate the DNS registry key to the Workload container (IP/Gateway/MAC is + // set separately than DNS). + // TODO(feiskyer): remove this workaround after Namespace is supported in Windows RS5. ds.getIP(sandboxID, r) } } else { diff --git a/pkg/kubelet/dockershim/network/OWNERS b/pkg/kubelet/dockershim/network/OWNERS index cb71f3b3de9..73c2c95f9a3 100644 --- a/pkg/kubelet/dockershim/network/OWNERS +++ b/pkg/kubelet/dockershim/network/OWNERS @@ -3,6 +3,7 @@ approvers: - dchen1107 - matchstick - freehan +- dcbw reviewers: - sig-network-reviewers diff --git a/pkg/kubelet/dockershim/remote/docker_server.go b/pkg/kubelet/dockershim/remote/docker_server.go index 1ac7560d41b..546c3b6c4ab 100644 --- a/pkg/kubelet/dockershim/remote/docker_server.go +++ b/pkg/kubelet/dockershim/remote/docker_server.go @@ -49,7 +49,7 @@ func NewDockerServer(endpoint string, s dockershim.CRIService) *DockerServer { } // Start starts the dockershim grpc server. -func (s *DockerServer) Start(stopCh <-chan struct{}) error { +func (s *DockerServer) Start() error { // Start the internal service. if err := s.service.Start(); err != nil { glog.Errorf("Unable to start docker service") @@ -70,18 +70,8 @@ func (s *DockerServer) Start(stopCh <-chan struct{}) error { runtimeapi.RegisterImageServiceServer(s.server, s.service) go func() { if err := s.server.Serve(l); err != nil { - glog.Errorf("Failed to serve connections: %v", err) + glog.Fatalf("Failed to serve connections: %v", err) } }() - go func() { - <-stopCh - s.Stop() - }() return nil } - -// Stop stops the dockershim grpc server. -func (s *DockerServer) Stop() { - glog.V(2).Infof("Stop docker server") - s.server.Stop() -} diff --git a/pkg/kubelet/eviction/BUILD b/pkg/kubelet/eviction/BUILD index 08c744ba87d..a6e6c847694 100644 --- a/pkg/kubelet/eviction/BUILD +++ b/pkg/kubelet/eviction/BUILD @@ -11,6 +11,8 @@ go_test( srcs = [ "eviction_manager_test.go", "helpers_test.go", + "memory_threshold_notifier_test.go", + "mock_threshold_notifier_test.go", ], embed = [":go_default_library"], deps = [ @@ -20,6 +22,7 @@ go_test( "//pkg/kubelet/eviction/api:go_default_library", "//pkg/kubelet/lifecycle:go_default_library", "//pkg/kubelet/types:go_default_library", + "//vendor/github.com/stretchr/testify/mock:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -36,6 +39,7 @@ go_library( "doc.go", "eviction_manager.go", "helpers.go", + "memory_threshold_notifier.go", "types.go", ] + select({ "@io_bazel_rules_go//go/platform:android": [ diff --git a/pkg/kubelet/eviction/eviction_manager.go b/pkg/kubelet/eviction/eviction_manager.go index b601fe4763d..98833d9254d 100644 --- a/pkg/kubelet/eviction/eviction_manager.go +++ b/pkg/kubelet/eviction/eviction_manager.go @@ -19,7 +19,6 @@ package eviction import ( "fmt" "sort" - "strconv" "sync" "time" @@ -35,7 +34,6 @@ import ( v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos" "k8s.io/kubernetes/pkg/features" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" - "k8s.io/kubernetes/pkg/kubelet/cm" evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/metrics" @@ -85,10 +83,12 @@ type managerImpl struct { signalToNodeReclaimFuncs map[evictionapi.Signal]nodeReclaimFuncs // last observations from synchronize lastObservations signalObservations - // notifierStopCh is a channel used to stop all thresholdNotifiers - notifierStopCh ThresholdStopCh // dedicatedImageFs indicates if imagefs is on a separate device from the rootfs dedicatedImageFs *bool + // thresholdNotifiers is a list of memory threshold notifiers which each notify for a memory eviction threshold + thresholdNotifiers []ThresholdNotifier + // thresholdsLastUpdated is the last time the thresholdNotifiers were updated. + thresholdsLastUpdated time.Time } // ensure it implements the required interface @@ -116,8 +116,8 @@ func NewManager( nodeRef: nodeRef, nodeConditionsLastObservedAt: nodeConditionsObservedAt{}, thresholdsFirstObservedAt: thresholdsObservedAt{}, - notifierStopCh: NewInitialStopCh(clock), dedicatedImageFs: nil, + thresholdNotifiers: []ThresholdNotifier{}, } return manager, manager } @@ -157,12 +157,29 @@ func (m *managerImpl) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAd return lifecycle.PodAdmitResult{ Admit: false, Reason: Reason, - Message: fmt.Sprintf(message, m.nodeConditions), + Message: fmt.Sprintf(nodeLowMessageFmt, m.nodeConditions), } } // Start starts the control loop to observe and response to low compute resources. func (m *managerImpl) Start(diskInfoProvider DiskInfoProvider, podFunc ActivePodsFunc, podCleanedUpFunc PodCleanedUpFunc, monitoringInterval time.Duration) { + thresholdHandler := func(message string) { + glog.Infof(message) + m.synchronize(diskInfoProvider, podFunc) + } + if m.config.KernelMemcgNotification { + for _, threshold := range m.config.Thresholds { + if threshold.Signal == evictionapi.SignalMemoryAvailable || threshold.Signal == evictionapi.SignalAllocatableMemoryAvailable { + notifier, err := NewMemoryThresholdNotifier(threshold, m.config.PodCgroupRoot, &CgroupNotifierFactory{}, thresholdHandler) + if err != nil { + glog.Warningf("eviction manager: failed to create memory threshold notifier: %v", err) + } else { + go notifier.Start() + m.thresholdNotifiers = append(m.thresholdNotifiers, notifier) + } + } + } + } // start the eviction manager monitoring go func() { for { @@ -197,51 +214,6 @@ func (m *managerImpl) IsUnderPIDPressure() bool { return hasNodeCondition(m.nodeConditions, v1.NodePIDPressure) } -func (m *managerImpl) startMemoryThresholdNotifier(summary *statsapi.Summary, hard, allocatable bool, handler thresholdNotifierHandlerFunc) error { - for _, threshold := range m.config.Thresholds { - if threshold.Signal != evictionapi.SignalMemoryAvailable || hard != isHardEvictionThreshold(threshold) { - continue - } - cgroups, err := cm.GetCgroupSubsystems() - if err != nil { - return err - } - cgpath, found := cgroups.MountPoints["memory"] - if !found || len(cgpath) == 0 { - return fmt.Errorf("memory cgroup mount point not found") - } - attribute := "memory.usage_in_bytes" - memoryStats := summary.Node.Memory - if allocatable { - cgpath += m.config.PodCgroupRoot - allocatableContainer, err := getSysContainer(summary.Node.SystemContainers, statsapi.SystemContainerPods) - if err != nil { - return err - } - memoryStats = allocatableContainer.Memory - } - if memoryStats == nil || memoryStats.UsageBytes == nil || memoryStats.WorkingSetBytes == nil || memoryStats.AvailableBytes == nil { - return fmt.Errorf("summary was incomplete") - } - // Set threshold on usage to capacity - eviction_hard + inactive_file, - // since we want to be notified when working_set = capacity - eviction_hard - inactiveFile := resource.NewQuantity(int64(*memoryStats.UsageBytes-*memoryStats.WorkingSetBytes), resource.BinarySI) - capacity := resource.NewQuantity(int64(*memoryStats.AvailableBytes+*memoryStats.WorkingSetBytes), resource.BinarySI) - evictionThresholdQuantity := evictionapi.GetThresholdQuantity(threshold.Value, capacity) - memcgThreshold := capacity.DeepCopy() - memcgThreshold.Sub(*evictionThresholdQuantity) - memcgThreshold.Add(*inactiveFile) - description := fmt.Sprintf("<%s available", formatThresholdValue(threshold.Value)) - memcgThresholdNotifier, err := NewMemCGThresholdNotifier(cgpath, attribute, strconv.FormatInt(memcgThreshold.Value(), 10), description, handler) - if err != nil { - return err - } - go memcgThresholdNotifier.Start(m.notifierStopCh) - return nil - } - return nil -} - // synchronize is the main control loop that enforces eviction thresholds. // Returns the pod that was killed, or nil if no pod was killed. func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc ActivePodsFunc) []*v1.Pod { @@ -272,41 +244,12 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act return nil } - // attempt to create a threshold notifier to improve eviction response time - if m.config.KernelMemcgNotification && m.notifierStopCh.Reset() { - glog.V(4).Infof("eviction manager attempting to integrate with kernel memcg notification api") - // start soft memory notification - err = m.startMemoryThresholdNotifier(summary, false, false, func(desc string) { - glog.Infof("soft memory eviction threshold crossed at %s", desc) - // TODO wait grace period for soft memory limit - m.synchronize(diskInfoProvider, podFunc) - }) - if err != nil { - glog.Warningf("eviction manager: failed to create soft memory threshold notifier: %v", err) - } // start soft memory notification - err = m.startMemoryThresholdNotifier(summary, false, true, func(desc string) { - glog.Infof("soft allocatable memory eviction threshold crossed at %s", desc) - // TODO wait grace period for soft memory limit - m.synchronize(diskInfoProvider, podFunc) - }) - if err != nil { - glog.Warningf("eviction manager: failed to create allocatable soft memory threshold notifier: %v", err) - } - // start hard memory notification - err = m.startMemoryThresholdNotifier(summary, true, false, func(desc string) { - glog.Infof("hard memory eviction threshold crossed at %s", desc) - m.synchronize(diskInfoProvider, podFunc) - }) - if err != nil { - glog.Warningf("eviction manager: failed to create hard memory threshold notifier: %v", err) - } - // start hard memory notification - err = m.startMemoryThresholdNotifier(summary, true, true, func(desc string) { - glog.Infof("hard allocatable memory eviction threshold crossed at %s", desc) - m.synchronize(diskInfoProvider, podFunc) - }) - if err != nil { - glog.Warningf("eviction manager: failed to create hard allocatable memory threshold notifier: %v", err) + if m.clock.Since(m.thresholdsLastUpdated) > notifierRefreshInterval { + m.thresholdsLastUpdated = m.clock.Now() + for _, notifier := range m.thresholdNotifiers { + if err := notifier.UpdateThreshold(summary); err != nil { + glog.Warningf("eviction manager: failed to update %s: %v", notifier.Description(), err) + } } } @@ -429,7 +372,8 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act if !isHardEvictionThreshold(thresholdToReclaim) { gracePeriodOverride = m.config.MaxPodGracePeriodSeconds } - if m.evictPod(pod, gracePeriodOverride, evictionMessage(resourceToReclaim, pod, statsFunc)) { + message, annotations := evictionMessage(resourceToReclaim, pod, statsFunc) + if m.evictPod(pod, gracePeriodOverride, message, annotations) { return []*v1.Pod{pod} } } @@ -534,7 +478,7 @@ func (m *managerImpl) emptyDirLimitEviction(podStats statsapi.PodStats, pod *v1. used := podVolumeUsed[pod.Spec.Volumes[i].Name] if used != nil && size != nil && size.Sign() == 1 && used.Cmp(*size) > 0 { // the emptyDir usage exceeds the size limit, evict the pod - return m.evictPod(pod, 0, fmt.Sprintf(emptyDirMessage, pod.Spec.Volumes[i].Name, size.String())) + return m.evictPod(pod, 0, fmt.Sprintf(emptyDirMessageFmt, pod.Spec.Volumes[i].Name, size.String()), nil) } } } @@ -566,7 +510,7 @@ func (m *managerImpl) podEphemeralStorageLimitEviction(podStats statsapi.PodStat podEphemeralStorageLimit := podLimits[v1.ResourceEphemeralStorage] if podEphemeralStorageTotalUsage.Cmp(podEphemeralStorageLimit) > 0 { // the total usage of pod exceeds the total size limit of containers, evict the pod - return m.evictPod(pod, 0, fmt.Sprintf(podEphemeralStorageMessage, podEphemeralStorageLimit.String())) + return m.evictPod(pod, 0, fmt.Sprintf(podEphemeralStorageMessageFmt, podEphemeralStorageLimit.String()), nil) } return false } @@ -588,7 +532,7 @@ func (m *managerImpl) containerEphemeralStorageLimitEviction(podStats statsapi.P if ephemeralStorageThreshold, ok := thresholdsMap[containerStat.Name]; ok { if ephemeralStorageThreshold.Cmp(*containerUsed) < 0 { - return m.evictPod(pod, 0, fmt.Sprintf(containerEphemeralStorageMessage, containerStat.Name, ephemeralStorageThreshold.String())) + return m.evictPod(pod, 0, fmt.Sprintf(containerEphemeralStorageMessageFmt, containerStat.Name, ephemeralStorageThreshold.String()), nil) } } @@ -596,7 +540,7 @@ func (m *managerImpl) containerEphemeralStorageLimitEviction(podStats statsapi.P return false } -func (m *managerImpl) evictPod(pod *v1.Pod, gracePeriodOverride int64, evictMsg string) bool { +func (m *managerImpl) evictPod(pod *v1.Pod, gracePeriodOverride int64, evictMsg string, annotations map[string]string) bool { // If the pod is marked as critical and static, and support for critical pod annotations is enabled, // do not evict such pods. Static pods are not re-admitted after evictions. // https://github.com/kubernetes/kubernetes/issues/40573 has more details. @@ -611,7 +555,7 @@ func (m *managerImpl) evictPod(pod *v1.Pod, gracePeriodOverride int64, evictMsg Reason: Reason, } // record that we are evicting the pod - m.recorder.Eventf(pod, v1.EventTypeWarning, Reason, evictMsg) + m.recorder.AnnotatedEventf(pod, annotations, v1.EventTypeWarning, Reason, evictMsg) // this is a blocking call and should only return when the pod and its containers are killed. err := m.killPodFunc(pod, status, &gracePeriodOverride) if err != nil { diff --git a/pkg/kubelet/eviction/eviction_manager_test.go b/pkg/kubelet/eviction/eviction_manager_test.go index 9ec64c4089a..e8b4a4e36d3 100644 --- a/pkg/kubelet/eviction/eviction_manager_test.go +++ b/pkg/kubelet/eviction/eviction_manager_test.go @@ -17,6 +17,7 @@ limitations under the License. package eviction import ( + "fmt" "testing" "time" @@ -1434,3 +1435,74 @@ func TestAllocatableMemoryPressure(t *testing.T) { } } } + +func TestUpdateMemcgThreshold(t *testing.T) { + activePodsFunc := func() []*v1.Pod { + return []*v1.Pod{} + } + + fakeClock := clock.NewFakeClock(time.Now()) + podKiller := &mockPodKiller{} + diskInfoProvider := &mockDiskInfoProvider{dedicatedImageFs: false} + diskGC := &mockDiskGC{err: nil} + nodeRef := &v1.ObjectReference{Kind: "Node", Name: "test", UID: types.UID("test"), Namespace: ""} + + config := Config{ + MaxPodGracePeriodSeconds: 5, + PressureTransitionPeriod: time.Minute * 5, + Thresholds: []evictionapi.Threshold{ + { + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("1Gi"), + }, + }, + }, + PodCgroupRoot: "kubepods", + } + summaryProvider := &fakeSummaryProvider{result: makeMemoryStats("2Gi", map[*v1.Pod]statsapi.PodStats{})} + + thresholdNotifier := &MockThresholdNotifier{} + thresholdNotifier.On("UpdateThreshold", summaryProvider.result).Return(nil).Twice() + + manager := &managerImpl{ + clock: fakeClock, + killPodFunc: podKiller.killPodNow, + imageGC: diskGC, + containerGC: diskGC, + config: config, + recorder: &record.FakeRecorder{}, + summaryProvider: summaryProvider, + nodeRef: nodeRef, + nodeConditionsLastObservedAt: nodeConditionsObservedAt{}, + thresholdsFirstObservedAt: thresholdsObservedAt{}, + thresholdNotifiers: []ThresholdNotifier{thresholdNotifier}, + } + + manager.synchronize(diskInfoProvider, activePodsFunc) + // The UpdateThreshold method should have been called once, since this is the first run. + thresholdNotifier.AssertNumberOfCalls(t, "UpdateThreshold", 1) + + manager.synchronize(diskInfoProvider, activePodsFunc) + // The UpdateThreshold method should not have been called again, since not enough time has passed + thresholdNotifier.AssertNumberOfCalls(t, "UpdateThreshold", 1) + + fakeClock.Step(2 * notifierRefreshInterval) + manager.synchronize(diskInfoProvider, activePodsFunc) + // The UpdateThreshold method should be called again since enough time has passed + thresholdNotifier.AssertNumberOfCalls(t, "UpdateThreshold", 2) + + // new memory threshold notifier that returns an error + thresholdNotifier = &MockThresholdNotifier{} + thresholdNotifier.On("UpdateThreshold", summaryProvider.result).Return(fmt.Errorf("error updating threshold")) + thresholdNotifier.On("Description").Return("mock thresholdNotifier").Once() + manager.thresholdNotifiers = []ThresholdNotifier{thresholdNotifier} + + fakeClock.Step(2 * notifierRefreshInterval) + manager.synchronize(diskInfoProvider, activePodsFunc) + // The UpdateThreshold method should be called because at least notifierRefreshInterval time has passed. + // The Description method should be called because UpdateThreshold returned an error + thresholdNotifier.AssertNumberOfCalls(t, "UpdateThreshold", 1) + thresholdNotifier.AssertNumberOfCalls(t, "Description", 1) +} diff --git a/pkg/kubelet/eviction/helpers.go b/pkg/kubelet/eviction/helpers.go index fd862ea1cef..c078ce93d00 100644 --- a/pkg/kubelet/eviction/helpers.go +++ b/pkg/kubelet/eviction/helpers.go @@ -21,13 +21,11 @@ import ( "sort" "strconv" "strings" - "sync" "time" "github.com/golang/glog" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/util/clock" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/features" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" @@ -40,21 +38,24 @@ const ( unsupportedEvictionSignal = "unsupported eviction signal %v" // Reason is the reason reported back in status. Reason = "Evicted" - // the message associated with the reason. - message = "The node was low on resource: %v. " - // additional information for containers exceeding requests - containerMessage = "Container %s was using %s, which exceeds its request of %s. " - // additional information for containers which have exceeded their ES limit - containerEphemeralStorageMessage = "Container %s exceeded its local ephemeral storage limit %q. " - // additional information for pods which have exceeded their ES limit - podEphemeralStorageMessage = "Pod ephemeral local storage usage exceeds the total limit of containers %s. " - // additional information for empty-dir volumes which have exceeded their size limit - emptyDirMessage = "Usage of EmptyDir volume %q exceeds the limit %q. " + // nodeLowMessageFmt is the message for evictions due to resource pressure. + nodeLowMessageFmt = "The node was low on resource: %v. " + // containerMessageFmt provides additional information for containers exceeding requests + containerMessageFmt = "Container %s was using %s, which exceeds its request of %s. " + // containerEphemeralStorageMessageFmt provides additional information for containers which have exceeded their ES limit + containerEphemeralStorageMessageFmt = "Container %s exceeded its local ephemeral storage limit %q. " + // podEphemeralStorageMessageFmt provides additional information for pods which have exceeded their ES limit + podEphemeralStorageMessageFmt = "Pod ephemeral local storage usage exceeds the total limit of containers %s. " + // emptyDirMessageFmt provides additional information for empty-dir volumes which have exceeded their size limit + emptyDirMessageFmt = "Usage of EmptyDir volume %q exceeds the limit %q. " // inodes, number. internal to this module, used to account for local disk inode consumption. resourceInodes v1.ResourceName = "inodes" - // this prevents constantly updating the memcg notifier if synchronize - // is run frequently. - notifierRefreshInterval = 10 * time.Second + // OffendingContainersKey is the key in eviction event annotations for the list of container names which exceeded their requests + OffendingContainersKey = "offending_containers" + // OffendingContainersUsageKey is the key in eviction event annotations for the list of usage of containers which exceeded their requests + OffendingContainersUsageKey = "offending_containers_usage" + // StarvedResourceKey is the key for the starved resource in eviction event annotations + StarvedResourceKey = "starved_resource" ) var ( @@ -1001,6 +1002,10 @@ func isHardEvictionThreshold(threshold evictionapi.Threshold) bool { return threshold.GracePeriod == time.Duration(0) } +func isAllocatableEvictionThreshold(threshold evictionapi.Threshold) bool { + return threshold.Signal == evictionapi.SignalAllocatableMemoryAvailable +} + // buildSignalToRankFunc returns ranking functions associated with resources func buildSignalToRankFunc(withImageFs bool) map[evictionapi.Signal]rankFunc { signalToRankFunc := map[evictionapi.Signal]rankFunc{ @@ -1053,12 +1058,15 @@ func buildSignalToNodeReclaimFuncs(imageGC ImageGC, containerGC ContainerGC, wit return signalToReclaimFunc } -// evictionMessage constructs a useful message about why an eviction occurred -func evictionMessage(resourceToReclaim v1.ResourceName, pod *v1.Pod, stats statsFunc) string { - message := fmt.Sprintf(message, resourceToReclaim) +// evictionMessage constructs a useful message about why an eviction occurred, and annotations to provide metadata about the eviction +func evictionMessage(resourceToReclaim v1.ResourceName, pod *v1.Pod, stats statsFunc) (message string, annotations map[string]string) { + annotations = make(map[string]string) + message = fmt.Sprintf(nodeLowMessageFmt, resourceToReclaim) + containers := []string{} + containerUsage := []string{} podStats, ok := stats(pod) if !ok { - return message + return } for _, containerStats := range podStats.Containers { for _, container := range pod.Spec.Containers { @@ -1076,45 +1084,15 @@ func evictionMessage(resourceToReclaim v1.ResourceName, pod *v1.Pod, stats stats } } if usage != nil && usage.Cmp(requests) > 0 { - message += fmt.Sprintf(containerMessage, container.Name, usage.String(), requests.String()) + message += fmt.Sprintf(containerMessageFmt, container.Name, usage.String(), requests.String()) + containers = append(containers, container.Name) + containerUsage = append(containerUsage, usage.String()) } } } } - return message -} - -// thresholdStopCh is a ThresholdStopCh which can only be closed after notifierRefreshInterval time has passed -type thresholdStopCh struct { - lock sync.Mutex - ch chan struct{} - startTime time.Time - // used to track time - clock clock.Clock -} - -// NewInitialStopCh returns a ThresholdStopCh which can be closed immediately -func NewInitialStopCh(clock clock.Clock) ThresholdStopCh { - return &thresholdStopCh{ch: make(chan struct{}), clock: clock} -} - -// implements ThresholdStopCh.Reset -func (t *thresholdStopCh) Reset() (closed bool) { - t.lock.Lock() - defer t.lock.Unlock() - closed = t.clock.Since(t.startTime) > notifierRefreshInterval - if closed { - // close the old channel and reopen a new one - close(t.ch) - t.startTime = t.clock.Now() - t.ch = make(chan struct{}) - } + annotations[OffendingContainersKey] = strings.Join(containers, ",") + annotations[OffendingContainersUsageKey] = strings.Join(containerUsage, ",") + annotations[StarvedResourceKey] = string(resourceToReclaim) return } - -// implements ThresholdStopCh.Ch -func (t *thresholdStopCh) Ch() <-chan struct{} { - t.lock.Lock() - defer t.lock.Unlock() - return t.ch -} diff --git a/pkg/kubelet/eviction/helpers_test.go b/pkg/kubelet/eviction/helpers_test.go index d7ce3c8586f..0ed5a1b673f 100644 --- a/pkg/kubelet/eviction/helpers_test.go +++ b/pkg/kubelet/eviction/helpers_test.go @@ -20,7 +20,6 @@ import ( "fmt" "reflect" "sort" - "sync" "testing" "time" @@ -28,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/clock" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/features" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" @@ -1948,34 +1946,3 @@ func (s1 thresholdList) Equal(s2 thresholdList) bool { } return true } - -func TestThresholdStopCh(t *testing.T) { - var wg sync.WaitGroup - fakeClock := clock.NewFakeClock(time.Now()) - stop := NewInitialStopCh(fakeClock) - - // Should be able to reset the InitialStopCh right away - if !stop.Reset() { - t.Errorf("Expected to be able to close the initialStopCh, but was unsuccessful") - } - - // Need to wait notifierRefreshInterval before closing - if stop.Reset() { - t.Errorf("Expected not to be able to close the initialStopCh, but was successful") - } - - wg.Add(1) - ch := stop.Ch() - go func() { - defer wg.Done() - // wait for the channel to close - <-ch - }() - - fakeClock.Step(2 * notifierRefreshInterval) - if !stop.Reset() { - t.Errorf("Expected to be able to close the initialStopCh, but was unsuccessful") - } - // ensure the Reset() closed the channel - wg.Wait() -} diff --git a/pkg/kubelet/eviction/memory_threshold_notifier.go b/pkg/kubelet/eviction/memory_threshold_notifier.go new file mode 100644 index 00000000000..8d86944f39d --- /dev/null +++ b/pkg/kubelet/eviction/memory_threshold_notifier.go @@ -0,0 +1,135 @@ +/* +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 eviction + +import ( + "fmt" + "time" + + "github.com/golang/glog" + + "k8s.io/apimachinery/pkg/api/resource" + statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" + "k8s.io/kubernetes/pkg/kubelet/cm" + evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" +) + +const ( + memoryUsageAttribute = "memory.usage_in_bytes" + // this prevents constantly updating the memcg notifier if synchronize + // is run frequently. + notifierRefreshInterval = 10 * time.Second +) + +type memoryThresholdNotifier struct { + threshold evictionapi.Threshold + cgroupPath string + events chan struct{} + factory NotifierFactory + handler func(string) + notifier CgroupNotifier +} + +var _ ThresholdNotifier = &memoryThresholdNotifier{} + +// NewMemoryThresholdNotifier creates a ThresholdNotifier which is designed to respond to the given threshold. +// UpdateThreshold must be called once before the threshold will be active. +func NewMemoryThresholdNotifier(threshold evictionapi.Threshold, cgroupRoot string, factory NotifierFactory, handler func(string)) (ThresholdNotifier, error) { + cgroups, err := cm.GetCgroupSubsystems() + if err != nil { + return nil, err + } + cgpath, found := cgroups.MountPoints["memory"] + if !found || len(cgpath) == 0 { + return nil, fmt.Errorf("memory cgroup mount point not found") + } + if isAllocatableEvictionThreshold(threshold) { + // for allocatable thresholds, point the cgroup notifier at the allocatable cgroup + cgpath += cgroupRoot + } + return &memoryThresholdNotifier{ + threshold: threshold, + cgroupPath: cgpath, + events: make(chan struct{}), + handler: handler, + factory: factory, + }, nil +} + +func (m *memoryThresholdNotifier) Start() { + glog.Infof("eviction manager: created %s", m.Description()) + for range m.events { + m.handler(fmt.Sprintf("eviction manager: %s crossed", m.Description())) + } +} + +func (m *memoryThresholdNotifier) UpdateThreshold(summary *statsapi.Summary) error { + memoryStats := summary.Node.Memory + if isAllocatableEvictionThreshold(m.threshold) { + allocatableContainer, err := getSysContainer(summary.Node.SystemContainers, statsapi.SystemContainerPods) + if err != nil { + return err + } + memoryStats = allocatableContainer.Memory + } + if memoryStats == nil || memoryStats.UsageBytes == nil || memoryStats.WorkingSetBytes == nil || memoryStats.AvailableBytes == nil { + return fmt.Errorf("summary was incomplete. Expected MemoryStats and all subfields to be non-nil, but got %+v", memoryStats) + } + // Set threshold on usage to capacity - eviction_hard + inactive_file, + // since we want to be notified when working_set = capacity - eviction_hard + inactiveFile := resource.NewQuantity(int64(*memoryStats.UsageBytes-*memoryStats.WorkingSetBytes), resource.BinarySI) + capacity := resource.NewQuantity(int64(*memoryStats.AvailableBytes+*memoryStats.WorkingSetBytes), resource.BinarySI) + evictionThresholdQuantity := evictionapi.GetThresholdQuantity(m.threshold.Value, capacity) + memcgThreshold := capacity.DeepCopy() + memcgThreshold.Sub(*evictionThresholdQuantity) + memcgThreshold.Add(*inactiveFile) + + glog.V(3).Infof("eviction manager: setting %s to %s\n", m.Description(), memcgThreshold.String()) + if m.notifier != nil { + m.notifier.Stop() + } + newNotifier, err := m.factory.NewCgroupNotifier(m.cgroupPath, memoryUsageAttribute, memcgThreshold.Value()) + if err != nil { + return err + } + m.notifier = newNotifier + go m.notifier.Start(m.events) + return nil +} + +func (m *memoryThresholdNotifier) Description() string { + var hard, allocatable string + if isHardEvictionThreshold(m.threshold) { + hard = "hard " + } else { + hard = "soft " + } + if isAllocatableEvictionThreshold(m.threshold) { + allocatable = "allocatable " + } + return fmt.Sprintf("%s%smemory eviction threshold", hard, allocatable) +} + +var _ NotifierFactory = &CgroupNotifierFactory{} + +// CgroupNotifierFactory knows how to make CgroupNotifiers which integrate with the kernel +type CgroupNotifierFactory struct{} + +// NewCgroupNotifier implements the NotifierFactory interface +func (n *CgroupNotifierFactory) NewCgroupNotifier(path, attribute string, threshold int64) (CgroupNotifier, error) { + return NewCgroupNotifier(path, attribute, threshold) +} diff --git a/pkg/kubelet/eviction/memory_threshold_notifier_test.go b/pkg/kubelet/eviction/memory_threshold_notifier_test.go new file mode 100644 index 00000000000..8317e051fe6 --- /dev/null +++ b/pkg/kubelet/eviction/memory_threshold_notifier_test.go @@ -0,0 +1,270 @@ +/* +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 eviction + +import ( + "fmt" + "strings" + "sync" + "testing" + "time" + + "k8s.io/apimachinery/pkg/api/resource" + statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" + evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" +) + +const testCgroupPath = "/sys/fs/cgroups/memory" + +func nodeSummary(available, workingSet, usage resource.Quantity, allocatable bool) *statsapi.Summary { + availableBytes := uint64(available.Value()) + workingSetBytes := uint64(workingSet.Value()) + usageBytes := uint64(usage.Value()) + memoryStats := statsapi.MemoryStats{ + AvailableBytes: &availableBytes, + WorkingSetBytes: &workingSetBytes, + UsageBytes: &usageBytes, + } + if allocatable { + return &statsapi.Summary{ + Node: statsapi.NodeStats{ + SystemContainers: []statsapi.ContainerStats{ + { + Name: statsapi.SystemContainerPods, + Memory: &memoryStats, + }, + }, + }, + } + } + return &statsapi.Summary{ + Node: statsapi.NodeStats{ + Memory: &memoryStats, + }, + } +} + +func newTestMemoryThresholdNotifier(threshold evictionapi.Threshold, factory NotifierFactory, handler func(string)) *memoryThresholdNotifier { + return &memoryThresholdNotifier{ + threshold: threshold, + cgroupPath: testCgroupPath, + events: make(chan struct{}), + factory: factory, + handler: handler, + } +} + +func TestUpdateThreshold(t *testing.T) { + testCases := []struct { + description string + available resource.Quantity + workingSet resource.Quantity + usage resource.Quantity + evictionThreshold evictionapi.Threshold + expectedThreshold resource.Quantity + updateThresholdErr error + expectErr bool + }{ + { + description: "node level threshold", + available: resource.MustParse("3Gi"), + usage: resource.MustParse("2Gi"), + workingSet: resource.MustParse("1Gi"), + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("1Gi"), + }, + }, + expectedThreshold: resource.MustParse("4Gi"), + updateThresholdErr: nil, + expectErr: false, + }, + { + description: "allocatable threshold", + available: resource.MustParse("4Gi"), + usage: resource.MustParse("3Gi"), + workingSet: resource.MustParse("1Gi"), + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalAllocatableMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("1Gi"), + }, + }, + expectedThreshold: resource.MustParse("6Gi"), + updateThresholdErr: nil, + expectErr: false, + }, + { + description: "error updating node level threshold", + available: resource.MustParse("3Gi"), + usage: resource.MustParse("2Gi"), + workingSet: resource.MustParse("1Gi"), + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("1Gi"), + }, + }, + expectedThreshold: resource.MustParse("4Gi"), + updateThresholdErr: fmt.Errorf("unexpected error"), + expectErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + notifierFactory := &MockNotifierFactory{} + notifier := &MockCgroupNotifier{} + m := newTestMemoryThresholdNotifier(tc.evictionThreshold, notifierFactory, nil) + notifierFactory.On("NewCgroupNotifier", testCgroupPath, memoryUsageAttribute, tc.expectedThreshold.Value()).Return(notifier, tc.updateThresholdErr) + var events chan<- struct{} + events = m.events + notifier.On("Start", events).Return() + err := m.UpdateThreshold(nodeSummary(tc.available, tc.workingSet, tc.usage, isAllocatableEvictionThreshold(tc.evictionThreshold))) + if err != nil && !tc.expectErr { + t.Errorf("Unexpected error updating threshold: %v", err) + } else if err == nil && tc.expectErr { + t.Errorf("Expected error updating threshold, but got nil") + } + if !tc.expectErr { + notifierFactory.AssertNumberOfCalls(t, "NewCgroupNotifier", 1) + } + }) + } +} + +func TestStart(t *testing.T) { + noResources := resource.MustParse("0") + threshold := evictionapi.Threshold{ + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: &noResources, + }, + } + notifier := &MockCgroupNotifier{} + notifierFactory := &MockNotifierFactory{} + + var wg sync.WaitGroup + wg.Add(4) + m := newTestMemoryThresholdNotifier(threshold, notifierFactory, func(string) { + wg.Done() + }) + notifierFactory.On("NewCgroupNotifier", testCgroupPath, memoryUsageAttribute, int64(0)).Return(notifier, nil) + var events chan<- struct{} + events = m.events + notifier.On("Start", events).Return() + notifier.On("Stop").Return() + + err := m.UpdateThreshold(nodeSummary(noResources, noResources, noResources, isAllocatableEvictionThreshold(threshold))) + if err != nil { + t.Errorf("Unexpected error updating threshold: %v", err) + } + notifierFactory.AssertNumberOfCalls(t, "NewCgroupNotifier", 1) + + go m.Start() + + for i := 0; i < 4; i++ { + m.events <- struct{}{} + } + wg.Wait() +} + +func TestThresholdDescription(t *testing.T) { + testCases := []struct { + description string + evictionThreshold evictionapi.Threshold + expectedSubstrings []string + omittedSubstrings []string + }{ + { + description: "hard node level threshold", + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("2Gi"), + }, + }, + expectedSubstrings: []string{"hard"}, + omittedSubstrings: []string{"allocatable", "soft"}, + }, + { + description: "soft node level threshold", + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("2Gi"), + }, + GracePeriod: time.Minute * 2, + }, + expectedSubstrings: []string{"soft"}, + omittedSubstrings: []string{"allocatable", "hard"}, + }, + { + description: "hard allocatable threshold", + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalAllocatableMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("2Gi"), + }, + GracePeriod: time.Minute * 2, + }, + expectedSubstrings: []string{"soft", "allocatable"}, + omittedSubstrings: []string{"hard"}, + }, + { + description: "soft allocatable threshold", + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalAllocatableMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("2Gi"), + }, + }, + expectedSubstrings: []string{"hard", "allocatable"}, + omittedSubstrings: []string{"soft"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + m := &memoryThresholdNotifier{ + notifier: &MockCgroupNotifier{}, + threshold: tc.evictionThreshold, + cgroupPath: testCgroupPath, + } + desc := m.Description() + for _, expected := range tc.expectedSubstrings { + if !strings.Contains(desc, expected) { + t.Errorf("expected description for notifier with threshold %+v to contain %s, but it did not", tc.evictionThreshold, expected) + } + } + for _, omitted := range tc.omittedSubstrings { + if strings.Contains(desc, omitted) { + t.Errorf("expected description for notifier with threshold %+v NOT to contain %s, but it did", tc.evictionThreshold, omitted) + } + } + }) + } +} diff --git a/pkg/kubelet/eviction/mock_threshold_notifier_test.go b/pkg/kubelet/eviction/mock_threshold_notifier_test.go new file mode 100644 index 00000000000..c94e6fe5f32 --- /dev/null +++ b/pkg/kubelet/eviction/mock_threshold_notifier_test.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 eviction + +import ( + mock "github.com/stretchr/testify/mock" + statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" +) + +// MockCgroupNotifier is a mock implementation of the CgroupNotifier interface +type MockCgroupNotifier struct { + mock.Mock +} + +// Start implements the NotifierFactory interface +func (m *MockCgroupNotifier) Start(a0 chan<- struct{}) { + m.Called(a0) +} + +// Stop implements the NotifierFactory interface +func (m *MockCgroupNotifier) Stop() { + m.Called() +} + +// MockNotifierFactory is a mock of the NotifierFactory interface +type MockNotifierFactory struct { + mock.Mock +} + +// NewCgroupNotifier implements the NotifierFactory interface +func (m *MockNotifierFactory) NewCgroupNotifier(a0, a1 string, a2 int64) (CgroupNotifier, error) { + ret := m.Called(a0, a1, a2) + + var r0 CgroupNotifier + if rf, ok := ret.Get(0).(func(string, string, int64) CgroupNotifier); ok { + r0 = rf(a0, a1, a2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(CgroupNotifier) + } + } + var r1 error + if rf, ok := ret.Get(1).(func(string, string, int64) error); ok { + r1 = rf(a0, a1, a2) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// MockThresholdNotifier is a mock implementation of the ThresholdNotifier interface +type MockThresholdNotifier struct { + mock.Mock +} + +// Start implements the ThresholdNotifier interface +func (m *MockThresholdNotifier) Start() { + m.Called() +} + +// UpdateThreshold implements the ThresholdNotifier interface +func (m *MockThresholdNotifier) UpdateThreshold(a0 *statsapi.Summary) error { + ret := m.Called(a0) + + var r0 error + if rf, ok := ret.Get(0).(func(*statsapi.Summary) error); ok { + r0 = rf(a0) + } else { + r0 = ret.Error(0) + } + return r0 +} + +// Description implements the ThresholdNotifier interface +func (m *MockThresholdNotifier) Description() string { + ret := m.Called() + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.String(0) + } + return r0 +} diff --git a/pkg/kubelet/eviction/threshold_notifier_linux.go b/pkg/kubelet/eviction/threshold_notifier_linux.go index 89d7c79c8d7..4fabd7345a5 100644 --- a/pkg/kubelet/eviction/threshold_notifier_linux.go +++ b/pkg/kubelet/eviction/threshold_notifier_linux.go @@ -18,43 +18,47 @@ package eviction import ( "fmt" + "sync" + "time" "github.com/golang/glog" "golang.org/x/sys/unix" ) -type memcgThresholdNotifier struct { - watchfd int - controlfd int - eventfd int - handler thresholdNotifierHandlerFunc - description string +const ( + // eventSize is the number of bytes returned by a successful read from an eventfd + // see http://man7.org/linux/man-pages/man2/eventfd.2.html for more information + eventSize = 8 + // numFdEvents is the number of events we can record at once. + // If EpollWait finds more than this, they will be missed. + numFdEvents = 6 +) + +type linuxCgroupNotifier struct { + eventfd int + epfd int + stop chan struct{} + stopLock sync.Mutex } -var _ ThresholdNotifier = &memcgThresholdNotifier{} +var _ CgroupNotifier = &linuxCgroupNotifier{} -// NewMemCGThresholdNotifier sends notifications when a cgroup threshold -// is crossed (in either direction) for a given cgroup attribute -func NewMemCGThresholdNotifier(path, attribute, threshold, description string, handler thresholdNotifierHandlerFunc) (ThresholdNotifier, error) { - watchfd, err := unix.Open(fmt.Sprintf("%s/%s", path, attribute), unix.O_RDONLY, 0) +// NewCgroupNotifier returns a linuxCgroupNotifier, which performs cgroup control operations required +// to receive notifications from the cgroup when the threshold is crossed in either direction. +func NewCgroupNotifier(path, attribute string, threshold int64) (CgroupNotifier, error) { + var watchfd, eventfd, epfd, controlfd int + var err error + watchfd, err = unix.Open(fmt.Sprintf("%s/%s", path, attribute), unix.O_RDONLY, 0) if err != nil { return nil, err } - defer func() { - if err != nil { - unix.Close(watchfd) - } - }() - controlfd, err := unix.Open(fmt.Sprintf("%s/cgroup.event_control", path), unix.O_WRONLY, 0) + defer unix.Close(watchfd) + controlfd, err = unix.Open(fmt.Sprintf("%s/cgroup.event_control", path), unix.O_WRONLY, 0) if err != nil { return nil, err } - defer func() { - if err != nil { - unix.Close(controlfd) - } - }() - eventfd, err := unix.Eventfd(0, unix.EFD_CLOEXEC) + defer unix.Close(controlfd) + eventfd, err = unix.Eventfd(0, unix.EFD_CLOEXEC) if err != nil { return nil, err } @@ -63,55 +67,119 @@ func NewMemCGThresholdNotifier(path, attribute, threshold, description string, h return nil, err } defer func() { + // Close eventfd if we get an error later in initialization if err != nil { unix.Close(eventfd) } }() - glog.V(3).Infof("eviction: setting notification threshold to %s", threshold) - config := fmt.Sprintf("%d %d %s", eventfd, watchfd, threshold) + epfd, err = unix.EpollCreate1(0) + if err != nil { + return nil, err + } + if epfd < 0 { + err = fmt.Errorf("EpollCreate1 call failed") + return nil, err + } + defer func() { + // Close epfd if we get an error later in initialization + if err != nil { + unix.Close(epfd) + } + }() + config := fmt.Sprintf("%d %d %d", eventfd, watchfd, threshold) _, err = unix.Write(controlfd, []byte(config)) if err != nil { return nil, err } - return &memcgThresholdNotifier{ - watchfd: watchfd, - controlfd: controlfd, - eventfd: eventfd, - handler: handler, - description: description, + return &linuxCgroupNotifier{ + eventfd: eventfd, + epfd: epfd, + stop: make(chan struct{}), }, nil } -func getThresholdEvents(eventfd int, eventCh chan<- struct{}, stop ThresholdStopCh) { +func (n *linuxCgroupNotifier) Start(eventCh chan<- struct{}) { + err := unix.EpollCtl(n.epfd, unix.EPOLL_CTL_ADD, n.eventfd, &unix.EpollEvent{ + Fd: int32(n.eventfd), + Events: unix.EPOLLIN, + }) + if err != nil { + glog.Warningf("eviction manager: error adding epoll eventfd: %v", err) + return + } for { - buf := make([]byte, 8) - _, err := unix.Read(eventfd, buf) + select { + case <-n.stop: + return + default: + } + event, err := wait(n.epfd, n.eventfd, notifierRefreshInterval) if err != nil { + glog.Warningf("eviction manager: error while waiting for memcg events: %v", err) + return + } else if !event { + // Timeout on wait. This is expected if the threshold was not crossed + continue + } + // Consume the event from the eventfd + buf := make([]byte, eventSize) + _, err = unix.Read(n.eventfd, buf) + if err != nil { + glog.Warningf("eviction manager: error reading memcg events: %v", err) return } - - select { - case eventCh <- struct{}{}: - case <-stop.Ch(): - return - } + eventCh <- struct{}{} } } -func (n *memcgThresholdNotifier) Start(stop ThresholdStopCh) { - eventCh := make(chan struct{}) - go getThresholdEvents(n.eventfd, eventCh, stop) - for { - select { - case <-stop.Ch(): - glog.V(3).Infof("eviction: stopping threshold notifier") - unix.Close(n.watchfd) - unix.Close(n.controlfd) - unix.Close(n.eventfd) - return - case <-eventCh: - glog.V(2).Infof("eviction: threshold crossed") - n.handler(n.description) +// wait waits up to notifierRefreshInterval for an event on the Epoll FD for the +// eventfd we are concerned about. It returns an error if one occurrs, and true +// if the consumer should read from the eventfd. +func wait(epfd, eventfd int, timeout time.Duration) (bool, error) { + events := make([]unix.EpollEvent, numFdEvents+1) + timeoutMS := int(timeout / time.Millisecond) + n, err := unix.EpollWait(epfd, events, timeoutMS) + if n == -1 { + if err == unix.EINTR { + // Interrupt, ignore the error + return false, nil + } + return false, err + } + if n == 0 { + // Timeout + return false, nil + } + if n > numFdEvents { + return false, fmt.Errorf("epoll_wait returned more events than we know what to do with") + } + for _, event := range events[:n] { + if event.Fd == int32(eventfd) { + if event.Events&unix.EPOLLHUP != 0 || event.Events&unix.EPOLLERR != 0 || event.Events&unix.EPOLLIN != 0 { + // EPOLLHUP: should not happen, but if it does, treat it as a wakeup. + + // EPOLLERR: If an error is waiting on the file descriptor, we should pretend + // something is ready to read, and let unix.Read pick up the error. + + // EPOLLIN: There is data to read. + return true, nil + } } } + // An event occurred that we don't care about. + return false, nil +} + +func (n *linuxCgroupNotifier) Stop() { + n.stopLock.Lock() + defer n.stopLock.Unlock() + select { + case <-n.stop: + // the linuxCgroupNotifier is already stopped + return + default: + } + unix.Close(n.eventfd) + unix.Close(n.epfd) + close(n.stop) } diff --git a/pkg/kubelet/eviction/threshold_notifier_unsupported.go b/pkg/kubelet/eviction/threshold_notifier_unsupported.go index 77a9b26cfc2..7078c7865a9 100644 --- a/pkg/kubelet/eviction/threshold_notifier_unsupported.go +++ b/pkg/kubelet/eviction/threshold_notifier_unsupported.go @@ -18,10 +18,16 @@ limitations under the License. package eviction -import "fmt" +import "github.com/golang/glog" -// NewMemCGThresholdNotifier sends notifications when a cgroup threshold -// is crossed (in either direction) for a given cgroup attribute -func NewMemCGThresholdNotifier(path, attribute, threshold, description string, handler thresholdNotifierHandlerFunc) (ThresholdNotifier, error) { - return nil, fmt.Errorf("threshold notification not supported") +// NewCgroupNotifier creates a cgroup notifier that does nothing because cgroups do not exist on non-linux systems. +func NewCgroupNotifier(path, attribute string, threshold int64) (CgroupNotifier, error) { + glog.V(5).Infof("cgroup notifications not supported") + return &unsupportedThresholdNotifier{}, nil } + +type unsupportedThresholdNotifier struct{} + +func (*unsupportedThresholdNotifier) Start(_ chan<- struct{}) {} + +func (*unsupportedThresholdNotifier) Stop() {} diff --git a/pkg/kubelet/eviction/types.go b/pkg/kubelet/eviction/types.go index 26e0432fd9e..d78e7e0695b 100644 --- a/pkg/kubelet/eviction/types.go +++ b/pkg/kubelet/eviction/types.go @@ -131,20 +131,30 @@ type nodeReclaimFunc func() error // nodeReclaimFuncs is an ordered list of nodeReclaimFunc type nodeReclaimFuncs []nodeReclaimFunc -// thresholdNotifierHandlerFunc is a function that takes action in response to a crossed threshold -type thresholdNotifierHandlerFunc func(thresholdDescription string) - -// ThresholdStopCh is an interface for a channel which is closed to stop waiting goroutines. -// Implementations of ThresholdStopCh must correctly handle concurrent calls to all functions. -type ThresholdStopCh interface { - // Reset closes the channel if it can be closed, and returns true if it was closed. - // Reset also creates a new channel. - Reset() bool - // Ch returns the channel that is closed when Reset() is called - Ch() <-chan struct{} +// CgroupNotifier generates events from cgroup events +type CgroupNotifier interface { + // Start causes the CgroupNotifier to begin notifying on the eventCh + Start(eventCh chan<- struct{}) + // Stop stops all processes and cleans up file descriptors associated with the CgroupNotifier + Stop() } -// ThresholdNotifier notifies the user when an attribute crosses a threshold value +// NotifierFactory creates CgroupNotifer +type NotifierFactory interface { + // NewCgroupNotifier creates a CgroupNotifier that creates events when the threshold + // on the attribute in the cgroup specified by the path is crossed. + NewCgroupNotifier(path, attribute string, threshold int64) (CgroupNotifier, error) +} + +// ThresholdNotifier manages CgroupNotifiers based on memory eviction thresholds, and performs a function +// when memory eviction thresholds are crossed type ThresholdNotifier interface { - Start(ThresholdStopCh) + // Start calls the notifier function when the CgroupNotifier notifies the ThresholdNotifier that an event occurred + Start() + // UpdateThreshold updates the memory cgroup threshold based on the metrics provided. + // Calling UpdateThreshold with recent metrics allows the ThresholdNotifier to trigger at the + // eviction threshold more accurately + UpdateThreshold(summary *statsapi.Summary) error + // Description produces a relevant string describing the Memory Threshold Notifier + Description() string } diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 421c0c98bea..33f51997799 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -90,14 +90,17 @@ import ( "k8s.io/kubernetes/pkg/kubelet/stats" "k8s.io/kubernetes/pkg/kubelet/status" "k8s.io/kubernetes/pkg/kubelet/sysctl" + "k8s.io/kubernetes/pkg/kubelet/token" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/format" "k8s.io/kubernetes/pkg/kubelet/util/manager" + "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher" "k8s.io/kubernetes/pkg/kubelet/util/queue" "k8s.io/kubernetes/pkg/kubelet/util/sliceutils" "k8s.io/kubernetes/pkg/kubelet/volumemanager" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" "k8s.io/kubernetes/pkg/security/apparmor" + sysctlwhitelist "k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl" utildbus "k8s.io/kubernetes/pkg/util/dbus" kubeio "k8s.io/kubernetes/pkg/util/io" utilipt "k8s.io/kubernetes/pkg/util/iptables" @@ -105,6 +108,7 @@ import ( nodeutil "k8s.io/kubernetes/pkg/util/node" "k8s.io/kubernetes/pkg/util/oom" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/csi" utilexec "k8s.io/utils/exec" ) @@ -218,7 +222,8 @@ type Builder func(kubeCfg *kubeletconfiginternal.KubeletConfiguration, keepTerminatedPodVolumes bool, nodeLabels map[string]string, seccompProfileRoot string, - bootstrapCheckpointPath string) (Bootstrap, error) + bootstrapCheckpointPath string, + nodeStatusMaxImages int32) (Bootstrap, error) // Dependencies is a bin for things we might consider "injected dependencies" -- objects constructed // at runtime that are necessary for running the Kubelet. This is a temporary solution for grouping @@ -344,7 +349,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, nodeLabels map[string]string, seccompProfileRoot string, bootstrapCheckpointPath string, - stopCh <-chan struct{}) (*Kubelet, error) { + nodeStatusMaxImages int32) (*Kubelet, error) { if rootDirectory == "" { return nil, fmt.Errorf("invalid root directory %q", rootDirectory) } @@ -512,21 +517,22 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, nodeRef: nodeRef, nodeLabels: nodeLabels, nodeStatusUpdateFrequency: kubeCfg.NodeStatusUpdateFrequency.Duration, - os: kubeDeps.OSInterface, - oomWatcher: oomWatcher, - cgroupsPerQOS: kubeCfg.CgroupsPerQOS, - cgroupRoot: kubeCfg.CgroupRoot, - mounter: kubeDeps.Mounter, - writer: kubeDeps.Writer, - maxPods: int(kubeCfg.MaxPods), - podsPerCore: int(kubeCfg.PodsPerCore), - syncLoopMonitor: atomic.Value{}, - daemonEndpoints: daemonEndpoints, - containerManager: kubeDeps.ContainerManager, - containerRuntimeName: containerRuntime, - nodeIP: parsedNodeIP, - nodeIPValidator: validateNodeIP, - clock: clock.RealClock{}, + os: kubeDeps.OSInterface, + oomWatcher: oomWatcher, + cgroupsPerQOS: kubeCfg.CgroupsPerQOS, + cgroupRoot: kubeCfg.CgroupRoot, + mounter: kubeDeps.Mounter, + writer: kubeDeps.Writer, + maxPods: int(kubeCfg.MaxPods), + podsPerCore: int(kubeCfg.PodsPerCore), + syncLoopMonitor: atomic.Value{}, + daemonEndpoints: daemonEndpoints, + containerManager: kubeDeps.ContainerManager, + containerRuntimeName: containerRuntime, + redirectContainerStreaming: crOptions.RedirectContainerStreaming, + nodeIP: parsedNodeIP, + nodeIPValidator: validateNodeIP, + clock: clock.RealClock{}, enableControllerAttachDetach: kubeCfg.EnableControllerAttachDetach, iptClient: utilipt.New(utilexec.New(), utildbus.New(), utilipt.ProtocolIpv4), makeIPTablesUtilChains: kubeCfg.MakeIPTablesUtilChains, @@ -534,6 +540,8 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, iptablesDropBit: int(kubeCfg.IPTablesDropBit), experimentalHostUserNamespaceDefaulting: utilfeature.DefaultFeatureGate.Enabled(features.ExperimentalHostUserNamespaceDefaultingGate), keepTerminatedPodVolumes: keepTerminatedPodVolumes, + nodeStatusMaxImages: nodeStatusMaxImages, + enablePluginsWatcher: utilfeature.DefaultFeatureGate.Enabled(features.KubeletPluginsWatcher), } if klet.cloud != nil { @@ -605,16 +613,16 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, switch containerRuntime { case kubetypes.DockerContainerRuntime: // Create and start the CRI shim running as a grpc server. - streamingConfig := getStreamingConfig(kubeCfg, kubeDeps) + streamingConfig := getStreamingConfig(kubeCfg, kubeDeps, crOptions) ds, err := dockershim.NewDockerService(kubeDeps.DockerClientConfig, crOptions.PodSandboxImage, streamingConfig, &pluginSettings, runtimeCgroups, kubeCfg.CgroupDriver, crOptions.DockershimRootDirectory, - crOptions.DockerDisableSharedPID) + crOptions.DockerDisableSharedPID, !crOptions.RedirectContainerStreaming) if err != nil { return nil, err } - // For now, the CRI shim redirects the streaming requests to the - // kubelet, which handles the requests using DockerService.. - klet.criHandler = ds + if crOptions.RedirectContainerStreaming { + klet.criHandler = ds + } // The unix socket for kubelet <-> dockershim communication. glog.V(5).Infof("RemoteRuntimeEndpoint: %q, RemoteImageEndpoint: %q", @@ -622,7 +630,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, remoteImageEndpoint) glog.V(2).Infof("Starting the GRPC server for the docker CRI shim.") server := dockerremote.NewDockerServer(remoteRuntimeEndpoint, ds) - if err := server.Start(stopCh); err != nil { + if err := server.Start(); err != nil { return nil, err } @@ -670,6 +678,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, return nil, err } klet.containerRuntime = runtime + klet.streamingRuntime = runtime klet.runner = runtime if cadvisor.UsingLegacyCadvisorStats(containerRuntime, remoteRuntimeEndpoint) { @@ -770,11 +779,16 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, containerRefManager, kubeDeps.Recorder) + tokenManager := token.NewManager(kubeDeps.KubeClient) + klet.volumePluginMgr, err = - NewInitializedVolumePluginMgr(klet, secretManager, configMapManager, kubeDeps.VolumePlugins, kubeDeps.DynamicPluginProber) + NewInitializedVolumePluginMgr(klet, secretManager, configMapManager, tokenManager, kubeDeps.VolumePlugins, kubeDeps.DynamicPluginProber) if err != nil { return nil, err } + if klet.enablePluginsWatcher { + klet.pluginWatcher = pluginwatcher.NewWatcher(klet.getPluginsDir()) + } // If the experimentalMounterPathFlag is set, we do not want to // check node capabilities since the mount path is not the default @@ -819,25 +833,23 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, klet.evictionManager = evictionManager klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler) - // add sysctl admission - runtimeSupport, err := sysctl.NewRuntimeAdmitHandler(klet.containerRuntime) - if err != nil { - return nil, err + if utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) { + // add sysctl admission + runtimeSupport, err := sysctl.NewRuntimeAdmitHandler(klet.containerRuntime) + if err != nil { + return nil, err + } + + // Safe, whitelisted sysctls can always be used as unsafe sysctls in the spec. + // Hence, we concatenate those two lists. + safeAndUnsafeSysctls := append(sysctlwhitelist.SafeSysctlWhitelist(), allowedUnsafeSysctls...) + sysctlsWhitelist, err := sysctl.NewWhitelist(safeAndUnsafeSysctls) + if err != nil { + return nil, err + } + klet.admitHandlers.AddPodAdmitHandler(runtimeSupport) + klet.admitHandlers.AddPodAdmitHandler(sysctlsWhitelist) } - safeWhitelist, err := sysctl.NewWhitelist(sysctl.SafeSysctlWhitelist(), v1.SysctlsPodAnnotationKey) - if err != nil { - return nil, err - } - // Safe, whitelisted sysctls can always be used as unsafe sysctls in the spec - // Hence, we concatenate those two lists. - safeAndUnsafeSysctls := append(sysctl.SafeSysctlWhitelist(), allowedUnsafeSysctls...) - unsafeWhitelist, err := sysctl.NewWhitelist(safeAndUnsafeSysctls, v1.UnsafeSysctlsPodAnnotationKey) - if err != nil { - return nil, err - } - klet.admitHandlers.AddPodAdmitHandler(runtimeSupport) - klet.admitHandlers.AddPodAdmitHandler(safeWhitelist) - klet.admitHandlers.AddPodAdmitHandler(unsafeWhitelist) // enable active deadline handler activeDeadlineHandler, err := newActiveDeadlineHandler(klet.statusManager, kubeDeps.Recorder, klet.clock) @@ -999,9 +1011,15 @@ type Kubelet struct { // The name of the container runtime containerRuntimeName string + // redirectContainerStreaming enables container streaming redirect. + redirectContainerStreaming bool + // Container runtime. containerRuntime kubecontainer.Runtime + // Streaming runtime handles container streaming. + streamingRuntime kubecontainer.StreamingRuntime + // Container runtime service (needed by container runtime Start()). // TODO(CD): try to make this available without holding a reference in this // struct. For example, by adding a getter to generic runtime. @@ -1150,6 +1168,17 @@ type Kubelet struct { // This flag, if set, instructs the kubelet to keep volumes from terminated pods mounted to the node. // This can be useful for debugging volume related issues. keepTerminatedPodVolumes bool // DEPRECATED + + // pluginwatcher is a utility for Kubelet to register different types of node-level plugins + // such as device plugins or CSI plugins. It discovers plugins by monitoring inotify events under the + // directory returned by kubelet.getPluginsDir() + pluginWatcher pluginwatcher.Watcher + + // This flag sets a maximum number of images to report in the node status. + nodeStatusMaxImages int32 + + // This flag indicates that kubelet should start plugin watcher utility server for discovering Kubelet plugins + enablePluginsWatcher bool } func allGlobalUnicastIPs() ([]net.IP, error) { @@ -1311,6 +1340,16 @@ func (kl *Kubelet) initializeRuntimeDependentModules() { // container log manager must start after container runtime is up to retrieve information from container runtime // and inform container to reopen log file after log rotation. kl.containerLogManager.Start() + if kl.enablePluginsWatcher { + // Adding Registration Callback function for CSI Driver + kl.pluginWatcher.AddHandler("CSIPlugin", csi.RegistrationCallback) + // Start the plugin watcher + glog.V(4).Infof("starting watcher") + if err := kl.pluginWatcher.Start(); err != nil { + kl.recorder.Eventf(kl.nodeRef, v1.EventTypeWarning, events.KubeletSetupFailed, err.Error()) + glog.Fatalf("failed to start Plugin Watcher. err: %v", err) + } + } } // Run starts the kubelet reacting to config updates @@ -2010,11 +2049,18 @@ func (kl *Kubelet) HandlePodRemoves(pods []*v1.Pod) { // HandlePodReconcile is the callback in the SyncHandler interface for pods // that should be reconciled. func (kl *Kubelet) HandlePodReconcile(pods []*v1.Pod) { + start := kl.clock.Now() for _, pod := range pods { // Update the pod in pod manager, status manager will do periodically reconcile according // to the pod manager. kl.podManager.UpdatePod(pod) + // Reconcile Pod "Ready" condition if necessary. Trigger sync pod for reconciliation. + if status.NeedToReconcilePodReadiness(pod) { + mirrorPod, _ := kl.podManager.GetMirrorPodByPod(pod) + kl.dispatchWork(pod, kubetypes.SyncPodSync, mirrorPod, start) + } + // After an evicted pod is synced, all dead containers in the pod can be removed. if eviction.PodIsEvicted(pod.Status) { if podStatus, err := kl.podCache.Get(pod.UID); err == nil { @@ -2093,11 +2139,6 @@ func (kl *Kubelet) BirthCry() { kl.recorder.Eventf(kl.nodeRef, v1.EventTypeNormal, events.StartingKubelet, "Starting kubelet.") } -// StreamingConnectionIdleTimeout returns the timeout for streaming connections to the HTTP server. -func (kl *Kubelet) StreamingConnectionIdleTimeout() time.Duration { - return kl.streamingConnectionIdleTimeout -} - // ResyncInterval returns the interval used for periodic syncs. func (kl *Kubelet) ResyncInterval() time.Duration { return kl.resyncInterval @@ -2105,12 +2146,12 @@ func (kl *Kubelet) ResyncInterval() time.Duration { // ListenAndServe runs the kubelet HTTP server. func (kl *Kubelet) ListenAndServe(address net.IP, port uint, tlsOptions *server.TLSOptions, auth server.AuthInterface, enableDebuggingHandlers, enableContentionProfiling bool) { - server.ListenAndServeKubeletServer(kl, kl.resourceAnalyzer, address, port, tlsOptions, auth, enableDebuggingHandlers, enableContentionProfiling, kl.containerRuntime, kl.criHandler) + server.ListenAndServeKubeletServer(kl, kl.resourceAnalyzer, address, port, tlsOptions, auth, enableDebuggingHandlers, enableContentionProfiling, kl.redirectContainerStreaming, kl.criHandler) } // ListenAndServeReadOnly runs the kubelet HTTP server in read-only mode. func (kl *Kubelet) ListenAndServeReadOnly(address net.IP, port uint) { - server.ListenAndServeKubeletReadOnlyServer(kl, kl.resourceAnalyzer, address, port, kl.containerRuntime) + server.ListenAndServeKubeletReadOnlyServer(kl, kl.resourceAnalyzer, address, port) } // Delete the eligible dead container instances in a pod. Depending on the configuration, the latest dead containers may be kept around. @@ -2134,19 +2175,23 @@ func isSyncPodWorthy(event *pleg.PodLifecycleEvent) bool { } // Gets the streaming server configuration to use with in-process CRI shims. -func getStreamingConfig(kubeCfg *kubeletconfiginternal.KubeletConfiguration, kubeDeps *Dependencies) *streaming.Config { +func getStreamingConfig(kubeCfg *kubeletconfiginternal.KubeletConfiguration, kubeDeps *Dependencies, crOptions *config.ContainerRuntimeOptions) *streaming.Config { config := &streaming.Config{ - // Use a relative redirect (no scheme or host). - BaseURL: &url.URL{ - Path: "/cri/", - }, StreamIdleTimeout: kubeCfg.StreamingConnectionIdleTimeout.Duration, StreamCreationTimeout: streaming.DefaultConfig.StreamCreationTimeout, SupportedRemoteCommandProtocols: streaming.DefaultConfig.SupportedRemoteCommandProtocols, SupportedPortForwardProtocols: streaming.DefaultConfig.SupportedPortForwardProtocols, } - if kubeDeps.TLSOptions != nil { - config.TLSConfig = kubeDeps.TLSOptions.Config + if !crOptions.RedirectContainerStreaming { + config.Addr = net.JoinHostPort("localhost", "0") + } else { + // Use a relative redirect (no scheme or host). + config.BaseURL = &url.URL{ + Path: "/cri/", + } + if kubeDeps.TLSOptions != nil { + config.TLSConfig = kubeDeps.TLSOptions.Config + } } return config } diff --git a/pkg/kubelet/kubelet_node_status.go b/pkg/kubelet/kubelet_node_status.go index 9a1e6214b6a..4126eb997e2 100644 --- a/pkg/kubelet/kubelet_node_status.go +++ b/pkg/kubelet/kubelet_node_status.go @@ -49,9 +49,6 @@ import ( ) const ( - // maxImagesInNodeStatus is the number of max images we store in image status. - maxImagesInNodeStatus = 50 - // maxNamesPerImageInNodeStatus is max number of names per image stored in // the node status. maxNamesPerImageInNodeStatus = 5 @@ -130,6 +127,7 @@ func (kl *Kubelet) tryRegisterWithAPIServer(node *v1.Node) bool { // annotation. requiresUpdate := kl.reconcileCMADAnnotationWithExistingNode(node, existingNode) requiresUpdate = kl.updateDefaultLabels(node, existingNode) || requiresUpdate + requiresUpdate = kl.reconcileExtendedResource(node, existingNode) || requiresUpdate if requiresUpdate { if _, _, err := nodeutil.PatchNodeStatus(kl.kubeClient.CoreV1(), types.NodeName(kl.nodeName), originalNode, existingNode); err != nil { glog.Errorf("Unable to reconcile node %q with API server: error updating node: %v", kl.nodeName, err) @@ -140,6 +138,19 @@ func (kl *Kubelet) tryRegisterWithAPIServer(node *v1.Node) bool { return true } +// Zeros out extended resource capacity during reconciliation. +func (kl *Kubelet) reconcileExtendedResource(initialNode, node *v1.Node) bool { + requiresUpdate := false + for k := range node.Status.Capacity { + if v1helper.IsExtendedResourceName(k) { + node.Status.Capacity[k] = *resource.NewQuantity(int64(0), resource.DecimalSI) + node.Status.Allocatable[k] = *resource.NewQuantity(int64(0), resource.DecimalSI) + requiresUpdate = true + } + } + return requiresUpdate +} + // updateDefaultLabels will set the default labels on the node func (kl *Kubelet) updateDefaultLabels(initialNode, existingNode *v1.Node) bool { defaultLabels := []string{ @@ -329,6 +340,30 @@ func (kl *Kubelet) initialNode() (*v1.Node, error) { return node, nil } +// setVolumeLimits updates volume limits on the node +func (kl *Kubelet) setVolumeLimits(node *v1.Node) { + if node.Status.Capacity == nil { + node.Status.Capacity = v1.ResourceList{} + } + + if node.Status.Allocatable == nil { + node.Status.Allocatable = v1.ResourceList{} + } + + pluginWithLimits := kl.volumePluginMgr.ListVolumePluginWithLimits() + for _, volumePlugin := range pluginWithLimits { + attachLimits, err := volumePlugin.GetVolumeLimits() + if err != nil { + glog.V(4).Infof("Error getting volume limit for plugin %s", volumePlugin.GetPluginName()) + continue + } + for limitKey, value := range attachLimits { + node.Status.Capacity[v1.ResourceName(limitKey)] = *resource.NewQuantity(value, resource.DecimalSI) + node.Status.Allocatable[v1.ResourceName(limitKey)] = *resource.NewQuantity(value, resource.DecimalSI) + } + } +} + // syncNodeStatus should be called periodically from a goroutine. // It synchronizes node status to master, registering the kubelet first if // necessary. @@ -721,8 +756,9 @@ func (kl *Kubelet) setNodeStatusImages(node *v1.Node) { return } // sort the images from max to min, and only set top N images into the node status. - if maxImagesInNodeStatus < len(containerImages) { - containerImages = containerImages[0:maxImagesInNodeStatus] + if int(kl.nodeStatusMaxImages) > -1 && + int(kl.nodeStatusMaxImages) < len(containerImages) { + containerImages = containerImages[0:kl.nodeStatusMaxImages] } for _, image := range containerImages { @@ -753,6 +789,9 @@ func (kl *Kubelet) setNodeStatusInfo(node *v1.Node) { kl.setNodeStatusDaemonEndpoints(node) kl.setNodeStatusImages(node) kl.setNodeStatusGoRuntime(node) + if utilfeature.DefaultFeatureGate.Enabled(features.AttachVolumeLimit) { + kl.setVolumeLimits(node) + } } // Set Ready condition for the node. diff --git a/pkg/kubelet/kubelet_node_status_test.go b/pkg/kubelet/kubelet_node_status_test.go index a657d3f89ba..ab79aa41bf4 100644 --- a/pkg/kubelet/kubelet_node_status_test.go +++ b/pkg/kubelet/kubelet_node_status_test.go @@ -60,8 +60,8 @@ const ( maxImageTagsForTest = 20 ) -// generateTestingImageList generate randomly generated image list and corresponding expectedImageList. -func generateTestingImageList(count int) ([]kubecontainer.Image, []v1.ContainerImage) { +// generateTestingImageLists generate randomly generated image list and corresponding expectedImageList. +func generateTestingImageLists(count int, maxImages int) ([]kubecontainer.Image, []v1.ContainerImage) { // imageList is randomly generated image list var imageList []kubecontainer.Image for ; count > 0; count-- { @@ -73,7 +73,12 @@ func generateTestingImageList(count int) ([]kubecontainer.Image, []v1.ContainerI imageList = append(imageList, imageItem) } - // expectedImageList is generated by imageList according to size and maxImagesInNodeStatus + expectedImageList := makeExpectedImageList(imageList, maxImages) + return imageList, expectedImageList +} + +func makeExpectedImageList(imageList []kubecontainer.Image, maxImages int) []v1.ContainerImage { + // expectedImageList is generated by imageList according to size and maxImages // 1. sort the imageList by size sort.Sort(sliceutils.ByImageSize(imageList)) // 2. convert sorted imageList to v1.ContainerImage list @@ -86,8 +91,11 @@ func generateTestingImageList(count int) ([]kubecontainer.Image, []v1.ContainerI expectedImageList = append(expectedImageList, apiImage) } - // 3. only returns the top maxImagesInNodeStatus images in expectedImageList - return imageList, expectedImageList[0:maxImagesInNodeStatus] + // 3. only returns the top maxImages images in expectedImageList + if maxImages == -1 { // -1 means no limit + return expectedImageList + } + return expectedImageList[0:maxImages] } func generateImageTags() []string { @@ -299,165 +307,190 @@ func sortNodeAddresses(addrs sortableNodeAddress) { } func TestUpdateNewNodeStatus(t *testing.T) { - // generate one more than maxImagesInNodeStatus in inputImageList - inputImageList, expectedImageList := generateTestingImageList(maxImagesInNodeStatus + 1) - testKubelet := newTestKubeletWithImageList( - t, inputImageList, false /* controllerAttachDetachEnabled */) - defer testKubelet.Cleanup() - kubelet := testKubelet.kubelet - kubelet.kubeClient = nil // ensure only the heartbeat client is used - kubelet.containerManager = &localCM{ - ContainerManager: cm.NewStubContainerManager(), - allocatableReservation: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(100E6, resource.BinarySI), - v1.ResourceEphemeralStorage: *resource.NewQuantity(2000, resource.BinarySI), + cases := []struct { + desc string + nodeStatusMaxImages int32 + }{ + { + desc: "5 image limit", + nodeStatusMaxImages: 5, }, - capacity: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), - v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), - }, - } - kubeClient := testKubelet.fakeKubeClient - existingNode := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname}} - kubeClient.ReactionChain = fake.NewSimpleClientset(&v1.NodeList{Items: []v1.Node{existingNode}}).ReactionChain - machineInfo := &cadvisorapi.MachineInfo{ - MachineID: "123", - SystemUUID: "abc", - BootID: "1b3", - NumCores: 2, - MemoryCapacity: 10E9, // 10G - } - mockCadvisor := testKubelet.fakeCadvisor - mockCadvisor.On("Start").Return(nil) - mockCadvisor.On("MachineInfo").Return(machineInfo, nil) - versionInfo := &cadvisorapi.VersionInfo{ - KernelVersion: "3.16.0-0.bpo.4-amd64", - ContainerOsVersion: "Debian GNU/Linux 7 (wheezy)", - } - mockCadvisor.On("ImagesFsInfo").Return(cadvisorapiv2.FsInfo{ - Usage: 400, - Capacity: 5000, - Available: 600, - }, nil) - mockCadvisor.On("RootFsInfo").Return(cadvisorapiv2.FsInfo{ - Usage: 400, - Capacity: 5000, - Available: 600, - }, nil) - mockCadvisor.On("VersionInfo").Return(versionInfo, nil) - maxAge := 0 * time.Second - options := cadvisorapiv2.RequestOptions{IdType: cadvisorapiv2.TypeName, Count: 2, Recursive: false, MaxAge: &maxAge} - mockCadvisor.On("ContainerInfoV2", "/", options).Return(map[string]cadvisorapiv2.ContainerInfo{}, nil) - kubelet.machineInfo = machineInfo - - expectedNode := &v1.Node{ - ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname}, - Spec: v1.NodeSpec{}, - Status: v1.NodeStatus{ - Conditions: []v1.NodeCondition{ - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionFalse, - Reason: "KubeletHasSufficientDisk", - Message: fmt.Sprintf("kubelet has sufficient disk space available"), - LastHeartbeatTime: metav1.Time{}, - LastTransitionTime: metav1.Time{}, - }, - { - Type: v1.NodeMemoryPressure, - Status: v1.ConditionFalse, - Reason: "KubeletHasSufficientMemory", - Message: fmt.Sprintf("kubelet has sufficient memory available"), - LastHeartbeatTime: metav1.Time{}, - LastTransitionTime: metav1.Time{}, - }, - { - Type: v1.NodeDiskPressure, - Status: v1.ConditionFalse, - Reason: "KubeletHasNoDiskPressure", - Message: fmt.Sprintf("kubelet has no disk pressure"), - LastHeartbeatTime: metav1.Time{}, - LastTransitionTime: metav1.Time{}, - }, - { - Type: v1.NodePIDPressure, - Status: v1.ConditionFalse, - Reason: "KubeletHasSufficientPID", - Message: fmt.Sprintf("kubelet has sufficient PID available"), - LastHeartbeatTime: metav1.Time{}, - LastTransitionTime: metav1.Time{}, - }, - { - Type: v1.NodeReady, - Status: v1.ConditionTrue, - Reason: "KubeletReady", - Message: fmt.Sprintf("kubelet is posting ready status"), - LastHeartbeatTime: metav1.Time{}, - LastTransitionTime: metav1.Time{}, - }, - }, - NodeInfo: v1.NodeSystemInfo{ - MachineID: "123", - SystemUUID: "abc", - BootID: "1b3", - KernelVersion: "3.16.0-0.bpo.4-amd64", - OSImage: "Debian GNU/Linux 7 (wheezy)", - OperatingSystem: goruntime.GOOS, - Architecture: goruntime.GOARCH, - ContainerRuntimeVersion: "test://1.5.0", - KubeletVersion: version.Get().String(), - KubeProxyVersion: version.Get().String(), - }, - Capacity: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), - v1.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI), - v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), - }, - Allocatable: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(1800, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(9900E6, resource.BinarySI), - v1.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI), - v1.ResourceEphemeralStorage: *resource.NewQuantity(3000, resource.BinarySI), - }, - Addresses: []v1.NodeAddress{ - {Type: v1.NodeInternalIP, Address: "127.0.0.1"}, - {Type: v1.NodeHostName, Address: testKubeletHostname}, - }, - Images: expectedImageList, + { + desc: "no image limit", + nodeStatusMaxImages: -1, }, } - kubelet.updateRuntimeUp() - assert.NoError(t, kubelet.updateNodeStatus()) - actions := kubeClient.Actions() - require.Len(t, actions, 2) - require.True(t, actions[1].Matches("patch", "nodes")) - require.Equal(t, actions[1].GetSubresource(), "status") + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + // generate one more in inputImageList than we configure the Kubelet to report, + // or 5 images if unlimited + numTestImages := int(tc.nodeStatusMaxImages) + 1 + if tc.nodeStatusMaxImages == -1 { + numTestImages = 5 + } + inputImageList, expectedImageList := generateTestingImageLists(numTestImages, int(tc.nodeStatusMaxImages)) + testKubelet := newTestKubeletWithImageList( + t, inputImageList, false /* controllerAttachDetachEnabled */, true /*initFakeVolumePlugin*/) + defer testKubelet.Cleanup() + kubelet := testKubelet.kubelet + kubelet.nodeStatusMaxImages = tc.nodeStatusMaxImages + kubelet.kubeClient = nil // ensure only the heartbeat client is used + kubelet.containerManager = &localCM{ + ContainerManager: cm.NewStubContainerManager(), + allocatableReservation: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(100E6, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(2000, resource.BinarySI), + }, + capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + } + kubeClient := testKubelet.fakeKubeClient + existingNode := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname}} + kubeClient.ReactionChain = fake.NewSimpleClientset(&v1.NodeList{Items: []v1.Node{existingNode}}).ReactionChain + machineInfo := &cadvisorapi.MachineInfo{ + MachineID: "123", + SystemUUID: "abc", + BootID: "1b3", + NumCores: 2, + MemoryCapacity: 10E9, // 10G + } + mockCadvisor := testKubelet.fakeCadvisor + mockCadvisor.On("Start").Return(nil) + mockCadvisor.On("MachineInfo").Return(machineInfo, nil) + versionInfo := &cadvisorapi.VersionInfo{ + KernelVersion: "3.16.0-0.bpo.4-amd64", + ContainerOsVersion: "Debian GNU/Linux 7 (wheezy)", + } + mockCadvisor.On("ImagesFsInfo").Return(cadvisorapiv2.FsInfo{ + Usage: 400, + Capacity: 5000, + Available: 600, + }, nil) + mockCadvisor.On("RootFsInfo").Return(cadvisorapiv2.FsInfo{ + Usage: 400, + Capacity: 5000, + Available: 600, + }, nil) + mockCadvisor.On("VersionInfo").Return(versionInfo, nil) + maxAge := 0 * time.Second + options := cadvisorapiv2.RequestOptions{IdType: cadvisorapiv2.TypeName, Count: 2, Recursive: false, MaxAge: &maxAge} + mockCadvisor.On("ContainerInfoV2", "/", options).Return(map[string]cadvisorapiv2.ContainerInfo{}, nil) + kubelet.machineInfo = machineInfo - updatedNode, err := applyNodeStatusPatch(&existingNode, actions[1].(core.PatchActionImpl).GetPatch()) - assert.NoError(t, err) - for i, cond := range updatedNode.Status.Conditions { - assert.False(t, cond.LastHeartbeatTime.IsZero(), "LastHeartbeatTime for %v condition is zero", cond.Type) - assert.False(t, cond.LastTransitionTime.IsZero(), "LastTransitionTime for %v condition is zero", cond.Type) - updatedNode.Status.Conditions[i].LastHeartbeatTime = metav1.Time{} - updatedNode.Status.Conditions[i].LastTransitionTime = metav1.Time{} + expectedNode := &v1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname}, + Spec: v1.NodeSpec{}, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeOutOfDisk, + Status: v1.ConditionFalse, + Reason: "KubeletHasSufficientDisk", + Message: fmt.Sprintf("kubelet has sufficient disk space available"), + LastHeartbeatTime: metav1.Time{}, + LastTransitionTime: metav1.Time{}, + }, + { + Type: v1.NodeMemoryPressure, + Status: v1.ConditionFalse, + Reason: "KubeletHasSufficientMemory", + Message: fmt.Sprintf("kubelet has sufficient memory available"), + LastHeartbeatTime: metav1.Time{}, + LastTransitionTime: metav1.Time{}, + }, + { + Type: v1.NodeDiskPressure, + Status: v1.ConditionFalse, + Reason: "KubeletHasNoDiskPressure", + Message: fmt.Sprintf("kubelet has no disk pressure"), + LastHeartbeatTime: metav1.Time{}, + LastTransitionTime: metav1.Time{}, + }, + { + Type: v1.NodePIDPressure, + Status: v1.ConditionFalse, + Reason: "KubeletHasSufficientPID", + Message: fmt.Sprintf("kubelet has sufficient PID available"), + LastHeartbeatTime: metav1.Time{}, + LastTransitionTime: metav1.Time{}, + }, + { + Type: v1.NodeReady, + Status: v1.ConditionTrue, + Reason: "KubeletReady", + Message: fmt.Sprintf("kubelet is posting ready status"), + LastHeartbeatTime: metav1.Time{}, + LastTransitionTime: metav1.Time{}, + }, + }, + NodeInfo: v1.NodeSystemInfo{ + MachineID: "123", + SystemUUID: "abc", + BootID: "1b3", + KernelVersion: "3.16.0-0.bpo.4-amd64", + OSImage: "Debian GNU/Linux 7 (wheezy)", + OperatingSystem: goruntime.GOOS, + Architecture: goruntime.GOARCH, + ContainerRuntimeVersion: "test://1.5.0", + KubeletVersion: version.Get().String(), + KubeProxyVersion: version.Get().String(), + }, + Capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + Allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(1800, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(9900E6, resource.BinarySI), + v1.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(3000, resource.BinarySI), + }, + Addresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "127.0.0.1"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, + }, + Images: expectedImageList, + }, + } + + kubelet.updateRuntimeUp() + assert.NoError(t, kubelet.updateNodeStatus()) + actions := kubeClient.Actions() + require.Len(t, actions, 2) + require.True(t, actions[1].Matches("patch", "nodes")) + require.Equal(t, actions[1].GetSubresource(), "status") + + updatedNode, err := applyNodeStatusPatch(&existingNode, actions[1].(core.PatchActionImpl).GetPatch()) + assert.NoError(t, err) + for i, cond := range updatedNode.Status.Conditions { + assert.False(t, cond.LastHeartbeatTime.IsZero(), "LastHeartbeatTime for %v condition is zero", cond.Type) + assert.False(t, cond.LastTransitionTime.IsZero(), "LastTransitionTime for %v condition is zero", cond.Type) + updatedNode.Status.Conditions[i].LastHeartbeatTime = metav1.Time{} + updatedNode.Status.Conditions[i].LastTransitionTime = metav1.Time{} + } + + // Version skew workaround. See: https://github.com/kubernetes/kubernetes/issues/16961 + assert.Equal(t, v1.NodeReady, updatedNode.Status.Conditions[len(updatedNode.Status.Conditions)-1].Type, + "NotReady should be last") + assert.Len(t, updatedNode.Status.Images, len(expectedImageList)) + assert.True(t, apiequality.Semantic.DeepEqual(expectedNode, updatedNode), "%s", diff.ObjectDiff(expectedNode, updatedNode)) + }) } - - // Version skew workaround. See: https://github.com/kubernetes/kubernetes/issues/16961 - assert.Equal(t, v1.NodeReady, updatedNode.Status.Conditions[len(updatedNode.Status.Conditions)-1].Type, - "NotReady should be last") - assert.Len(t, updatedNode.Status.Images, maxImagesInNodeStatus) - assert.True(t, apiequality.Semantic.DeepEqual(expectedNode, updatedNode), "%s", diff.ObjectDiff(expectedNode, updatedNode)) } func TestUpdateExistingNodeStatus(t *testing.T) { testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) defer testKubelet.Cleanup() kubelet := testKubelet.kubelet - kubelet.kubeClient = nil // ensure only the heartbeat client is used + kubelet.nodeStatusMaxImages = 5 // don't truncate the image list that gets constructed by hand for this test + kubelet.kubeClient = nil // ensure only the heartbeat client is used kubelet.containerManager = &localCM{ ContainerManager: cm.NewStubContainerManager(), allocatableReservation: v1.ResourceList{ @@ -742,7 +775,8 @@ func TestUpdateNodeStatusWithRuntimeStateError(t *testing.T) { testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) defer testKubelet.Cleanup() kubelet := testKubelet.kubelet - kubelet.kubeClient = nil // ensure only the heartbeat client is used + kubelet.nodeStatusMaxImages = 5 // don't truncate the image list that gets constructed by hand for this test + kubelet.kubeClient = nil // ensure only the heartbeat client is used kubelet.containerManager = &localCM{ ContainerManager: cm.NewStubContainerManager(), allocatableReservation: v1.ResourceList{ @@ -879,7 +913,7 @@ func TestUpdateNodeStatusWithRuntimeStateError(t *testing.T) { require.True(t, actions[1].Matches("patch", "nodes")) require.Equal(t, actions[1].GetSubresource(), "status") - updatedNode, err := applyNodeStatusPatch(&existingNode, actions[1].(core.PatchActionImpl).GetPatch()) + updatedNode, err := kubeClient.CoreV1().Nodes().Get(testKubeletHostname, metav1.GetOptions{}) require.NoError(t, err, "can't apply node status patch") for i, cond := range updatedNode.Status.Conditions { @@ -891,7 +925,6 @@ func TestUpdateNodeStatusWithRuntimeStateError(t *testing.T) { // Version skew workaround. See: https://github.com/kubernetes/kubernetes/issues/16961 lastIndex := len(updatedNode.Status.Conditions) - 1 - assert.Equal(t, v1.NodeReady, updatedNode.Status.Conditions[lastIndex].Type, "NodeReady should be the last condition") assert.NotEmpty(t, updatedNode.Status.Conditions[lastIndex].Message) @@ -1214,12 +1247,15 @@ func TestTryRegisterWithApiServer(t *testing.T) { } func TestUpdateNewNodeStatusTooLargeReservation(t *testing.T) { - // generate one more than maxImagesInNodeStatus in inputImageList - inputImageList, _ := generateTestingImageList(maxImagesInNodeStatus + 1) + const nodeStatusMaxImages = 5 + + // generate one more in inputImageList than we configure the Kubelet to report + inputImageList, _ := generateTestingImageLists(nodeStatusMaxImages+1, nodeStatusMaxImages) testKubelet := newTestKubeletWithImageList( - t, inputImageList, false /* controllerAttachDetachEnabled */) + t, inputImageList, false /* controllerAttachDetachEnabled */, true /* initFakeVolumePlugin */) defer testKubelet.Cleanup() kubelet := testKubelet.kubelet + kubelet.nodeStatusMaxImages = nodeStatusMaxImages kubelet.kubeClient = nil // ensure only the heartbeat client is used kubelet.containerManager = &localCM{ ContainerManager: cm.NewStubContainerManager(), @@ -1490,6 +1526,104 @@ func TestUpdateDefaultLabels(t *testing.T) { } } +func TestReconcileExtendedResource(t *testing.T) { + testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) + testKubelet.kubelet.kubeClient = nil // ensure only the heartbeat client is used + extendedResourceName1 := v1.ResourceName("test.com/resource1") + extendedResourceName2 := v1.ResourceName("test.com/resource2") + + cases := []struct { + name string + existingNode *v1.Node + expectedNode *v1.Node + needsUpdate bool + }{ + { + name: "no update needed without extended resource", + existingNode: &v1.Node{ + Status: v1.NodeStatus{ + Capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + Allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + }, + }, + expectedNode: &v1.Node{ + Status: v1.NodeStatus{ + Capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + Allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + }, + }, + needsUpdate: false, + }, + { + name: "extended resource capacity is zeroed", + existingNode: &v1.Node{ + Status: v1.NodeStatus{ + Capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + extendedResourceName1: *resource.NewQuantity(int64(2), resource.DecimalSI), + extendedResourceName2: *resource.NewQuantity(int64(10), resource.DecimalSI), + }, + Allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + extendedResourceName1: *resource.NewQuantity(int64(2), resource.DecimalSI), + extendedResourceName2: *resource.NewQuantity(int64(10), resource.DecimalSI), + }, + }, + }, + expectedNode: &v1.Node{ + Status: v1.NodeStatus{ + Capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + extendedResourceName1: *resource.NewQuantity(int64(0), resource.DecimalSI), + extendedResourceName2: *resource.NewQuantity(int64(0), resource.DecimalSI), + }, + Allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + extendedResourceName1: *resource.NewQuantity(int64(0), resource.DecimalSI), + extendedResourceName2: *resource.NewQuantity(int64(0), resource.DecimalSI), + }, + }, + }, + needsUpdate: true, + }, + } + + for _, tc := range cases { + defer testKubelet.Cleanup() + kubelet := testKubelet.kubelet + initialNode := &v1.Node{} + + needsUpdate := kubelet.reconcileExtendedResource(initialNode, tc.existingNode) + assert.Equal(t, tc.needsUpdate, needsUpdate, tc.name) + assert.Equal(t, tc.expectedNode, tc.existingNode, tc.name) + } + +} + func TestValidateNodeIPParam(t *testing.T) { type test struct { nodeIP string @@ -1580,3 +1714,88 @@ func TestValidateNodeIPParam(t *testing.T) { } } } + +func TestSetVolumeLimits(t *testing.T) { + testKubelet := newTestKubeletWithoutFakeVolumePlugin(t, false /* controllerAttachDetachEnabled */) + defer testKubelet.Cleanup() + kubelet := testKubelet.kubelet + kubelet.kubeClient = nil // ensure only the heartbeat client is used + kubelet.hostname = testKubeletHostname + + var testcases = []struct { + name string + cloudProviderName string + expectedVolumeKey string + expectedLimit int64 + }{ + { + name: "For default GCE cloudprovider", + cloudProviderName: "gce", + expectedVolumeKey: util.GCEVolumeLimitKey, + expectedLimit: 16, + }, + { + name: "For default AWS Cloudprovider", + cloudProviderName: "aws", + expectedVolumeKey: util.EBSVolumeLimitKey, + expectedLimit: 39, + }, + { + name: "for default Azure cloudprovider", + cloudProviderName: "azure", + expectedVolumeKey: util.AzureVolumeLimitKey, + expectedLimit: 16, + }, + { + name: "when no cloudprovider is present", + cloudProviderName: "", + expectedVolumeKey: util.AzureVolumeLimitKey, + expectedLimit: -1, + }, + } + for _, test := range testcases { + node := &v1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname, Annotations: make(map[string]string)}, + Spec: v1.NodeSpec{}, + } + + if test.cloudProviderName != "" { + fakeCloud := &fakecloud.FakeCloud{ + Provider: test.cloudProviderName, + Err: nil, + } + kubelet.cloud = fakeCloud + kubelet.cloudproviderRequestParallelism = make(chan int, 1) + kubelet.cloudproviderRequestSync = make(chan int) + kubelet.cloudproviderRequestTimeout = 10 * time.Second + } else { + kubelet.cloud = nil + } + + kubelet.setVolumeLimits(node) + nodeLimits := []v1.ResourceList{} + nodeLimits = append(nodeLimits, node.Status.Allocatable) + nodeLimits = append(nodeLimits, node.Status.Capacity) + for _, volumeLimits := range nodeLimits { + if test.expectedLimit == -1 { + _, ok := volumeLimits[v1.ResourceName(test.expectedVolumeKey)] + if ok { + t.Errorf("Expected no volume limit found for %s", test.expectedVolumeKey) + } + } else { + fl, ok := volumeLimits[v1.ResourceName(test.expectedVolumeKey)] + + if !ok { + t.Errorf("Expected to found volume limit for %s found none", test.expectedVolumeKey) + } + foundLimit, _ := fl.AsInt64() + expectedValue := resource.NewQuantity(test.expectedLimit, resource.DecimalSI) + if expectedValue.Cmp(fl) != 0 { + t.Errorf("Expected volume limit for %s to be %v found %v", test.expectedVolumeKey, test.expectedLimit, foundLimit) + } + } + + } + + } +} diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index 46a17a01a58..0e9ea8682b7 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -30,7 +30,6 @@ import ( "sort" "strings" "sync" - "time" "github.com/golang/glog" "k8s.io/api/core/v1" @@ -41,7 +40,6 @@ import ( "k8s.io/apimachinery/pkg/util/sets" utilvalidation "k8s.io/apimachinery/pkg/util/validation" utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/client-go/tools/remotecommand" podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/api/v1/resource" podshelper "k8s.io/kubernetes/pkg/apis/core/pods" @@ -60,7 +58,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/status" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/format" - utilfile "k8s.io/kubernetes/pkg/util/file" mountutil "k8s.io/kubernetes/pkg/util/mount" volumeutil "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util/volumepathhandler" @@ -129,7 +126,8 @@ func (kl *Kubelet) makeBlockVolumes(pod *v1.Pod, container *v1.Container, podVol } // makeMounts determines the mount points for the given container. -func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, hostDomain, podIP string, podVolumes kubecontainer.VolumeMap, mounter mountutil.Interface) ([]kubecontainer.Mount, func(), error) { +func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, hostDomain, podIP string, podVolumes kubecontainer.VolumeMap, mounter mountutil.Interface, expandEnvs []kubecontainer.EnvVar) ([]kubecontainer.Mount, func(), error) { + // Kubernetes only mounts on /etc/hosts if: // - container is not an infrastructure (pause) container // - container is not already mounting on /etc/hosts @@ -166,6 +164,11 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h return nil, cleanupAction, fmt.Errorf("volume subpaths are disabled") } + // Expand subpath variables + if utilfeature.DefaultFeatureGate.Enabled(features.VolumeSubpathEnvExpansion) { + mount.SubPath = kubecontainer.ExpandContainerVolumeMounts(mount, expandEnvs) + } + if filepath.IsAbs(mount.SubPath) { return nil, cleanupAction, fmt.Errorf("error SubPath `%s` must not be an absolute path", mount.SubPath) } @@ -175,19 +178,10 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h return nil, cleanupAction, fmt.Errorf("unable to provision SubPath `%s`: %v", mount.SubPath, err) } - fileinfo, err := os.Lstat(hostPath) - if err != nil { - return nil, cleanupAction, err - } - perm := fileinfo.Mode() - - volumePath, err := filepath.EvalSymlinks(hostPath) - if err != nil { - return nil, cleanupAction, err - } + volumePath := hostPath hostPath = filepath.Join(volumePath, mount.SubPath) - if subPathExists, err := utilfile.FileOrSymlinkExists(hostPath); err != nil { + if subPathExists, err := mounter.ExistsPath(hostPath); err != nil { glog.Errorf("Could not determine if subPath %s exists; will not attempt to change its permissions", hostPath) } else if !subPathExists { // Create the sub path now because if it's auto-created later when referenced, it may have an @@ -195,10 +189,15 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h // when the pod specifies an fsGroup, and if the directory is not created here, Docker will // later auto-create it with the incorrect mode 0750 // Make extra care not to escape the volume! - if err := mounter.SafeMakeDir(hostPath, volumePath, perm); err != nil { - glog.Errorf("failed to mkdir %q: %v", hostPath, err) + perm, err := mounter.GetMode(volumePath) + if err != nil { return nil, cleanupAction, err } + if err := mounter.SafeMakeDir(mount.SubPath, volumePath, perm); err != nil { + // Don't pass detailed error back to the user because it could give information about host filesystem + glog.Errorf("failed to create subPath directory for volumeMount %q of container %q: %v", mount.Name, container.Name, err) + return nil, cleanupAction, fmt.Errorf("failed to create subPath directory for volumeMount %q of container %q", mount.Name, container.Name) + } } hostPath, cleanupAction, err = mounter.PrepareSafeSubpath(mountutil.Subpath{ VolumeMountIndex: i, @@ -207,7 +206,6 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h VolumePath: volumePath, PodDir: podDir, ContainerName: container.Name, - ReadOnly: mount.ReadOnly || vol.Mounter.GetAttributes().ReadOnly, }) if err != nil { // Don't pass detailed error back to the user because it could give information about host filesystem @@ -454,18 +452,18 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *v1.Pod, container *v1.Contai opts.Devices = append(opts.Devices, blkVolumes...) } - mounts, cleanupAction, err := makeMounts(pod, kl.getPodDir(pod.UID), container, hostname, hostDomainName, podIP, volumes, kl.mounter) + envs, err := kl.makeEnvironmentVariables(pod, container, podIP) + if err != nil { + return nil, nil, err + } + opts.Envs = append(opts.Envs, envs...) + + mounts, cleanupAction, err := makeMounts(pod, kl.getPodDir(pod.UID), container, hostname, hostDomainName, podIP, volumes, kl.mounter, opts.Envs) if err != nil { return nil, cleanupAction, err } opts.Mounts = append(opts.Mounts, mounts...) - envs, err := kl.makeEnvironmentVariables(pod, container, podIP) - if err != nil { - return nil, cleanupAction, err - } - opts.Envs = append(opts.Envs, envs...) - // Disabling adding TerminationMessagePath on Windows as these files would be mounted as docker volume and // Docker for Windows has a bug where only directories can be mounted if len(container.TerminationMessagePath) != 0 && runtime.GOOS != "windows" { @@ -1355,7 +1353,8 @@ func (kl *Kubelet) generateAPIPodStatus(pod *v1.Pod, podStatus *kubecontainer.Po } kl.probeManager.UpdatePodStatus(pod.UID, s) s.Conditions = append(s.Conditions, status.GeneratePodInitializedCondition(spec, s.InitContainerStatuses, s.Phase)) - s.Conditions = append(s.Conditions, status.GeneratePodReadyCondition(spec, s.ContainerStatuses, s.Phase)) + s.Conditions = append(s.Conditions, status.GeneratePodReadyCondition(spec, s.Conditions, s.ContainerStatuses, s.Phase)) + s.Conditions = append(s.Conditions, status.GenerateContainersReadyCondition(spec, s.ContainerStatuses, s.Phase)) // Status manager will take care of the LastTransitionTimestamp, either preserve // the timestamp from apiserver, or set a new one. When kubelet sees the pod, // `PodScheduled` condition must be true. @@ -1408,6 +1407,12 @@ func (kl *Kubelet) convertStatusToAPIStatus(pod *v1.Pod, podStatus *kubecontaine true, ) + // Preserves conditions not controlled by kubelet + for _, c := range pod.Status.Conditions { + if !kubetypes.PodConditionByKubelet(c.Type) { + apiPodStatus.Conditions = append(apiPodStatus.Conditions, c) + } + } return &apiPodStatus } @@ -1589,142 +1594,60 @@ func (kl *Kubelet) RunInContainer(podFullName string, podUID types.UID, containe return kl.runner.RunInContainer(container.ID, cmd, 0) } -// ExecInContainer executes a command in a container, connecting the supplied -// stdin/stdout/stderr to the command's IO streams. -func (kl *Kubelet) ExecInContainer(podFullName string, podUID types.UID, containerName string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error { - streamingRuntime, ok := kl.containerRuntime.(kubecontainer.DirectStreamingRuntime) - if !ok { - return fmt.Errorf("streaming methods not supported by runtime") - } - - container, err := kl.findContainer(podFullName, podUID, containerName) - if err != nil { - return err - } - if container == nil { - return fmt.Errorf("container not found (%q)", containerName) - } - return streamingRuntime.ExecInContainer(container.ID, cmd, stdin, stdout, stderr, tty, resize, timeout) -} - -// AttachContainer uses the container runtime to attach the given streams to -// the given container. -func (kl *Kubelet) AttachContainer(podFullName string, podUID types.UID, containerName string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - streamingRuntime, ok := kl.containerRuntime.(kubecontainer.DirectStreamingRuntime) - if !ok { - return fmt.Errorf("streaming methods not supported by runtime") - } - - container, err := kl.findContainer(podFullName, podUID, containerName) - if err != nil { - return err - } - if container == nil { - return fmt.Errorf("container not found (%q)", containerName) - } - return streamingRuntime.AttachContainer(container.ID, stdin, stdout, stderr, tty, resize) -} - -// PortForward connects to the pod's port and copies data between the port -// and the stream. -func (kl *Kubelet) PortForward(podFullName string, podUID types.UID, port int32, stream io.ReadWriteCloser) error { - streamingRuntime, ok := kl.containerRuntime.(kubecontainer.DirectStreamingRuntime) - if !ok { - return fmt.Errorf("streaming methods not supported by runtime") - } - - pods, err := kl.containerRuntime.GetPods(false) - if err != nil { - return err - } - // Resolve and type convert back again. - // We need the static pod UID but the kubecontainer API works with types.UID. - podUID = types.UID(kl.podManager.TranslatePodUID(podUID)) - pod := kubecontainer.Pods(pods).FindPod(podFullName, podUID) - if pod.IsEmpty() { - return fmt.Errorf("pod not found (%q)", podFullName) - } - return streamingRuntime.PortForward(&pod, port, stream) -} - // GetExec gets the URL the exec will be served from, or nil if the Kubelet will serve it. func (kl *Kubelet) GetExec(podFullName string, podUID types.UID, containerName string, cmd []string, streamOpts remotecommandserver.Options) (*url.URL, error) { - switch streamingRuntime := kl.containerRuntime.(type) { - case kubecontainer.DirectStreamingRuntime: - // Kubelet will serve the exec directly. - return nil, nil - case kubecontainer.IndirectStreamingRuntime: - container, err := kl.findContainer(podFullName, podUID, containerName) - if err != nil { - return nil, err - } - if container == nil { - return nil, fmt.Errorf("container not found (%q)", containerName) - } - return streamingRuntime.GetExec(container.ID, cmd, streamOpts.Stdin, streamOpts.Stdout, streamOpts.Stderr, streamOpts.TTY) - default: - return nil, fmt.Errorf("container runtime does not support exec") + container, err := kl.findContainer(podFullName, podUID, containerName) + if err != nil { + return nil, err } + if container == nil { + return nil, fmt.Errorf("container not found (%q)", containerName) + } + return kl.streamingRuntime.GetExec(container.ID, cmd, streamOpts.Stdin, streamOpts.Stdout, streamOpts.Stderr, streamOpts.TTY) } // GetAttach gets the URL the attach will be served from, or nil if the Kubelet will serve it. func (kl *Kubelet) GetAttach(podFullName string, podUID types.UID, containerName string, streamOpts remotecommandserver.Options) (*url.URL, error) { - switch streamingRuntime := kl.containerRuntime.(type) { - case kubecontainer.DirectStreamingRuntime: - // Kubelet will serve the attach directly. - return nil, nil - case kubecontainer.IndirectStreamingRuntime: - container, err := kl.findContainer(podFullName, podUID, containerName) - if err != nil { - return nil, err - } - if container == nil { - return nil, fmt.Errorf("container %s not found in pod %s", containerName, podFullName) - } - - // The TTY setting for attach must match the TTY setting in the initial container configuration, - // since whether the process is running in a TTY cannot be changed after it has started. We - // need the api.Pod to get the TTY status. - pod, found := kl.GetPodByFullName(podFullName) - if !found || (string(podUID) != "" && pod.UID != podUID) { - return nil, fmt.Errorf("pod %s not found", podFullName) - } - containerSpec := kubecontainer.GetContainerSpec(pod, containerName) - if containerSpec == nil { - return nil, fmt.Errorf("container %s not found in pod %s", containerName, podFullName) - } - tty := containerSpec.TTY - - return streamingRuntime.GetAttach(container.ID, streamOpts.Stdin, streamOpts.Stdout, streamOpts.Stderr, tty) - default: - return nil, fmt.Errorf("container runtime does not support attach") + container, err := kl.findContainer(podFullName, podUID, containerName) + if err != nil { + return nil, err } + if container == nil { + return nil, fmt.Errorf("container %s not found in pod %s", containerName, podFullName) + } + + // The TTY setting for attach must match the TTY setting in the initial container configuration, + // since whether the process is running in a TTY cannot be changed after it has started. We + // need the api.Pod to get the TTY status. + pod, found := kl.GetPodByFullName(podFullName) + if !found || (string(podUID) != "" && pod.UID != podUID) { + return nil, fmt.Errorf("pod %s not found", podFullName) + } + containerSpec := kubecontainer.GetContainerSpec(pod, containerName) + if containerSpec == nil { + return nil, fmt.Errorf("container %s not found in pod %s", containerName, podFullName) + } + tty := containerSpec.TTY + + return kl.streamingRuntime.GetAttach(container.ID, streamOpts.Stdin, streamOpts.Stdout, streamOpts.Stderr, tty) } // GetPortForward gets the URL the port-forward will be served from, or nil if the Kubelet will serve it. func (kl *Kubelet) GetPortForward(podName, podNamespace string, podUID types.UID, portForwardOpts portforward.V4Options) (*url.URL, error) { - switch streamingRuntime := kl.containerRuntime.(type) { - case kubecontainer.DirectStreamingRuntime: - // Kubelet will serve the attach directly. - return nil, nil - case kubecontainer.IndirectStreamingRuntime: - pods, err := kl.containerRuntime.GetPods(false) - if err != nil { - return nil, err - } - // Resolve and type convert back again. - // We need the static pod UID but the kubecontainer API works with types.UID. - podUID = types.UID(kl.podManager.TranslatePodUID(podUID)) - podFullName := kubecontainer.BuildPodFullName(podName, podNamespace) - pod := kubecontainer.Pods(pods).FindPod(podFullName, podUID) - if pod.IsEmpty() { - return nil, fmt.Errorf("pod not found (%q)", podFullName) - } - - return streamingRuntime.GetPortForward(podName, podNamespace, podUID, portForwardOpts.Ports) - default: - return nil, fmt.Errorf("container runtime does not support port-forward") + pods, err := kl.containerRuntime.GetPods(false) + if err != nil { + return nil, err } + // Resolve and type convert back again. + // We need the static pod UID but the kubecontainer API works with types.UID. + podUID = types.UID(kl.podManager.TranslatePodUID(podUID)) + podFullName := kubecontainer.BuildPodFullName(podName, podNamespace) + pod := kubecontainer.Pods(pods).FindPod(podFullName, podUID) + if pod.IsEmpty() { + return nil, fmt.Errorf("pod not found (%q)", podFullName) + } + + return kl.streamingRuntime.GetPortForward(podName, podNamespace, podUID, portForwardOpts.Ports) } // cleanupOrphanedPodCgroups removes cgroups that should no longer exist. diff --git a/pkg/kubelet/kubelet_pods_test.go b/pkg/kubelet/kubelet_pods_test.go index 9d2c813848b..f4fc43b5fe1 100644 --- a/pkg/kubelet/kubelet_pods_test.go +++ b/pkg/kubelet/kubelet_pods_test.go @@ -17,7 +17,6 @@ limitations under the License. package kubelet import ( - "bytes" "errors" "fmt" "io/ioutil" @@ -273,7 +272,7 @@ func TestMakeMounts(t *testing.T) { return } - mounts, _, err := makeMounts(&pod, "/pod", &tc.container, "fakepodname", "", "", tc.podVolumes, fm) + mounts, _, err := makeMounts(&pod, "/pod", &tc.container, "fakepodname", "", "", tc.podVolumes, fm, nil) // validate only the error if we expect an error if tc.expectErr { @@ -296,7 +295,7 @@ func TestMakeMounts(t *testing.T) { t.Errorf("Failed to enable feature gate for MountPropagation: %v", err) return } - mounts, _, err = makeMounts(&pod, "/pod", &tc.container, "fakepodname", "", "", tc.podVolumes, fm) + mounts, _, err = makeMounts(&pod, "/pod", &tc.container, "fakepodname", "", "", tc.podVolumes, fm, nil) if !tc.expectErr { expectedPrivateMounts := []kubecontainer.Mount{} for _, mount := range tc.expectedMounts { @@ -357,7 +356,7 @@ func TestDisabledSubpath(t *testing.T) { defer utilfeature.DefaultFeatureGate.Set("VolumeSubpath=true") for name, test := range cases { - _, _, err := makeMounts(&pod, "/pod", &test.container, "fakepodname", "", "", podVolumes, fm) + _, _, err := makeMounts(&pod, "/pod", &test.container, "fakepodname", "", "", podVolumes, fm, nil) if err != nil && !test.expectError { t.Errorf("test %v failed: %v", name, err) } @@ -2095,7 +2094,7 @@ func (f *fakeReadWriteCloser) Close() error { return nil } -func TestExec(t *testing.T) { +func TestGetExec(t *testing.T) { const ( podName = "podFoo" podNamespace = "nsFoo" @@ -2106,9 +2105,6 @@ func TestExec(t *testing.T) { var ( podFullName = kubecontainer.GetPodFullName(podWithUIDNameNs(podUID, podName, podNamespace)) command = []string{"ls"} - stdin = &bytes.Buffer{} - stdout = &fakeReadWriteCloser{} - stderr = &fakeReadWriteCloser{} ) testcases := []struct { @@ -2149,66 +2145,28 @@ func TestExec(t *testing.T) { }}, } - { // No streaming case - description := "no streaming - " + tc.description - redirect, err := kubelet.GetExec(tc.podFullName, podUID, tc.container, command, remotecommand.Options{}) - assert.Error(t, err, description) - assert.Nil(t, redirect, description) + description := "streaming - " + tc.description + fakeRuntime := &containertest.FakeStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} + kubelet.containerRuntime = fakeRuntime + kubelet.streamingRuntime = fakeRuntime - err = kubelet.ExecInContainer(tc.podFullName, podUID, tc.container, command, stdin, stdout, stderr, tty, nil, 0) + redirect, err := kubelet.GetExec(tc.podFullName, podUID, tc.container, command, remotecommand.Options{}) + if tc.expectError { assert.Error(t, err, description) - } - { // Direct streaming case - description := "direct streaming - " + tc.description - fakeRuntime := &containertest.FakeDirectStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} - kubelet.containerRuntime = fakeRuntime - - redirect, err := kubelet.GetExec(tc.podFullName, podUID, tc.container, command, remotecommand.Options{}) + } else { assert.NoError(t, err, description) - assert.Nil(t, redirect, description) - - err = kubelet.ExecInContainer(tc.podFullName, podUID, tc.container, command, stdin, stdout, stderr, tty, nil, 0) - if tc.expectError { - assert.Error(t, err, description) - } else { - assert.NoError(t, err, description) - assert.Equal(t, fakeRuntime.Args.ContainerID.ID, containerID, description+": ID") - assert.Equal(t, fakeRuntime.Args.Cmd, command, description+": Command") - assert.Equal(t, fakeRuntime.Args.Stdin, stdin, description+": Stdin") - assert.Equal(t, fakeRuntime.Args.Stdout, stdout, description+": Stdout") - assert.Equal(t, fakeRuntime.Args.Stderr, stderr, description+": Stderr") - assert.Equal(t, fakeRuntime.Args.TTY, tty, description+": TTY") - } - } - { // Indirect streaming case - description := "indirect streaming - " + tc.description - fakeRuntime := &containertest.FakeIndirectStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} - kubelet.containerRuntime = fakeRuntime - - redirect, err := kubelet.GetExec(tc.podFullName, podUID, tc.container, command, remotecommand.Options{}) - if tc.expectError { - assert.Error(t, err, description) - } else { - assert.NoError(t, err, description) - assert.Equal(t, containertest.FakeHost, redirect.Host, description+": redirect") - } - - err = kubelet.ExecInContainer(tc.podFullName, podUID, tc.container, command, stdin, stdout, stderr, tty, nil, 0) - assert.Error(t, err, description) + assert.Equal(t, containertest.FakeHost, redirect.Host, description+": redirect") } } } -func TestPortForward(t *testing.T) { +func TestGetPortForward(t *testing.T) { const ( podName = "podFoo" podNamespace = "nsFoo" podUID types.UID = "12345678" port int32 = 5000 ) - var ( - stream = &fakeReadWriteCloser{} - ) testcases := []struct { description string @@ -2240,50 +2198,17 @@ func TestPortForward(t *testing.T) { }}, } - podFullName := kubecontainer.GetPodFullName(podWithUIDNameNs(podUID, tc.podName, podNamespace)) - { // No streaming case - description := "no streaming - " + tc.description - redirect, err := kubelet.GetPortForward(tc.podName, podNamespace, podUID, portforward.V4Options{}) - assert.Error(t, err, description) - assert.Nil(t, redirect, description) + description := "streaming - " + tc.description + fakeRuntime := &containertest.FakeStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} + kubelet.containerRuntime = fakeRuntime + kubelet.streamingRuntime = fakeRuntime - err = kubelet.PortForward(podFullName, podUID, port, stream) + redirect, err := kubelet.GetPortForward(tc.podName, podNamespace, podUID, portforward.V4Options{}) + if tc.expectError { assert.Error(t, err, description) - } - { // Direct streaming case - description := "direct streaming - " + tc.description - fakeRuntime := &containertest.FakeDirectStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} - kubelet.containerRuntime = fakeRuntime - - redirect, err := kubelet.GetPortForward(tc.podName, podNamespace, podUID, portforward.V4Options{}) + } else { assert.NoError(t, err, description) - assert.Nil(t, redirect, description) - - err = kubelet.PortForward(podFullName, podUID, port, stream) - if tc.expectError { - assert.Error(t, err, description) - } else { - assert.NoError(t, err, description) - require.Equal(t, fakeRuntime.Args.Pod.ID, podUID, description+": Pod UID") - require.Equal(t, fakeRuntime.Args.Port, port, description+": Port") - require.Equal(t, fakeRuntime.Args.Stream, stream, description+": stream") - } - } - { // Indirect streaming case - description := "indirect streaming - " + tc.description - fakeRuntime := &containertest.FakeIndirectStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} - kubelet.containerRuntime = fakeRuntime - - redirect, err := kubelet.GetPortForward(tc.podName, podNamespace, podUID, portforward.V4Options{}) - if tc.expectError { - assert.Error(t, err, description) - } else { - assert.NoError(t, err, description) - assert.Equal(t, containertest.FakeHost, redirect.Host, description+": redirect") - } - - err = kubelet.PortForward(podFullName, podUID, port, stream) - assert.Error(t, err, description) + assert.Equal(t, containertest.FakeHost, redirect.Host, description+": redirect") } } } diff --git a/pkg/kubelet/kubelet_pods_windows_test.go b/pkg/kubelet/kubelet_pods_windows_test.go index cc16b358fb0..628c2ecdd7a 100644 --- a/pkg/kubelet/kubelet_pods_windows_test.go +++ b/pkg/kubelet/kubelet_pods_windows_test.go @@ -66,7 +66,7 @@ func TestMakeMountsWindows(t *testing.T) { } fm := &mount.FakeMounter{} - mounts, _, _ := makeMounts(&pod, "/pod", &container, "fakepodname", "", "", podVolumes, fm) + mounts, _, _ := makeMounts(&pod, "/pod", &container, "fakepodname", "", "", podVolumes, fm, nil) expectedMounts := []kubecontainer.Mount{ { diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index a3df9ae555f..fd18b128331 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -61,12 +61,16 @@ import ( "k8s.io/kubernetes/pkg/kubelet/stats" "k8s.io/kubernetes/pkg/kubelet/status" statustest "k8s.io/kubernetes/pkg/kubelet/status/testing" + "k8s.io/kubernetes/pkg/kubelet/token" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/queue" kubeletvolume "k8s.io/kubernetes/pkg/kubelet/volumemanager" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/aws_ebs" + "k8s.io/kubernetes/pkg/volume/azure_dd" + "k8s.io/kubernetes/pkg/volume/gce_pd" _ "k8s.io/kubernetes/pkg/volume/host_path" volumetest "k8s.io/kubernetes/pkg/volume/testing" "k8s.io/kubernetes/pkg/volume/util" @@ -133,13 +137,30 @@ func newTestKubelet(t *testing.T, controllerAttachDetachEnabled bool) *TestKubel Size: 456, }, } - return newTestKubeletWithImageList(t, imageList, controllerAttachDetachEnabled) + return newTestKubeletWithImageList(t, imageList, controllerAttachDetachEnabled, true /*initFakeVolumePlugin*/) +} + +func newTestKubeletWithoutFakeVolumePlugin(t *testing.T, controllerAttachDetachEnabled bool) *TestKubelet { + imageList := []kubecontainer.Image{ + { + ID: "abc", + RepoTags: []string{"k8s.gcr.io:v1", "k8s.gcr.io:v2"}, + Size: 123, + }, + { + ID: "efg", + RepoTags: []string{"k8s.gcr.io:v3", "k8s.gcr.io:v4"}, + Size: 456, + }, + } + return newTestKubeletWithImageList(t, imageList, controllerAttachDetachEnabled, false /*initFakeVolumePlugin*/) } func newTestKubeletWithImageList( t *testing.T, imageList []kubecontainer.Image, - controllerAttachDetachEnabled bool) *TestKubelet { + controllerAttachDetachEnabled bool, + initFakeVolumePlugin bool) *TestKubelet { fakeRuntime := &containertest.FakeRuntime{} fakeRuntime.RuntimeType = "test" fakeRuntime.VersionInfo = "1.5.0" @@ -293,10 +314,19 @@ func newTestKubeletWithImageList( // Add this as cleanup predicate pod admitter kubelet.admitHandlers.AddPodAdmitHandler(lifecycle.NewPredicateAdmitHandler(kubelet.getNodeAnyWay, lifecycle.NewAdmissionFailureHandlerStub(), kubelet.containerManager.UpdatePluginResources)) + allPlugins := []volume.VolumePlugin{} plug := &volumetest.FakeVolumePlugin{PluginName: "fake", Host: nil} + if initFakeVolumePlugin { + allPlugins = append(allPlugins, plug) + } else { + allPlugins = append(allPlugins, aws_ebs.ProbeVolumePlugins()...) + allPlugins = append(allPlugins, gce_pd.ProbeVolumePlugins()...) + allPlugins = append(allPlugins, azure_dd.ProbeVolumePlugins()...) + } + var prober volume.DynamicPluginProber = nil // TODO (#51147) inject mock kubelet.volumePluginMgr, err = - NewInitializedVolumePluginMgr(kubelet, kubelet.secretManager, kubelet.configMapManager, []volume.VolumePlugin{plug}, prober) + NewInitializedVolumePluginMgr(kubelet, kubelet.secretManager, kubelet.configMapManager, token.NewManager(kubelet.kubeClient), allPlugins, prober) require.NoError(t, err, "Failed to initialize VolumePluginMgr") kubelet.mounter = &mount.FakeMounter{} diff --git a/pkg/kubelet/kubelet_volumes_test.go b/pkg/kubelet/kubelet_volumes_test.go index efdcfcc3bf0..a82aa061632 100644 --- a/pkg/kubelet/kubelet_volumes_test.go +++ b/pkg/kubelet/kubelet_volumes_test.go @@ -463,6 +463,11 @@ func (f *stubBlockVolume) GetPodDeviceMapPath() (string, string) { func (f *stubBlockVolume) SetUpDevice() (string, error) { return "", nil } + +func (f stubBlockVolume) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return nil +} + func (f *stubBlockVolume) TearDownDevice(mapPath string, devicePath string) error { return nil } diff --git a/pkg/kubelet/kubeletconfig/status/status.go b/pkg/kubelet/kubeletconfig/status/status.go index 750a504cf3e..d1fdfeb8c9b 100644 --- a/pkg/kubelet/kubeletconfig/status/status.go +++ b/pkg/kubelet/kubeletconfig/status/status.go @@ -37,10 +37,6 @@ const ( // AllNilSubfieldsError is used when no subfields are set // This could happen in the case that an old client tries to read an object from a newer API server with a set subfield it does not know about AllNilSubfieldsError = "invalid NodeConfigSource, exactly one subfield must be non-nil, but all were nil" - // UIDMismatchErrorFmt is used when there is a UID mismatch between the referenced and downloaded ConfigMaps, - // this can happen because objects must be downloaded by namespace/name, rather than by UID - // TODO(mtaufen): remove this in #63221 - UIDMismatchErrorFmt = "invalid ConfigSource.ConfigMap.UID: %s does not match %s.UID: %s" // DownloadError is used when the download fails, e.g. due to network issues DownloadError = "failed to download config, see Kubelet log for details" // InternalError indicates that some internal error happened while trying to sync config, e.g. filesystem issues diff --git a/pkg/kubelet/kuberuntime/BUILD b/pkg/kubelet/kuberuntime/BUILD index 7fc904d311a..29121b94426 100644 --- a/pkg/kubelet/kuberuntime/BUILD +++ b/pkg/kubelet/kuberuntime/BUILD @@ -72,7 +72,6 @@ go_library( importpath = "k8s.io/kubernetes/pkg/kubelet/kuberuntime", deps = [ "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/core/v1/helper:go_default_library", "//pkg/credentialprovider:go_default_library", "//pkg/credentialprovider/secrets:go_default_library", "//pkg/features:go_default_library", diff --git a/pkg/kubelet/kuberuntime/helpers.go b/pkg/kubelet/kuberuntime/helpers.go index a1e6119a2a9..d52faa06407 100644 --- a/pkg/kubelet/kuberuntime/helpers.go +++ b/pkg/kubelet/kuberuntime/helpers.go @@ -26,7 +26,6 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" utilfeature "k8s.io/apiserver/pkg/util/feature" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/features" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" @@ -191,24 +190,6 @@ func toKubeRuntimeStatus(status *runtimeapi.RuntimeStatus) *kubecontainer.Runtim return &kubecontainer.RuntimeStatus{Conditions: conditions} } -// getSysctlsFromAnnotations gets sysctls and unsafeSysctls from annotations. -func getSysctlsFromAnnotations(annotations map[string]string) (map[string]string, error) { - apiSysctls, apiUnsafeSysctls, err := v1helper.SysctlsFromPodAnnotations(annotations) - if err != nil { - return nil, err - } - - sysctls := make(map[string]string) - for _, c := range apiSysctls { - sysctls[c.Name] = c.Value - } - for _, c := range apiUnsafeSysctls { - sysctls[c.Name] = c.Value - } - - return sysctls, nil -} - // getSeccompProfileFromAnnotations gets seccomp profile from annotations. // It gets pod's profile if containerName is empty. func (m *kubeGenericRuntimeManager) getSeccompProfileFromAnnotations(annotations map[string]string, containerName string) string { diff --git a/pkg/kubelet/kuberuntime/helpers_test.go b/pkg/kubelet/kuberuntime/helpers_test.go index f10fc04a236..0db2ad4d7ed 100644 --- a/pkg/kubelet/kuberuntime/helpers_test.go +++ b/pkg/kubelet/kuberuntime/helpers_test.go @@ -56,46 +56,6 @@ func TestStableKey(t *testing.T) { assert.NotEqual(t, oldKey, newKey) } -// TestGetSystclsFromAnnotations tests the logic of getting sysctls from annotations. -func TestGetSystclsFromAnnotations(t *testing.T) { - tests := []struct { - annotations map[string]string - expectedSysctls map[string]string - }{{ - annotations: map[string]string{ - v1.SysctlsPodAnnotationKey: "kernel.shmmni=32768,kernel.shmmax=1000000000", - v1.UnsafeSysctlsPodAnnotationKey: "knet.ipv4.route.min_pmtu=1000", - }, - expectedSysctls: map[string]string{ - "kernel.shmmni": "32768", - "kernel.shmmax": "1000000000", - "knet.ipv4.route.min_pmtu": "1000", - }, - }, { - annotations: map[string]string{ - v1.SysctlsPodAnnotationKey: "kernel.shmmni=32768,kernel.shmmax=1000000000", - }, - expectedSysctls: map[string]string{ - "kernel.shmmni": "32768", - "kernel.shmmax": "1000000000", - }, - }, { - annotations: map[string]string{ - v1.UnsafeSysctlsPodAnnotationKey: "knet.ipv4.route.min_pmtu=1000", - }, - expectedSysctls: map[string]string{ - "knet.ipv4.route.min_pmtu": "1000", - }, - }} - - for i, test := range tests { - actualSysctls, err := getSysctlsFromAnnotations(test.annotations) - assert.NoError(t, err, "TestCase[%d]", i) - assert.Len(t, actualSysctls, len(test.expectedSysctls), "TestCase[%d]", i) - assert.Equal(t, test.expectedSysctls, actualSysctls, "TestCase[%d]", i) - } -} - func TestToKubeContainer(t *testing.T) { c := &runtimeapi.Container{ Id: "test-id", diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container_windows.go b/pkg/kubelet/kuberuntime/kuberuntime_container_windows.go index 6ea1928cf93..77165e81b21 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container_windows.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container_windows.go @@ -19,24 +19,32 @@ limitations under the License. package kuberuntime import ( + "fmt" "github.com/docker/docker/pkg/sysinfo" "k8s.io/api/core/v1" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" + "k8s.io/kubernetes/pkg/securitycontext" ) // applyPlatformSpecificContainerConfig applies platform specific configurations to runtimeapi.ContainerConfig. func (m *kubeGenericRuntimeManager) applyPlatformSpecificContainerConfig(config *runtimeapi.ContainerConfig, container *v1.Container, pod *v1.Pod, uid *int64, username string) error { - config.Windows = m.generateWindowsContainerConfig(container, pod, uid, username) + windowsConfig, err := m.generateWindowsContainerConfig(container, pod, uid, username) + if err != nil { + return err + } + + config.Windows = windowsConfig return nil } // generateWindowsContainerConfig generates windows container config for kubelet runtime v1. // Refer https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/cri-windows.md. -func (m *kubeGenericRuntimeManager) generateWindowsContainerConfig(container *v1.Container, pod *v1.Pod, uid *int64, username string) *runtimeapi.WindowsContainerConfig { +func (m *kubeGenericRuntimeManager) generateWindowsContainerConfig(container *v1.Container, pod *v1.Pod, uid *int64, username string) (*runtimeapi.WindowsContainerConfig, error) { wc := &runtimeapi.WindowsContainerConfig{ - Resources: &runtimeapi.WindowsContainerResources{}, + Resources: &runtimeapi.WindowsContainerResources{}, + SecurityContext: &runtimeapi.WindowsContainerSecurityContext{}, } cpuRequest := container.Resources.Requests.Cpu() @@ -77,5 +85,15 @@ func (m *kubeGenericRuntimeManager) generateWindowsContainerConfig(container *v1 wc.Resources.MemoryLimitInBytes = memoryLimit } - return wc + // setup security context + effectiveSc := securitycontext.DetermineEffectiveSecurityContext(pod, container) + // RunAsUser only supports int64 from Kubernetes API, but Windows containers only support username. + if effectiveSc.RunAsUser != nil { + return nil, fmt.Errorf("run as uid (%d) is not supported on Windows", *effectiveSc.RunAsUser) + } + if username != "" { + wc.SecurityContext.RunAsUsername = username + } + + return wc, nil } diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager.go b/pkg/kubelet/kuberuntime/kuberuntime_manager.go index c34136b569a..df207fb4352 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager.go @@ -120,7 +120,7 @@ type kubeGenericRuntimeManager struct { type KubeGenericRuntime interface { kubecontainer.Runtime - kubecontainer.IndirectStreamingRuntime + kubecontainer.StreamingRuntime kubecontainer.ContainerCommandRunner } diff --git a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go index cddf3385d90..33d0881f11e 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go @@ -25,6 +25,8 @@ import ( "github.com/golang/glog" "k8s.io/api/core/v1" kubetypes "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/types" @@ -134,10 +136,15 @@ func (m *kubeGenericRuntimeManager) generatePodSandboxLinuxConfig(pod *v1.Pod) ( }, } - sysctls, err := getSysctlsFromAnnotations(pod.Annotations) - if err != nil { - return nil, fmt.Errorf("failed to get sysctls from annotations %v for pod %q: %v", pod.Annotations, format.Pod(pod), err) + sysctls := make(map[string]string) + if utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) { + if pod.Spec.SecurityContext != nil { + for _, c := range pod.Spec.SecurityContext.Sysctls { + sysctls[c.Name] = c.Value + } + } } + lc.Sysctls = sysctls if pod.Spec.SecurityContext != nil { diff --git a/pkg/kubelet/lifecycle/BUILD b/pkg/kubelet/lifecycle/BUILD index 54932656ae8..74be426ffe8 100644 --- a/pkg/kubelet/lifecycle/BUILD +++ b/pkg/kubelet/lifecycle/BUILD @@ -23,7 +23,7 @@ go_library( "//pkg/kubelet/util/format:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/security/apparmor:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", @@ -42,7 +42,7 @@ go_test( deps = [ "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/util/format:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", diff --git a/pkg/kubelet/lifecycle/predicate.go b/pkg/kubelet/lifecycle/predicate.go index e917acab37f..420bae21672 100644 --- a/pkg/kubelet/lifecycle/predicate.go +++ b/pkg/kubelet/lifecycle/predicate.go @@ -26,7 +26,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/util/format" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) type getNodeAnyWayFuncType func() (*v1.Node, error) diff --git a/pkg/kubelet/lifecycle/predicate_test.go b/pkg/kubelet/lifecycle/predicate_test.go index 325bafe0213..47b792fbbde 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) var ( diff --git a/pkg/kubelet/runonce_test.go b/pkg/kubelet/runonce_test.go index d8e943c1f75..6047d664bc0 100644 --- a/pkg/kubelet/runonce_test.go +++ b/pkg/kubelet/runonce_test.go @@ -90,7 +90,7 @@ func TestRunOnce(t *testing.T) { plug := &volumetest.FakeVolumePlugin{PluginName: "fake", Host: nil} kb.volumePluginMgr, err = - NewInitializedVolumePluginMgr(kb, fakeSecretManager, fakeConfigMapManager, []volume.VolumePlugin{plug}, nil /* prober */) + NewInitializedVolumePluginMgr(kb, fakeSecretManager, fakeConfigMapManager, nil, []volume.VolumePlugin{plug}, nil /* prober */) if err != nil { t.Fatalf("failed to initialize VolumePluginMgr: %v", err) } diff --git a/pkg/kubelet/server/BUILD b/pkg/kubelet/server/BUILD index c2e338a1ad8..69a71140f0f 100644 --- a/pkg/kubelet/server/BUILD +++ b/pkg/kubelet/server/BUILD @@ -37,7 +37,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/remotecommand:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/proxy:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", @@ -45,7 +45,6 @@ go_library( "//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/httplog:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flushwriter:go_default_library", - "//vendor/k8s.io/client-go/tools/remotecommand:go_default_library", ], ) @@ -60,13 +59,14 @@ go_test( deps = [ "//pkg/apis/core:go_default_library", "//pkg/apis/core/install:go_default_library", + "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", "//pkg/kubelet/apis/stats/v1alpha1:go_default_library", "//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/container/testing:go_default_library", "//pkg/kubelet/server/portforward:go_default_library", "//pkg/kubelet/server/remotecommand:go_default_library", "//pkg/kubelet/server/stats:go_default_library", + "//pkg/kubelet/server/streaming:go_default_library", "//pkg/volume:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go index fdde1fee4e8..b96bf6b1448 100644 --- a/pkg/kubelet/server/server.go +++ b/pkg/kubelet/server/server.go @@ -42,14 +42,13 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" - remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand" + "k8s.io/apimachinery/pkg/util/proxy" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/httplog" "k8s.io/apiserver/pkg/util/flushwriter" - "k8s.io/client-go/tools/remotecommand" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core/v1/validation" @@ -74,11 +73,11 @@ const ( // Server is a http.Handler which exposes kubelet functionality over HTTP. type Server struct { - auth AuthInterface - host HostInterface - restfulCont containerInterface - resourceAnalyzer stats.ResourceAnalyzer - runtime kubecontainer.Runtime + auth AuthInterface + host HostInterface + restfulCont containerInterface + resourceAnalyzer stats.ResourceAnalyzer + redirectContainerStreaming bool } type TLSOptions struct { @@ -124,11 +123,11 @@ func ListenAndServeKubeletServer( tlsOptions *TLSOptions, auth AuthInterface, enableDebuggingHandlers, - enableContentionProfiling bool, - runtime kubecontainer.Runtime, + enableContentionProfiling, + redirectContainerStreaming bool, criHandler http.Handler) { glog.Infof("Starting to listen on %s:%d", address, port) - handler := NewServer(host, resourceAnalyzer, auth, enableDebuggingHandlers, enableContentionProfiling, runtime, criHandler) + handler := NewServer(host, resourceAnalyzer, auth, enableDebuggingHandlers, enableContentionProfiling, redirectContainerStreaming, criHandler) s := &http.Server{ Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)), Handler: &handler, @@ -146,9 +145,9 @@ func ListenAndServeKubeletServer( } // ListenAndServeKubeletReadOnlyServer initializes a server to respond to HTTP network requests on the Kubelet. -func ListenAndServeKubeletReadOnlyServer(host HostInterface, resourceAnalyzer stats.ResourceAnalyzer, address net.IP, port uint, runtime kubecontainer.Runtime) { +func ListenAndServeKubeletReadOnlyServer(host HostInterface, resourceAnalyzer stats.ResourceAnalyzer, address net.IP, port uint) { glog.V(1).Infof("Starting to listen read-only on %s:%d", address, port) - s := NewServer(host, resourceAnalyzer, nil, false, false, runtime, nil) + s := NewServer(host, resourceAnalyzer, nil, false, false, false, nil) server := &http.Server{ Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)), @@ -173,12 +172,8 @@ type HostInterface interface { GetCachedMachineInfo() (*cadvisorapi.MachineInfo, error) GetRunningPods() ([]*v1.Pod, error) RunInContainer(name string, uid types.UID, container string, cmd []string) ([]byte, error) - ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error - AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error GetKubeletContainerLogs(podFullName, containerName string, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) error ServeLogs(w http.ResponseWriter, req *http.Request) - PortForward(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error - StreamingConnectionIdleTimeout() time.Duration ResyncInterval() time.Duration GetHostname() string LatestLoopEntryTime() time.Time @@ -193,15 +188,15 @@ func NewServer( resourceAnalyzer stats.ResourceAnalyzer, auth AuthInterface, enableDebuggingHandlers, - enableContentionProfiling bool, - runtime kubecontainer.Runtime, + enableContentionProfiling, + redirectContainerStreaming bool, criHandler http.Handler) Server { server := Server{ - host: host, - resourceAnalyzer: resourceAnalyzer, - auth: auth, - restfulCont: &filteringContainer{Container: restful.NewContainer()}, - runtime: runtime, + host: host, + resourceAnalyzer: resourceAnalyzer, + auth: auth, + restfulCont: &filteringContainer{Container: restful.NewContainer()}, + redirectContainerStreaming: redirectContainerStreaming, } if auth != nil { server.InstallAuthFilter() @@ -627,6 +622,22 @@ func getPortForwardRequestParams(req *restful.Request) portForwardRequestParams } } +type responder struct { + errorMessage string +} + +func (r *responder) Error(w http.ResponseWriter, req *http.Request, err error) { + glog.Errorf("Error while proxying request: %v", err) + http.Error(w, err.Error(), http.StatusInternalServerError) +} + +// proxyStream proxies stream to url. +func proxyStream(w http.ResponseWriter, r *http.Request, url *url.URL) { + // TODO(random-liu): Set MaxBytesPerSec to throttle the stream. + handler := proxy.NewUpgradeAwareHandler(url, nil /*transport*/, false /*wrapTransport*/, true /*upgradeRequired*/, &responder{}) + handler.ServeHTTP(w, r) +} + // getAttach handles requests to attach to a container. func (s *Server) getAttach(request *restful.Request, response *restful.Response) { params := getExecRequestParams(request) @@ -643,26 +654,17 @@ func (s *Server) getAttach(request *restful.Request, response *restful.Response) } podFullName := kubecontainer.GetPodFullName(pod) - redirect, err := s.host.GetAttach(podFullName, params.podUID, params.containerName, *streamOpts) + url, err := s.host.GetAttach(podFullName, params.podUID, params.containerName, *streamOpts) if err != nil { streaming.WriteError(err, response.ResponseWriter) return } - if redirect != nil { - http.Redirect(response.ResponseWriter, request.Request, redirect.String(), http.StatusFound) + + if s.redirectContainerStreaming { + http.Redirect(response.ResponseWriter, request.Request, url.String(), http.StatusFound) return } - - remotecommandserver.ServeAttach(response.ResponseWriter, - request.Request, - s.host, - podFullName, - params.podUID, - params.containerName, - streamOpts, - s.host.StreamingConnectionIdleTimeout(), - remotecommandconsts.DefaultStreamCreationTimeout, - remotecommandconsts.SupportedStreamingProtocols) + proxyStream(response.ResponseWriter, request.Request, url) } // getExec handles requests to run a command inside a container. @@ -681,27 +683,16 @@ func (s *Server) getExec(request *restful.Request, response *restful.Response) { } podFullName := kubecontainer.GetPodFullName(pod) - redirect, err := s.host.GetExec(podFullName, params.podUID, params.containerName, params.cmd, *streamOpts) + url, err := s.host.GetExec(podFullName, params.podUID, params.containerName, params.cmd, *streamOpts) if err != nil { streaming.WriteError(err, response.ResponseWriter) return } - if redirect != nil { - http.Redirect(response.ResponseWriter, request.Request, redirect.String(), http.StatusFound) + if s.redirectContainerStreaming { + http.Redirect(response.ResponseWriter, request.Request, url.String(), http.StatusFound) return } - - remotecommandserver.ServeExec(response.ResponseWriter, - request.Request, - s.host, - podFullName, - params.podUID, - params.containerName, - params.cmd, - streamOpts, - s.host.StreamingConnectionIdleTimeout(), - remotecommandconsts.DefaultStreamCreationTimeout, - remotecommandconsts.SupportedStreamingProtocols) + proxyStream(response.ResponseWriter, request.Request, url) } // getRun handles requests to run a command inside a container. @@ -758,25 +749,16 @@ func (s *Server) getPortForward(request *restful.Request, response *restful.Resp return } - redirect, err := s.host.GetPortForward(pod.Name, pod.Namespace, pod.UID, *portForwardOptions) + url, err := s.host.GetPortForward(pod.Name, pod.Namespace, pod.UID, *portForwardOptions) if err != nil { streaming.WriteError(err, response.ResponseWriter) return } - if redirect != nil { - http.Redirect(response.ResponseWriter, request.Request, redirect.String(), http.StatusFound) + if s.redirectContainerStreaming { + http.Redirect(response.ResponseWriter, request.Request, url.String(), http.StatusFound) return } - - portforward.ServePortForward(response.ResponseWriter, - request.Request, - s.host, - kubecontainer.GetPodFullName(pod), - params.podUID, - portForwardOptions, - s.host.StreamingConnectionIdleTimeout(), - remotecommandconsts.DefaultStreamCreationTimeout, - portforward.SupportedProtocols) + proxyStream(response.ResponseWriter, request.Request, url) } // ServeHTTP responds to HTTP requests on the Kubelet. diff --git a/pkg/kubelet/server/server_test.go b/pkg/kubelet/server/server_test.go index cdb978078cf..e84bec4d649 100644 --- a/pkg/kubelet/server/server_test.go +++ b/pkg/kubelet/server/server_test.go @@ -48,41 +48,44 @@ import ( "k8s.io/client-go/tools/remotecommand" utiltesting "k8s.io/client-go/util/testing" api "k8s.io/kubernetes/pkg/apis/core" + runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" // Do some initialization to decode the query parameters correctly. _ "k8s.io/kubernetes/pkg/apis/core/install" "k8s.io/kubernetes/pkg/kubelet/cm" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - kubecontainertesting "k8s.io/kubernetes/pkg/kubelet/container/testing" "k8s.io/kubernetes/pkg/kubelet/server/portforward" remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand" "k8s.io/kubernetes/pkg/kubelet/server/stats" + "k8s.io/kubernetes/pkg/kubelet/server/streaming" "k8s.io/kubernetes/pkg/volume" ) const ( - testUID = "9b01b80f-8fb4-11e4-95ab-4200af06647" + testUID = "9b01b80f-8fb4-11e4-95ab-4200af06647" + testContainerID = "container789" + testPodSandboxID = "pod0987" ) type fakeKubelet struct { - podByNameFunc func(namespace, name string) (*v1.Pod, bool) - containerInfoFunc func(podFullName string, uid types.UID, containerName string, req *cadvisorapi.ContainerInfoRequest) (*cadvisorapi.ContainerInfo, error) - rawInfoFunc func(query *cadvisorapi.ContainerInfoRequest) (map[string]*cadvisorapi.ContainerInfo, error) - machineInfoFunc func() (*cadvisorapi.MachineInfo, error) - podsFunc func() []*v1.Pod - runningPodsFunc func() ([]*v1.Pod, error) - logFunc func(w http.ResponseWriter, req *http.Request) - runFunc func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error) - execFunc func(pod string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool) error - attachFunc func(pod string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool) error - portForwardFunc func(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error - containerLogsFunc func(podFullName, containerName string, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) error - streamingConnectionIdleTimeoutFunc func() time.Duration - hostnameFunc func() string - resyncInterval time.Duration - loopEntryTime time.Time - plegHealth bool - redirectURL *url.URL + podByNameFunc func(namespace, name string) (*v1.Pod, bool) + containerInfoFunc func(podFullName string, uid types.UID, containerName string, req *cadvisorapi.ContainerInfoRequest) (*cadvisorapi.ContainerInfo, error) + rawInfoFunc func(query *cadvisorapi.ContainerInfoRequest) (map[string]*cadvisorapi.ContainerInfo, error) + machineInfoFunc func() (*cadvisorapi.MachineInfo, error) + podsFunc func() []*v1.Pod + runningPodsFunc func() ([]*v1.Pod, error) + logFunc func(w http.ResponseWriter, req *http.Request) + runFunc func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error) + getExecCheck func(string, types.UID, string, []string, remotecommandserver.Options) + getAttachCheck func(string, types.UID, string, remotecommandserver.Options) + getPortForwardCheck func(string, string, types.UID, portforward.V4Options) + + containerLogsFunc func(podFullName, containerName string, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) error + hostnameFunc func() string + resyncInterval time.Duration + loopEntryTime time.Time + plegHealth bool + streamingRuntime streaming.Server } func (fk *fakeKubelet) ResyncInterval() time.Duration { @@ -137,32 +140,109 @@ func (fk *fakeKubelet) RunInContainer(podFullName string, uid types.UID, contain return fk.runFunc(podFullName, uid, containerName, cmd) } -func (fk *fakeKubelet) ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error { - return fk.execFunc(name, uid, container, cmd, in, out, err, tty) +type fakeRuntime struct { + execFunc func(string, []string, io.Reader, io.WriteCloser, io.WriteCloser, bool, <-chan remotecommand.TerminalSize) error + attachFunc func(string, io.Reader, io.WriteCloser, io.WriteCloser, bool, <-chan remotecommand.TerminalSize) error + portForwardFunc func(string, int32, io.ReadWriteCloser) error } -func (fk *fakeKubelet) AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - return fk.attachFunc(name, uid, container, in, out, err, tty) +func (f *fakeRuntime) Exec(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { + return f.execFunc(containerID, cmd, stdin, stdout, stderr, tty, resize) } -func (fk *fakeKubelet) PortForward(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error { - return fk.portForwardFunc(name, uid, port, stream) +func (f *fakeRuntime) Attach(containerID string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { + return f.attachFunc(containerID, stdin, stdout, stderr, tty, resize) +} + +func (f *fakeRuntime) PortForward(podSandboxID string, port int32, stream io.ReadWriteCloser) error { + return f.portForwardFunc(podSandboxID, port, stream) +} + +type testStreamingServer struct { + streaming.Server + fakeRuntime *fakeRuntime + testHTTPServer *httptest.Server +} + +func newTestStreamingServer(streamIdleTimeout time.Duration) (s *testStreamingServer, err error) { + s = &testStreamingServer{} + s.testHTTPServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.ServeHTTP(w, r) + })) + defer func() { + if err != nil { + s.testHTTPServer.Close() + } + }() + + testURL, err := url.Parse(s.testHTTPServer.URL) + if err != nil { + return nil, err + } + + s.fakeRuntime = &fakeRuntime{} + config := streaming.DefaultConfig + config.BaseURL = testURL + if streamIdleTimeout != 0 { + config.StreamIdleTimeout = streamIdleTimeout + } + s.Server, err = streaming.NewServer(config, s.fakeRuntime) + if err != nil { + return nil, err + } + return s, nil } func (fk *fakeKubelet) GetExec(podFullName string, podUID types.UID, containerName string, cmd []string, streamOpts remotecommandserver.Options) (*url.URL, error) { - return fk.redirectURL, nil + if fk.getExecCheck != nil { + fk.getExecCheck(podFullName, podUID, containerName, cmd, streamOpts) + } + // Always use testContainerID + resp, err := fk.streamingRuntime.GetExec(&runtimeapi.ExecRequest{ + ContainerId: testContainerID, + Cmd: cmd, + Tty: streamOpts.TTY, + Stdin: streamOpts.Stdin, + Stdout: streamOpts.Stdout, + Stderr: streamOpts.Stderr, + }) + if err != nil { + return nil, err + } + return url.Parse(resp.GetUrl()) } func (fk *fakeKubelet) GetAttach(podFullName string, podUID types.UID, containerName string, streamOpts remotecommandserver.Options) (*url.URL, error) { - return fk.redirectURL, nil + if fk.getAttachCheck != nil { + fk.getAttachCheck(podFullName, podUID, containerName, streamOpts) + } + // Always use testContainerID + resp, err := fk.streamingRuntime.GetAttach(&runtimeapi.AttachRequest{ + ContainerId: testContainerID, + Tty: streamOpts.TTY, + Stdin: streamOpts.Stdin, + Stdout: streamOpts.Stdout, + Stderr: streamOpts.Stderr, + }) + if err != nil { + return nil, err + } + return url.Parse(resp.GetUrl()) } func (fk *fakeKubelet) GetPortForward(podName, podNamespace string, podUID types.UID, portForwardOpts portforward.V4Options) (*url.URL, error) { - return fk.redirectURL, nil -} - -func (fk *fakeKubelet) StreamingConnectionIdleTimeout() time.Duration { - return fk.streamingConnectionIdleTimeoutFunc() + if fk.getPortForwardCheck != nil { + fk.getPortForwardCheck(podName, podNamespace, podUID, portForwardOpts) + } + // Always use testPodSandboxID + resp, err := fk.streamingRuntime.GetPortForward(&runtimeapi.PortForwardRequest{ + PodSandboxId: testPodSandboxID, + Port: portForwardOpts.Ports, + }) + if err != nil { + return nil, err + } + return url.Parse(resp.GetUrl()) } // Unused functions @@ -199,18 +279,20 @@ func (f *fakeAuth) Authorize(a authorizer.Attributes) (authorized authorizer.Dec } type serverTestFramework struct { - serverUnderTest *Server - fakeKubelet *fakeKubelet - fakeAuth *fakeAuth - testHTTPServer *httptest.Server - criHandler *utiltesting.FakeHandler + serverUnderTest *Server + fakeKubelet *fakeKubelet + fakeAuth *fakeAuth + testHTTPServer *httptest.Server + fakeRuntime *fakeRuntime + testStreamingHTTPServer *httptest.Server + criHandler *utiltesting.FakeHandler } func newServerTest() *serverTestFramework { - return newServerTestWithDebug(true) + return newServerTestWithDebug(true, false, nil) } -func newServerTestWithDebug(enableDebugging bool) *serverTestFramework { +func newServerTestWithDebug(enableDebugging, redirectContainerStreaming bool, streamingServer streaming.Server) *serverTestFramework { fw := &serverTestFramework{} fw.fakeKubelet = &fakeKubelet{ hostnameFunc: func() string { @@ -225,7 +307,8 @@ func newServerTestWithDebug(enableDebugging bool) *serverTestFramework { }, }, true }, - plegHealth: true, + plegHealth: true, + streamingRuntime: streamingServer, } fw.fakeAuth = &fakeAuth{ authenticateFunc: func(req *http.Request) (user.Info, bool, error) { @@ -247,7 +330,7 @@ func newServerTestWithDebug(enableDebugging bool) *serverTestFramework { fw.fakeAuth, enableDebugging, false, - &kubecontainertesting.Mock{}, + redirectContainerStreaming, fw.criHandler) fw.serverUnderTest = &server fw.testHTTPServer = httptest.NewServer(fw.serverUnderTest) @@ -1070,13 +1153,12 @@ func TestContainerLogsWithFollow(t *testing.T) { } func TestServeExecInContainerIdleTimeout(t *testing.T) { - fw := newServerTest() + ss, err := newTestStreamingServer(100 * time.Millisecond) + require.NoError(t, err) + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, false, ss) defer fw.testHTTPServer.Close() - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 100 * time.Millisecond - } - podNamespace := "other" podName := "foo" expectedContainerName := "baz" @@ -1108,280 +1190,221 @@ func TestServeExecInContainerIdleTimeout(t *testing.T) { } func testExecAttach(t *testing.T, verb string) { - tests := []struct { + tests := map[string]struct { stdin bool stdout bool stderr bool tty bool responseStatusCode int uid bool - responseLocation string + redirect bool }{ - {responseStatusCode: http.StatusBadRequest}, - {stdin: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stdout: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stdout: true, stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stdout: true, stderr: true, tty: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stdin: true, stdout: true, stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stdout: true, responseStatusCode: http.StatusFound, responseLocation: "http://localhost:12345/" + verb}, + "no input or output": {responseStatusCode: http.StatusBadRequest}, + "stdin": {stdin: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stdout": {stdout: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stderr": {stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stdout and stderr": {stdout: true, stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stdout stderr and tty": {stdout: true, stderr: true, tty: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stdin stdout and stderr": {stdin: true, stdout: true, stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stdin stdout stderr with uid": {stdin: true, stdout: true, stderr: true, responseStatusCode: http.StatusSwitchingProtocols, uid: true}, + "stdout with redirect": {stdout: true, responseStatusCode: http.StatusFound, redirect: true}, } - for i, test := range tests { - fw := newServerTest() - defer fw.testHTTPServer.Close() - - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 0 - } - - if test.responseLocation != "" { - var err error - fw.fakeKubelet.redirectURL, err = url.Parse(test.responseLocation) + for desc, test := range tests { + test := test + t.Run(desc, func(t *testing.T) { + ss, err := newTestStreamingServer(0) require.NoError(t, err) - } + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, test.redirect, ss) + defer fw.testHTTPServer.Close() + fmt.Println(desc) - podNamespace := "other" - podName := "foo" - expectedPodName := getPodName(podName, podNamespace) - expectedContainerName := "baz" - expectedCommand := "ls -a" - expectedStdin := "stdin" - expectedStdout := "stdout" - expectedStderr := "stderr" - done := make(chan struct{}) - clientStdoutReadDone := make(chan struct{}) - clientStderrReadDone := make(chan struct{}) - execInvoked := false - attachInvoked := false + podNamespace := "other" + podName := "foo" + expectedPodName := getPodName(podName, podNamespace) + expectedContainerName := "baz" + expectedCommand := "ls -a" + expectedStdin := "stdin" + expectedStdout := "stdout" + expectedStderr := "stderr" + done := make(chan struct{}) + clientStdoutReadDone := make(chan struct{}) + clientStderrReadDone := make(chan struct{}) + execInvoked := false + attachInvoked := false - testStreamFunc := func(podFullName string, uid types.UID, containerName string, cmd []string, in io.Reader, out, stderr io.WriteCloser, tty bool, done chan struct{}) error { - defer close(done) + checkStream := func(podFullName string, uid types.UID, containerName string, streamOpts remotecommandserver.Options) { + assert.Equal(t, expectedPodName, podFullName, "podFullName") + if test.uid { + assert.Equal(t, testUID, string(uid), "uid") + } + assert.Equal(t, expectedContainerName, containerName, "containerName") + assert.Equal(t, test.stdin, streamOpts.Stdin, "stdin") + assert.Equal(t, test.stdout, streamOpts.Stdout, "stdout") + assert.Equal(t, test.tty, streamOpts.TTY, "tty") + assert.Equal(t, !test.tty && test.stderr, streamOpts.Stderr, "stderr") + } - if podFullName != expectedPodName { - t.Fatalf("%d: podFullName: expected %s, got %s", i, expectedPodName, podFullName) + fw.fakeKubelet.getExecCheck = func(podFullName string, uid types.UID, containerName string, cmd []string, streamOpts remotecommandserver.Options) { + execInvoked = true + assert.Equal(t, expectedCommand, strings.Join(cmd, " "), "cmd") + checkStream(podFullName, uid, containerName, streamOpts) } - if test.uid && string(uid) != testUID { - t.Fatalf("%d: uid: expected %v, got %v", i, testUID, uid) + + fw.fakeKubelet.getAttachCheck = func(podFullName string, uid types.UID, containerName string, streamOpts remotecommandserver.Options) { + attachInvoked = true + checkStream(podFullName, uid, containerName, streamOpts) } - if containerName != expectedContainerName { - t.Fatalf("%d: containerName: expected %s, got %s", i, expectedContainerName, containerName) + + testStream := func(containerID string, in io.Reader, out, stderr io.WriteCloser, tty bool, done chan struct{}) error { + close(done) + assert.Equal(t, testContainerID, containerID, "containerID") + assert.Equal(t, test.tty, tty, "tty") + require.Equal(t, test.stdin, in != nil, "in") + require.Equal(t, test.stdout, out != nil, "out") + require.Equal(t, !test.tty && test.stderr, stderr != nil, "err") + + if test.stdin { + b := make([]byte, 10) + n, err := in.Read(b) + assert.NoError(t, err, "reading from stdin") + assert.Equal(t, expectedStdin, string(b[0:n]), "content from stdin") + } + + if test.stdout { + _, err := out.Write([]byte(expectedStdout)) + assert.NoError(t, err, "writing to stdout") + out.Close() + <-clientStdoutReadDone + } + + if !test.tty && test.stderr { + _, err := stderr.Write([]byte(expectedStderr)) + assert.NoError(t, err, "writing to stderr") + stderr.Close() + <-clientStderrReadDone + } + return nil } + ss.fakeRuntime.execFunc = func(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { + assert.Equal(t, expectedCommand, strings.Join(cmd, " "), "cmd") + return testStream(containerID, stdin, stdout, stderr, tty, done) + } + + ss.fakeRuntime.attachFunc = func(containerID string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { + return testStream(containerID, stdin, stdout, stderr, tty, done) + } + + var url string + if test.uid { + url = fw.testHTTPServer.URL + "/" + verb + "/" + podNamespace + "/" + podName + "/" + testUID + "/" + expectedContainerName + "?ignore=1" + } else { + url = fw.testHTTPServer.URL + "/" + verb + "/" + podNamespace + "/" + podName + "/" + expectedContainerName + "?ignore=1" + } + if verb == "exec" { + url += "&command=ls&command=-a" + } + if test.stdin { + url += "&" + api.ExecStdinParam + "=1" + } + if test.stdout { + url += "&" + api.ExecStdoutParam + "=1" + } + if test.stderr && !test.tty { + url += "&" + api.ExecStderrParam + "=1" + } + if test.tty { + url += "&" + api.ExecTTYParam + "=1" + } + + var ( + resp *http.Response + upgradeRoundTripper httpstream.UpgradeRoundTripper + c *http.Client + ) + if test.redirect { + c = &http.Client{} + // Don't follow redirects, since we want to inspect the redirect response. + c.CheckRedirect = func(*http.Request, []*http.Request) error { + return http.ErrUseLastResponse + } + } else { + upgradeRoundTripper = spdy.NewRoundTripper(nil, true) + c = &http.Client{Transport: upgradeRoundTripper} + } + + resp, err = c.Post(url, "", nil) + require.NoError(t, err, "POSTing") + defer resp.Body.Close() + + _, err = ioutil.ReadAll(resp.Body) + assert.NoError(t, err, "reading response body") + + require.Equal(t, test.responseStatusCode, resp.StatusCode, "response status") + if test.responseStatusCode != http.StatusSwitchingProtocols { + return + } + + conn, err := upgradeRoundTripper.NewConnection(resp) + require.NoError(t, err, "creating streaming connection") + defer conn.Close() + + h := http.Header{} + h.Set(api.StreamType, api.StreamTypeError) + _, err = conn.CreateStream(h) + require.NoError(t, err, "creating error stream") + if test.stdin { - if in == nil { - t.Fatalf("%d: stdin: expected non-nil", i) - } - b := make([]byte, 10) - n, err := in.Read(b) - if err != nil { - t.Fatalf("%d: error reading from stdin: %v", i, err) - } - if e, a := expectedStdin, string(b[0:n]); e != a { - t.Fatalf("%d: stdin: expected to read %v, got %v", i, e, a) - } - } else if in != nil { - t.Fatalf("%d: stdin: expected nil: %#v", i, in) + h.Set(api.StreamType, api.StreamTypeStdin) + stream, err := conn.CreateStream(h) + require.NoError(t, err, "creating stdin stream") + _, err = stream.Write([]byte(expectedStdin)) + require.NoError(t, err, "writing to stdin stream") + } + + var stdoutStream httpstream.Stream + if test.stdout { + h.Set(api.StreamType, api.StreamTypeStdout) + stdoutStream, err = conn.CreateStream(h) + require.NoError(t, err, "creating stdout stream") + } + + var stderrStream httpstream.Stream + if test.stderr && !test.tty { + h.Set(api.StreamType, api.StreamTypeStderr) + stderrStream, err = conn.CreateStream(h) + require.NoError(t, err, "creating stderr stream") } if test.stdout { - if out == nil { - t.Fatalf("%d: stdout: expected non-nil", i) - } - _, err := out.Write([]byte(expectedStdout)) - if err != nil { - t.Fatalf("%d:, error writing to stdout: %v", i, err) - } - out.Close() - <-clientStdoutReadDone - } else if out != nil { - t.Fatalf("%d: stdout: expected nil: %#v", i, out) + output := make([]byte, 10) + n, err := stdoutStream.Read(output) + close(clientStdoutReadDone) + assert.NoError(t, err, "reading from stdout stream") + assert.Equal(t, expectedStdout, string(output[0:n]), "stdout") } - if tty { - if stderr != nil { - t.Fatalf("%d: tty set but received non-nil stderr: %v", i, stderr) - } - } else if test.stderr { - if stderr == nil { - t.Fatalf("%d: stderr: expected non-nil", i) - } - _, err := stderr.Write([]byte(expectedStderr)) - if err != nil { - t.Fatalf("%d:, error writing to stderr: %v", i, err) - } - stderr.Close() - <-clientStderrReadDone - } else if stderr != nil { - t.Fatalf("%d: stderr: expected nil: %#v", i, stderr) + if test.stderr && !test.tty { + output := make([]byte, 10) + n, err := stderrStream.Read(output) + close(clientStderrReadDone) + assert.NoError(t, err, "reading from stderr stream") + assert.Equal(t, expectedStderr, string(output[0:n]), "stderr") } - return nil - } + // wait for the server to finish before checking if the attach/exec funcs were invoked + <-done - fw.fakeKubelet.execFunc = func(podFullName string, uid types.UID, containerName string, cmd []string, in io.Reader, out, stderr io.WriteCloser, tty bool) error { - execInvoked = true - if strings.Join(cmd, " ") != expectedCommand { - t.Fatalf("%d: cmd: expected: %s, got %v", i, expectedCommand, cmd) + if verb == "exec" { + assert.True(t, execInvoked, "exec should be invoked") + assert.False(t, attachInvoked, "attach should not be invoked") + } else { + assert.True(t, attachInvoked, "attach should be invoked") + assert.False(t, execInvoked, "exec should not be invoked") } - return testStreamFunc(podFullName, uid, containerName, cmd, in, out, stderr, tty, done) - } - - fw.fakeKubelet.attachFunc = func(podFullName string, uid types.UID, containerName string, in io.Reader, out, stderr io.WriteCloser, tty bool) error { - attachInvoked = true - return testStreamFunc(podFullName, uid, containerName, nil, in, out, stderr, tty, done) - } - - var url string - if test.uid { - url = fw.testHTTPServer.URL + "/" + verb + "/" + podNamespace + "/" + podName + "/" + testUID + "/" + expectedContainerName + "?ignore=1" - } else { - url = fw.testHTTPServer.URL + "/" + verb + "/" + podNamespace + "/" + podName + "/" + expectedContainerName + "?ignore=1" - } - if verb == "exec" { - url += "&command=ls&command=-a" - } - if test.stdin { - url += "&" + api.ExecStdinParam + "=1" - } - if test.stdout { - url += "&" + api.ExecStdoutParam + "=1" - } - if test.stderr && !test.tty { - url += "&" + api.ExecStderrParam + "=1" - } - if test.tty { - url += "&" + api.ExecTTYParam + "=1" - } - - var ( - resp *http.Response - err error - upgradeRoundTripper httpstream.UpgradeRoundTripper - c *http.Client - ) - - if test.responseStatusCode != http.StatusSwitchingProtocols { - c = &http.Client{} - // Don't follow redirects, since we want to inspect the redirect response. - c.CheckRedirect = func(*http.Request, []*http.Request) error { - return http.ErrUseLastResponse - } - } else { - upgradeRoundTripper = spdy.NewRoundTripper(nil, true) - c = &http.Client{Transport: upgradeRoundTripper} - } - - resp, err = c.Post(url, "", nil) - if err != nil { - t.Fatalf("%d: Got error POSTing: %v", i, err) - } - defer resp.Body.Close() - - _, err = ioutil.ReadAll(resp.Body) - if err != nil { - t.Errorf("%d: Error reading response body: %v", i, err) - } - - if e, a := test.responseStatusCode, resp.StatusCode; e != a { - t.Fatalf("%d: response status: expected %v, got %v", i, e, a) - } - - if e, a := test.responseLocation, resp.Header.Get("Location"); e != a { - t.Errorf("%d: response location: expected %v, got %v", i, e, a) - } - - if test.responseStatusCode != http.StatusSwitchingProtocols { - continue - } - - conn, err := upgradeRoundTripper.NewConnection(resp) - if err != nil { - t.Fatalf("Unexpected error creating streaming connection: %s", err) - } - if conn == nil { - t.Fatalf("%d: unexpected nil conn", i) - } - defer conn.Close() - - h := http.Header{} - h.Set(api.StreamType, api.StreamTypeError) - if _, err := conn.CreateStream(h); err != nil { - t.Fatalf("%d: error creating error stream: %v", i, err) - } - - if test.stdin { - h.Set(api.StreamType, api.StreamTypeStdin) - stream, err := conn.CreateStream(h) - if err != nil { - t.Fatalf("%d: error creating stdin stream: %v", i, err) - } - _, err = stream.Write([]byte(expectedStdin)) - if err != nil { - t.Fatalf("%d: error writing to stdin stream: %v", i, err) - } - } - - var stdoutStream httpstream.Stream - if test.stdout { - h.Set(api.StreamType, api.StreamTypeStdout) - stdoutStream, err = conn.CreateStream(h) - if err != nil { - t.Fatalf("%d: error creating stdout stream: %v", i, err) - } - } - - var stderrStream httpstream.Stream - if test.stderr && !test.tty { - h.Set(api.StreamType, api.StreamTypeStderr) - stderrStream, err = conn.CreateStream(h) - if err != nil { - t.Fatalf("%d: error creating stderr stream: %v", i, err) - } - } - - if test.stdout { - output := make([]byte, 10) - n, err := stdoutStream.Read(output) - close(clientStdoutReadDone) - if err != nil { - t.Fatalf("%d: error reading from stdout stream: %v", i, err) - } - if e, a := expectedStdout, string(output[0:n]); e != a { - t.Fatalf("%d: stdout: expected '%v', got '%v'", i, e, a) - } - } - - if test.stderr && !test.tty { - output := make([]byte, 10) - n, err := stderrStream.Read(output) - close(clientStderrReadDone) - if err != nil { - t.Fatalf("%d: error reading from stderr stream: %v", i, err) - } - if e, a := expectedStderr, string(output[0:n]); e != a { - t.Fatalf("%d: stderr: expected '%v', got '%v'", i, e, a) - } - } - - // wait for the server to finish before checking if the attach/exec funcs were invoked - <-done - - if verb == "exec" { - if !execInvoked { - t.Errorf("%d: exec was not invoked", i) - } - if attachInvoked { - t.Errorf("%d: attach should not have been invoked", i) - } - } else { - if !attachInvoked { - t.Errorf("%d: attach was not invoked", i) - } - if execInvoked { - t.Errorf("%d: exec should not have been invoked", i) - } - } + }) } } @@ -1394,13 +1417,12 @@ func TestServeAttachContainer(t *testing.T) { } func TestServePortForwardIdleTimeout(t *testing.T) { - fw := newServerTest() + ss, err := newTestStreamingServer(100 * time.Millisecond) + require.NoError(t, err) + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, false, ss) defer fw.testHTTPServer.Close() - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 100 * time.Millisecond - } - podNamespace := "other" podName := "foo" @@ -1428,174 +1450,139 @@ func TestServePortForwardIdleTimeout(t *testing.T) { } func TestServePortForward(t *testing.T) { - tests := []struct { - port string - uid bool - clientData string - containerData string - shouldError bool - responseLocation string + tests := map[string]struct { + port string + uid bool + clientData string + containerData string + redirect bool + shouldError bool }{ - {port: "", shouldError: true}, - {port: "abc", shouldError: true}, - {port: "-1", shouldError: true}, - {port: "65536", shouldError: true}, - {port: "0", shouldError: true}, - {port: "1", shouldError: false}, - {port: "8000", shouldError: false}, - {port: "8000", clientData: "client data", containerData: "container data", shouldError: false}, - {port: "65535", shouldError: false}, - {port: "65535", uid: true, shouldError: false}, - {port: "65535", responseLocation: "http://localhost:12345/portforward", shouldError: false}, + "no port": {port: "", shouldError: true}, + "none number port": {port: "abc", shouldError: true}, + "negative port": {port: "-1", shouldError: true}, + "too large port": {port: "65536", shouldError: true}, + "0 port": {port: "0", shouldError: true}, + "min port": {port: "1", shouldError: false}, + "normal port": {port: "8000", shouldError: false}, + "normal port with data forward": {port: "8000", clientData: "client data", containerData: "container data", shouldError: false}, + "max port": {port: "65535", shouldError: false}, + "normal port with uid": {port: "8000", uid: true, shouldError: false}, + "normal port with redirect": {port: "8000", redirect: true, shouldError: false}, } podNamespace := "other" podName := "foo" - expectedPodName := getPodName(podName, podNamespace) - for i, test := range tests { - fw := newServerTest() - defer fw.testHTTPServer.Close() - - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 0 - } - - if test.responseLocation != "" { - var err error - fw.fakeKubelet.redirectURL, err = url.Parse(test.responseLocation) + for desc, test := range tests { + test := test + t.Run(desc, func(t *testing.T) { + ss, err := newTestStreamingServer(0) require.NoError(t, err) - } + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, test.redirect, ss) + defer fw.testHTTPServer.Close() - portForwardFuncDone := make(chan struct{}) + portForwardFuncDone := make(chan struct{}) - fw.fakeKubelet.portForwardFunc = func(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error { - defer close(portForwardFuncDone) - - if e, a := expectedPodName, name; e != a { - t.Fatalf("%d: pod name: expected '%v', got '%v'", i, e, a) + fw.fakeKubelet.getPortForwardCheck = func(name, namespace string, uid types.UID, opts portforward.V4Options) { + assert.Equal(t, podName, name, "pod name") + assert.Equal(t, podNamespace, namespace, "pod namespace") + if test.uid { + assert.Equal(t, testUID, string(uid), "uid") + } } - if e, a := testUID, uid; test.uid && e != string(a) { - t.Fatalf("%d: uid: expected '%v', got '%v'", i, e, a) + ss.fakeRuntime.portForwardFunc = func(podSandboxID string, port int32, stream io.ReadWriteCloser) error { + defer close(portForwardFuncDone) + assert.Equal(t, testPodSandboxID, podSandboxID, "pod sandbox id") + // The port should be valid if it reaches here. + testPort, err := strconv.ParseInt(test.port, 10, 32) + require.NoError(t, err, "parse port") + assert.Equal(t, int32(testPort), port, "port") + + if test.clientData != "" { + fromClient := make([]byte, 32) + n, err := stream.Read(fromClient) + assert.NoError(t, err, "reading client data") + assert.Equal(t, test.clientData, string(fromClient[0:n]), "client data") + } + + if test.containerData != "" { + _, err := stream.Write([]byte(test.containerData)) + assert.NoError(t, err, "writing container data") + } + + return nil } - p, err := strconv.ParseInt(test.port, 10, 32) - if err != nil { - t.Fatalf("%d: error parsing port string '%s': %v", i, test.port, err) + var url string + if test.uid { + url = fmt.Sprintf("%s/portForward/%s/%s/%s", fw.testHTTPServer.URL, podNamespace, podName, testUID) + } else { + url = fmt.Sprintf("%s/portForward/%s/%s", fw.testHTTPServer.URL, podNamespace, podName) } - if e, a := int32(p), port; e != a { - t.Fatalf("%d: port: expected '%v', got '%v'", i, e, a) + + var ( + upgradeRoundTripper httpstream.UpgradeRoundTripper + c *http.Client + ) + + if test.redirect { + c = &http.Client{} + // Don't follow redirects, since we want to inspect the redirect response. + c.CheckRedirect = func(*http.Request, []*http.Request) error { + return http.ErrUseLastResponse + } + } else { + upgradeRoundTripper = spdy.NewRoundTripper(nil, true) + c = &http.Client{Transport: upgradeRoundTripper} } + resp, err := c.Post(url, "", nil) + require.NoError(t, err, "POSTing") + defer resp.Body.Close() + + if test.redirect { + assert.Equal(t, http.StatusFound, resp.StatusCode, "status code") + return + } else { + assert.Equal(t, http.StatusSwitchingProtocols, resp.StatusCode, "status code") + } + + conn, err := upgradeRoundTripper.NewConnection(resp) + require.NoError(t, err, "creating streaming connection") + defer conn.Close() + + headers := http.Header{} + headers.Set("streamType", "error") + headers.Set("port", test.port) + _, err = conn.CreateStream(headers) + assert.Equal(t, test.shouldError, err != nil, "expect error") + + if test.shouldError { + return + } + + headers.Set("streamType", "data") + headers.Set("port", test.port) + dataStream, err := conn.CreateStream(headers) + require.NoError(t, err, "create stream") + if test.clientData != "" { - fromClient := make([]byte, 32) - n, err := stream.Read(fromClient) - if err != nil { - t.Fatalf("%d: error reading client data: %v", i, err) - } - if e, a := test.clientData, string(fromClient[0:n]); e != a { - t.Fatalf("%d: client data: expected to receive '%v', got '%v'", i, e, a) - } + _, err := dataStream.Write([]byte(test.clientData)) + assert.NoError(t, err, "writing client data") } if test.containerData != "" { - _, err := stream.Write([]byte(test.containerData)) - if err != nil { - t.Fatalf("%d: error writing container data: %v", i, err) - } + fromContainer := make([]byte, 32) + n, err := dataStream.Read(fromContainer) + assert.NoError(t, err, "reading container data") + assert.Equal(t, test.containerData, string(fromContainer[0:n]), "container data") } - return nil - } - - var url string - if test.uid { - url = fmt.Sprintf("%s/portForward/%s/%s/%s", fw.testHTTPServer.URL, podNamespace, podName, testUID) - } else { - url = fmt.Sprintf("%s/portForward/%s/%s", fw.testHTTPServer.URL, podNamespace, podName) - } - - var ( - upgradeRoundTripper httpstream.UpgradeRoundTripper - c *http.Client - ) - - if len(test.responseLocation) > 0 { - c = &http.Client{} - // Don't follow redirects, since we want to inspect the redirect response. - c.CheckRedirect = func(*http.Request, []*http.Request) error { - return http.ErrUseLastResponse - } - } else { - upgradeRoundTripper = spdy.NewRoundTripper(nil, true) - c = &http.Client{Transport: upgradeRoundTripper} - } - - resp, err := c.Post(url, "", nil) - if err != nil { - t.Fatalf("%d: Got error POSTing: %v", i, err) - } - defer resp.Body.Close() - - if test.responseLocation != "" { - assert.Equal(t, http.StatusFound, resp.StatusCode, "%d: status code", i) - assert.Equal(t, test.responseLocation, resp.Header.Get("Location"), "%d: location", i) - continue - } else { - assert.Equal(t, http.StatusSwitchingProtocols, resp.StatusCode, "%d: status code", i) - } - - conn, err := upgradeRoundTripper.NewConnection(resp) - if err != nil { - t.Fatalf("Unexpected error creating streaming connection: %s", err) - } - if conn == nil { - t.Fatalf("%d: Unexpected nil connection", i) - } - defer conn.Close() - - headers := http.Header{} - headers.Set("streamType", "error") - headers.Set("port", test.port) - errorStream, err := conn.CreateStream(headers) - _ = errorStream - haveErr := err != nil - if e, a := test.shouldError, haveErr; e != a { - t.Fatalf("%d: create stream: expected err=%t, got %t: %v", i, e, a, err) - } - - if test.shouldError { - continue - } - - headers.Set("streamType", "data") - headers.Set("port", test.port) - dataStream, err := conn.CreateStream(headers) - haveErr = err != nil - if e, a := test.shouldError, haveErr; e != a { - t.Fatalf("%d: create stream: expected err=%t, got %t: %v", i, e, a, err) - } - - if test.clientData != "" { - _, err := dataStream.Write([]byte(test.clientData)) - if err != nil { - t.Fatalf("%d: unexpected error writing client data: %v", i, err) - } - } - - if test.containerData != "" { - fromContainer := make([]byte, 32) - n, err := dataStream.Read(fromContainer) - if err != nil { - t.Fatalf("%d: unexpected error reading container data: %v", i, err) - } - if e, a := test.containerData, string(fromContainer[0:n]); e != a { - t.Fatalf("%d: expected to receive '%v' from container, got '%v'", i, e, a) - } - } - - <-portForwardFuncDone + <-portForwardFuncDone + }) } } @@ -1616,7 +1603,7 @@ func TestCRIHandler(t *testing.T) { } func TestDebuggingDisabledHandlers(t *testing.T) { - fw := newServerTestWithDebug(false) + fw := newServerTestWithDebug(false, false, nil) defer fw.testHTTPServer.Close() paths := []string{ diff --git a/pkg/kubelet/server/server_websocket_test.go b/pkg/kubelet/server/server_websocket_test.go index 058b67d978a..daf6d356b63 100644 --- a/pkg/kubelet/server/server_websocket_test.go +++ b/pkg/kubelet/server/server_websocket_test.go @@ -23,11 +23,13 @@ import ( "strconv" "sync" "testing" - "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "golang.org/x/net/websocket" "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/kubelet/server/portforward" ) const ( @@ -36,152 +38,114 @@ const ( ) func TestServeWSPortForward(t *testing.T) { - tests := []struct { + tests := map[string]struct { port string uid bool clientData string containerData string shouldError bool }{ - {port: "", shouldError: true}, - {port: "abc", shouldError: true}, - {port: "-1", shouldError: true}, - {port: "65536", shouldError: true}, - {port: "0", shouldError: true}, - {port: "1", shouldError: false}, - {port: "8000", shouldError: false}, - {port: "8000", clientData: "client data", containerData: "container data", shouldError: false}, - {port: "65535", shouldError: false}, - {port: "65535", uid: true, shouldError: false}, + "no port": {port: "", shouldError: true}, + "none number port": {port: "abc", shouldError: true}, + "negative port": {port: "-1", shouldError: true}, + "too large port": {port: "65536", shouldError: true}, + "0 port": {port: "0", shouldError: true}, + "min port": {port: "1", shouldError: false}, + "normal port": {port: "8000", shouldError: false}, + "normal port with data forward": {port: "8000", clientData: "client data", containerData: "container data", shouldError: false}, + "max port": {port: "65535", shouldError: false}, + "normal port with uid": {port: "8000", uid: true, shouldError: false}, } podNamespace := "other" podName := "foo" - expectedPodName := getPodName(podName, podNamespace) - expectedUid := "9b01b80f-8fb4-11e4-95ab-4200af06647" - for i, test := range tests { - fw := newServerTest() - defer fw.testHTTPServer.Close() + for desc, test := range tests { + test := test + t.Run(desc, func(t *testing.T) { + ss, err := newTestStreamingServer(0) + require.NoError(t, err) + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, false, ss) + defer fw.testHTTPServer.Close() - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 0 - } + portForwardFuncDone := make(chan struct{}) - portForwardFuncDone := make(chan struct{}) - - fw.fakeKubelet.portForwardFunc = func(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error { - defer close(portForwardFuncDone) - - if e, a := expectedPodName, name; e != a { - t.Fatalf("%d: pod name: expected '%v', got '%v'", i, e, a) + fw.fakeKubelet.getPortForwardCheck = func(name, namespace string, uid types.UID, opts portforward.V4Options) { + assert.Equal(t, podName, name, "pod name") + assert.Equal(t, podNamespace, namespace, "pod namespace") + if test.uid { + assert.Equal(t, testUID, string(uid), "uid") + } } - if e, a := expectedUid, uid; test.uid && e != string(a) { - t.Fatalf("%d: uid: expected '%v', got '%v'", i, e, a) + ss.fakeRuntime.portForwardFunc = func(podSandboxID string, port int32, stream io.ReadWriteCloser) error { + defer close(portForwardFuncDone) + assert.Equal(t, testPodSandboxID, podSandboxID, "pod sandbox id") + // The port should be valid if it reaches here. + testPort, err := strconv.ParseInt(test.port, 10, 32) + require.NoError(t, err, "parse port") + assert.Equal(t, int32(testPort), port, "port") + + if test.clientData != "" { + fromClient := make([]byte, 32) + n, err := stream.Read(fromClient) + assert.NoError(t, err, "reading client data") + assert.Equal(t, test.clientData, string(fromClient[0:n]), "client data") + } + + if test.containerData != "" { + _, err := stream.Write([]byte(test.containerData)) + assert.NoError(t, err, "writing container data") + } + + return nil } - p, err := strconv.ParseInt(test.port, 10, 32) - if err != nil { - t.Fatalf("%d: error parsing port string '%s': %v", i, test.port, err) + var url string + if test.uid { + url = fmt.Sprintf("ws://%s/portForward/%s/%s/%s?port=%s", fw.testHTTPServer.Listener.Addr().String(), podNamespace, podName, testUID, test.port) + } else { + url = fmt.Sprintf("ws://%s/portForward/%s/%s?port=%s", fw.testHTTPServer.Listener.Addr().String(), podNamespace, podName, test.port) } - if e, a := int32(p), port; e != a { - t.Fatalf("%d: port: expected '%v', got '%v'", i, e, a) + + ws, err := websocket.Dial(url, "", "http://127.0.0.1/") + assert.Equal(t, test.shouldError, err != nil, "websocket dial") + if test.shouldError { + return } + defer ws.Close() + + p, err := strconv.ParseUint(test.port, 10, 16) + require.NoError(t, err, "parse port") + p16 := uint16(p) + + channel, data, err := wsRead(ws) + require.NoError(t, err, "read") + assert.Equal(t, dataChannel, int(channel), "channel") + assert.Len(t, data, binary.Size(p16), "data size") + assert.Equal(t, p16, binary.LittleEndian.Uint16(data), "data") + + channel, data, err = wsRead(ws) + assert.NoError(t, err, "read") + assert.Equal(t, errorChannel, int(channel), "channel") + assert.Len(t, data, binary.Size(p16), "data size") + assert.Equal(t, p16, binary.LittleEndian.Uint16(data), "data") if test.clientData != "" { - fromClient := make([]byte, 32) - n, err := stream.Read(fromClient) - if err != nil { - t.Fatalf("%d: error reading client data: %v", i, err) - } - if e, a := test.clientData, string(fromClient[0:n]); e != a { - t.Fatalf("%d: client data: expected to receive '%v', got '%v'", i, e, a) - } + println("writing the client data") + err := wsWrite(ws, dataChannel, []byte(test.clientData)) + assert.NoError(t, err, "writing client data") } if test.containerData != "" { - _, err := stream.Write([]byte(test.containerData)) - if err != nil { - t.Fatalf("%d: error writing container data: %v", i, err) - } + _, data, err = wsRead(ws) + assert.NoError(t, err, "reading container data") + assert.Equal(t, test.containerData, string(data), "container data") } - return nil - } - - var url string - if test.uid { - url = fmt.Sprintf("ws://%s/portForward/%s/%s/%s?port=%s", fw.testHTTPServer.Listener.Addr().String(), podNamespace, podName, expectedUid, test.port) - } else { - url = fmt.Sprintf("ws://%s/portForward/%s/%s?port=%s", fw.testHTTPServer.Listener.Addr().String(), podNamespace, podName, test.port) - } - - ws, err := websocket.Dial(url, "", "http://127.0.0.1/") - if test.shouldError { - if err == nil { - t.Fatalf("%d: websocket dial expected err", i) - } - continue - } else if err != nil { - t.Fatalf("%d: websocket dial unexpected err: %v", i, err) - } - - defer ws.Close() - - p, err := strconv.ParseUint(test.port, 10, 16) - if err != nil { - t.Fatalf("%d: error parsing port string '%s': %v", i, test.port, err) - } - p16 := uint16(p) - - channel, data, err := wsRead(ws) - if err != nil { - t.Fatalf("%d: read failed: expected no error: got %v", i, err) - } - if channel != dataChannel { - t.Fatalf("%d: wrong channel: got %q: expected %q", i, channel, dataChannel) - } - if len(data) != binary.Size(p16) { - t.Fatalf("%d: wrong data size: got %q: expected %d", i, data, binary.Size(p16)) - } - if e, a := p16, binary.LittleEndian.Uint16(data); e != a { - t.Fatalf("%d: wrong data: got %q: expected %s", i, data, test.port) - } - - channel, data, err = wsRead(ws) - if err != nil { - t.Fatalf("%d: read succeeded: expected no error: got %v", i, err) - } - if channel != errorChannel { - t.Fatalf("%d: wrong channel: got %q: expected %q", i, channel, errorChannel) - } - if len(data) != binary.Size(p16) { - t.Fatalf("%d: wrong data size: got %q: expected %d", i, data, binary.Size(p16)) - } - if e, a := p16, binary.LittleEndian.Uint16(data); e != a { - t.Fatalf("%d: wrong data: got %q: expected %s", i, data, test.port) - } - - if test.clientData != "" { - println("writing the client data") - err := wsWrite(ws, dataChannel, []byte(test.clientData)) - if err != nil { - t.Fatalf("%d: unexpected error writing client data: %v", i, err) - } - } - - if test.containerData != "" { - _, data, err = wsRead(ws) - if err != nil { - t.Fatalf("%d: unexpected error reading container data: %v", i, err) - } - if e, a := test.containerData, string(data); e != a { - t.Fatalf("%d: expected to receive '%v' from container, got '%v'", i, e, a) - } - } - - <-portForwardFuncDone + <-portForwardFuncDone + }) } } @@ -190,27 +154,27 @@ func TestServeWSMultiplePortForward(t *testing.T) { ports := []uint16{7000, 8000, 9000} podNamespace := "other" podName := "foo" - expectedPodName := getPodName(podName, podNamespace) - fw := newServerTest() + ss, err := newTestStreamingServer(0) + require.NoError(t, err) + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, false, ss) defer fw.testHTTPServer.Close() - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 0 - } - portForwardWG := sync.WaitGroup{} portForwardWG.Add(len(ports)) portsMutex := sync.Mutex{} portsForwarded := map[int32]struct{}{} - fw.fakeKubelet.portForwardFunc = func(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error { - defer portForwardWG.Done() + fw.fakeKubelet.getPortForwardCheck = func(name, namespace string, uid types.UID, opts portforward.V4Options) { + assert.Equal(t, podName, name, "pod name") + assert.Equal(t, podNamespace, namespace, "pod namespace") + } - if e, a := expectedPodName, name; e != a { - t.Fatalf("%d: pod name: expected '%v', got '%v'", port, e, a) - } + ss.fakeRuntime.portForwardFunc = func(podSandboxID string, port int32, stream io.ReadWriteCloser) error { + defer portForwardWG.Done() + assert.Equal(t, testPodSandboxID, podSandboxID, "pod sandbox id") portsMutex.Lock() portsForwarded[port] = struct{}{} @@ -218,17 +182,11 @@ func TestServeWSMultiplePortForward(t *testing.T) { fromClient := make([]byte, 32) n, err := stream.Read(fromClient) - if err != nil { - t.Fatalf("%d: error reading client data: %v", port, err) - } - if e, a := fmt.Sprintf("client data on port %d", port), string(fromClient[0:n]); e != a { - t.Fatalf("%d: client data: expected to receive '%v', got '%v'", port, e, a) - } + assert.NoError(t, err, "reading client data") + assert.Equal(t, fmt.Sprintf("client data on port %d", port), string(fromClient[0:n]), "client data") _, err = stream.Write([]byte(fmt.Sprintf("container data on port %d", port))) - if err != nil { - t.Fatalf("%d: error writing container data: %v", port, err) - } + assert.NoError(t, err, "writing container data") return nil } @@ -239,70 +197,42 @@ func TestServeWSMultiplePortForward(t *testing.T) { } ws, err := websocket.Dial(url, "", "http://127.0.0.1/") - if err != nil { - t.Fatalf("websocket dial unexpected err: %v", err) - } + require.NoError(t, err, "websocket dial") defer ws.Close() for i, port := range ports { channel, data, err := wsRead(ws) - if err != nil { - t.Fatalf("%d: read failed: expected no error: got %v", i, err) - } - if int(channel) != i*2+dataChannel { - t.Fatalf("%d: wrong channel: got %q: expected %q", i, channel, i*2+dataChannel) - } - if len(data) != binary.Size(port) { - t.Fatalf("%d: wrong data size: got %q: expected %d", i, data, binary.Size(port)) - } - if e, a := port, binary.LittleEndian.Uint16(data); e != a { - t.Fatalf("%d: wrong data: got %q: expected %d", i, data, port) - } + assert.NoError(t, err, "port %d read", port) + assert.Equal(t, i*2+dataChannel, int(channel), "port %d channel", port) + assert.Len(t, data, binary.Size(port), "port %d data size", port) + assert.Equal(t, binary.LittleEndian.Uint16(data), port, "port %d data", port) channel, data, err = wsRead(ws) - if err != nil { - t.Fatalf("%d: read succeeded: expected no error: got %v", i, err) - } - if int(channel) != i*2+errorChannel { - t.Fatalf("%d: wrong channel: got %q: expected %q", i, channel, i*2+errorChannel) - } - if len(data) != binary.Size(port) { - t.Fatalf("%d: wrong data size: got %q: expected %d", i, data, binary.Size(port)) - } - if e, a := port, binary.LittleEndian.Uint16(data); e != a { - t.Fatalf("%d: wrong data: got %q: expected %d", i, data, port) - } + assert.NoError(t, err, "port %d read", port) + assert.Equal(t, i*2+errorChannel, int(channel), "port %d channel", port) + assert.Len(t, data, binary.Size(port), "port %d data size", port) + assert.Equal(t, binary.LittleEndian.Uint16(data), port, "port %d data", port) } for i, port := range ports { - println("writing the client data", port) + t.Logf("port %d writing the client data", port) err := wsWrite(ws, byte(i*2+dataChannel), []byte(fmt.Sprintf("client data on port %d", port))) - if err != nil { - t.Fatalf("%d: unexpected error writing client data: %v", i, err) - } + assert.NoError(t, err, "port %d write client data", port) channel, data, err := wsRead(ws) - if err != nil { - t.Fatalf("%d: unexpected error reading container data: %v", i, err) - } - - if int(channel) != i*2+dataChannel { - t.Fatalf("%d: wrong channel: got %q: expected %q", port, channel, i*2+dataChannel) - } - if e, a := fmt.Sprintf("container data on port %d", port), string(data); e != a { - t.Fatalf("%d: expected to receive '%v' from container, got '%v'", i, e, a) - } + assert.NoError(t, err, "port %d read container data", port) + assert.Equal(t, i*2+dataChannel, int(channel), "port %d channel", port) + assert.Equal(t, fmt.Sprintf("container data on port %d", port), string(data), "port %d container data", port) } portForwardWG.Wait() portsMutex.Lock() defer portsMutex.Unlock() - if len(ports) != len(portsForwarded) { - t.Fatalf("expected to forward %d ports; got %v", len(ports), portsForwarded) - } + assert.Len(t, portsForwarded, len(ports), "all ports forwarded") } + func wsWrite(conn *websocket.Conn, channel byte, data []byte) error { frame := make([]byte, len(data)+1) frame[0] = channel diff --git a/pkg/kubelet/server/streaming/server.go b/pkg/kubelet/server/streaming/server.go index ae1c046b025..7cbc424c41e 100644 --- a/pkg/kubelet/server/streaming/server.go +++ b/pkg/kubelet/server/streaming/server.go @@ -20,6 +20,7 @@ import ( "crypto/tls" "errors" "io" + "net" "net/http" "net/url" "path" @@ -71,6 +72,7 @@ type Config struct { Addr string // The optional base URL for constructing streaming URLs. If empty, the baseURL will be // constructed from the serve address. + // Note that for port "0", the URL port will be set to actual port in use. BaseURL *url.URL // How long to leave idle connections open for. @@ -233,10 +235,16 @@ func (s *server) Start(stayUp bool) error { return errors.New("stayUp=false is not yet implemented") } + listener, err := net.Listen("tcp", s.config.Addr) + if err != nil { + return err + } + // Use the actual address as baseURL host. This handles the "0" port case. + s.config.BaseURL.Host = listener.Addr().String() if s.config.TLSConfig != nil { - return s.server.ListenAndServeTLS("", "") // Use certs from TLSConfig. + return s.server.ServeTLS(listener, "", "") // Use certs from TLSConfig. } else { - return s.server.ListenAndServe() + return s.server.Serve(listener) } } diff --git a/pkg/kubelet/stats/cri_stats_provider.go b/pkg/kubelet/stats/cri_stats_provider.go index e82ca97a0d8..1af0a0cbfb3 100644 --- a/pkg/kubelet/stats/cri_stats_provider.go +++ b/pkg/kubelet/stats/cri_stats_provider.go @@ -142,12 +142,14 @@ func (p *criStatsProvider) ListPodStats() ([]statsapi.PodStats, error) { ps, found := sandboxIDToPodStats[podSandboxID] if !found { ps = buildPodStats(podSandbox) - // Fill stats from cadvisor is available for full set of required pod stats - p.addCadvisorPodNetworkStats(ps, podSandboxID, caInfos) - p.addCadvisorPodCPUMemoryStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos) sandboxIDToPodStats[podSandboxID] = ps } + + // Fill available stats for full set of required pod stats cs := p.makeContainerStats(stats, container, &rootFsInfo, fsIDtoInfo, podSandbox.GetMetadata().GetUid()) + p.addPodNetworkStats(ps, podSandboxID, caInfos, cs) + p.addPodCPUMemoryStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs) + // If cadvisor stats is available for the container, use it to populate // container stats caStats, caFound := caInfos[containerID] @@ -263,29 +265,69 @@ func (p *criStatsProvider) makePodStorageStats(s *statsapi.PodStats, rootFsInfo return s } -func (p *criStatsProvider) addCadvisorPodNetworkStats( +func (p *criStatsProvider) addPodNetworkStats( ps *statsapi.PodStats, podSandboxID string, caInfos map[string]cadvisorapiv2.ContainerInfo, + cs *statsapi.ContainerStats, ) { caPodSandbox, found := caInfos[podSandboxID] + // try get network stats from cadvisor first. if found { ps.Network = cadvisorInfoToNetworkStats(ps.PodRef.Name, &caPodSandbox) - } else { - glog.V(4).Infof("Unable to find cadvisor stats for sandbox %q", podSandboxID) + return } + + // TODO: sum Pod network stats from container stats. + glog.V(4).Infof("Unable to find cadvisor stats for sandbox %q", podSandboxID) } -func (p *criStatsProvider) addCadvisorPodCPUMemoryStats( +func (p *criStatsProvider) addPodCPUMemoryStats( ps *statsapi.PodStats, podUID types.UID, allInfos map[string]cadvisorapiv2.ContainerInfo, + cs *statsapi.ContainerStats, ) { + // try get cpu and memory stats from cadvisor first. podCgroupInfo := getCadvisorPodInfoFromPodUID(podUID, allInfos) if podCgroupInfo != nil { cpu, memory := cadvisorInfoToCPUandMemoryStats(podCgroupInfo) ps.CPU = cpu ps.Memory = memory + return + } + + // Sum Pod cpu and memory stats from containers stats. + if cs.CPU != nil { + if ps.CPU == nil { + ps.CPU = &statsapi.CPUStats{} + } + + ps.CPU.Time = cs.StartTime + usageCoreNanoSeconds := getUint64Value(cs.CPU.UsageCoreNanoSeconds) + getUint64Value(ps.CPU.UsageCoreNanoSeconds) + usageNanoCores := getUint64Value(cs.CPU.UsageNanoCores) + getUint64Value(ps.CPU.UsageNanoCores) + ps.CPU.UsageCoreNanoSeconds = &usageCoreNanoSeconds + ps.CPU.UsageNanoCores = &usageNanoCores + } + + if cs.Memory != nil { + if ps.Memory == nil { + ps.Memory = &statsapi.MemoryStats{} + } + + ps.Memory.Time = cs.Memory.Time + availableBytes := getUint64Value(cs.Memory.AvailableBytes) + getUint64Value(ps.Memory.AvailableBytes) + usageBytes := getUint64Value(cs.Memory.UsageBytes) + getUint64Value(ps.Memory.UsageBytes) + workingSetBytes := getUint64Value(cs.Memory.WorkingSetBytes) + getUint64Value(ps.Memory.WorkingSetBytes) + rSSBytes := getUint64Value(cs.Memory.RSSBytes) + getUint64Value(ps.Memory.RSSBytes) + pageFaults := getUint64Value(cs.Memory.PageFaults) + getUint64Value(ps.Memory.PageFaults) + majorPageFaults := getUint64Value(cs.Memory.MajorPageFaults) + getUint64Value(ps.Memory.MajorPageFaults) + ps.Memory.AvailableBytes = &availableBytes + ps.Memory.UsageBytes = &usageBytes + ps.Memory.WorkingSetBytes = &workingSetBytes + ps.Memory.RSSBytes = &rSSBytes + ps.Memory.PageFaults = &pageFaults + ps.Memory.MajorPageFaults = &majorPageFaults } } diff --git a/pkg/kubelet/stats/helper.go b/pkg/kubelet/stats/helper.go index 77f3a6569e8..a195b9c634a 100644 --- a/pkg/kubelet/stats/helper.go +++ b/pkg/kubelet/stats/helper.go @@ -303,3 +303,11 @@ func buildRootfsStats(cstat *cadvisorapiv2.ContainerStats, imageFs *cadvisorapiv Inodes: imageFs.Inodes, } } + +func getUint64Value(value *uint64) uint64 { + if value == nil { + return 0 + } + + return *value +} diff --git a/pkg/kubelet/status/BUILD b/pkg/kubelet/status/BUILD index ccc78651f0f..63e32a391d9 100644 --- a/pkg/kubelet/status/BUILD +++ b/pkg/kubelet/status/BUILD @@ -19,6 +19,7 @@ go_library( "//pkg/kubelet/pod:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util/format:go_default_library", + "//pkg/util/pod:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", diff --git a/pkg/kubelet/status/generate.go b/pkg/kubelet/status/generate.go index c094a95d8a5..8d9415d2247 100644 --- a/pkg/kubelet/status/generate.go +++ b/pkg/kubelet/status/generate.go @@ -29,15 +29,16 @@ const ( PodCompleted = "PodCompleted" ContainersNotReady = "ContainersNotReady" ContainersNotInitialized = "ContainersNotInitialized" + ReadinessGatesNotReady = "ReadinessGatesNotReady" ) -// GeneratePodReadyCondition returns ready condition if all containers in a pod are ready, else it -// returns an unready condition. -func GeneratePodReadyCondition(spec *v1.PodSpec, containerStatuses []v1.ContainerStatus, podPhase v1.PodPhase) v1.PodCondition { +// GenerateContainersReadyCondition returns the status of "ContainersReady" condition. +// The status of "ContainersReady" condition is true when all containers are ready. +func GenerateContainersReadyCondition(spec *v1.PodSpec, containerStatuses []v1.ContainerStatus, podPhase v1.PodPhase) v1.PodCondition { // Find if all containers are ready or not. if containerStatuses == nil { return v1.PodCondition{ - Type: v1.PodReady, + Type: v1.ContainersReady, Status: v1.ConditionFalse, Reason: UnknownContainerStatuses, } @@ -57,12 +58,13 @@ func GeneratePodReadyCondition(spec *v1.PodSpec, containerStatuses []v1.Containe // If all containers are known and succeeded, just return PodCompleted. if podPhase == v1.PodSucceeded && len(unknownContainers) == 0 { return v1.PodCondition{ - Type: v1.PodReady, + Type: v1.ContainersReady, Status: v1.ConditionFalse, Reason: PodCompleted, } } + // Generate message for containers in unknown condition. unreadyMessages := []string{} if len(unknownContainers) > 0 { unreadyMessages = append(unreadyMessages, fmt.Sprintf("containers with unknown status: %s", unknownContainers)) @@ -73,13 +75,57 @@ func GeneratePodReadyCondition(spec *v1.PodSpec, containerStatuses []v1.Containe unreadyMessage := strings.Join(unreadyMessages, ", ") if unreadyMessage != "" { return v1.PodCondition{ - Type: v1.PodReady, + Type: v1.ContainersReady, Status: v1.ConditionFalse, Reason: ContainersNotReady, Message: unreadyMessage, } } + return v1.PodCondition{ + Type: v1.ContainersReady, + Status: v1.ConditionTrue, + } +} + +// GeneratePodReadyCondition returns "Ready" condition of a pod. +// The status of "Ready" condition is "True", if all containers in a pod are ready +// AND all matching conditions specified in the ReadinessGates have status equal to "True". +func GeneratePodReadyCondition(spec *v1.PodSpec, conditions []v1.PodCondition, containerStatuses []v1.ContainerStatus, podPhase v1.PodPhase) v1.PodCondition { + containersReady := GenerateContainersReadyCondition(spec, containerStatuses, podPhase) + // If the status of ContainersReady is not True, return the same status, reason and message as ContainersReady. + if containersReady.Status != v1.ConditionTrue { + return v1.PodCondition{ + Type: v1.PodReady, + Status: containersReady.Status, + Reason: containersReady.Reason, + Message: containersReady.Message, + } + } + + // Evaluate corresponding conditions specified in readiness gate + // Generate message if any readiness gate is not satisfied. + unreadyMessages := []string{} + for _, rg := range spec.ReadinessGates { + _, c := podutil.GetPodConditionFromList(conditions, rg.ConditionType) + if c == nil { + unreadyMessages = append(unreadyMessages, fmt.Sprintf("corresponding condition of pod readiness gate %q does not exist.", string(rg.ConditionType))) + } else if c.Status != v1.ConditionTrue { + unreadyMessages = append(unreadyMessages, fmt.Sprintf("the status of pod readiness gate %q is not \"True\", but %v", string(rg.ConditionType), c.Status)) + } + } + + // Set "Ready" condition to "False" if any readiness gate is not ready. + if len(unreadyMessages) != 0 { + unreadyMessage := strings.Join(unreadyMessages, ", ") + return v1.PodCondition{ + Type: v1.PodReady, + Status: v1.ConditionFalse, + Reason: ReadinessGatesNotReady, + Message: unreadyMessage, + } + } + return v1.PodCondition{ Type: v1.PodReady, Status: v1.ConditionTrue, diff --git a/pkg/kubelet/status/generate_test.go b/pkg/kubelet/status/generate_test.go index 9b0b61cdb40..a8a191d1bc0 100644 --- a/pkg/kubelet/status/generate_test.go +++ b/pkg/kubelet/status/generate_test.go @@ -24,24 +24,24 @@ import ( "k8s.io/api/core/v1" ) -func TestGeneratePodReadyCondition(t *testing.T) { +func TestGenerateContainersReadyCondition(t *testing.T) { tests := []struct { spec *v1.PodSpec containerStatuses []v1.ContainerStatus podPhase v1.PodPhase - expected v1.PodCondition + expectReady v1.PodCondition }{ { spec: nil, containerStatuses: nil, podPhase: v1.PodRunning, - expected: getReadyCondition(false, UnknownContainerStatuses, ""), + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, UnknownContainerStatuses, ""), }, { spec: &v1.PodSpec{}, containerStatuses: []v1.ContainerStatus{}, podPhase: v1.PodRunning, - expected: getReadyCondition(true, "", ""), + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionTrue, "", ""), }, { spec: &v1.PodSpec{ @@ -51,7 +51,7 @@ func TestGeneratePodReadyCondition(t *testing.T) { }, containerStatuses: []v1.ContainerStatus{}, podPhase: v1.PodRunning, - expected: getReadyCondition(false, ContainersNotReady, "containers with unknown status: [1234]"), + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, ContainersNotReady, "containers with unknown status: [1234]"), }, { spec: &v1.PodSpec{ @@ -64,8 +64,8 @@ func TestGeneratePodReadyCondition(t *testing.T) { getReadyStatus("1234"), getReadyStatus("5678"), }, - podPhase: v1.PodRunning, - expected: getReadyCondition(true, "", ""), + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionTrue, "", ""), }, { spec: &v1.PodSpec{ @@ -77,8 +77,8 @@ func TestGeneratePodReadyCondition(t *testing.T) { containerStatuses: []v1.ContainerStatus{ getReadyStatus("1234"), }, - podPhase: v1.PodRunning, - expected: getReadyCondition(false, ContainersNotReady, "containers with unknown status: [5678]"), + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, ContainersNotReady, "containers with unknown status: [5678]"), }, { spec: &v1.PodSpec{ @@ -91,8 +91,8 @@ func TestGeneratePodReadyCondition(t *testing.T) { getReadyStatus("1234"), getNotReadyStatus("5678"), }, - podPhase: v1.PodRunning, - expected: getReadyCondition(false, ContainersNotReady, "containers with unready status: [5678]"), + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, ContainersNotReady, "containers with unready status: [5678]"), }, { spec: &v1.PodSpec{ @@ -103,15 +103,212 @@ func TestGeneratePodReadyCondition(t *testing.T) { containerStatuses: []v1.ContainerStatus{ getNotReadyStatus("1234"), }, - podPhase: v1.PodSucceeded, - expected: getReadyCondition(false, PodCompleted, ""), + podPhase: v1.PodSucceeded, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, PodCompleted, ""), }, } for i, test := range tests { - condition := GeneratePodReadyCondition(test.spec, test.containerStatuses, test.podPhase) - if !reflect.DeepEqual(condition, test.expected) { - t.Errorf("On test case %v, expected:\n%+v\ngot\n%+v\n", i, test.expected, condition) + ready := GenerateContainersReadyCondition(test.spec, test.containerStatuses, test.podPhase) + if !reflect.DeepEqual(ready, test.expectReady) { + t.Errorf("On test case %v, expectReady:\n%+v\ngot\n%+v\n", i, test.expectReady, ready) + } + } +} + +func TestGeneratePodReadyCondition(t *testing.T) { + tests := []struct { + spec *v1.PodSpec + conditions []v1.PodCondition + containerStatuses []v1.ContainerStatus + podPhase v1.PodPhase + expectReady v1.PodCondition + }{ + { + spec: nil, + conditions: nil, + containerStatuses: nil, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, UnknownContainerStatuses, ""), + }, + { + spec: &v1.PodSpec{}, + conditions: nil, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionTrue, "", ""), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + }, + }, + conditions: nil, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ContainersNotReady, "containers with unknown status: [1234]"), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + {Name: "5678"}, + }, + }, + conditions: nil, + containerStatuses: []v1.ContainerStatus{ + getReadyStatus("1234"), + getReadyStatus("5678"), + }, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionTrue, "", ""), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + {Name: "5678"}, + }, + }, + conditions: nil, + containerStatuses: []v1.ContainerStatus{ + getReadyStatus("1234"), + }, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ContainersNotReady, "containers with unknown status: [5678]"), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + {Name: "5678"}, + }, + }, + conditions: nil, + containerStatuses: []v1.ContainerStatus{ + getReadyStatus("1234"), + getNotReadyStatus("5678"), + }, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ContainersNotReady, "containers with unready status: [5678]"), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + }, + }, + conditions: nil, + containerStatuses: []v1.ContainerStatus{ + getNotReadyStatus("1234"), + }, + podPhase: v1.PodSucceeded, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, PodCompleted, ""), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + }, + }, + conditions: nil, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ReadinessGatesNotReady, `corresponding condition of pod readiness gate "gate1" does not exist.`), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionFalse, "", ""), + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ReadinessGatesNotReady, `the status of pod readiness gate "gate1" is not "True", but False`), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionTrue, "", ""), + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionTrue, "", ""), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + {ConditionType: v1.PodConditionType("gate2")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionTrue, "", ""), + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ReadinessGatesNotReady, `corresponding condition of pod readiness gate "gate2" does not exist.`), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + {ConditionType: v1.PodConditionType("gate2")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionTrue, "", ""), + getPodCondition("gate2", v1.ConditionFalse, "", ""), + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ReadinessGatesNotReady, `the status of pod readiness gate "gate2" is not "True", but False`), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + {ConditionType: v1.PodConditionType("gate2")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionTrue, "", ""), + getPodCondition("gate2", v1.ConditionTrue, "", ""), + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionTrue, "", ""), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + }, + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionTrue, "", ""), + }, + containerStatuses: []v1.ContainerStatus{getNotReadyStatus("1234")}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ContainersNotReady, "containers with unready status: [1234]"), + }, + } + + for i, test := range tests { + ready := GeneratePodReadyCondition(test.spec, test.conditions, test.containerStatuses, test.podPhase) + if !reflect.DeepEqual(ready, test.expectReady) { + t.Errorf("On test case %v, expectReady:\n%+v\ngot\n%+v\n", i, test.expectReady, ready) } } } @@ -220,13 +417,9 @@ func TestGeneratePodInitializedCondition(t *testing.T) { } } -func getReadyCondition(ready bool, reason, message string) v1.PodCondition { - status := v1.ConditionFalse - if ready { - status = v1.ConditionTrue - } +func getPodCondition(conditionType v1.PodConditionType, status v1.ConditionStatus, reason, message string) v1.PodCondition { return v1.PodCondition{ - Type: v1.PodReady, + Type: conditionType, Status: status, Reason: reason, Message: message, diff --git a/pkg/kubelet/status/status_manager.go b/pkg/kubelet/status/status_manager.go index eaf5b9a0512..1dbfc6aa5e7 100644 --- a/pkg/kubelet/status/status_manager.go +++ b/pkg/kubelet/status/status_manager.go @@ -37,6 +37,7 @@ import ( kubepod "k8s.io/kubernetes/pkg/kubelet/pod" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/format" + statusutil "k8s.io/kubernetes/pkg/util/pod" ) // A wrapper around v1.PodStatus that includes a version to enforce that stale pod statuses are @@ -121,11 +122,22 @@ func NewManager(kubeClient clientset.Interface, podManager kubepod.Manager, podD } } -// isStatusEqual returns true if the given pod statuses are equal, false otherwise. +// isPodStatusByKubeletEqual returns true if the given pod statuses are equal when non-kubelet-owned +// pod conditions are excluded. // This method normalizes the status before comparing so as to make sure that meaningless // changes will be ignored. -func isStatusEqual(oldStatus, status *v1.PodStatus) bool { - return apiequality.Semantic.DeepEqual(status, oldStatus) +func isPodStatusByKubeletEqual(oldStatus, status *v1.PodStatus) bool { + oldCopy := oldStatus.DeepCopy() + for _, c := range status.Conditions { + if kubetypes.PodConditionByKubelet(c.Type) { + _, oc := podutil.GetPodCondition(oldCopy, c.Type) + if oc == nil || oc.Status != c.Status { + return false + } + } + } + oldCopy.Conditions = status.Conditions + return apiequality.Semantic.DeepEqual(oldCopy, status) } func (m *manager) Start() { @@ -162,6 +174,13 @@ func (m *manager) GetPodStatus(uid types.UID) (v1.PodStatus, bool) { func (m *manager) SetPodStatus(pod *v1.Pod, status v1.PodStatus) { m.podStatusesLock.Lock() defer m.podStatusesLock.Unlock() + + for _, c := range pod.Status.Conditions { + if !kubetypes.PodConditionByKubelet(c.Type) { + glog.Errorf("Kubelet is trying to update pod condition %q for pod %q. "+ + "But it is not owned by kubelet.", string(c.Type), format.Pod(pod)) + } + } // Make sure we're caching a deep copy. status = *status.DeepCopy() @@ -207,22 +226,24 @@ func (m *manager) SetContainerReadiness(podUID types.UID, containerID kubecontai containerStatus, _, _ = findContainerStatus(&status, containerID.String()) containerStatus.Ready = ready - // Update pod condition. - readyConditionIndex := -1 - for i, condition := range status.Conditions { - if condition.Type == v1.PodReady { - readyConditionIndex = i - break + // updateConditionFunc updates the corresponding type of condition + updateConditionFunc := func(conditionType v1.PodConditionType, condition v1.PodCondition) { + conditionIndex := -1 + for i, condition := range status.Conditions { + if condition.Type == conditionType { + conditionIndex = i + break + } + } + if conditionIndex != -1 { + status.Conditions[conditionIndex] = condition + } else { + glog.Warningf("PodStatus missing %s type condition: %+v", conditionType, status) + status.Conditions = append(status.Conditions, condition) } } - readyCondition := GeneratePodReadyCondition(&pod.Spec, status.ContainerStatuses, status.Phase) - if readyConditionIndex != -1 { - status.Conditions[readyConditionIndex] = readyCondition - } else { - glog.Warningf("PodStatus missing PodReady condition: %+v", status) - status.Conditions = append(status.Conditions, readyCondition) - } - + updateConditionFunc(v1.PodReady, GeneratePodReadyCondition(&pod.Spec, status.Conditions, status.ContainerStatuses, status.Phase)) + updateConditionFunc(v1.ContainersReady, GenerateContainersReadyCondition(&pod.Spec, status.ContainerStatuses, status.Phase)) m.updateStatusInternal(pod, status, false) } @@ -336,7 +357,7 @@ func (m *manager) updateStatusInternal(pod *v1.Pod, status v1.PodStatus, forceUp normalizeStatus(pod, &status) // The intent here is to prevent concurrent updates to a pod's status from // clobbering each other so the phase of a pod progresses monotonically. - if isCached && isStatusEqual(&cachedStatus.status, &status) && !forceUpdate { + if isCached && isPodStatusByKubeletEqual(&cachedStatus.status, &status) && !forceUpdate { glog.V(3).Infof("Ignoring same status for pod %q, status: %+v", format.Pod(pod), status) return false // No new status. } @@ -469,9 +490,10 @@ func (m *manager) syncPod(uid types.UID, status versionedPodStatus) { m.deletePodStatus(uid) return } - pod.Status = status.status - // TODO: handle conflict as a retry, make that easier too. - newPod, err := m.kubeClient.CoreV1().Pods(pod.Namespace).UpdateStatus(pod) + + oldStatus := pod.Status.DeepCopy() + newPod, patchBytes, err := statusutil.PatchPodStatus(m.kubeClient, pod.Namespace, pod.Name, *oldStatus, mergePodStatus(*oldStatus, status.status)) + glog.V(3).Infof("Patch status for pod %q with %q", format.Pod(pod), patchBytes) if err != nil { glog.Warningf("Failed to update status for pod %q: %v", format.Pod(pod), err) return @@ -546,7 +568,7 @@ func (m *manager) needsReconcile(uid types.UID, status v1.PodStatus) bool { podStatus := pod.Status.DeepCopy() normalizeStatus(pod, podStatus) - if isStatusEqual(podStatus, &status) { + if isPodStatusByKubeletEqual(podStatus, &status) { // If the status from the source is the same with the cached status, // reconcile is not needed. Just return. return false @@ -559,7 +581,7 @@ func (m *manager) needsReconcile(uid types.UID, status v1.PodStatus) bool { // We add this function, because apiserver only supports *RFC3339* now, which means that the timestamp returned by // apiserver has no nanosecond information. However, the timestamp returned by metav1.Now() contains nanosecond, -// so when we do comparison between status from apiserver and cached status, isStatusEqual() will always return false. +// so when we do comparison between status from apiserver and cached status, isPodStatusByKubeletEqual() will always return false. // There is related issue #15262 and PR #15263 about this. // In fact, the best way to solve this is to do it on api side. However, for now, we normalize the status locally in // kubelet temporarily. @@ -613,3 +635,36 @@ func normalizeStatus(pod *v1.Pod, status *v1.PodStatus) *v1.PodStatus { kubetypes.SortInitContainerStatuses(pod, status.InitContainerStatuses) return status } + +// mergePodStatus merges oldPodStatus and newPodStatus where pod conditions +// not owned by kubelet is preserved from oldPodStatus +func mergePodStatus(oldPodStatus, newPodStatus v1.PodStatus) v1.PodStatus { + podConditions := []v1.PodCondition{} + for _, c := range oldPodStatus.Conditions { + if !kubetypes.PodConditionByKubelet(c.Type) { + podConditions = append(podConditions, c) + } + } + + for _, c := range newPodStatus.Conditions { + if kubetypes.PodConditionByKubelet(c.Type) { + podConditions = append(podConditions, c) + } + } + newPodStatus.Conditions = podConditions + return newPodStatus +} + +// NeedToReconcilePodReadiness returns if the pod "Ready" condition need to be reconcile +func NeedToReconcilePodReadiness(pod *v1.Pod) bool { + if len(pod.Spec.ReadinessGates) == 0 { + return false + } + podReadyCondition := GeneratePodReadyCondition(&pod.Spec, pod.Status.Conditions, pod.Status.ContainerStatuses, pod.Status.Phase) + i, curCondition := podutil.GetPodConditionFromList(pod.Status.Conditions, v1.PodReady) + // Only reconcile if "Ready" condition is present + if i >= 0 && curCondition.Status != podReadyCondition.Status { + return true + } + return false +} diff --git a/pkg/kubelet/status/status_manager_test.go b/pkg/kubelet/status/status_manager_test.go index 84ddec36e3b..03f79b2a1bb 100644 --- a/pkg/kubelet/status/status_manager_test.go +++ b/pkg/kubelet/status/status_manager_test.go @@ -19,6 +19,7 @@ package status import ( "fmt" "math/rand" + "reflect" "strconv" "strings" "testing" @@ -48,6 +49,10 @@ import ( // Generate new instance of test pod with the same initial value. func getTestPod() *v1.Pod { return &v1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: "v1", + }, ObjectMeta: metav1.ObjectMeta{ UID: "12345678", Name: "foo", @@ -303,7 +308,7 @@ func TestSyncPod(t *testing.T) { testPod := getTestPod() syncer.kubeClient = fake.NewSimpleClientset(testPod) syncer.SetPodStatus(testPod, getRandomPodStatus()) - verifyActions(t, syncer, []core.Action{getAction(), updateAction()}) + verifyActions(t, syncer, []core.Action{getAction(), patchAction()}) } func TestSyncPodChecksMismatchedUID(t *testing.T) { @@ -357,18 +362,18 @@ func TestSyncPodNoDeadlock(t *testing.T) { t.Logf("Pod not deleted (success case).") ret = getTestPod() m.SetPodStatus(pod, getRandomPodStatus()) - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("Pod is terminated, but still running.") - pod.DeletionTimestamp = new(metav1.Time) + pod.DeletionTimestamp = &metav1.Time{Time: time.Now()} m.SetPodStatus(pod, getRandomPodStatus()) - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("Pod is terminated successfully.") pod.Status.ContainerStatuses[0].State.Running = nil pod.Status.ContainerStatuses[0].State.Terminated = &v1.ContainerStateTerminated{} m.SetPodStatus(pod, getRandomPodStatus()) - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("Error case.") ret = nil @@ -392,7 +397,7 @@ func TestStaleUpdates(t *testing.T) { t.Logf("sync batch before syncPods pushes latest status, so we should see three statuses in the channel, but only one update") m.syncBatch() verifyUpdates(t, m, 3) - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("Nothing left in the channel to sync") verifyActions(t, m, []core.Action{}) @@ -406,7 +411,7 @@ func TestStaleUpdates(t *testing.T) { m.SetPodStatus(pod, status) m.syncBatch() - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("Nothing stuck in the pipe.") verifyUpdates(t, m, 0) @@ -443,10 +448,27 @@ func TestStatusEquality(t *testing.T) { } normalizeStatus(&pod, &oldPodStatus) normalizeStatus(&pod, &podStatus) - if !isStatusEqual(&oldPodStatus, &podStatus) { + if !isPodStatusByKubeletEqual(&oldPodStatus, &podStatus) { t.Fatalf("Order of container statuses should not affect normalized equality.") } } + + oldPodStatus := podStatus + podStatus.Conditions = append(podStatus.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("www.example.com/feature"), + Status: v1.ConditionTrue, + }) + + oldPodStatus.Conditions = append(podStatus.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("www.example.com/feature"), + Status: v1.ConditionFalse, + }) + + normalizeStatus(&pod, &oldPodStatus) + normalizeStatus(&pod, &podStatus) + if !isPodStatusByKubeletEqual(&oldPodStatus, &podStatus) { + t.Fatalf("Differences in pod condition not owned by kubelet should not affect normalized equality.") + } } func TestStatusNormalizationEnforcesMaxBytes(t *testing.T) { @@ -507,7 +529,7 @@ func TestStaticPod(t *testing.T) { t.Logf("Should be able to get the static pod status from status manager") retrievedStatus := expectPodStatus(t, m, staticPod) normalizeStatus(staticPod, &status) - assert.True(t, isStatusEqual(&status, &retrievedStatus), "Expected: %+v, Got: %+v", status, retrievedStatus) + assert.True(t, isPodStatusByKubeletEqual(&status, &retrievedStatus), "Expected: %+v, Got: %+v", status, retrievedStatus) t.Logf("Should not sync pod in syncBatch because there is no corresponding mirror pod for the static pod.") m.syncBatch() @@ -520,10 +542,10 @@ func TestStaticPod(t *testing.T) { t.Logf("Should be able to get the mirror pod status from status manager") retrievedStatus, _ = m.GetPodStatus(mirrorPod.UID) - assert.True(t, isStatusEqual(&status, &retrievedStatus), "Expected: %+v, Got: %+v", status, retrievedStatus) + assert.True(t, isPodStatusByKubeletEqual(&status, &retrievedStatus), "Expected: %+v, Got: %+v", status, retrievedStatus) t.Logf("Should sync pod because the corresponding mirror pod is created") - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("syncBatch should not sync any pods because nothing is changed.") m.testSyncBatch() @@ -741,7 +763,7 @@ func TestReconcilePodStatus(t *testing.T) { t.Errorf("Pod status is different, a reconciliation is needed") } syncer.syncBatch() - verifyActions(t, syncer, []core.Action{getAction(), updateAction()}) + verifyActions(t, syncer, []core.Action{getAction(), patchAction()}) } func expectPodStatus(t *testing.T, m *manager, pod *v1.Pod) v1.PodStatus { @@ -755,18 +777,16 @@ func expectPodStatus(t *testing.T, m *manager, pod *v1.Pod) v1.PodStatus { func TestDeletePods(t *testing.T) { pod := getTestPod() t.Logf("Set the deletion timestamp.") - pod.DeletionTimestamp = new(metav1.Time) + pod.DeletionTimestamp = &metav1.Time{Time: time.Now()} client := fake.NewSimpleClientset(pod) m := newTestManager(client) m.podManager.AddPod(pod) - status := getRandomPodStatus() now := metav1.Now() status.StartTime = &now m.SetPodStatus(pod, status) - t.Logf("Expect to see a delete action.") - verifyActions(t, m, []core.Action{getAction(), updateAction(), deleteAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction(), deleteAction()}) } func TestDoNotDeleteMirrorPods(t *testing.T) { @@ -779,7 +799,7 @@ func TestDoNotDeleteMirrorPods(t *testing.T) { kubetypes.ConfigMirrorAnnotationKey: "mirror", } t.Logf("Set the deletion timestamp.") - mirrorPod.DeletionTimestamp = new(metav1.Time) + mirrorPod.DeletionTimestamp = &metav1.Time{Time: time.Now()} client := fake.NewSimpleClientset(mirrorPod) m := newTestManager(client) m.podManager.AddPod(staticPod) @@ -795,7 +815,7 @@ func TestDoNotDeleteMirrorPods(t *testing.T) { m.SetPodStatus(staticPod, status) t.Logf("Expect not to see a delete action.") - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) } func TestUpdateLastTransitionTime(t *testing.T) { @@ -867,6 +887,197 @@ func updateAction() core.UpdateAction { return core.UpdateActionImpl{ActionImpl: core.ActionImpl{Verb: "update", Resource: schema.GroupVersionResource{Resource: "pods"}, Subresource: "status"}} } +func patchAction() core.PatchAction { + return core.PatchActionImpl{ActionImpl: core.ActionImpl{Verb: "patch", Resource: schema.GroupVersionResource{Resource: "pods"}, Subresource: "status"}} +} + func deleteAction() core.DeleteAction { return core.DeleteActionImpl{ActionImpl: core.ActionImpl{Verb: "delete", Resource: schema.GroupVersionResource{Resource: "pods"}}} } + +func TestMergePodStatus(t *testing.T) { + useCases := []struct { + desc string + oldPodStatus func(input v1.PodStatus) v1.PodStatus + newPodStatus func(input v1.PodStatus) v1.PodStatus + expectPodStatus v1.PodStatus + }{ + { + "no change", + func(input v1.PodStatus) v1.PodStatus { return input }, + func(input v1.PodStatus) v1.PodStatus { return input }, + getPodStatus(), + }, + { + "readiness changes", + func(input v1.PodStatus) v1.PodStatus { return input }, + func(input v1.PodStatus) v1.PodStatus { + input.Conditions[0].Status = v1.ConditionFalse + return input + }, + v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionFalse, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + }, + Message: "Message", + }, + }, + { + "additional pod condition", + func(input v1.PodStatus) v1.PodStatus { + input.Conditions = append(input.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }) + return input + }, + func(input v1.PodStatus) v1.PodStatus { return input }, + v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }, + }, + Message: "Message", + }, + }, + { + "additional pod condition and readiness changes", + func(input v1.PodStatus) v1.PodStatus { + input.Conditions = append(input.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }) + return input + }, + func(input v1.PodStatus) v1.PodStatus { + input.Conditions[0].Status = v1.ConditionFalse + return input + }, + v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionFalse, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }, + }, + Message: "Message", + }, + }, + { + "additional pod condition changes", + func(input v1.PodStatus) v1.PodStatus { + input.Conditions = append(input.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }) + return input + }, + func(input v1.PodStatus) v1.PodStatus { + input.Conditions = append(input.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionFalse, + }) + return input + }, + v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }, + }, + Message: "Message", + }, + }, + } + + for _, tc := range useCases { + output := mergePodStatus(tc.oldPodStatus(getPodStatus()), tc.newPodStatus(getPodStatus())) + if !conditionsEqual(output.Conditions, tc.expectPodStatus.Conditions) || !statusEqual(output, tc.expectPodStatus) { + t.Errorf("test case %q failed, expect: %+v, got %+v", tc.desc, tc.expectPodStatus, output) + } + } + +} + +func statusEqual(left, right v1.PodStatus) bool { + left.Conditions = nil + right.Conditions = nil + return reflect.DeepEqual(left, right) +} + +func conditionsEqual(left, right []v1.PodCondition) bool { + if len(left) != len(right) { + return false + } + + for _, l := range left { + found := false + for _, r := range right { + if l.Type == r.Type { + found = true + if l.Status != r.Status { + return false + } + } + } + if !found { + return false + } + } + return true +} + +func getPodStatus() v1.PodStatus { + return v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + }, + Message: "Message", + } +} diff --git a/pkg/kubelet/sysctl/BUILD b/pkg/kubelet/sysctl/BUILD index 620eadf309e..f8c52b92d92 100644 --- a/pkg/kubelet/sysctl/BUILD +++ b/pkg/kubelet/sysctl/BUILD @@ -15,7 +15,6 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/kubelet/sysctl", deps = [ - "//pkg/apis/core/v1/helper:go_default_library", "//pkg/apis/core/validation:go_default_library", "//pkg/apis/policy/validation:go_default_library", "//pkg/kubelet/container:go_default_library", @@ -30,7 +29,7 @@ go_test( "whitelist_test.go", ], embed = [":go_default_library"], - deps = ["//vendor/k8s.io/api/core/v1:go_default_library"], + deps = ["//pkg/security/podsecuritypolicy/sysctl:go_default_library"], ) filegroup( diff --git a/pkg/kubelet/sysctl/runtime.go b/pkg/kubelet/sysctl/runtime.go index a7aa49e9ba5..8b37c65c55a 100644 --- a/pkg/kubelet/sysctl/runtime.go +++ b/pkg/kubelet/sysctl/runtime.go @@ -19,7 +19,6 @@ package sysctl import ( "fmt" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/lifecycle" ) @@ -83,17 +82,11 @@ func NewRuntimeAdmitHandler(runtime container.Runtime) (*runtimeAdmitHandler, er // Admit checks whether the runtime supports sysctls. func (w *runtimeAdmitHandler) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult { - sysctls, unsafeSysctls, err := v1helper.SysctlsFromPodAnnotations(attrs.Pod.Annotations) - if err != nil { - return lifecycle.PodAdmitResult{ - Admit: false, - Reason: AnnotationInvalidReason, - Message: fmt.Sprintf("invalid sysctl annotation: %v", err), - } - } + if attrs.Pod.Spec.SecurityContext != nil { - if len(sysctls)+len(unsafeSysctls) > 0 { - return w.result + if len(attrs.Pod.Spec.SecurityContext.Sysctls) > 0 { + return w.result + } } return lifecycle.PodAdmitResult{ diff --git a/pkg/kubelet/sysctl/whitelist.go b/pkg/kubelet/sysctl/whitelist.go index 8269e94bb37..067409a7e8f 100644 --- a/pkg/kubelet/sysctl/whitelist.go +++ b/pkg/kubelet/sysctl/whitelist.go @@ -20,7 +20,6 @@ import ( "fmt" "strings" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/apis/core/validation" policyvalidation "k8s.io/kubernetes/pkg/apis/policy/validation" "k8s.io/kubernetes/pkg/kubelet/lifecycle" @@ -31,36 +30,21 @@ const ( ForbiddenReason = "SysctlForbidden" ) -// SafeSysctlWhitelist returns the whitelist of safe sysctls and safe sysctl patterns (ending in *). -// -// A sysctl is called safe iff -// - it is namespaced in the container or the pod -// - it is isolated, i.e. has no influence on any other pod on the same node. -func SafeSysctlWhitelist() []string { - return []string{ - "kernel.shm_rmid_forced", - "net.ipv4.ip_local_port_range", - "net.ipv4.tcp_syncookies", - } -} - // patternWhitelist takes a list of sysctls or sysctl patterns (ending in *) and // checks validity via a sysctl and prefix map, rejecting those which are not known // to be namespaced. type patternWhitelist struct { - sysctls map[string]Namespace - prefixes map[string]Namespace - annotationKey string + sysctls map[string]Namespace + prefixes map[string]Namespace } var _ lifecycle.PodAdmitHandler = &patternWhitelist{} // NewWhitelist creates a new Whitelist from a list of sysctls and sysctl pattern (ending in *). -func NewWhitelist(patterns []string, annotationKey string) (*patternWhitelist, error) { +func NewWhitelist(patterns []string) (*patternWhitelist, error) { w := &patternWhitelist{ - sysctls: map[string]Namespace{}, - prefixes: map[string]Namespace{}, - annotationKey: annotationKey, + sysctls: map[string]Namespace{}, + prefixes: map[string]Namespace{}, } for _, s := range patterns { @@ -121,32 +105,22 @@ func (w *patternWhitelist) validateSysctl(sysctl string, hostNet, hostIPC bool) return fmt.Errorf("%q not whitelisted", sysctl) } -// Admit checks that all sysctls given in annotations v1.SysctlsPodAnnotationKey and v1.UnsafeSysctlsPodAnnotationKey +// Admit checks that all sysctls given in pod's security context // are valid according to the whitelist. func (w *patternWhitelist) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult { pod := attrs.Pod - a := pod.Annotations[w.annotationKey] - if a == "" { + if pod.Spec.SecurityContext == nil || len(pod.Spec.SecurityContext.Sysctls) == 0 { return lifecycle.PodAdmitResult{ Admit: true, } } - sysctls, err := v1helper.SysctlsFromPodAnnotation(a) - if err != nil { - return lifecycle.PodAdmitResult{ - Admit: false, - Reason: AnnotationInvalidReason, - Message: fmt.Sprintf("invalid %s annotation: %v", w.annotationKey, err), - } - } - var hostNet, hostIPC bool if pod.Spec.SecurityContext != nil { hostNet = pod.Spec.HostNetwork hostIPC = pod.Spec.HostIPC } - for _, s := range sysctls { + for _, s := range pod.Spec.SecurityContext.Sysctls { if err := w.validateSysctl(s.Name, hostNet, hostIPC); err != nil { return lifecycle.PodAdmitResult{ Admit: false, diff --git a/pkg/kubelet/sysctl/whitelist_test.go b/pkg/kubelet/sysctl/whitelist_test.go index 77f253337f9..0b6401e3423 100644 --- a/pkg/kubelet/sysctl/whitelist_test.go +++ b/pkg/kubelet/sysctl/whitelist_test.go @@ -19,7 +19,7 @@ package sysctl import ( "testing" - "k8s.io/api/core/v1" + "k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl" ) func TestNewWhitelist(t *testing.T) { @@ -35,7 +35,7 @@ func TestNewWhitelist(t *testing.T) { {sysctls: []string{"net.*.foo"}, err: true}, {sysctls: []string{"foo"}, err: true}, } { - _, err := NewWhitelist(append(SafeSysctlWhitelist(), test.sysctls...), v1.SysctlsPodAnnotationKey) + _, err := NewWhitelist(append(sysctl.SafeSysctlWhitelist(), test.sysctls...)) if test.err && err == nil { t.Errorf("expected an error creating a whitelist for %v", test.sysctls) } else if !test.err && err != nil { @@ -65,7 +65,7 @@ func TestWhitelist(t *testing.T) { {sysctl: "kernel.sem", hostIPC: true}, } - w, err := NewWhitelist(append(SafeSysctlWhitelist(), "kernel.msg*", "kernel.sem"), v1.SysctlsPodAnnotationKey) + w, err := NewWhitelist(append(sysctl.SafeSysctlWhitelist(), "kernel.msg*", "kernel.sem")) if err != nil { t.Fatalf("failed to create whitelist: %v", err) } diff --git a/pkg/kubelet/token/BUILD b/pkg/kubelet/token/BUILD new file mode 100644 index 00000000000..d4d812a25a5 --- /dev/null +++ b/pkg/kubelet/token/BUILD @@ -0,0 +1,40 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_library( + name = "go_default_library", + srcs = ["token_manager.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/token", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["token_manager_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/authentication/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", + ], +) diff --git a/pkg/kubelet/token/OWNERS b/pkg/kubelet/token/OWNERS new file mode 100644 index 00000000000..33904f77888 --- /dev/null +++ b/pkg/kubelet/token/OWNERS @@ -0,0 +1,6 @@ +approvers: +- mikedanese +reviewers: +- mikedanese +- awly +- tallclair diff --git a/pkg/kubelet/token/token_manager.go b/pkg/kubelet/token/token_manager.go new file mode 100644 index 00000000000..d081bdd149d --- /dev/null +++ b/pkg/kubelet/token/token_manager.go @@ -0,0 +1,151 @@ +/* +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 token implements a manager of serviceaccount tokens for pods running +// on the node. +package token + +import ( + "errors" + "fmt" + "sync" + "time" + + "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" + "k8s.io/apimachinery/pkg/util/clock" + "k8s.io/apimachinery/pkg/util/wait" + clientset "k8s.io/client-go/kubernetes" +) + +const ( + maxTTL = 24 * time.Hour + gcPeriod = time.Minute +) + +// NewManager returns a new token manager. +func NewManager(c clientset.Interface) *Manager { + m := &Manager{ + getToken: func(name, namespace string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + if c == nil { + return nil, errors.New("cannot use TokenManager when kubelet is in standalone mode") + } + return c.CoreV1().ServiceAccounts(namespace).CreateToken(name, tr) + }, + cache: make(map[string]*authenticationv1.TokenRequest), + clock: clock.RealClock{}, + } + go wait.Forever(m.cleanup, gcPeriod) + return m +} + +// Manager manages service account tokens for pods. +type Manager struct { + + // cacheMutex guards the cache + cacheMutex sync.RWMutex + cache map[string]*authenticationv1.TokenRequest + + // mocked for testing + getToken func(name, namespace string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) + clock clock.Clock +} + +// GetServiceAccountToken gets a service account token for a pod from cache or +// from the TokenRequest API. This process is as follows: +// * Check the cache for the current token request. +// * If the token exists and does not require a refresh, return the current token. +// * Attempt to refresh the token. +// * If the token is refreshed successfully, save it in the cache and return the token. +// * If refresh fails and the old token is still valid, log an error and return the old token. +// * If refresh fails and the old token is no longer valid, return an error +func (m *Manager) GetServiceAccountToken(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + key := keyFunc(name, namespace, tr) + ctr, ok := m.get(key) + + if ok && !m.requiresRefresh(ctr) { + return ctr, nil + } + + tr, err := m.getToken(name, namespace, tr) + if err != nil { + switch { + case !ok: + return nil, fmt.Errorf("failed to fetch token: %v", err) + case m.expired(ctr): + return nil, fmt.Errorf("token %s expired and refresh failed: %v", key, err) + default: + glog.Errorf("couldn't update token %s: %v", key, err) + return ctr, nil + } + } + + m.set(key, tr) + return tr, nil +} + +func (m *Manager) cleanup() { + m.cacheMutex.Lock() + defer m.cacheMutex.Unlock() + for k, tr := range m.cache { + if m.expired(tr) { + delete(m.cache, k) + } + } +} + +func (m *Manager) get(key string) (*authenticationv1.TokenRequest, bool) { + m.cacheMutex.RLock() + defer m.cacheMutex.RUnlock() + ctr, ok := m.cache[key] + return ctr, ok +} + +func (m *Manager) set(key string, tr *authenticationv1.TokenRequest) { + m.cacheMutex.Lock() + defer m.cacheMutex.Unlock() + m.cache[key] = tr +} + +func (m *Manager) expired(t *authenticationv1.TokenRequest) bool { + return m.clock.Now().After(t.Status.ExpirationTimestamp.Time) +} + +// requiresRefresh returns true if the token is older than 80% of its total +// ttl, or if the token is older than 24 hours. +func (m *Manager) requiresRefresh(tr *authenticationv1.TokenRequest) bool { + if tr.Spec.ExpirationSeconds == nil { + glog.Errorf("expiration seconds was nil for tr: %#v", tr) + return false + } + now := m.clock.Now() + exp := tr.Status.ExpirationTimestamp.Time + iat := exp.Add(-1 * time.Duration(*tr.Spec.ExpirationSeconds) * time.Second) + + if now.After(iat.Add(maxTTL)) { + return true + } + // Require a refresh if within 20% of the TTL from the expiration time. + if now.After(exp.Add(-1 * time.Duration((*tr.Spec.ExpirationSeconds*20)/100) * time.Second)) { + return true + } + return false +} + +// keys should be nonconfidential and safe to log +func keyFunc(name, namespace string, tr *authenticationv1.TokenRequest) string { + return fmt.Sprintf("%q/%q/%#v", name, namespace, tr.Spec) +} diff --git a/pkg/kubelet/token/token_manager_test.go b/pkg/kubelet/token/token_manager_test.go new file mode 100644 index 00000000000..2d877652dd6 --- /dev/null +++ b/pkg/kubelet/token/token_manager_test.go @@ -0,0 +1,223 @@ +/* +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 token + +import ( + "fmt" + "testing" + "time" + + authenticationv1 "k8s.io/api/authentication/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/clock" +) + +func TestTokenCachingAndExpiration(t *testing.T) { + type suite struct { + clock *clock.FakeClock + tg *fakeTokenGetter + mgr *Manager + } + + cases := []struct { + name string + exp time.Duration + f func(t *testing.T, s *suite) + }{ + { + name: "rotate hour token expires in the last 12 minutes", + exp: time.Hour, + f: func(t *testing.T, s *suite) { + s.clock.SetTime(s.clock.Now().Add(50 * time.Minute)) + if _, err := s.mgr.GetServiceAccountToken("a", "b", &authenticationv1.TokenRequest{}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if s.tg.count != 2 { + t.Fatalf("expected token to be refreshed: call count was %d", s.tg.count) + } + }, + }, + { + name: "rotate 24 hour token that expires in 40 hours", + exp: 40 * time.Hour, + f: func(t *testing.T, s *suite) { + s.clock.SetTime(s.clock.Now().Add(25 * time.Hour)) + if _, err := s.mgr.GetServiceAccountToken("a", "b", &authenticationv1.TokenRequest{}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if s.tg.count != 2 { + t.Fatalf("expected token to be refreshed: call count was %d", s.tg.count) + } + }, + }, + { + name: "rotate hour token fails, old token is still valid, doesn't error", + exp: time.Hour, + f: func(t *testing.T, s *suite) { + s.clock.SetTime(s.clock.Now().Add(50 * time.Minute)) + tg := &fakeTokenGetter{ + err: fmt.Errorf("err"), + } + s.mgr.getToken = tg.getToken + tr, err := s.mgr.GetServiceAccountToken("a", "b", &authenticationv1.TokenRequest{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if tr.Status.Token != "foo" { + t.Fatalf("unexpected token: %v", tr.Status.Token) + } + }, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + clock := clock.NewFakeClock(time.Time{}.Add(30 * 24 * time.Hour)) + expSecs := int64(c.exp.Seconds()) + s := &suite{ + clock: clock, + mgr: NewManager(nil), + tg: &fakeTokenGetter{ + tr: &authenticationv1.TokenRequest{ + Spec: authenticationv1.TokenRequestSpec{ + ExpirationSeconds: &expSecs, + }, + Status: authenticationv1.TokenRequestStatus{ + Token: "foo", + ExpirationTimestamp: metav1.Time{Time: clock.Now().Add(c.exp)}, + }, + }, + }, + } + s.mgr.getToken = s.tg.getToken + s.mgr.clock = s.clock + if _, err := s.mgr.GetServiceAccountToken("a", "b", &authenticationv1.TokenRequest{}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if s.tg.count != 1 { + t.Fatalf("unexpected client call, got: %d, want: 1", s.tg.count) + } + + if _, err := s.mgr.GetServiceAccountToken("a", "b", &authenticationv1.TokenRequest{}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if s.tg.count != 1 { + t.Fatalf("expected token to be served from cache: saw %d", s.tg.count) + } + + c.f(t, s) + }) + } +} + +func TestRequiresRefresh(t *testing.T) { + start := time.Now() + cases := []struct { + now, exp time.Time + expectRefresh bool + }{ + { + now: start.Add(10 * time.Minute), + exp: start.Add(60 * time.Minute), + expectRefresh: false, + }, + { + now: start.Add(50 * time.Minute), + exp: start.Add(60 * time.Minute), + expectRefresh: true, + }, + { + now: start.Add(25 * time.Hour), + exp: start.Add(60 * time.Hour), + expectRefresh: true, + }, + { + now: start.Add(70 * time.Minute), + exp: start.Add(60 * time.Minute), + expectRefresh: true, + }, + } + + for i, c := range cases { + t.Run(fmt.Sprint(i), func(t *testing.T) { + clock := clock.NewFakeClock(c.now) + secs := int64(c.exp.Sub(start).Seconds()) + tr := &authenticationv1.TokenRequest{ + Spec: authenticationv1.TokenRequestSpec{ + ExpirationSeconds: &secs, + }, + Status: authenticationv1.TokenRequestStatus{ + ExpirationTimestamp: metav1.Time{Time: c.exp}, + }, + } + mgr := NewManager(nil) + mgr.clock = clock + + rr := mgr.requiresRefresh(tr) + if rr != c.expectRefresh { + t.Fatalf("unexpected requiresRefresh result, got: %v, want: %v", rr, c.expectRefresh) + } + }) + } +} + +type fakeTokenGetter struct { + count int + tr *authenticationv1.TokenRequest + err error +} + +func (ftg *fakeTokenGetter) getToken(name, namespace string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + ftg.count++ + return ftg.tr, ftg.err +} + +func TestCleanup(t *testing.T) { + cases := []struct { + name string + relativeExp time.Duration + expectedCacheSize int + }{ + { + name: "don't cleanup unexpired tokens", + relativeExp: -1 * time.Hour, + expectedCacheSize: 0, + }, + { + name: "cleanup expired tokens", + relativeExp: time.Hour, + expectedCacheSize: 1, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + clock := clock.NewFakeClock(time.Time{}.Add(24 * time.Hour)) + mgr := NewManager(nil) + mgr.clock = clock + + mgr.set("key", &authenticationv1.TokenRequest{ + Status: authenticationv1.TokenRequestStatus{ + ExpirationTimestamp: metav1.Time{Time: mgr.clock.Now().Add(c.relativeExp)}, + }, + }) + mgr.cleanup() + if got, want := len(mgr.cache), c.expectedCacheSize; got != want { + t.Fatalf("unexpected number of cache entries after cleanup, got: %d, want: %d", got, want) + } + }) + } +} diff --git a/pkg/kubelet/types/BUILD b/pkg/kubelet/types/BUILD index c362d096de2..b1d5ffd1ae5 100644 --- a/pkg/kubelet/types/BUILD +++ b/pkg/kubelet/types/BUILD @@ -12,6 +12,7 @@ go_library( "constants.go", "doc.go", "labels.go", + "pod_status.go", "pod_update.go", "types.go", ], @@ -29,6 +30,7 @@ go_test( name = "go_default_test", srcs = [ "labels_test.go", + "pod_status_test.go", "pod_update_test.go", "types_test.go", ], diff --git a/pkg/kubelet/types/pod_status.go b/pkg/kubelet/types/pod_status.go new file mode 100644 index 00000000000..8c46ba39eb6 --- /dev/null +++ b/pkg/kubelet/types/pod_status.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 types + +import ( + "k8s.io/api/core/v1" +) + +// PodConditionsByKubelet is the list of pod conditions owned by kubelet +var PodConditionsByKubelet = []v1.PodConditionType{ + v1.PodScheduled, + v1.PodReady, + v1.PodInitialized, + v1.PodReasonUnschedulable, + v1.ContainersReady, +} + +// PodConditionByKubelet returns if the pod condition type is owned by kubelet +func PodConditionByKubelet(conditionType v1.PodConditionType) bool { + for _, c := range PodConditionsByKubelet { + if c == conditionType { + return true + } + } + return false +} diff --git a/pkg/kubelet/types/pod_status_test.go b/pkg/kubelet/types/pod_status_test.go new file mode 100644 index 00000000000..61c837748d3 --- /dev/null +++ b/pkg/kubelet/types/pod_status_test.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 types + +import ( + "k8s.io/api/core/v1" + "testing" +) + +func TestPodConditionByKubelet(t *testing.T) { + trueCases := []v1.PodConditionType{ + v1.PodScheduled, + v1.PodReady, + v1.PodInitialized, + v1.PodReasonUnschedulable, + } + + for _, tc := range trueCases { + if !PodConditionByKubelet(tc) { + t.Errorf("Expect %q to be condition owned by kubelet.", tc) + } + } + + falseCases := []v1.PodConditionType{ + v1.PodConditionType("abcd"), + } + + for _, tc := range falseCases { + if PodConditionByKubelet(tc) { + t.Errorf("Expect %q NOT to be condition owned by kubelet.", tc) + } + } +} diff --git a/pkg/kubelet/util/BUILD b/pkg/kubelet/util/BUILD index df02ebdcd25..ff1755ebd11 100644 --- a/pkg/kubelet/util/BUILD +++ b/pkg/kubelet/util/BUILD @@ -93,9 +93,11 @@ filegroup( "//pkg/kubelet/util/format:all-srcs", "//pkg/kubelet/util/ioutils:all-srcs", "//pkg/kubelet/util/manager:all-srcs", + "//pkg/kubelet/util/pluginwatcher:all-srcs", "//pkg/kubelet/util/queue:all-srcs", "//pkg/kubelet/util/sliceutils:all-srcs", "//pkg/kubelet/util/store:all-srcs", ], tags = ["automanaged"], + visibility = ["//visibility:public"], ) diff --git a/pkg/kubelet/util/pluginwatcher/BUILD b/pkg/kubelet/util/pluginwatcher/BUILD new file mode 100644 index 00000000000..b4173ab5e1c --- /dev/null +++ b/pkg/kubelet/util/pluginwatcher/BUILD @@ -0,0 +1,58 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = [ + "example_plugin.go", + "plugin_watcher.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher", + deps = [ + "//pkg/kubelet/apis/pluginregistration/v1alpha1:go_default_library", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1:go_default_library", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2:go_default_library", + "//pkg/util/filesystem:go_default_library", + "//vendor/github.com/fsnotify/fsnotify:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1:all-srcs", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["plugin_watcher_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/kubelet/apis/pluginregistration/v1alpha1:go_default_library", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1:go_default_library", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2:go_default_library", + "//vendor/github.com/stretchr/testify/require:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + ], +) diff --git a/pkg/kubelet/util/pluginwatcher/README b/pkg/kubelet/util/pluginwatcher/README new file mode 100644 index 00000000000..9654b2cf62a --- /dev/null +++ b/pkg/kubelet/util/pluginwatcher/README @@ -0,0 +1,29 @@ +This folder contains a utility, pluginwatcher, for Kubelet to register +different types of node-level plugins such as device plugins or CSI plugins. +It discovers plugins by monitoring inotify events under the directory returned by +kubelet.getPluginsDir(). Lets refer this directory as PluginsSockDir. +For any discovered plugin, pluginwatcher issues Registration.GetInfo grpc call +to get plugin type, name and supported service API versions. For any registered plugin type, +pluginwatcher calls the registered callback function with the received plugin +name, supported service API versions, and the full socket path. The Kubelet +component that receives this callback can acknowledge or reject the plugin +according to its own logic, and use the socket path to establish its service +communication with any API version supported by the plugin. + +Here are the general rules that Kubelet plugin developers should follow: +- Run as 'root' user. Currently creating socket under PluginsSockDir, a root owned directory, requires + plugin process to be running as 'root'. +- Implements the Registration service specified in + pkg/kubelet/apis/pluginregistration/v*/api.proto. +- The plugin name sent during Registration.GetInfo grpc should be unique + for the given plugin type (CSIPlugin or DevicePlugin). +- The socket path needs to be unique and doesn't conflict with the path chosen + by any other potential plugins. Currently we only support flat fs namespace + under PluginsSockDir but will soon support recursive inotify watch for + hierarchical socket paths. +- A plugin should clean up its own socket upon exiting or when a new instance + comes up. A plugin should NOT remove any sockets belonging to other plugins. +- A plugin should make sure it has service ready for any supported service API + version listed in the PluginInfo. +- For an example plugin implementation, take a look at example_plugin.go + included in this directory. diff --git a/pkg/kubelet/util/pluginwatcher/example_plugin.go b/pkg/kubelet/util/pluginwatcher/example_plugin.go new file mode 100644 index 00000000000..fbca43acad5 --- /dev/null +++ b/pkg/kubelet/util/pluginwatcher/example_plugin.go @@ -0,0 +1,150 @@ +/* +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 pluginwatcher + +import ( + "fmt" + "net" + "sync" + "time" + + "github.com/golang/glog" + "golang.org/x/net/context" + "google.golang.org/grpc" + + registerapi "k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1" + v1beta1 "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1" + v1beta2 "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2" +) + +const ( + PluginName = "example-plugin" + PluginType = "example-plugin-type" +) + +// examplePlugin is a sample plugin to work with plugin watcher +type examplePlugin struct { + grpcServer *grpc.Server + wg sync.WaitGroup + registrationStatus chan registerapi.RegistrationStatus // for testing + endpoint string // for testing +} + +type pluginServiceV1Beta1 struct { + server *examplePlugin +} + +func (s *pluginServiceV1Beta1) GetExampleInfo(ctx context.Context, rqt *v1beta1.ExampleRequest) (*v1beta1.ExampleResponse, error) { + glog.Infof("GetExampleInfo v1beta1field: %s", rqt.V1Beta1Field) + return &v1beta1.ExampleResponse{}, nil +} + +func (s *pluginServiceV1Beta1) RegisterService() { + v1beta1.RegisterExampleServer(s.server.grpcServer, s) +} + +type pluginServiceV1Beta2 struct { + server *examplePlugin +} + +func (s *pluginServiceV1Beta2) GetExampleInfo(ctx context.Context, rqt *v1beta2.ExampleRequest) (*v1beta2.ExampleResponse, error) { + glog.Infof("GetExampleInfo v1beta2_field: %s", rqt.V1Beta2Field) + return &v1beta2.ExampleResponse{}, nil +} + +func (s *pluginServiceV1Beta2) RegisterService() { + v1beta2.RegisterExampleServer(s.server.grpcServer, s) +} + +// NewExamplePlugin returns an initialized examplePlugin instance +func NewExamplePlugin() *examplePlugin { + return &examplePlugin{} +} + +// NewTestExamplePlugin returns an initialized examplePlugin instance for testing +func NewTestExamplePlugin(endpoint string) *examplePlugin { + return &examplePlugin{ + registrationStatus: make(chan registerapi.RegistrationStatus), + endpoint: endpoint, + } +} + +// GetInfo is the RPC invoked by plugin watcher +func (e *examplePlugin) GetInfo(ctx context.Context, req *registerapi.InfoRequest) (*registerapi.PluginInfo, error) { + return ®isterapi.PluginInfo{ + Type: PluginType, + Name: PluginName, + Endpoint: e.endpoint, + SupportedVersions: []string{"v1beta1", "v1beta2"}, + }, nil +} + +func (e *examplePlugin) NotifyRegistrationStatus(ctx context.Context, status *registerapi.RegistrationStatus) (*registerapi.RegistrationStatusResponse, error) { + if e.registrationStatus != nil { + e.registrationStatus <- *status + } + if !status.PluginRegistered { + glog.Errorf("Registration failed: %s\n", status.Error) + } + return ®isterapi.RegistrationStatusResponse{}, nil +} + +// Serve starts example plugin grpc server +func (e *examplePlugin) Serve(socketPath string) error { + glog.Infof("starting example server at: %s\n", socketPath) + lis, err := net.Listen("unix", socketPath) + if err != nil { + return err + } + glog.Infof("example server started at: %s\n", socketPath) + e.grpcServer = grpc.NewServer() + // Registers kubelet plugin watcher api. + registerapi.RegisterRegistrationServer(e.grpcServer, e) + // Registers services for both v1beta1 and v1beta2 versions. + v1beta1 := &pluginServiceV1Beta1{server: e} + v1beta1.RegisterService() + v1beta2 := &pluginServiceV1Beta2{server: e} + v1beta2.RegisterService() + + // Starts service + e.wg.Add(1) + go func() { + defer e.wg.Done() + // Blocking call to accept incoming connections. + if err := e.grpcServer.Serve(lis); err != nil { + glog.Errorf("example server stopped serving: %v", err) + } + }() + return nil +} + +func (e *examplePlugin) Stop() error { + glog.Infof("Stopping example server\n") + e.grpcServer.Stop() + c := make(chan struct{}) + go func() { + defer close(c) + e.wg.Wait() + }() + select { + case <-c: + return nil + case <-time.After(time.Second): + glog.Errorf("Timed out on waiting for stop completion") + return fmt.Errorf("Timed out on waiting for stop completion") + } +} diff --git a/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/BUILD b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/BUILD new file mode 100644 index 00000000000..affbd0aee4a --- /dev/null +++ b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/BUILD @@ -0,0 +1,34 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +filegroup( + name = "go_default_library_protos", + srcs = ["api.proto"], + visibility = ["//visibility:public"], +) + +go_library( + name = "go_default_library", + srcs = ["api.pb.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library", + "//vendor/github.com/gogo/protobuf/proto:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc: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/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.pb.go b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.pb.go new file mode 100644 index 00000000000..671e3df493b --- /dev/null +++ b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.pb.go @@ -0,0 +1,632 @@ +/* +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. +// source: api.proto +// DO NOT EDIT! + +/* + Package v1beta1 is a generated protocol buffer package. + + It is generated from these files: + api.proto + + It has these top-level messages: + ExampleRequest + ExampleResponse +*/ +package v1beta1 + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +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 + +type ExampleRequest struct { + Request string `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` + V1Beta1Field string `protobuf:"bytes,2,opt,name=v1beta1_field,json=v1beta1Field,proto3" json:"v1beta1_field,omitempty"` +} + +func (m *ExampleRequest) Reset() { *m = ExampleRequest{} } +func (*ExampleRequest) ProtoMessage() {} +func (*ExampleRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{0} } + +func (m *ExampleRequest) GetRequest() string { + if m != nil { + return m.Request + } + return "" +} + +func (m *ExampleRequest) GetV1Beta1Field() string { + if m != nil { + return m.V1Beta1Field + } + return "" +} + +type ExampleResponse struct { + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *ExampleResponse) Reset() { *m = ExampleResponse{} } +func (*ExampleResponse) ProtoMessage() {} +func (*ExampleResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{1} } + +func (m *ExampleResponse) GetError() string { + if m != nil { + return m.Error + } + return "" +} + +func init() { + proto.RegisterType((*ExampleRequest)(nil), "v1beta1.ExampleRequest") + proto.RegisterType((*ExampleResponse)(nil), "v1beta1.ExampleResponse") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Example service + +type ExampleClient interface { + GetExampleInfo(ctx context.Context, in *ExampleRequest, opts ...grpc.CallOption) (*ExampleResponse, error) +} + +type exampleClient struct { + cc *grpc.ClientConn +} + +func NewExampleClient(cc *grpc.ClientConn) ExampleClient { + return &exampleClient{cc} +} + +func (c *exampleClient) GetExampleInfo(ctx context.Context, in *ExampleRequest, opts ...grpc.CallOption) (*ExampleResponse, error) { + out := new(ExampleResponse) + err := grpc.Invoke(ctx, "/v1beta1.Example/GetExampleInfo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Example service + +type ExampleServer interface { + GetExampleInfo(context.Context, *ExampleRequest) (*ExampleResponse, error) +} + +func RegisterExampleServer(s *grpc.Server, srv ExampleServer) { + s.RegisterService(&_Example_serviceDesc, srv) +} + +func _Example_GetExampleInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExampleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExampleServer).GetExampleInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/v1beta1.Example/GetExampleInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExampleServer).GetExampleInfo(ctx, req.(*ExampleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Example_serviceDesc = grpc.ServiceDesc{ + ServiceName: "v1beta1.Example", + HandlerType: (*ExampleServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetExampleInfo", + Handler: _Example_GetExampleInfo_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "api.proto", +} + +func (m *ExampleRequest) 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 *ExampleRequest) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Request) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Request))) + i += copy(dAtA[i:], m.Request) + } + if len(m.V1Beta1Field) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.V1Beta1Field))) + i += copy(dAtA[i:], m.V1Beta1Field) + } + return i, nil +} + +func (m *ExampleResponse) 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 *ExampleResponse) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Error) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Error))) + i += copy(dAtA[i:], m.Error) + } + return i, nil +} + +func encodeFixed64Api(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Api(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintApi(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 *ExampleRequest) Size() (n int) { + var l int + _ = l + l = len(m.Request) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.V1Beta1Field) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *ExampleResponse) Size() (n int) { + var l int + _ = l + l = len(m.Error) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func sovApi(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozApi(x uint64) (n int) { + return sovApi(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *ExampleRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ExampleRequest{`, + `Request:` + fmt.Sprintf("%v", this.Request) + `,`, + `V1Beta1Field:` + fmt.Sprintf("%v", this.V1Beta1Field) + `,`, + `}`, + }, "") + return s +} +func (this *ExampleResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ExampleResponse{`, + `Error:` + fmt.Sprintf("%v", this.Error) + `,`, + `}`, + }, "") + return s +} +func valueToStringApi(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *ExampleRequest) 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 ErrIntOverflowApi + } + 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: ExampleRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExampleRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Request", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Request = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field V1Beta1Field", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.V1Beta1Field = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExampleResponse) 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 ErrIntOverflowApi + } + 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: ExampleResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExampleResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipApi(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, ErrIntOverflowApi + } + 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, ErrIntOverflowApi + } + 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, ErrIntOverflowApi + } + 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, ErrInvalidLengthApi + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + 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 := skipApi(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 ( + ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowApi = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("api.proto", fileDescriptorApi) } + +var fileDescriptorApi = []byte{ + // 227 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0x2c, 0xc8, 0xd4, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0x94, 0xd2, + 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0x4f, 0xcf, 0xd7, + 0x07, 0xcb, 0x27, 0x95, 0xa6, 0x81, 0x79, 0x60, 0x0e, 0x98, 0x05, 0xd1, 0xa7, 0xe4, 0xcf, 0xc5, + 0xe7, 0x5a, 0x91, 0x98, 0x5b, 0x90, 0x93, 0x1a, 0x94, 0x5a, 0x58, 0x9a, 0x5a, 0x5c, 0x22, 0x24, + 0xc1, 0xc5, 0x5e, 0x04, 0x61, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0xc1, 0xb8, 0x42, 0xca, + 0x5c, 0xbc, 0x50, 0x5b, 0xe2, 0xd3, 0x32, 0x53, 0x73, 0x52, 0x24, 0x98, 0xc0, 0xf2, 0x3c, 0x50, + 0x41, 0x37, 0x90, 0x98, 0x92, 0x3a, 0x17, 0x3f, 0xdc, 0xc0, 0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, + 0x21, 0x11, 0x2e, 0xd6, 0xd4, 0xa2, 0xa2, 0xfc, 0x22, 0xa8, 0x79, 0x10, 0x8e, 0x51, 0x00, 0x17, + 0x3b, 0x54, 0xa1, 0x90, 0x2b, 0x17, 0x9f, 0x7b, 0x6a, 0x09, 0x94, 0xe7, 0x99, 0x97, 0x96, 0x2f, + 0x24, 0xae, 0x07, 0x35, 0x54, 0x0f, 0xd5, 0x75, 0x52, 0x12, 0x98, 0x12, 0x10, 0x5b, 0x94, 0x18, + 0x9c, 0x64, 0x4e, 0x3c, 0x94, 0x63, 0xbc, 0xf1, 0x50, 0x8e, 0xa1, 0xe1, 0x91, 0x1c, 0xe3, 0x89, + 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0x43, + 0x12, 0x1b, 0xd8, 0xc3, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x99, 0x62, 0xd1, 0x9c, 0x35, + 0x01, 0x00, 0x00, +} diff --git a/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.proto b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.proto new file mode 100644 index 00000000000..14aa7df2c4d --- /dev/null +++ b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.proto @@ -0,0 +1,28 @@ +syntax = 'proto3'; + +package v1beta1; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +option (gogoproto.goproto_stringer_all) = false; +option (gogoproto.stringer_all) = true; +option (gogoproto.goproto_getters_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.goproto_unrecognized_all) = false; + +message ExampleRequest { + string request = 1; + string v1beta1_field = 2; +} + +message ExampleResponse { + string error = 1; +} + +// Example is a simple example service for general reference on the recommended +// kubelet plugin model and plugin watcher testing. +service Example { + rpc GetExampleInfo(ExampleRequest) returns (ExampleResponse) {} +} diff --git a/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/BUILD b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/BUILD new file mode 100644 index 00000000000..f2b53898d38 --- /dev/null +++ b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/BUILD @@ -0,0 +1,34 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +filegroup( + name = "go_default_library_protos", + srcs = ["api.proto"], + visibility = ["//visibility:public"], +) + +go_library( + name = "go_default_library", + srcs = ["api.pb.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library", + "//vendor/github.com/gogo/protobuf/proto:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc: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/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.pb.go b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.pb.go new file mode 100644 index 00000000000..0c63b31429f --- /dev/null +++ b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.pb.go @@ -0,0 +1,633 @@ +/* +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. +// source: api.proto +// DO NOT EDIT! + +/* + Package v1beta2 is a generated protocol buffer package. + + It is generated from these files: + api.proto + + It has these top-level messages: + ExampleRequest + ExampleResponse +*/ +package v1beta2 + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +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 + +// Renames a field from v1beta1 ExampleRequest. +type ExampleRequest struct { + Request string `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` + V1Beta2Field string `protobuf:"bytes,2,opt,name=v1beta2_field,json=v1beta2Field,proto3" json:"v1beta2_field,omitempty"` +} + +func (m *ExampleRequest) Reset() { *m = ExampleRequest{} } +func (*ExampleRequest) ProtoMessage() {} +func (*ExampleRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{0} } + +func (m *ExampleRequest) GetRequest() string { + if m != nil { + return m.Request + } + return "" +} + +func (m *ExampleRequest) GetV1Beta2Field() string { + if m != nil { + return m.V1Beta2Field + } + return "" +} + +type ExampleResponse struct { + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *ExampleResponse) Reset() { *m = ExampleResponse{} } +func (*ExampleResponse) ProtoMessage() {} +func (*ExampleResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{1} } + +func (m *ExampleResponse) GetError() string { + if m != nil { + return m.Error + } + return "" +} + +func init() { + proto.RegisterType((*ExampleRequest)(nil), "v1beta2.ExampleRequest") + proto.RegisterType((*ExampleResponse)(nil), "v1beta2.ExampleResponse") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Example service + +type ExampleClient interface { + GetExampleInfo(ctx context.Context, in *ExampleRequest, opts ...grpc.CallOption) (*ExampleResponse, error) +} + +type exampleClient struct { + cc *grpc.ClientConn +} + +func NewExampleClient(cc *grpc.ClientConn) ExampleClient { + return &exampleClient{cc} +} + +func (c *exampleClient) GetExampleInfo(ctx context.Context, in *ExampleRequest, opts ...grpc.CallOption) (*ExampleResponse, error) { + out := new(ExampleResponse) + err := grpc.Invoke(ctx, "/v1beta2.Example/GetExampleInfo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Example service + +type ExampleServer interface { + GetExampleInfo(context.Context, *ExampleRequest) (*ExampleResponse, error) +} + +func RegisterExampleServer(s *grpc.Server, srv ExampleServer) { + s.RegisterService(&_Example_serviceDesc, srv) +} + +func _Example_GetExampleInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExampleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExampleServer).GetExampleInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/v1beta2.Example/GetExampleInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExampleServer).GetExampleInfo(ctx, req.(*ExampleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Example_serviceDesc = grpc.ServiceDesc{ + ServiceName: "v1beta2.Example", + HandlerType: (*ExampleServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetExampleInfo", + Handler: _Example_GetExampleInfo_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "api.proto", +} + +func (m *ExampleRequest) 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 *ExampleRequest) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Request) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Request))) + i += copy(dAtA[i:], m.Request) + } + if len(m.V1Beta2Field) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.V1Beta2Field))) + i += copy(dAtA[i:], m.V1Beta2Field) + } + return i, nil +} + +func (m *ExampleResponse) 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 *ExampleResponse) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Error) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Error))) + i += copy(dAtA[i:], m.Error) + } + return i, nil +} + +func encodeFixed64Api(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Api(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintApi(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 *ExampleRequest) Size() (n int) { + var l int + _ = l + l = len(m.Request) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.V1Beta2Field) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *ExampleResponse) Size() (n int) { + var l int + _ = l + l = len(m.Error) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func sovApi(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozApi(x uint64) (n int) { + return sovApi(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *ExampleRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ExampleRequest{`, + `Request:` + fmt.Sprintf("%v", this.Request) + `,`, + `V1Beta2Field:` + fmt.Sprintf("%v", this.V1Beta2Field) + `,`, + `}`, + }, "") + return s +} +func (this *ExampleResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ExampleResponse{`, + `Error:` + fmt.Sprintf("%v", this.Error) + `,`, + `}`, + }, "") + return s +} +func valueToStringApi(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *ExampleRequest) 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 ErrIntOverflowApi + } + 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: ExampleRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExampleRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Request", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Request = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field V1Beta2Field", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.V1Beta2Field = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExampleResponse) 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 ErrIntOverflowApi + } + 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: ExampleResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExampleResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + 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 ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipApi(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, ErrIntOverflowApi + } + 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, ErrIntOverflowApi + } + 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, ErrIntOverflowApi + } + 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, ErrInvalidLengthApi + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + 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 := skipApi(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 ( + ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowApi = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("api.proto", fileDescriptorApi) } + +var fileDescriptorApi = []byte{ + // 227 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0x2c, 0xc8, 0xd4, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0x92, 0xd2, + 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0x4f, 0xcf, 0xd7, + 0x07, 0xcb, 0x27, 0x95, 0xa6, 0x81, 0x79, 0x60, 0x0e, 0x98, 0x05, 0xd1, 0xa7, 0xe4, 0xcf, 0xc5, + 0xe7, 0x5a, 0x91, 0x98, 0x5b, 0x90, 0x93, 0x1a, 0x94, 0x5a, 0x58, 0x9a, 0x5a, 0x5c, 0x22, 0x24, + 0xc1, 0xc5, 0x5e, 0x04, 0x61, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0xc1, 0xb8, 0x42, 0xca, + 0x5c, 0xbc, 0x50, 0x5b, 0xe2, 0xd3, 0x32, 0x53, 0x73, 0x52, 0x24, 0x98, 0xc0, 0xf2, 0x3c, 0x50, + 0x41, 0x37, 0x90, 0x98, 0x92, 0x3a, 0x17, 0x3f, 0xdc, 0xc0, 0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, + 0x21, 0x11, 0x2e, 0xd6, 0xd4, 0xa2, 0xa2, 0xfc, 0x22, 0xa8, 0x79, 0x10, 0x8e, 0x51, 0x00, 0x17, + 0x3b, 0x54, 0xa1, 0x90, 0x2b, 0x17, 0x9f, 0x7b, 0x6a, 0x09, 0x94, 0xe7, 0x99, 0x97, 0x96, 0x2f, + 0x24, 0xae, 0x07, 0x35, 0x54, 0x0f, 0xd5, 0x75, 0x52, 0x12, 0x98, 0x12, 0x10, 0x5b, 0x94, 0x18, + 0x9c, 0x64, 0x4e, 0x3c, 0x94, 0x63, 0xbc, 0xf1, 0x50, 0x8e, 0xa1, 0xe1, 0x91, 0x1c, 0xe3, 0x89, + 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0x43, + 0x12, 0x1b, 0xd8, 0xc3, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa8, 0x79, 0x17, 0x13, 0x35, + 0x01, 0x00, 0x00, +} diff --git a/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.proto b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.proto new file mode 100644 index 00000000000..e34697f3a66 --- /dev/null +++ b/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.proto @@ -0,0 +1,29 @@ +syntax = 'proto3'; + +package v1beta2; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +option (gogoproto.goproto_stringer_all) = false; +option (gogoproto.stringer_all) = true; +option (gogoproto.goproto_getters_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.goproto_unrecognized_all) = false; + +// Renames a field from v1beta1 ExampleRequest. +message ExampleRequest { + string request = 1; + string v1beta2_field = 2; +} + +message ExampleResponse { + string error = 1; +} + +// Example is a simple example service for general reference on the recommended +// kubelet plugin model and plugin watcher testing. +service Example { + rpc GetExampleInfo(ExampleRequest) returns (ExampleResponse) {} +} diff --git a/pkg/kubelet/util/pluginwatcher/plugin_watcher.go b/pkg/kubelet/util/pluginwatcher/plugin_watcher.go new file mode 100644 index 00000000000..9a5241cb2e5 --- /dev/null +++ b/pkg/kubelet/util/pluginwatcher/plugin_watcher.go @@ -0,0 +1,260 @@ +/* +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 pluginwatcher + +import ( + "fmt" + "net" + "os" + "path" + "path/filepath" + "sync" + "time" + + "github.com/fsnotify/fsnotify" + "github.com/golang/glog" + "golang.org/x/net/context" + "google.golang.org/grpc" + registerapi "k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1" + utilfs "k8s.io/kubernetes/pkg/util/filesystem" +) + +// RegisterCallbackFn is the type of the callback function that handlers will provide +type RegisterCallbackFn func(pluginName string, endpoint string, versions []string, socketPath string) (error, chan bool) + +// Watcher is the plugin watcher +type Watcher struct { + path string + handlers map[string]RegisterCallbackFn + stopCh chan interface{} + fs utilfs.Filesystem + watcher *fsnotify.Watcher + wg sync.WaitGroup + mutex sync.Mutex +} + +// NewWatcher provides a new watcher +func NewWatcher(sockDir string) Watcher { + return Watcher{ + path: sockDir, + handlers: make(map[string]RegisterCallbackFn), + fs: &utilfs.DefaultFs{}, + } +} + +// AddHandler registers a callback to be invoked for a particular type of plugin +func (w *Watcher) AddHandler(handlerType string, handlerCbkFn RegisterCallbackFn) { + w.mutex.Lock() + defer w.mutex.Unlock() + w.handlers[handlerType] = handlerCbkFn +} + +// Creates the plugin directory, if it doesn't already exist. +func (w *Watcher) createPluginDir() error { + glog.V(4).Infof("Ensuring Plugin directory at %s ", w.path) + if err := w.fs.MkdirAll(w.path, 0755); err != nil { + return fmt.Errorf("error (re-)creating driver directory: %s", err) + } + return nil +} + +// Walks through the plugin directory to discover any existing plugin sockets. +func (w *Watcher) traversePluginDir() error { + files, err := w.fs.ReadDir(w.path) + if err != nil { + return fmt.Errorf("error reading the plugin directory: %v", err) + } + for _, f := range files { + // Currently only supports flat fs namespace under the plugin directory. + // TODO: adds support for hierarchical fs namespace. + if !f.IsDir() && filepath.Base(f.Name())[0] != '.' { + go func(sockName string) { + w.watcher.Events <- fsnotify.Event{ + Name: sockName, + Op: fsnotify.Op(uint32(1)), + } + }(path.Join(w.path, f.Name())) + } + } + return nil +} + +func (w *Watcher) init() error { + if err := w.createPluginDir(); err != nil { + return err + } + return nil +} + +func (w *Watcher) registerPlugin(socketPath string) error { + //TODO: Implement rate limiting to mitigate any DOS kind of attacks. + glog.V(4).Infof("registerPlugin called for socketPath: %s", socketPath) + client, conn, err := dial(socketPath) + if err != nil { + return fmt.Errorf("dial failed at socket %s, err: %v", socketPath, err) + } + defer conn.Close() + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + infoResp, err := client.GetInfo(ctx, ®isterapi.InfoRequest{}) + if err != nil { + return fmt.Errorf("failed to get plugin info using RPC GetInfo at socket %s, err: %v", socketPath, err) + } + if err := w.invokeRegistrationCallbackAtHandler(ctx, client, infoResp, socketPath); err != nil { + return fmt.Errorf("failed to register plugin. Callback handler returned err: %v", err) + } + glog.V(4).Infof("Successfully registered plugin for plugin type: %s, name: %s, socket: %s", infoResp.Type, infoResp.Name, socketPath) + return nil +} + +func (w *Watcher) invokeRegistrationCallbackAtHandler(ctx context.Context, client registerapi.RegistrationClient, infoResp *registerapi.PluginInfo, socketPath string) error { + var handlerCbkFn RegisterCallbackFn + var ok bool + handlerCbkFn, ok = w.handlers[infoResp.Type] + if !ok { + if _, err := client.NotifyRegistrationStatus(ctx, ®isterapi.RegistrationStatus{ + PluginRegistered: false, + Error: fmt.Sprintf("No handler found registered for plugin type: %s, socket: %s", infoResp.Type, socketPath), + }); err != nil { + glog.Errorf("Failed to send registration status at socket %s, err: %v", socketPath, err) + } + return fmt.Errorf("no handler found registered for plugin type: %s, socket: %s", infoResp.Type, socketPath) + } + + var versions []string + for _, version := range infoResp.SupportedVersions { + versions = append(versions, version) + } + // calls handler callback to verify registration request + err, chanForAckOfNotification := handlerCbkFn(infoResp.Name, infoResp.Endpoint, versions, socketPath) + if err != nil { + if _, err := client.NotifyRegistrationStatus(ctx, ®isterapi.RegistrationStatus{ + PluginRegistered: false, + Error: fmt.Sprintf("Plugin registration failed with err: %v", err), + }); err != nil { + glog.Errorf("Failed to send registration status at socket %s, err: %v", socketPath, err) + } + chanForAckOfNotification <- false + return fmt.Errorf("plugin registration failed with err: %v", err) + } + + if _, err := client.NotifyRegistrationStatus(ctx, ®isterapi.RegistrationStatus{ + PluginRegistered: true, + }); err != nil { + return fmt.Errorf("failed to send registration status at socket %s, err: %v", socketPath, err) + } + chanForAckOfNotification <- true + return nil +} + +// Start watches for the creation of plugin sockets at the path +func (w *Watcher) Start() error { + glog.V(2).Infof("Plugin Watcher Start at %s", w.path) + w.stopCh = make(chan interface{}) + + // Creating the directory to be watched if it doesn't exist yet, + // and walks through the directory to discover the existing plugins. + if err := w.init(); err != nil { + return err + } + + watcher, err := fsnotify.NewWatcher() + if err != nil { + return fmt.Errorf("failed to start plugin watcher, err: %v", err) + } + + if err := watcher.Add(w.path); err != nil { + watcher.Close() + return fmt.Errorf("failed to start plugin watcher, err: %v", err) + } + + w.watcher = watcher + + if err := w.traversePluginDir(); err != nil { + watcher.Close() + return fmt.Errorf("failed to traverse plugin socket path, err: %v", err) + } + + w.wg.Add(1) + go func(watcher *fsnotify.Watcher) { + defer w.wg.Done() + for { + select { + case event := <-watcher.Events: + if event.Op&fsnotify.Create == fsnotify.Create { + go func(eventName string) { + err := w.registerPlugin(eventName) + if err != nil { + glog.Errorf("Plugin %s registration failed with error: %v", eventName, err) + } + }(event.Name) + } + continue + case err := <-watcher.Errors: + //TODO: Handle errors by taking corrective measures + if err != nil { + glog.Errorf("Watcher received error: %v", err) + } + continue + + case <-w.stopCh: + watcher.Close() + break + } + break + } + }(watcher) + return nil +} + +// Stop stops probing the creation of plugin sockets at the path +func (w *Watcher) Stop() error { + close(w.stopCh) + c := make(chan struct{}) + go func() { + defer close(c) + w.wg.Wait() + }() + select { + case <-c: + case <-time.After(10 * time.Second): + return fmt.Errorf("timeout on stopping watcher") + } + return nil +} + +// Cleanup cleans the path by removing sockets +func (w *Watcher) Cleanup() error { + return os.RemoveAll(w.path) +} + +// Dial establishes the gRPC communication with the picked up plugin socket. https://godoc.org/google.golang.org/grpc#Dial +func dial(unixSocketPath string) (registerapi.RegistrationClient, *grpc.ClientConn, error) { + c, err := grpc.Dial(unixSocketPath, grpc.WithInsecure(), grpc.WithBlock(), + grpc.WithTimeout(10*time.Second), + grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { + return net.DialTimeout("unix", addr, timeout) + }), + ) + + if err != nil { + return nil, nil, fmt.Errorf("failed to dial socket %s, err: %v", unixSocketPath, err) + } + + return registerapi.NewRegistrationClient(c), c, nil +} diff --git a/pkg/kubelet/util/pluginwatcher/plugin_watcher_test.go b/pkg/kubelet/util/pluginwatcher/plugin_watcher_test.go new file mode 100644 index 00000000000..44bccf9a6f3 --- /dev/null +++ b/pkg/kubelet/util/pluginwatcher/plugin_watcher_test.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 pluginwatcher + +import ( + "fmt" + "io/ioutil" + "strconv" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" + "golang.org/x/net/context" + + "k8s.io/apimachinery/pkg/util/sets" + registerapi "k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1" + v1beta1 "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1" + v1beta2 "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2" +) + +func TestExamplePlugin(t *testing.T) { + socketDir, err := ioutil.TempDir("", "plugin_test") + require.NoError(t, err) + socketPath := socketDir + "/plugin.sock" + w := NewWatcher(socketDir) + + testCases := []struct { + description string + expectedEndpoint string + returnErr error + }{ + { + description: "Successfully register plugin through inotify", + expectedEndpoint: "", + returnErr: nil, + }, + { + description: "Successfully register plugin through inotify and got expected optional endpoint", + expectedEndpoint: "dummyEndpoint", + returnErr: nil, + }, + { + description: "Fails registration because endpoint is expected to be non-empty", + expectedEndpoint: "dummyEndpoint", + returnErr: fmt.Errorf("empty endpoint received"), + }, + { + description: "Successfully register plugin through inotify after plugin restarts", + expectedEndpoint: "", + returnErr: nil, + }, + { + description: "Fails registration with conflicting plugin name", + expectedEndpoint: "", + returnErr: fmt.Errorf("conflicting plugin name"), + }, + { + description: "Successfully register plugin during initial traverse after plugin watcher restarts", + expectedEndpoint: "", + returnErr: nil, + }, + { + description: "Fails registration with conflicting plugin name during initial traverse after plugin watcher restarts", + expectedEndpoint: "", + returnErr: fmt.Errorf("conflicting plugin name"), + }, + } + + callbackCount := struct { + mutex sync.Mutex + count int32 + }{} + w.AddHandler(PluginType, func(name string, endpoint string, versions []string, sockPath string) (error, chan bool) { + callbackCount.mutex.Lock() + localCount := callbackCount.count + callbackCount.count = callbackCount.count + 1 + callbackCount.mutex.Unlock() + + require.True(t, localCount <= int32((len(testCases)-1))) + require.Equal(t, PluginName, name, "Plugin name mismatched!!") + retError := testCases[localCount].returnErr + if retError == nil || retError.Error() != "empty endpoint received" { + require.Equal(t, testCases[localCount].expectedEndpoint, endpoint, "Unexpected endpoint") + } else { + require.NotEqual(t, testCases[localCount].expectedEndpoint, endpoint, "Unexpected endpoint") + } + + require.Equal(t, []string{"v1beta1", "v1beta2"}, versions, "Plugin version mismatched!!") + // Verifies the grpcServer is ready to serve services. + _, conn, err := dial(sockPath) + require.Nil(t, err) + defer conn.Close() + + // The plugin handler should be able to use any listed service API version. + v1beta1Client := v1beta1.NewExampleClient(conn) + v1beta2Client := v1beta2.NewExampleClient(conn) + + // Tests v1beta1 GetExampleInfo + _, err = v1beta1Client.GetExampleInfo(context.Background(), &v1beta1.ExampleRequest{}) + require.Nil(t, err) + + // Tests v1beta1 GetExampleInfo + _, err = v1beta2Client.GetExampleInfo(context.Background(), &v1beta2.ExampleRequest{}) + //atomic.AddInt32(&callbackCount, 1) + chanForAckOfNotification := make(chan bool) + + go func() { + select { + case <-chanForAckOfNotification: + close(chanForAckOfNotification) + case <-time.After(time.Second): + t.Fatalf("Timed out while waiting for notification ack") + } + }() + return retError, chanForAckOfNotification + }) + require.NoError(t, w.Start()) + + p := NewTestExamplePlugin("") + require.NoError(t, p.Serve(socketPath)) + require.True(t, waitForPluginRegistrationStatus(t, p.registrationStatus)) + + require.NoError(t, p.Stop()) + + p = NewTestExamplePlugin("dummyEndpoint") + require.NoError(t, p.Serve(socketPath)) + require.True(t, waitForPluginRegistrationStatus(t, p.registrationStatus)) + + require.NoError(t, p.Stop()) + + p = NewTestExamplePlugin("") + require.NoError(t, p.Serve(socketPath)) + require.False(t, waitForPluginRegistrationStatus(t, p.registrationStatus)) + + // Trying to start a plugin service at the same socket path should fail + // with "bind: address already in use" + require.NotNil(t, p.Serve(socketPath)) + + // grpcServer.Stop() will remove the socket and starting plugin service + // at the same path again should succeeds and trigger another callback. + require.NoError(t, p.Stop()) + p = NewTestExamplePlugin("") + go func() { + require.Nil(t, p.Serve(socketPath)) + }() + require.True(t, waitForPluginRegistrationStatus(t, p.registrationStatus)) + + // Starting another plugin with the same name got verification error. + p2 := NewTestExamplePlugin("") + socketPath2 := socketDir + "/plugin2.sock" + go func() { + require.NoError(t, p2.Serve(socketPath2)) + }() + require.False(t, waitForPluginRegistrationStatus(t, p2.registrationStatus)) + + // Restarts plugin watcher should traverse the socket directory and issues a + // callback for every existing socket. + require.NoError(t, w.Stop()) + errCh := make(chan error) + go func() { + errCh <- w.Start() + }() + + var wg sync.WaitGroup + wg.Add(2) + var pStatus string + var p2Status string + go func() { + pStatus = strconv.FormatBool(waitForPluginRegistrationStatus(t, p.registrationStatus)) + wg.Done() + }() + go func() { + p2Status = strconv.FormatBool(waitForPluginRegistrationStatus(t, p2.registrationStatus)) + wg.Done() + }() + wg.Wait() + expectedSet := sets.NewString() + expectedSet.Insert("true", "false") + actualSet := sets.NewString() + actualSet.Insert(pStatus, p2Status) + + require.Equal(t, expectedSet, actualSet) + + select { + case err = <-errCh: + require.NoError(t, err) + case <-time.After(time.Second): + t.Fatalf("Timed out while waiting for watcher start") + + } + + require.NoError(t, w.Stop()) + err = w.Cleanup() + require.NoError(t, err) +} + +func waitForPluginRegistrationStatus(t *testing.T, statusCh chan registerapi.RegistrationStatus) bool { + select { + case status := <-statusCh: + return status.PluginRegistered + case <-time.After(10 * time.Second): + t.Fatalf("Timed out while waiting for registration status") + } + return false +} diff --git a/pkg/kubelet/volume_host.go b/pkg/kubelet/volume_host.go index 9336d7cde3b..1d8bfcc9f68 100644 --- a/pkg/kubelet/volume_host.go +++ b/pkg/kubelet/volume_host.go @@ -23,6 +23,7 @@ import ( "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -34,6 +35,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/mountpod" "k8s.io/kubernetes/pkg/kubelet/secret" + "k8s.io/kubernetes/pkg/kubelet/token" "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" @@ -50,6 +52,7 @@ func NewInitializedVolumePluginMgr( kubelet *Kubelet, secretManager secret.Manager, configMapManager configmap.Manager, + tokenManager *token.Manager, plugins []volume.VolumePlugin, prober volume.DynamicPluginProber) (*volume.VolumePluginMgr, error) { @@ -62,6 +65,7 @@ func NewInitializedVolumePluginMgr( volumePluginMgr: volume.VolumePluginMgr{}, secretManager: secretManager, configMapManager: configMapManager, + tokenManager: tokenManager, mountPodManager: mountPodManager, } @@ -85,6 +89,7 @@ type kubeletVolumeHost struct { kubelet *Kubelet volumePluginMgr volume.VolumePluginMgr secretManager secret.Manager + tokenManager *token.Manager configMapManager configmap.Manager mountPodManager mountpod.Manager } @@ -191,6 +196,10 @@ func (kvh *kubeletVolumeHost) GetConfigMapFunc() func(namespace, name string) (* return kvh.configMapManager.GetConfigMap } +func (kvh *kubeletVolumeHost) GetServiceAccountTokenFunc() func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return kvh.tokenManager.GetServiceAccountToken +} + func (kvh *kubeletVolumeHost) GetNodeLabels() (map[string]string, error) { node, err := kvh.kubelet.GetNode() if err != nil { diff --git a/pkg/kubelet/volumemanager/cache/BUILD b/pkg/kubelet/volumemanager/cache/BUILD index bac59a12bd8..c79fad51379 100644 --- a/pkg/kubelet/volumemanager/cache/BUILD +++ b/pkg/kubelet/volumemanager/cache/BUILD @@ -14,6 +14,7 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/kubelet/volumemanager/cache", deps = [ + "//pkg/features:go_default_library", "//pkg/volume:go_default_library", "//pkg/volume/util:go_default_library", "//pkg/volume/util/operationexecutor:go_default_library", @@ -21,6 +22,7 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/pkg/kubelet/volumemanager/cache/actual_state_of_world.go b/pkg/kubelet/volumemanager/cache/actual_state_of_world.go index 6ba3cd0dfda..82aef86c720 100644 --- a/pkg/kubelet/volumemanager/cache/actual_state_of_world.go +++ b/pkg/kubelet/volumemanager/cache/actual_state_of_world.go @@ -28,6 +28,8 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util/operationexecutor" @@ -148,6 +150,11 @@ type ActualStateOfWorld interface { // with pod's unique name. This map can be used to determine which pod is currently // in actual state of world. GetPods() map[volumetypes.UniquePodName]bool + + // MarkFSResizeRequired marks each volume that is successfully attached and + // mounted for the specified pod as requiring file system resize (if the plugin for the + // volume indicates it requires file system resize). + MarkFSResizeRequired(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) } // MountedVolume represents a volume that has successfully been mounted to a pod. @@ -291,6 +298,10 @@ type mountedPod struct { // volumeGidValue contains the value of the GID annotation, if present. volumeGidValue string + + // fsResizeRequired indicates the underlying volume has been successfully + // mounted to this pod but its size has been expanded after that. + fsResizeRequired bool } func (asw *actualStateOfWorld) MarkVolumeAsAttached( @@ -444,6 +455,34 @@ func (asw *actualStateOfWorld) AddPodToVolume( return nil } +func (asw *actualStateOfWorld) MarkVolumeAsResized( + podName volumetypes.UniquePodName, + volumeName v1.UniqueVolumeName) error { + asw.Lock() + defer asw.Unlock() + + volumeObj, volumeExists := asw.attachedVolumes[volumeName] + if !volumeExists { + return fmt.Errorf( + "no volume with the name %q exists in the list of attached volumes", + volumeName) + } + + podObj, podExists := volumeObj.mountedPods[podName] + if !podExists { + return fmt.Errorf( + "no pod with the name %q exists in the mounted pods list of volume %s", + podName, + volumeName) + } + + glog.V(5).Infof("Volume %s(OuterVolumeSpecName %s) of pod %s has been resized", + volumeName, podObj.outerVolumeSpecName, podName) + podObj.fsResizeRequired = false + asw.attachedVolumes[volumeName].mountedPods[podName] = podObj + return nil +} + func (asw *actualStateOfWorld) MarkRemountRequired( podName volumetypes.UniquePodName) { asw.Lock() @@ -475,6 +514,46 @@ func (asw *actualStateOfWorld) MarkRemountRequired( } } +func (asw *actualStateOfWorld) MarkFSResizeRequired( + volumeName v1.UniqueVolumeName, + podName volumetypes.UniquePodName) { + asw.Lock() + defer asw.Unlock() + volumeObj, exist := asw.attachedVolumes[volumeName] + if !exist { + glog.Warningf("MarkFSResizeRequired for volume %s failed as volume not exist", volumeName) + return + } + + podObj, exist := volumeObj.mountedPods[podName] + if !exist { + glog.Warningf("MarkFSResizeRequired for volume %s failed "+ + "as pod(%s) not exist", volumeName, podName) + return + } + + volumePlugin, err := + asw.volumePluginMgr.FindExpandablePluginBySpec(podObj.volumeSpec) + if err != nil || volumePlugin == nil { + // Log and continue processing + glog.Errorf( + "MarkFSResizeRequired failed to find expandable plugin for pod %q volume: %q (volSpecName: %q)", + podObj.podName, + volumeObj.volumeName, + podObj.volumeSpec.Name()) + return + } + + if volumePlugin.RequiresFSResize() { + if !podObj.fsResizeRequired { + glog.V(3).Infof("PVC volume %s(OuterVolumeSpecName %s) of pod %s requires file system resize", + volumeName, podObj.outerVolumeSpecName, podName) + podObj.fsResizeRequired = true + } + asw.attachedVolumes[volumeName].mountedPods[podName] = podObj + } +} + func (asw *actualStateOfWorld) SetVolumeGloballyMounted( volumeName v1.UniqueVolumeName, globallyMounted bool, devicePath, deviceMountPath string) error { asw.Lock() @@ -546,8 +625,14 @@ func (asw *actualStateOfWorld) PodExistsInVolume( } podObj, podExists := volumeObj.mountedPods[podName] - if podExists && podObj.remountRequired { - return true, volumeObj.devicePath, newRemountRequiredError(volumeObj.volumeName, podObj.podName) + if podExists { + if podObj.remountRequired { + return true, volumeObj.devicePath, newRemountRequiredError(volumeObj.volumeName, podObj.podName) + } + if podObj.fsResizeRequired && + utilfeature.DefaultFeatureGate.Enabled(features.ExpandInUsePersistentVolumes) { + return true, volumeObj.devicePath, newFsResizeRequiredError(volumeObj.volumeName, podObj.podName) + } } return podExists, volumeObj.devicePath, nil @@ -716,6 +801,35 @@ func newRemountRequiredError( } } +// fsResizeRequiredError is an error returned when PodExistsInVolume() found +// volume/pod attached/mounted but fsResizeRequired was true, indicating the +// given volume receives an resize request after attached/mounted. +type fsResizeRequiredError struct { + volumeName v1.UniqueVolumeName + podName volumetypes.UniquePodName +} + +func (err fsResizeRequiredError) Error() string { + return fmt.Sprintf( + "volumeName %q mounted to %q needs to resize file system", + err.volumeName, err.podName) +} + +func newFsResizeRequiredError( + volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) error { + return fsResizeRequiredError{ + volumeName: volumeName, + podName: podName, + } +} + +// IsFSResizeRequiredError returns true if the specified error is a +// fsResizeRequiredError. +func IsFSResizeRequiredError(err error) bool { + _, ok := err.(fsResizeRequiredError) + return ok +} + // getMountedVolume constructs and returns a MountedVolume object from the given // mountedPod and attachedVolume objects. func getMountedVolume( diff --git a/pkg/kubelet/volumemanager/populator/BUILD b/pkg/kubelet/volumemanager/populator/BUILD index c44312cb7f0..fe4d2da5a45 100644 --- a/pkg/kubelet/volumemanager/populator/BUILD +++ b/pkg/kubelet/volumemanager/populator/BUILD @@ -25,6 +25,7 @@ go_library( "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", @@ -49,6 +50,7 @@ go_test( srcs = ["desired_state_of_world_populator_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/features:go_default_library", "//pkg/kubelet/configmap:go_default_library", "//pkg/kubelet/container/testing:go_default_library", "//pkg/kubelet/pod:go_default_library", @@ -61,6 +63,7 @@ go_test( "//pkg/volume/util:go_default_library", "//pkg/volume/util/types:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", diff --git a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go index cc642511a72..e65fdc1b2f8 100644 --- a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go +++ b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go @@ -30,6 +30,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" utilfeature "k8s.io/apiserver/pkg/util/feature" clientset "k8s.io/client-go/kubernetes" @@ -182,12 +183,26 @@ func (dswp *desiredStateOfWorldPopulator) isPodTerminated(pod *v1.Pod) bool { // Iterate through all pods and add to desired state of world if they don't // exist but should func (dswp *desiredStateOfWorldPopulator) findAndAddNewPods() { + // Map unique pod name to outer volume name to MountedVolume. + mountedVolumesForPod := make(map[volumetypes.UniquePodName]map[string]cache.MountedVolume) + if utilfeature.DefaultFeatureGate.Enabled(features.ExpandInUsePersistentVolumes) { + for _, mountedVolume := range dswp.actualStateOfWorld.GetMountedVolumes() { + mountedVolumes, exist := mountedVolumesForPod[mountedVolume.PodName] + if !exist { + mountedVolumes = make(map[string]cache.MountedVolume) + mountedVolumesForPod[mountedVolume.PodName] = mountedVolumes + } + mountedVolumes[mountedVolume.OuterVolumeSpecName] = mountedVolume + } + } + + processedVolumesForFSResize := sets.NewString() for _, pod := range dswp.podManager.GetPods() { if dswp.isPodTerminated(pod) { // Do not (re)add volumes for terminated pods continue } - dswp.processPodVolumes(pod) + dswp.processPodVolumes(pod, mountedVolumesForPod, processedVolumesForFSResize) } } @@ -259,7 +274,10 @@ func (dswp *desiredStateOfWorldPopulator) findAndRemoveDeletedPods() { // processPodVolumes processes the volumes in the given pod and adds them to the // desired state of the world. -func (dswp *desiredStateOfWorldPopulator) processPodVolumes(pod *v1.Pod) { +func (dswp *desiredStateOfWorldPopulator) processPodVolumes( + pod *v1.Pod, + mountedVolumesForPod map[volumetypes.UniquePodName]map[string]cache.MountedVolume, + processedVolumesForFSResize sets.String) { if pod == nil { return } @@ -274,7 +292,7 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes(pod *v1.Pod) { // Process volume spec for each volume defined in pod for _, podVolume := range pod.Spec.Volumes { - volumeSpec, volumeGidValue, err := + pvc, volumeSpec, volumeGidValue, err := dswp.createVolumeSpec(podVolume, pod.Name, pod.Namespace, mountsMap, devicesMap) if err != nil { glog.Errorf( @@ -304,6 +322,11 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes(pod *v1.Pod) { podVolume.Name, volumeSpec.Name(), uniquePodName) + + if utilfeature.DefaultFeatureGate.Enabled(features.ExpandInUsePersistentVolumes) { + dswp.checkVolumeFSResize(pod, podVolume, pvc, volumeSpec, + uniquePodName, mountedVolumesForPod, processedVolumesForFSResize) + } } // some of the volume additions may have failed, should not mark this pod as fully processed @@ -316,6 +339,106 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes(pod *v1.Pod) { } +// checkVolumeFSResize checks whether a PVC mounted by the pod requires file +// system resize or not. If so, marks this volume as fsResizeRequired in ASW. +// - mountedVolumesForPod stores all mounted volumes in ASW, because online +// volume resize only considers mounted volumes. +// - processedVolumesForFSResize stores all volumes we have checked in current loop, +// because file system resize operation is a global operation for volume, so +// we only need to check it once if more than one pod use it. +func (dswp *desiredStateOfWorldPopulator) checkVolumeFSResize( + pod *v1.Pod, + podVolume v1.Volume, + pvc *v1.PersistentVolumeClaim, + volumeSpec *volume.Spec, + uniquePodName volumetypes.UniquePodName, + mountedVolumesForPod map[volumetypes.UniquePodName]map[string]cache.MountedVolume, + processedVolumesForFSResize sets.String) { + if podVolume.PersistentVolumeClaim == nil { + // Only PVC supports resize operation. + return + } + uniqueVolumeName, exist := getUniqueVolumeName(uniquePodName, podVolume.Name, mountedVolumesForPod) + if !exist { + // Volume not exist in ASW, we assume it hasn't been mounted yet. If it needs resize, + // it will be handled as offline resize(if it indeed hasn't been mounted yet), + // or online resize in subsequent loop(after we confirm it has been mounted). + return + } + fsVolume, err := util.CheckVolumeModeFilesystem(volumeSpec) + if err != nil { + glog.Errorf("Check volume mode failed for volume %s(OuterVolumeSpecName %s): %v", + uniqueVolumeName, podVolume.Name, err) + return + } + if !fsVolume { + glog.V(5).Infof("Block mode volume needn't to check file system resize request") + return + } + if processedVolumesForFSResize.Has(string(uniqueVolumeName)) { + // File system resize operation is a global operation for volume, + // so we only need to check it once if more than one pod use it. + return + } + if mountedReadOnlyByPod(podVolume, pod) { + // This volume is used as read only by this pod, we don't perform resize for read only volumes. + glog.V(5).Infof("Skip file system resize check for volume %s in pod %s/%s "+ + "as the volume is mounted as readonly", podVolume.Name, pod.Namespace, pod.Name) + return + } + if volumeRequiresFSResize(pvc, volumeSpec.PersistentVolume) { + dswp.actualStateOfWorld.MarkFSResizeRequired(uniqueVolumeName, uniquePodName) + } + processedVolumesForFSResize.Insert(string(uniqueVolumeName)) +} + +func mountedReadOnlyByPod(podVolume v1.Volume, pod *v1.Pod) bool { + if podVolume.PersistentVolumeClaim.ReadOnly { + return true + } + for _, container := range pod.Spec.InitContainers { + if !mountedReadOnlyByContainer(podVolume.Name, &container) { + return false + } + } + for _, container := range pod.Spec.Containers { + if !mountedReadOnlyByContainer(podVolume.Name, &container) { + return false + } + } + return true +} + +func mountedReadOnlyByContainer(volumeName string, container *v1.Container) bool { + for _, volumeMount := range container.VolumeMounts { + if volumeMount.Name == volumeName && !volumeMount.ReadOnly { + return false + } + } + return true +} + +func getUniqueVolumeName( + podName volumetypes.UniquePodName, + outerVolumeSpecName string, + mountedVolumesForPod map[volumetypes.UniquePodName]map[string]cache.MountedVolume) (v1.UniqueVolumeName, bool) { + mountedVolumes, exist := mountedVolumesForPod[podName] + if !exist { + return "", false + } + mountedVolume, exist := mountedVolumes[outerVolumeSpecName] + if !exist { + return "", false + } + return mountedVolume.VolumeName, true +} + +func volumeRequiresFSResize(pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) bool { + capacity := pvc.Status.Capacity[v1.ResourceStorage] + requested := pv.Spec.Capacity[v1.ResourceStorage] + return requested.Cmp(capacity) > 0 +} + // podPreviouslyProcessed returns true if the volumes for this pod have already // been processed by the populator func (dswp *desiredStateOfWorldPopulator) podPreviouslyProcessed( @@ -350,7 +473,7 @@ func (dswp *desiredStateOfWorldPopulator) deleteProcessedPod( // specified volume. It dereference any PVC to get PV objects, if needed. // Returns an error if unable to obtain the volume at this time. func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( - podVolume v1.Volume, podName string, podNamespace string, mountsMap map[string]bool, devicesMap map[string]bool) (*volume.Spec, string, error) { + podVolume v1.Volume, podName string, podNamespace string, mountsMap map[string]bool, devicesMap map[string]bool) (*v1.PersistentVolumeClaim, *volume.Spec, string, error) { if pvcSource := podVolume.VolumeSource.PersistentVolumeClaim; pvcSource != nil { glog.V(5).Infof( @@ -359,15 +482,16 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( pvcSource.ClaimName) // If podVolume is a PVC, fetch the real PV behind the claim - pvName, pvcUID, err := dswp.getPVCExtractPV( + pvc, err := dswp.getPVCExtractPV( podNamespace, pvcSource.ClaimName) if err != nil { - return nil, "", fmt.Errorf( + return nil, nil, "", fmt.Errorf( "error processing PVC %q/%q: %v", podNamespace, pvcSource.ClaimName, err) } + pvName, pvcUID := pvc.Spec.VolumeName, pvc.UID glog.V(5).Infof( "Found bound PV for PVC (ClaimName %q/%q pvcUID %v): pvName=%q", @@ -380,7 +504,7 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( volumeSpec, volumeGidValue, err := dswp.getPVSpec(pvName, pvcSource.ReadOnly, pvcUID) if err != nil { - return nil, "", fmt.Errorf( + return nil, nil, "", fmt.Errorf( "error processing PVC %q/%q: %v", podNamespace, pvcSource.ClaimName, @@ -399,11 +523,11 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { volumeMode, err := util.GetVolumeMode(volumeSpec) if err != nil { - return nil, "", err + return nil, nil, "", err } // Error if a container has volumeMounts but the volumeMode of PVC isn't Filesystem if mountsMap[podVolume.Name] && volumeMode != v1.PersistentVolumeFilesystem { - return nil, "", fmt.Errorf( + return nil, nil, "", fmt.Errorf( "Volume %q has volumeMode %q, but is specified in volumeMounts for pod %q/%q", podVolume.Name, volumeMode, @@ -412,7 +536,7 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( } // Error if a container has volumeDevices but the volumeMode of PVC isn't Block if devicesMap[podVolume.Name] && volumeMode != v1.PersistentVolumeBlock { - return nil, "", fmt.Errorf( + return nil, nil, "", fmt.Errorf( "Volume %q has volumeMode %q, but is specified in volumeDevices for pod %q/%q", podVolume.Name, volumeMode, @@ -420,13 +544,13 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( podName) } } - return volumeSpec, volumeGidValue, nil + return pvc, volumeSpec, volumeGidValue, nil } // Do not return the original volume object, since the source could mutate it clonedPodVolume := podVolume.DeepCopy() - return volume.NewSpecFromVolume(clonedPodVolume), "", nil + return nil, volume.NewSpecFromVolume(clonedPodVolume), "", nil } // getPVCExtractPV fetches the PVC object with the given namespace and name from @@ -434,11 +558,11 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( // it is pointing to and returns it. // An error is returned if the PVC object's phase is not "Bound". func (dswp *desiredStateOfWorldPopulator) getPVCExtractPV( - namespace string, claimName string) (string, types.UID, error) { + namespace string, claimName string) (*v1.PersistentVolumeClaim, error) { pvc, err := dswp.kubeClient.CoreV1().PersistentVolumeClaims(namespace).Get(claimName, metav1.GetOptions{}) if err != nil || pvc == nil { - return "", "", fmt.Errorf( + return nil, fmt.Errorf( "failed to fetch PVC %s/%s from API server. err=%v", namespace, claimName, @@ -455,7 +579,7 @@ func (dswp *desiredStateOfWorldPopulator) getPVCExtractPV( // It should happen only in very rare case when scheduler schedules // a pod and user deletes a PVC that's used by it at the same time. if pvc.ObjectMeta.DeletionTimestamp != nil { - return "", "", fmt.Errorf( + return nil, fmt.Errorf( "can't start pod because PVC %s/%s is being deleted", namespace, claimName) @@ -464,7 +588,7 @@ func (dswp *desiredStateOfWorldPopulator) getPVCExtractPV( if pvc.Status.Phase != v1.ClaimBound || pvc.Spec.VolumeName == "" { - return "", "", fmt.Errorf( + return nil, fmt.Errorf( "PVC %s/%s has non-bound phase (%q) or empty pvc.Spec.VolumeName (%q)", namespace, claimName, @@ -472,7 +596,7 @@ func (dswp *desiredStateOfWorldPopulator) getPVCExtractPV( pvc.Spec.VolumeName) } - return pvc.Spec.VolumeName, pvc.UID, nil + return pvc, nil } // getPVSpec fetches the PV object with the given name from the API server diff --git a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go index 1ecf9674dd8..969ac66911f 100644 --- a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go +++ b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go @@ -20,12 +20,16 @@ import ( "testing" "time" + "fmt" + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/configmap" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" kubepod "k8s.io/kubernetes/pkg/kubelet/pod" @@ -294,7 +298,7 @@ func TestCreateVolumeSpec_Valid_File_VolumeMounts(t *testing.T) { fakePodManager.AddPod(pod) mountsMap, devicesMap := dswp.makeVolumeMap(pod.Spec.Containers) - volumeSpec, _, err := + _, volumeSpec, _, err := dswp.createVolumeSpec(pod.Spec.Volumes[0], pod.Name, pod.Namespace, mountsMap, devicesMap) // Assert @@ -343,7 +347,7 @@ func TestCreateVolumeSpec_Valid_Block_VolumeDevices(t *testing.T) { fakePodManager.AddPod(pod) mountsMap, devicesMap := dswp.makeVolumeMap(pod.Spec.Containers) - volumeSpec, _, err := + _, volumeSpec, _, err := dswp.createVolumeSpec(pod.Spec.Volumes[0], pod.Name, pod.Namespace, mountsMap, devicesMap) // Assert @@ -395,7 +399,7 @@ func TestCreateVolumeSpec_Invalid_File_VolumeDevices(t *testing.T) { fakePodManager.AddPod(pod) mountsMap, devicesMap := dswp.makeVolumeMap(pod.Spec.Containers) - volumeSpec, _, err := + _, volumeSpec, _, err := dswp.createVolumeSpec(pod.Spec.Volumes[0], pod.Name, pod.Namespace, mountsMap, devicesMap) // Assert @@ -447,7 +451,7 @@ func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) { fakePodManager.AddPod(pod) mountsMap, devicesMap := dswp.makeVolumeMap(pod.Spec.Containers) - volumeSpec, _, err := + _, volumeSpec, _, err := dswp.createVolumeSpec(pod.Spec.Volumes[0], pod.Name, pod.Namespace, mountsMap, devicesMap) // Assert @@ -459,6 +463,155 @@ func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) { utilfeature.DefaultFeatureGate.Set("BlockVolume=false") } +func TestCheckVolumeFSResize(t *testing.T) { + pv := &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dswp-test-volume-name", + }, + Spec: v1.PersistentVolumeSpec{ + PersistentVolumeSource: v1.PersistentVolumeSource{RBD: &v1.RBDPersistentVolumeSource{}}, + Capacity: volumeCapacity(1), + ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"}, + }, + } + pvc := &v1.PersistentVolumeClaim{ + Spec: v1.PersistentVolumeClaimSpec{ + VolumeName: "dswp-test-volume-name", + Resources: v1.ResourceRequirements{ + Requests: volumeCapacity(1), + }, + }, + Status: v1.PersistentVolumeClaimStatus{ + Phase: v1.ClaimBound, + Capacity: volumeCapacity(1), + }, + } + dswp, fakePodManager, fakeDSW := createDswpWithVolume(t, pv, pvc) + fakeASW := dswp.actualStateOfWorld + + // create pod + containers := []v1.Container{ + { + VolumeMounts: []v1.VolumeMount{ + { + Name: "dswp-test-volume-name", + MountPath: "/mnt", + }, + }, + }, + } + pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "file-bound", containers) + uniquePodName := types.UniquePodName(pod.UID) + uniqueVolumeName := v1.UniqueVolumeName("fake-plugin/" + pod.Spec.Volumes[0].Name) + + fakePodManager.AddPod(pod) + // Fill the dsw to contains volumes and pods. + dswp.findAndAddNewPods() + reconcileASW(fakeASW, fakeDSW, t) + + // No resize request for volume, volumes in ASW shouldn't be marked as fsResizeRequired. + setExpandOnlinePersistentVolumesFeatureGate("true", t) + resizeRequiredVolumes := reprocess(dswp, uniquePodName, fakeDSW, fakeASW) + if len(resizeRequiredVolumes) > 0 { + t.Fatalf("No resize request for any volumes, but found resize required volumes in ASW: %v", resizeRequiredVolumes) + } + + // Add a resize request to volume. + pv.Spec.Capacity = volumeCapacity(2) + pvc.Spec.Resources.Requests = volumeCapacity(2) + + // Disable the feature gate, so volume shouldn't be marked as fsResizeRequired. + setExpandOnlinePersistentVolumesFeatureGate("false", t) + resizeRequiredVolumes = reprocess(dswp, uniquePodName, fakeDSW, fakeASW) + if len(resizeRequiredVolumes) > 0 { + t.Fatalf("Feature gate disabled, but found resize required volumes in ASW: %v", resizeRequiredVolumes) + } + + // Make volume used as ReadOnly, so volume shouldn't be marked as fsResizeRequired. + setExpandOnlinePersistentVolumesFeatureGate("true", t) + pod.Spec.Containers[0].VolumeMounts[0].ReadOnly = true + resizeRequiredVolumes = reprocess(dswp, uniquePodName, fakeDSW, fakeASW) + if len(resizeRequiredVolumes) > 0 { + t.Fatalf("volume mounted as ReadOnly, but found resize required volumes in ASW: %v", resizeRequiredVolumes) + } + + // Clear ASW, so volume shouldn't be marked as fsResizeRequired because they are not mounted. + pod.Spec.Containers[0].VolumeMounts[0].ReadOnly = false + clearASW(fakeASW, fakeDSW, t) + resizeRequiredVolumes = reprocess(dswp, uniquePodName, fakeDSW, fakeASW) + if len(resizeRequiredVolumes) > 0 { + t.Fatalf("volume hasn't been mounted, but found resize required volumes in ASW: %v", resizeRequiredVolumes) + } + + // volume in ASW should be marked as fsResizeRequired. + reconcileASW(fakeASW, fakeDSW, t) + resizeRequiredVolumes = reprocess(dswp, uniquePodName, fakeDSW, fakeASW) + if len(resizeRequiredVolumes) == 0 { + t.Fatalf("Request resize for volume, but volume in ASW hasn't been marked as fsResizeRequired") + } + if len(resizeRequiredVolumes) != 1 { + t.Fatalf("Some unexpected volumes are marked as fsResizeRequired: %v", resizeRequiredVolumes) + } + if resizeRequiredVolumes[0] != uniqueVolumeName { + t.Fatalf("Mark wrong volume as fsResizeRequired: %s", resizeRequiredVolumes[0]) + } +} + +func volumeCapacity(size int) v1.ResourceList { + return v1.ResourceList{v1.ResourceStorage: resource.MustParse(fmt.Sprintf("%dGi", size))} +} + +func setExpandOnlinePersistentVolumesFeatureGate(value string, t *testing.T) { + err := utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=%s", features.ExpandInUsePersistentVolumes, value)) + if err != nil { + t.Fatalf("Set ExpandInUsePersistentVolumes feature gate to %s failed: %v", value, err) + } +} + +func reconcileASW(asw cache.ActualStateOfWorld, dsw cache.DesiredStateOfWorld, t *testing.T) { + for _, volumeToMount := range dsw.GetVolumesToMount() { + err := asw.MarkVolumeAsAttached(volumeToMount.VolumeName, volumeToMount.VolumeSpec, "", "") + if err != nil { + t.Fatalf("Unexpected error when MarkVolumeAsAttached: %v", err) + } + err = asw.MarkVolumeAsMounted(volumeToMount.PodName, volumeToMount.Pod.UID, + volumeToMount.VolumeName, nil, nil, volumeToMount.OuterVolumeSpecName, volumeToMount.VolumeGidValue, volumeToMount.VolumeSpec) + if err != nil { + t.Fatalf("Unexpected error when MarkVolumeAsMounted: %v", err) + } + } +} + +func clearASW(asw cache.ActualStateOfWorld, dsw cache.DesiredStateOfWorld, t *testing.T) { + for _, volumeToMount := range dsw.GetVolumesToMount() { + err := asw.MarkVolumeAsUnmounted(volumeToMount.PodName, volumeToMount.VolumeName) + if err != nil { + t.Fatalf("Unexpected error when MarkVolumeAsUnmounted: %v", err) + } + } + for _, volumeToMount := range dsw.GetVolumesToMount() { + asw.MarkVolumeAsDetached(volumeToMount.VolumeName, "") + } +} + +func reprocess(dswp *desiredStateOfWorldPopulator, uniquePodName types.UniquePodName, + dsw cache.DesiredStateOfWorld, asw cache.ActualStateOfWorld) []v1.UniqueVolumeName { + dswp.ReprocessPod(uniquePodName) + dswp.findAndAddNewPods() + return getResizeRequiredVolumes(dsw, asw) +} + +func getResizeRequiredVolumes(dsw cache.DesiredStateOfWorld, asw cache.ActualStateOfWorld) []v1.UniqueVolumeName { + resizeRequiredVolumes := []v1.UniqueVolumeName{} + for _, volumeToMount := range dsw.GetVolumesToMount() { + _, _, err := asw.PodExistsInVolume(volumeToMount.PodName, volumeToMount.VolumeName) + if cache.IsFSResizeRequiredError(err) { + resizeRequiredVolumes = append(resizeRequiredVolumes, volumeToMount.VolumeName) + } + } + return resizeRequiredVolumes +} + func verifyVolumeExistsInVolumesToMount(t *testing.T, expectedVolumeName v1.UniqueVolumeName, expectReportedInUse bool, dsw cache.DesiredStateOfWorld) { volumesToMount := dsw.GetVolumesToMount() for _, volume := range volumesToMount { diff --git a/pkg/kubelet/volumemanager/reconciler/BUILD b/pkg/kubelet/volumemanager/reconciler/BUILD index b2a41d00065..5877ceced44 100644 --- a/pkg/kubelet/volumemanager/reconciler/BUILD +++ b/pkg/kubelet/volumemanager/reconciler/BUILD @@ -38,6 +38,7 @@ go_test( srcs = ["reconciler_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/features:go_default_library", "//pkg/kubelet/volumemanager/cache:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/volume:go_default_library", diff --git a/pkg/kubelet/volumemanager/reconciler/reconciler.go b/pkg/kubelet/volumemanager/reconciler/reconciler.go index 5d6619d5b32..2ffb5c99fa7 100644 --- a/pkg/kubelet/volumemanager/reconciler/reconciler.go +++ b/pkg/kubelet/volumemanager/reconciler/reconciler.go @@ -254,6 +254,22 @@ func (rc *reconciler) reconcile() { glog.V(5).Infof(volumeToMount.GenerateMsgDetailed("operationExecutor.MountVolume started", remountingLogStr)) } } + } else if cache.IsFSResizeRequiredError(err) && + utilfeature.DefaultFeatureGate.Enabled(features.ExpandInUsePersistentVolumes) { + glog.V(4).Infof(volumeToMount.GenerateMsgDetailed("Starting operationExecutor.ExpandVolumeFSWithoutUnmounting", "")) + err := rc.operationExecutor.ExpandVolumeFSWithoutUnmounting( + volumeToMount.VolumeToMount, + rc.actualStateOfWorld) + if err != nil && + !nestedpendingoperations.IsAlreadyExists(err) && + !exponentialbackoff.IsExponentialBackoff(err) { + // Ignore nestedpendingoperations.IsAlreadyExists and exponentialbackoff.IsExponentialBackoff errors, they are expected. + // Log all other errors. + glog.Errorf(volumeToMount.GenerateErrorDetailed("operationExecutor.ExpandVolumeFSWithoutUnmounting failed", err).Error()) + } + if err == nil { + glog.V(4).Infof(volumeToMount.GenerateMsgDetailed("operationExecutor.ExpandVolumeFSWithoutUnmounting started", "")) + } } } diff --git a/pkg/kubelet/volumemanager/reconciler/reconciler_test.go b/pkg/kubelet/volumemanager/reconciler/reconciler_test.go index bc615ddcaa2..38eaba2f03c 100644 --- a/pkg/kubelet/volumemanager/reconciler/reconciler_test.go +++ b/pkg/kubelet/volumemanager/reconciler/reconciler_test.go @@ -32,6 +32,7 @@ import ( "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" "k8s.io/client-go/tools/record" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/volumemanager/cache" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" @@ -508,12 +509,8 @@ func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) { 1 /* expectedAttachCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyWaitForAttachCallCount( 1 /* expectedWaitForAttachCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetGlobalMapPathCallCount( - 1 /* expectedGetGlobalMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetPodDeviceMapPathCallCount( - 1 /* expectedPodDeviceMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifySetUpDeviceCallCount( - 1 /* expectedSetUpDeviceCallCount */, fakePlugin)) + assert.NoError(t, volumetesting.VerifyGetMapDeviceCallCount( + 1 /* expectedGetMapDeviceCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroTearDownDeviceCallCount(fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroDetachCallCount(fakePlugin)) @@ -600,12 +597,8 @@ func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) { assert.NoError(t, volumetesting.VerifyZeroAttachCalls(fakePlugin)) assert.NoError(t, volumetesting.VerifyWaitForAttachCallCount( 1 /* expectedWaitForAttachCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetGlobalMapPathCallCount( - 1 /* expectedGetGlobalMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetPodDeviceMapPathCallCount( - 1 /* expectedPodDeviceMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifySetUpDeviceCallCount( - 1 /* expectedSetUpCallCount */, fakePlugin)) + assert.NoError(t, volumetesting.VerifyGetMapDeviceCallCount( + 1 /* expectedGetMapDeviceCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroTearDownDeviceCallCount(fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroDetachCallCount(fakePlugin)) @@ -691,12 +684,8 @@ func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) { 1 /* expectedAttachCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyWaitForAttachCallCount( 1 /* expectedWaitForAttachCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetGlobalMapPathCallCount( - 1 /* expectedGetGlobalMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetPodDeviceMapPathCallCount( - 1 /* expectedPodDeviceMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifySetUpDeviceCallCount( - 1 /* expectedSetUpCallCount */, fakePlugin)) + assert.NoError(t, volumetesting.VerifyGetMapDeviceCallCount( + 1 /* expectedGetMapDeviceCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroTearDownDeviceCallCount(fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroDetachCallCount(fakePlugin)) @@ -795,12 +784,8 @@ func Test_Run_Positive_VolumeUnmapControllerAttachEnabled(t *testing.T) { assert.NoError(t, volumetesting.VerifyZeroAttachCalls(fakePlugin)) assert.NoError(t, volumetesting.VerifyWaitForAttachCallCount( 1 /* expectedWaitForAttachCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetGlobalMapPathCallCount( - 1 /* expectedGetGlobalMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetPodDeviceMapPathCallCount( - 1 /* expectedPodDeviceMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifySetUpDeviceCallCount( - 1 /* expectedSetUpCallCount */, fakePlugin)) + assert.NoError(t, volumetesting.VerifyGetMapDeviceCallCount( + 1 /* expectedGetMapDeviceCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroTearDownDeviceCallCount(fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroDetachCallCount(fakePlugin)) @@ -965,6 +950,120 @@ func Test_GenerateUnmapDeviceFunc_Plugin_Not_Found(t *testing.T) { utilfeature.DefaultFeatureGate.Set("BlockVolume=false") } +// Populates desiredStateOfWorld cache with one volume/pod. +// Enables controllerAttachDetachEnabled. +// Calls Run() +// Wait for volume mounted. +// Mark volume as fsResizeRequired in ASW. +// Verifies volume's fsResizeRequired flag is cleared later. +func Test_Run_Positive_VolumeFSResizeControllerAttachEnabled(t *testing.T) { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.ExpandInUsePersistentVolumes)) + pv := &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pv", + UID: "pvuid", + }, + Spec: v1.PersistentVolumeSpec{ + ClaimRef: &v1.ObjectReference{Name: "pvc"}, + }, + } + pvc := &v1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pvc", + UID: "pvcuid", + }, + Spec: v1.PersistentVolumeClaimSpec{ + VolumeName: "pv", + }, + } + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + UID: "pod1uid", + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: "volume-name", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc.Name, + }, + }, + }, + }, + }, + } + + volumePluginMgr, fakePlugin := volumetesting.GetTestVolumePluginMgr(t) + dsw := cache.NewDesiredStateOfWorld(volumePluginMgr) + asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr) + kubeClient := createtestClientWithPVPVC(pv, pvc) + fakeRecorder := &record.FakeRecorder{} + fakeHandler := volumetesting.NewBlockVolumePathHandler() + oex := operationexecutor.NewOperationExecutor(operationexecutor.NewOperationGenerator( + kubeClient, + volumePluginMgr, + fakeRecorder, + false, /* checkNodeCapabilitiesBeforeMount */ + fakeHandler)) + + reconciler := NewReconciler( + kubeClient, + true, /* controllerAttachDetachEnabled */ + reconcilerLoopSleepDuration, + reconcilerSyncStatesSleepPeriod, + waitForAttachTimeout, + nodeName, + dsw, + asw, + hasAddedPods, + oex, + &mount.FakeMounter{}, + volumePluginMgr, + kubeletPodsDir) + + volumeSpec := &volume.Spec{PersistentVolume: pv} + podName := util.GetUniquePodName(pod) + volumeName, err := dsw.AddPodToVolume( + podName, pod, volumeSpec, volumeSpec.Name(), "" /* volumeGidValue */) + // Assert + if err != nil { + t.Fatalf("AddPodToVolume failed. Expected: Actual: <%v>", err) + } + dsw.MarkVolumesReportedInUse([]v1.UniqueVolumeName{volumeName}) + + // Start the reconciler to fill ASW. + stopChan, stoppedChan := make(chan struct{}), make(chan struct{}) + go func() { + reconciler.Run(stopChan) + close(stoppedChan) + }() + waitForMount(t, fakePlugin, volumeName, asw) + // Stop the reconciler. + close(stopChan) + <-stoppedChan + + // Mark volume as fsResizeRequired. + asw.MarkFSResizeRequired(volumeName, podName) + _, _, podExistErr := asw.PodExistsInVolume(podName, volumeName) + if !cache.IsFSResizeRequiredError(podExistErr) { + t.Fatalf("Volume should be marked as fsResizeRequired, but receive unexpected error: %v", podExistErr) + } + + // Start the reconciler again, we hope reconciler will perform the + // resize operation and clear the fsResizeRequired flag for volume. + go reconciler.Run(wait.NeverStop) + + waitErr := retryWithExponentialBackOff(500*time.Millisecond, func() (done bool, err error) { + mounted, _, err := asw.PodExistsInVolume(podName, volumeName) + return mounted && err == nil, nil + }) + if waitErr != nil { + t.Fatal("Volume resize should succeeded") + } +} + func waitForMount( t *testing.T, fakePlugin *volumetesting.FakeVolumePlugin, @@ -1044,3 +1143,30 @@ func createTestClient() *fake.Clientset { func runReconciler(reconciler Reconciler) { go reconciler.Run(wait.NeverStop) } + +func createtestClientWithPVPVC(pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim) *fake.Clientset { + fakeClient := &fake.Clientset{} + fakeClient.AddReactor("get", "nodes", + func(action core.Action) (bool, runtime.Object, error) { + return true, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: string(nodeName)}, + Status: v1.NodeStatus{ + VolumesAttached: []v1.AttachedVolume{ + { + Name: "fake-plugin/pv", + DevicePath: "fake/path", + }, + }}, + }, nil + }) + fakeClient.AddReactor("get", "persistentvolumeclaims", func(action core.Action) (bool, runtime.Object, error) { + return true, pvc, nil + }) + fakeClient.AddReactor("get", "persistentvolumes", func(action core.Action) (bool, runtime.Object, error) { + return true, pv, nil + }) + fakeClient.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) { + return true, nil, fmt.Errorf("no reaction implemented for %s", action) + }) + return fakeClient +} diff --git a/pkg/kubemark/BUILD b/pkg/kubemark/BUILD index b22cdbc47ca..a11620af86f 100644 --- a/pkg/kubemark/BUILD +++ b/pkg/kubemark/BUILD @@ -46,7 +46,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/informers/core/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", diff --git a/pkg/kubemark/hollow_kubelet.go b/pkg/kubemark/hollow_kubelet.go index 10cde110577..8e79abed32c 100644 --- a/pkg/kubemark/hollow_kubelet.go +++ b/pkg/kubemark/hollow_kubelet.go @@ -20,7 +20,6 @@ import ( "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" kubeletapp "k8s.io/kubernetes/cmd/kubelet/app" "k8s.io/kubernetes/cmd/kubelet/app/options" @@ -90,7 +89,7 @@ func NewHollowKubelet( // Starts this HollowKubelet and blocks. func (hk *HollowKubelet) Run() { - if err := kubeletapp.RunKubelet(hk.KubeletFlags, hk.KubeletConfiguration, hk.KubeletDeps, false, wait.NeverStop); err != nil { + if err := kubeletapp.RunKubelet(hk.KubeletFlags, hk.KubeletConfiguration, hk.KubeletDeps, false); err != nil { glog.Fatalf("Failed to run HollowKubelet: %v. Exiting.", err) } select {} diff --git a/pkg/master/client_ca_hook_test.go b/pkg/master/client_ca_hook_test.go index 64aa61712c1..011078bddb9 100644 --- a/pkg/master/client_ca_hook_test.go +++ b/pkg/master/client_ca_hook_test.go @@ -189,18 +189,18 @@ func TestWriteClientCAs(t *testing.T) { } for _, test := range tests { - client := fake.NewSimpleClientset(test.preexistingObjs...) - test.hook.tryToWriteClientCAs(client.Core()) + t.Run(test.name, func(t *testing.T) { + client := fake.NewSimpleClientset(test.preexistingObjs...) + test.hook.tryToWriteClientCAs(client.Core()) - actualConfigMaps, updated := getFinalConfiMaps(client) - if !reflect.DeepEqual(test.expectedConfigMaps, actualConfigMaps) { - t.Errorf("%s: %v", test.name, diff.ObjectReflectDiff(test.expectedConfigMaps, actualConfigMaps)) - continue - } - if test.expectUpdate != updated { - t.Errorf("%s: expected %v, got %v", test.name, test.expectUpdate, updated) - continue - } + actualConfigMaps, updated := getFinalConfiMaps(client) + if !reflect.DeepEqual(test.expectedConfigMaps, actualConfigMaps) { + t.Fatalf("%s: %v", test.name, diff.ObjectReflectDiff(test.expectedConfigMaps, actualConfigMaps)) + } + if test.expectUpdate != updated { + t.Fatalf("%s: expected %v, got %v", test.name, test.expectUpdate, updated) + } + }) } } diff --git a/pkg/master/controller/crdregistration/crdregistration_controller_test.go b/pkg/master/controller/crdregistration/crdregistration_controller_test.go index 0a06c147e9c..ec553dec47c 100644 --- a/pkg/master/controller/crdregistration/crdregistration_controller_test.go +++ b/pkg/master/controller/crdregistration/crdregistration_controller_test.go @@ -92,25 +92,27 @@ func TestHandleVersionUpdate(t *testing.T) { } for _, test := range tests { - registration := &fakeAPIServiceRegistration{} - crdCache := cache.NewIndexer(cache.DeletionHandlingMetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) - crdLister := crdlisters.NewCustomResourceDefinitionLister(crdCache) - c := crdRegistrationController{ - crdLister: crdLister, - apiServiceRegistration: registration, - } - for i := range test.startingCRDs { - crdCache.Add(test.startingCRDs[i]) - } + t.Run(test.name, func(t *testing.T) { + registration := &fakeAPIServiceRegistration{} + crdCache := cache.NewIndexer(cache.DeletionHandlingMetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) + crdLister := crdlisters.NewCustomResourceDefinitionLister(crdCache) + c := crdRegistrationController{ + crdLister: crdLister, + apiServiceRegistration: registration, + } + for i := range test.startingCRDs { + crdCache.Add(test.startingCRDs[i]) + } - c.handleVersionUpdate(test.version) + c.handleVersionUpdate(test.version) - if !reflect.DeepEqual(test.expectedAdded, registration.added) { - t.Errorf("%s expected %v, got %v", test.name, test.expectedAdded, registration.added) - } - if !reflect.DeepEqual(test.expectedRemoved, registration.removed) { - t.Errorf("%s expected %v, got %v", test.name, test.expectedRemoved, registration.removed) - } + if !reflect.DeepEqual(test.expectedAdded, registration.added) { + t.Errorf("%s expected %v, got %v", test.name, test.expectedAdded, registration.added) + } + if !reflect.DeepEqual(test.expectedRemoved, registration.removed) { + t.Errorf("%s expected %v, got %v", test.name, test.expectedRemoved, registration.removed) + } + }) } } diff --git a/pkg/master/reconcilers/lease_test.go b/pkg/master/reconcilers/lease_test.go index e16612e255e..97000d39fba 100644 --- a/pkg/master/reconcilers/lease_test.go +++ b/pkg/master/reconcilers/lease_test.go @@ -509,29 +509,31 @@ func TestLeaseEndpointReconciler(t *testing.T) { }, } for _, test := range nonReconcileTests { - fakeLeases := newFakeLeases() - fakeLeases.SetKeys(test.endpointKeys) - registry := ®istrytest.EndpointRegistry{ - Endpoints: test.endpoints, - } - r := NewLeaseEndpointReconciler(registry, fakeLeases) - err := r.ReconcileEndpoints(test.serviceName, net.ParseIP(test.ip), test.endpointPorts, false) - if err != nil { - t.Errorf("case %q: unexpected error: %v", test.testName, err) - } - if test.expectUpdate != nil { - if len(registry.Updates) != 1 { - t.Errorf("case %q: unexpected updates: %v", test.testName, registry.Updates) - } else if e, a := test.expectUpdate, ®istry.Updates[0]; !reflect.DeepEqual(e, a) { - t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) + t.Run(test.testName, func(t *testing.T) { + fakeLeases := newFakeLeases() + fakeLeases.SetKeys(test.endpointKeys) + registry := ®istrytest.EndpointRegistry{ + Endpoints: test.endpoints, } - } - if test.expectUpdate == nil && len(registry.Updates) > 0 { - t.Errorf("case %q: no update expected, yet saw: %v", test.testName, registry.Updates) - } - if updatedKeys := fakeLeases.GetUpdatedKeys(); len(updatedKeys) != 1 || updatedKeys[0] != test.ip { - t.Errorf("case %q: expected the master's IP to be refreshed, but the following IPs were refreshed instead: %v", test.testName, updatedKeys) - } + r := NewLeaseEndpointReconciler(registry, fakeLeases) + err := r.ReconcileEndpoints(test.serviceName, net.ParseIP(test.ip), test.endpointPorts, false) + if err != nil { + t.Errorf("case %q: unexpected error: %v", test.testName, err) + } + if test.expectUpdate != nil { + if len(registry.Updates) != 1 { + t.Errorf("case %q: unexpected updates: %v", test.testName, registry.Updates) + } else if e, a := test.expectUpdate, ®istry.Updates[0]; !reflect.DeepEqual(e, a) { + t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) + } + } + if test.expectUpdate == nil && len(registry.Updates) > 0 { + t.Errorf("case %q: no update expected, yet saw: %v", test.testName, registry.Updates) + } + if updatedKeys := fakeLeases.GetUpdatedKeys(); len(updatedKeys) != 1 || updatedKeys[0] != test.ip { + t.Errorf("case %q: expected the master's IP to be refreshed, but the following IPs were refreshed instead: %v", test.testName, updatedKeys) + } + }) } } @@ -604,30 +606,32 @@ func TestLeaseStopReconciling(t *testing.T) { }, } for _, test := range stopTests { - fakeLeases := newFakeLeases() - fakeLeases.SetKeys(test.endpointKeys) - registry := ®istrytest.EndpointRegistry{ - Endpoints: test.endpoints, - } - r := NewLeaseEndpointReconciler(registry, fakeLeases) - err := r.StopReconciling(test.serviceName, net.ParseIP(test.ip), test.endpointPorts) - if err != nil { - t.Errorf("case %q: unexpected error: %v", test.testName, err) - } - if test.expectUpdate != nil { - if len(registry.Updates) != 1 { - t.Errorf("case %q: unexpected updates: %v", test.testName, registry.Updates) - } else if e, a := test.expectUpdate, ®istry.Updates[0]; !reflect.DeepEqual(e, a) { - t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) + t.Run(test.testName, func(t *testing.T) { + fakeLeases := newFakeLeases() + fakeLeases.SetKeys(test.endpointKeys) + registry := ®istrytest.EndpointRegistry{ + Endpoints: test.endpoints, } - } - if test.expectUpdate == nil && len(registry.Updates) > 0 { - t.Errorf("case %q: no update expected, yet saw: %v", test.testName, registry.Updates) - } - for _, key := range fakeLeases.GetUpdatedKeys() { - if key == test.ip { - t.Errorf("case %q: Found ip %s in leases but shouldn't be there", test.testName, key) + r := NewLeaseEndpointReconciler(registry, fakeLeases) + err := r.StopReconciling(test.serviceName, net.ParseIP(test.ip), test.endpointPorts) + if err != nil { + t.Errorf("case %q: unexpected error: %v", test.testName, err) } - } + if test.expectUpdate != nil { + if len(registry.Updates) != 1 { + t.Errorf("case %q: unexpected updates: %v", test.testName, registry.Updates) + } else if e, a := test.expectUpdate, ®istry.Updates[0]; !reflect.DeepEqual(e, a) { + t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) + } + } + if test.expectUpdate == nil && len(registry.Updates) > 0 { + t.Errorf("case %q: no update expected, yet saw: %v", test.testName, registry.Updates) + } + for _, key := range fakeLeases.GetUpdatedKeys() { + if key == test.ip { + t.Errorf("case %q: Found ip %s in leases but shouldn't be there", test.testName, key) + } + } + }) } } diff --git a/pkg/master/tunneler/ssh_test.go b/pkg/master/tunneler/ssh_test.go index 1ff23dbd592..f4f58b0f6e8 100644 --- a/pkg/master/tunneler/ssh_test.go +++ b/pkg/master/tunneler/ssh_test.go @@ -33,39 +33,66 @@ import ( // TestSecondsSinceSync verifies that proper results are returned // when checking the time between syncs func TestSecondsSinceSync(t *testing.T) { - tunneler := &SSHTunneler{} - assert := assert.New(t) + tests := []struct { + name string + lastSync int64 + clock *clock.FakeClock + want int64 + }{ + { + name: "Nano Second. No difference", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 1, 2, time.UTC)), + want: int64(0), + }, + { + name: "Second", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 2, 1, time.UTC)), + want: int64(1), + }, + { + name: "Minute", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 2, 1, 1, time.UTC)), + want: int64(60), + }, + { + name: "Hour", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 1, 2, 1, 1, 1, time.UTC)), + want: int64(3600), + }, + { + name: "Day", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 2, 1, 1, 1, 1, time.UTC)), + want: int64(86400), + }, + { + name: "Month", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.February, 1, 1, 1, 1, 1, time.UTC)), + want: int64(2678400), + }, + { + name: "Future Month. Should be -Month", + lastSync: time.Date(2015, time.February, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 1, 2, time.UTC)), + want: int64(-2678400), + }, + } - tunneler.lastSync = time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tunneler := &SSHTunneler{} + assert := assert.New(t) + tunneler.lastSync = tt.lastSync + tunneler.clock = tt.clock + assert.Equal(int64(tt.want), tunneler.SecondsSinceSync()) + }) + } - // Nano Second. No difference. - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 1, 2, time.UTC)) - assert.Equal(int64(0), tunneler.SecondsSinceSync()) - - // Second - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 2, 1, time.UTC)) - assert.Equal(int64(1), tunneler.SecondsSinceSync()) - - // Minute - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 2, 1, 1, time.UTC)) - assert.Equal(int64(60), tunneler.SecondsSinceSync()) - - // Hour - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 1, 2, 1, 1, 1, time.UTC)) - assert.Equal(int64(3600), tunneler.SecondsSinceSync()) - - // Day - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 2, 1, 1, 1, 1, time.UTC)) - assert.Equal(int64(86400), tunneler.SecondsSinceSync()) - - // Month - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.February, 1, 1, 1, 1, 1, time.UTC)) - assert.Equal(int64(2678400), tunneler.SecondsSinceSync()) - - // Future Month. Should be -Month. - tunneler.lastSync = time.Date(2015, time.February, 1, 1, 1, 1, 1, time.UTC).Unix() - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC)) - assert.Equal(int64(-2678400), tunneler.SecondsSinceSync()) } // generateTempFile creates a temporary file path diff --git a/pkg/printers/customcolumn_flags.go b/pkg/printers/customcolumn_flags.go index b982942ae9b..9ef91f97e73 100644 --- a/pkg/printers/customcolumn_flags.go +++ b/pkg/printers/customcolumn_flags.go @@ -27,6 +27,11 @@ import ( "k8s.io/kubernetes/pkg/kubectl/scheme" ) +var columnsFormats = map[string]bool{ + "custom-columns-file": true, + "custom-columns": true, +} + // CustomColumnsPrintFlags provides default flags necessary for printing // custom resource columns from an inline-template or file. type CustomColumnsPrintFlags struct { @@ -34,6 +39,14 @@ type CustomColumnsPrintFlags struct { TemplateArgument string } +func (f *CustomColumnsPrintFlags) AllowedFormats() []string { + formats := make([]string, 0, len(columnsFormats)) + for format := range columnsFormats { + formats = append(formats, format) + } + return formats +} + // ToPrinter receives an templateFormat and returns a printer capable of // handling custom-column printing. // Returns false if the specified templateFormat does not match a supported format. @@ -45,13 +58,8 @@ func (f *CustomColumnsPrintFlags) ToPrinter(templateFormat string) (ResourcePrin templateValue := "" - supportedFormats := map[string]bool{ - "custom-columns-file": true, - "custom-columns": true, - } - if len(f.TemplateArgument) == 0 { - for format := range supportedFormats { + for format := range columnsFormats { format = format + "=" if strings.HasPrefix(templateFormat, format) { templateValue = templateFormat[len(format):] @@ -63,8 +71,8 @@ func (f *CustomColumnsPrintFlags) ToPrinter(templateFormat string) (ResourcePrin templateValue = f.TemplateArgument } - if _, supportedFormat := supportedFormats[templateFormat]; !supportedFormat { - return nil, genericclioptions.NoCompatiblePrinterError{} + if _, supportedFormat := columnsFormats[templateFormat]; !supportedFormat { + return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()} } if len(templateValue) == 0 { diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index 14b11b39e65..c1b59cf96ef 100644 --- a/pkg/printers/internalversion/describe.go +++ b/pkg/printers/internalversion/describe.go @@ -966,7 +966,17 @@ func printCinderVolumeSource(cinder *api.CinderVolumeSource, w PrefixWriter) { " VolumeID:\t%v\n"+ " FSType:\t%v\n"+ " ReadOnly:\t%v\n", - cinder.VolumeID, cinder.FSType, cinder.ReadOnly) + " SecretRef:\t%v\n"+ + cinder.VolumeID, cinder.FSType, cinder.ReadOnly, cinder.SecretRef) +} + +func printCinderPersistentVolumeSource(cinder *api.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) } func printScaleIOVolumeSource(sio *api.ScaleIOVolumeSource, w PrefixWriter) { @@ -1228,7 +1238,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) ( case pv.Spec.VsphereVolume != nil: printVsphereVolumeSource(pv.Spec.VsphereVolume, w) case pv.Spec.Cinder != nil: - printCinderVolumeSource(pv.Spec.Cinder, w) + printCinderPersistentVolumeSource(pv.Spec.Cinder, w) case pv.Spec.AzureDisk != nil: printAzureDiskVolumeSource(pv.Spec.AzureDisk, w) case pv.Spec.PhotonPersistentDisk != nil: diff --git a/pkg/printers/internalversion/describe_test.go b/pkg/printers/internalversion/describe_test.go index 37472877e19..284ece57972 100644 --- a/pkg/printers/internalversion/describe_test.go +++ b/pkg/printers/internalversion/describe_test.go @@ -1012,7 +1012,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "bar"}, Spec: api.PersistentVolumeSpec{ PersistentVolumeSource: api.PersistentVolumeSource{ - Cinder: &api.CinderVolumeSource{}, + Cinder: &api.CinderPersistentVolumeSource{}, }, }, }, diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index a1be6cbd865..1a804d08fcb 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -608,7 +608,7 @@ func printPod(pod *api.Pod, options printers.PrintOptions) ([]metav1beta1.TableR reason = "Terminating" } - row.Cells = append(row.Cells, pod.Name, fmt.Sprintf("%d/%d", readyContainers, totalContainers), reason, restarts, translateTimestamp(pod.CreationTimestamp)) + row.Cells = append(row.Cells, pod.Name, fmt.Sprintf("%d/%d", readyContainers, totalContainers), reason, int64(restarts), translateTimestamp(pod.CreationTimestamp)) if options.Wide { nodeName := pod.Spec.NodeName @@ -668,7 +668,7 @@ func printPodDisruptionBudget(obj *policy.PodDisruptionBudget, options printers. maxUnavailable = "N/A" } - row.Cells = append(row.Cells, obj.Name, minAvailable, maxUnavailable, obj.Status.PodDisruptionsAllowed, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, minAvailable, maxUnavailable, int64(obj.Status.PodDisruptionsAllowed), translateTimestamp(obj.CreationTimestamp)) return []metav1beta1.TableRow{row}, nil } @@ -694,7 +694,7 @@ func printReplicationController(obj *api.ReplicationController, options printers currentReplicas := obj.Status.Replicas readyReplicas := obj.Status.ReadyReplicas - row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, readyReplicas, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestamp(obj.CreationTimestamp)) if options.Wide { names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images, labels.FormatLabels(obj.Spec.Selector)) @@ -723,7 +723,7 @@ func printReplicaSet(obj *extensions.ReplicaSet, options printers.PrintOptions) currentReplicas := obj.Status.Replicas readyReplicas := obj.Status.ReadyReplicas - row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, readyReplicas, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestamp(obj.CreationTimestamp)) if options.Wide { names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector)) @@ -755,7 +755,7 @@ func printJob(obj *batch.Job, options printers.PrintOptions) ([]metav1beta1.Tabl completions = "" } - row.Cells = append(row.Cells, obj.Name, completions, obj.Status.Succeeded, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, completions, int64(obj.Status.Succeeded), translateTimestamp(obj.CreationTimestamp)) if options.Wide { names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector)) @@ -785,7 +785,7 @@ func printCronJob(obj *batch.CronJob, options printers.PrintOptions) ([]metav1be lastScheduleTime = translateTimestamp(*obj.Status.LastScheduleTime) } - row.Cells = append(row.Cells, obj.Name, obj.Spec.Schedule, printBoolPtr(obj.Spec.Suspend), len(obj.Status.Active), lastScheduleTime, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, obj.Spec.Schedule, printBoolPtr(obj.Spec.Suspend), int64(len(obj.Status.Active)), lastScheduleTime, translateTimestamp(obj.CreationTimestamp)) if options.Wide { names, images := layoutContainerCells(obj.Spec.JobTemplate.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.JobTemplate.Spec.Selector)) @@ -972,7 +972,7 @@ func printStatefulSet(obj *apps.StatefulSet, options printers.PrintOptions) ([]m desiredReplicas := obj.Spec.Replicas currentReplicas := obj.Status.Replicas createTime := translateTimestamp(obj.CreationTimestamp) - row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, createTime) + row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), createTime) if options.Wide { names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images) @@ -1003,7 +1003,7 @@ func printDaemonSet(obj *extensions.DaemonSet, options printers.PrintOptions) ([ numberUpdated := obj.Status.UpdatedNumberScheduled numberAvailable := obj.Status.NumberAvailable - row.Cells = append(row.Cells, obj.Name, desiredScheduled, currentScheduled, numberReady, numberUpdated, numberAvailable, labels.FormatLabels(obj.Spec.Template.Spec.NodeSelector), translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(desiredScheduled), int64(currentScheduled), int64(numberReady), int64(numberUpdated), int64(numberAvailable), labels.FormatLabels(obj.Spec.Template.Spec.NodeSelector), translateTimestamp(obj.CreationTimestamp)) if options.Wide { names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector)) @@ -1067,7 +1067,7 @@ func printSecret(obj *api.Secret, options printers.PrintOptions) ([]metav1beta1. row := metav1beta1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells = append(row.Cells, obj.Name, string(obj.Type), len(obj.Data), translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, string(obj.Type), int64(len(obj.Data)), translateTimestamp(obj.CreationTimestamp)) return []metav1beta1.TableRow{row}, nil } @@ -1087,7 +1087,7 @@ func printServiceAccount(obj *api.ServiceAccount, options printers.PrintOptions) row := metav1beta1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells = append(row.Cells, obj.Name, len(obj.Secrets), translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(len(obj.Secrets)), translateTimestamp(obj.CreationTimestamp)) return []metav1beta1.TableRow{row}, nil } @@ -1299,7 +1299,7 @@ func printEvent(obj *api.Event, options printers.PrintOptions) ([]metav1beta1.Ta LastTimestamp = translateTimestamp(obj.LastTimestamp) } row.Cells = append(row.Cells, LastTimestamp, FirstTimestamp, - obj.Count, obj.Name, obj.InvolvedObject.Kind, + int64(obj.Count), obj.Name, obj.InvolvedObject.Kind, obj.InvolvedObject.FieldPath, obj.Type, obj.Reason, formatEventSource(obj.Source), obj.Message) @@ -1482,7 +1482,7 @@ func printDeployment(obj *extensions.Deployment, options printers.PrintOptions) // this shouldn't happen if LabelSelector passed validation return nil, err } - row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, updatedReplicas, availableReplicas, age) + row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(updatedReplicas), int64(availableReplicas), age) if options.Wide { containers, images := layoutContainerCells(containers) row.Cells = append(row.Cells, containers, images, selector.String()) @@ -1591,7 +1591,7 @@ func printHorizontalPodAutoscaler(obj *autoscaling.HorizontalPodAutoscaler, opti } maxPods := obj.Spec.MaxReplicas currentReplicas := obj.Status.CurrentReplicas - row.Cells = append(row.Cells, obj.Name, reference, metrics, minPods, maxPods, currentReplicas, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, reference, metrics, minPods, int64(maxPods), int64(currentReplicas), translateTimestamp(obj.CreationTimestamp)) return []metav1beta1.TableRow{row}, nil } @@ -1611,7 +1611,7 @@ func printConfigMap(obj *api.ConfigMap, options printers.PrintOptions) ([]metav1 row := metav1beta1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells = append(row.Cells, obj.Name, len(obj.Data), translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(len(obj.Data)), translateTimestamp(obj.CreationTimestamp)) return []metav1beta1.TableRow{row}, nil } diff --git a/pkg/printers/internalversion/printers_test.go b/pkg/printers/internalversion/printers_test.go index a3739cf3ea1..ee612d19cc2 100644 --- a/pkg/printers/internalversion/printers_test.go +++ b/pkg/printers/internalversion/printers_test.go @@ -1098,6 +1098,7 @@ func TestPrintHunmanReadableIngressWithColumnLabels(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buff, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -1227,6 +1228,7 @@ func TestPrintHumanReadableService(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buff, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -1505,6 +1507,7 @@ func TestPrintPodTable(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) buf := &bytes.Buffer{} p := printers.NewHumanReadablePrinter(nil, test.opts).With(AddHandlers).AddTabWriter(false) if err := p.PrintObj(table, buf); err != nil { @@ -1545,7 +1548,7 @@ func TestPrintPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), ""}}}, }, { // Test container error overwrites pod phase @@ -1560,7 +1563,7 @@ func TestPrintPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", int64(6), ""}}}, }, { // Test the same as the above but with Terminated state and the first container overwrites the rest @@ -1575,7 +1578,7 @@ func TestPrintPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test3", "0/2", "ContainerWaitingReason", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test3", "0/2", "ContainerWaitingReason", int64(6), ""}}}, }, { // Test ready is not enough for reporting running @@ -1590,7 +1593,7 @@ func TestPrintPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test4", "1/2", "podPhase", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test4", "1/2", "podPhase", int64(6), ""}}}, }, { // Test ready is not enough for reporting running @@ -1606,7 +1609,7 @@ func TestPrintPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test5", "1/2", "podReason", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test5", "1/2", "podReason", int64(6), ""}}}, }, { // Test pod has 2 containers, one is running and the other is completed. @@ -1622,7 +1625,7 @@ func TestPrintPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test6", "1/2", "Running", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test6", "1/2", "Running", int64(6), ""}}}, }, } @@ -1663,7 +1666,7 @@ func TestPrintPodwide(t *testing.T) { NominatedNodeName: "node1", }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "", "1.1.1.1", "test1", "node1"}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), "", "1.1.1.1", "test1", "node1"}}}, }, { // Test when the NodeName and PodIP are none @@ -1682,7 +1685,7 @@ func TestPrintPodwide(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", 6, "", "", ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", int64(6), "", "", ""}}}, }, } @@ -1732,7 +1735,7 @@ func TestPrintPodList(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "2/2", "podPhase", 6, ""}}, {Cells: []interface{}{"test2", "1/1", "podPhase", 1, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "2/2", "podPhase", int64(6), ""}}, {Cells: []interface{}{"test2", "1/1", "podPhase", int64(1), ""}}}, }, } @@ -1769,7 +1772,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "Running", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "Running", int64(6), ""}}}, }, { // Test pod phase Pending should be printed @@ -1784,7 +1787,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "Pending", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "Pending", int64(6), ""}}}, }, { // Test pod phase Unknown should be printed @@ -1799,7 +1802,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test3", "1/2", "Unknown", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test3", "1/2", "Unknown", int64(6), ""}}}, }, { // Test pod phase Succeeded shouldn't be printed @@ -1814,7 +1817,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test4", "1/2", "Succeeded", 6, ""}, Conditions: podSuccessConditions}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test4", "1/2", "Succeeded", int64(6), ""}, Conditions: podSuccessConditions}}, }, { // Test pod phase Failed shouldn't be printed @@ -1829,7 +1832,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test5", "1/2", "Failed", 6, ""}, Conditions: podFailedConditions}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test5", "1/2", "Failed", int64(6), ""}, Conditions: podFailedConditions}}, }, } @@ -1838,6 +1841,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) rows := table.Rows for i := range rows { rows[i].Object.Object = nil @@ -1871,7 +1875,7 @@ func TestPrintPodWithLabels(t *testing.T) { }, }, []string{"col1", "COL2"}, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "", "asd", "zxc"}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), "", "asd", "zxc"}}}, }, { // Test name, num of containers, restarts, container ready status @@ -1890,7 +1894,7 @@ func TestPrintPodWithLabels(t *testing.T) { }, }, []string{}, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), ""}}}, }, } @@ -1899,6 +1903,7 @@ func TestPrintPodWithLabels(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) rows := table.Rows for i := range rows { rows[i].Object.Object = nil @@ -1982,6 +1987,7 @@ func TestPrintDeployment(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -1990,6 +1996,7 @@ func TestPrintDeployment(t *testing.T) { } buf.Reset() table, err = printers.NewTablePrinter().With(AddHandlers).PrintTable(&test.deployment, printers.PrintOptions{Wide: true}) + verifyTable(t, table) // print deployment with '-o wide' option if err := printers.PrintTable(table, buf, printers.PrintOptions{Wide: true, NoHeaders: true}); err != nil { t.Fatal(err) @@ -2035,6 +2042,7 @@ func TestPrintDaemonSet(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -2089,6 +2097,7 @@ func TestPrintJob(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -2620,6 +2629,7 @@ func TestPrintHPA(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buff, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -2654,7 +2664,7 @@ func TestPrintPodShowLabels(t *testing.T) { }, }, true, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "", "COL2=zxc,col1=asd"}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), "", "COL2=zxc,col1=asd"}}}, }, { // Test name, num of containers, restarts, container ready status @@ -2673,7 +2683,7 @@ func TestPrintPodShowLabels(t *testing.T) { }, }, false, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), ""}}}, }, } @@ -2682,6 +2692,7 @@ func TestPrintPodShowLabels(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) rows := table.Rows for i := range rows { rows[i].Object.Object = nil @@ -2848,6 +2859,7 @@ func TestPrintService(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -2905,6 +2917,7 @@ func TestPrintPodDisruptionBudget(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -2985,6 +2998,7 @@ func TestPrintControllerRevision(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -3045,6 +3059,7 @@ func TestPrintReplicaSet(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -3057,6 +3072,7 @@ func TestPrintReplicaSet(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true, Wide: true}); err != nil { t.Fatal(err) } @@ -3155,6 +3171,7 @@ func TestPrintPersistentVolumeClaim(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -3227,6 +3244,7 @@ func TestPrintCronJob(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -3270,6 +3288,7 @@ func TestPrintStorageClass(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -3279,3 +3298,17 @@ func TestPrintStorageClass(t *testing.T) { buf.Reset() } } + +func verifyTable(t *testing.T, table *metav1beta1.Table) { + var panicErr interface{} + func() { + defer func() { + panicErr = recover() + }() + table.DeepCopyObject() // cells are untyped, better check that types are JSON types and can be deep copied + }() + + if panicErr != nil { + t.Errorf("unexpected panic during deepcopy of table %#v: %v", table, panicErr) + } +} diff --git a/pkg/printers/jsonpath_flags.go b/pkg/printers/jsonpath_flags.go index 49a559d6248..d95f737620f 100644 --- a/pkg/printers/jsonpath_flags.go +++ b/pkg/printers/jsonpath_flags.go @@ -26,6 +26,14 @@ import ( "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) +// templates are logically optional for specifying a format. +// this allows a user to specify a template format value +// as --output=jsonpath= +var jsonFormats = map[string]bool{ + "jsonpath": true, + "jsonpath-file": true, +} + // JSONPathPrintFlags provides default flags necessary for template printing. // Given the following flag values, a printer can be requested that knows // how to handle printing based on these values. @@ -36,6 +44,14 @@ type JSONPathPrintFlags struct { TemplateArgument *string } +func (f *JSONPathPrintFlags) AllowedFormats() []string { + formats := make([]string, 0, len(jsonFormats)) + for format := range jsonFormats { + formats = append(formats, format) + } + return formats +} + // ToPrinter receives an templateFormat and returns a printer capable of // handling --template format printing. // Returns false if the specified templateFormat does not match a template format. @@ -46,16 +62,8 @@ func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter, templateValue := "" - // templates are logically optional for specifying a format. - // this allows a user to specify a template format value - // as --output=jsonpath= - templateFormats := map[string]bool{ - "jsonpath": true, - "jsonpath-file": true, - } - if f.TemplateArgument == nil || len(*f.TemplateArgument) == 0 { - for format := range templateFormats { + for format := range jsonFormats { format = format + "=" if strings.HasPrefix(templateFormat, format) { templateValue = templateFormat[len(format):] @@ -67,8 +75,8 @@ func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter, templateValue = *f.TemplateArgument } - if _, supportedFormat := templateFormats[templateFormat]; !supportedFormat { - return nil, genericclioptions.NoCompatiblePrinterError{Options: f, OutputFormat: &templateFormat} + if _, supportedFormat := jsonFormats[templateFormat]; !supportedFormat { + return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()} } if len(templateValue) == 0 { diff --git a/pkg/printers/kube_template_flags.go b/pkg/printers/kube_template_flags.go index a5b0c71326c..8b53e60cdc5 100644 --- a/pkg/printers/kube_template_flags.go +++ b/pkg/printers/kube_template_flags.go @@ -33,6 +33,10 @@ type KubeTemplatePrintFlags struct { TemplateArgument *string } +func (f *KubeTemplatePrintFlags) AllowedFormats() []string { + return append(f.GoTemplatePrintFlags.AllowedFormats(), f.JSONPathPrintFlags.AllowedFormats()...) +} + func (f *KubeTemplatePrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, error) { if p, err := f.JSONPathPrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { return p, err diff --git a/pkg/printers/template_flags.go b/pkg/printers/template_flags.go index 0e6d825895d..ffd7a24dca6 100644 --- a/pkg/printers/template_flags.go +++ b/pkg/printers/template_flags.go @@ -26,6 +26,16 @@ import ( "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) +// templates are logically optional for specifying a format. +// this allows a user to specify a template format value +// as --output=go-template= +var templateFormats = map[string]bool{ + "template": true, + "go-template": true, + "go-template-file": true, + "templatefile": true, +} + // GoTemplatePrintFlags provides default flags necessary for template printing. // Given the following flag values, a printer can be requested that knows // how to handle printing based on these values. @@ -36,6 +46,14 @@ type GoTemplatePrintFlags struct { TemplateArgument *string } +func (f *GoTemplatePrintFlags) AllowedFormats() []string { + formats := make([]string, 0, len(templateFormats)) + for format := range templateFormats { + formats = append(formats, format) + } + return formats +} + // ToPrinter receives an templateFormat and returns a printer capable of // handling --template format printing. // Returns false if the specified templateFormat does not match a template format. @@ -46,18 +64,8 @@ func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (ResourcePrinter templateValue := "" - // templates are logically optional for specifying a format. - // this allows a user to specify a template format value - // as --output=go-template= - supportedFormats := map[string]bool{ - "template": true, - "go-template": true, - "go-template-file": true, - "templatefile": true, - } - if f.TemplateArgument == nil || len(*f.TemplateArgument) == 0 { - for format := range supportedFormats { + for format := range templateFormats { format = format + "=" if strings.HasPrefix(templateFormat, format) { templateValue = templateFormat[len(format):] @@ -69,8 +77,8 @@ func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (ResourcePrinter templateValue = *f.TemplateArgument } - if _, supportedFormat := supportedFormats[templateFormat]; !supportedFormat { - return nil, genericclioptions.NoCompatiblePrinterError{Options: f, OutputFormat: &templateFormat} + if _, supportedFormat := templateFormats[templateFormat]; !supportedFormat { + return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()} } if len(templateValue) == 0 { diff --git a/pkg/proxy/apis/kubeproxyconfig/v1alpha1/types.go b/pkg/proxy/apis/kubeproxyconfig/v1alpha1/types.go index c9936e701f7..beab095d605 100644 --- a/pkg/proxy/apis/kubeproxyconfig/v1alpha1/types.go +++ b/pkg/proxy/apis/kubeproxyconfig/v1alpha1/types.go @@ -65,7 +65,7 @@ type KubeProxyIPVSConfiguration struct { Scheduler string `json:"scheduler"` // excludeCIDRs is a list of CIDR's which the ipvs proxier should not touch // when cleaning up ipvs services. - ExcludeCIDRs []string + ExcludeCIDRs []string `json:"excludeCIDRs"` } // KubeProxyConntrackConfiguration contains conntrack settings for diff --git a/pkg/proxy/iptables/proxier_test.go b/pkg/proxy/iptables/proxier_test.go index 65be9536ee8..7f315262b92 100644 --- a/pkg/proxy/iptables/proxier_test.go +++ b/pkg/proxy/iptables/proxier_test.go @@ -595,7 +595,7 @@ func TestClusterIPReject(t *testing.T) { } makeServiceMap(fp, - makeTestService(svcPortName.Namespace, svcPortName.Namespace, func(svc *api.Service) { + makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *api.Service) { svc.Spec.ClusterIP = svcIP svc.Spec.Ports = []api.ServicePort{{ Name: svcPortName.Port, diff --git a/pkg/proxy/ipvs/OWNERS b/pkg/proxy/ipvs/OWNERS index 6cc306c646a..bccd989d475 100644 --- a/pkg/proxy/ipvs/OWNERS +++ b/pkg/proxy/ipvs/OWNERS @@ -2,6 +2,7 @@ reviewers: - thockin - brendandburns - m1093782566 +- Lion-Wei approvers: - thockin - brendandburns diff --git a/pkg/proxy/ipvs/README.md b/pkg/proxy/ipvs/README.md index e98c525504d..3860bdaf1fc 100644 --- a/pkg/proxy/ipvs/README.md +++ b/pkg/proxy/ipvs/README.md @@ -30,178 +30,236 @@ and UDP-based services to the real servers, and make services of real servers ap IPVS mode was introduced in Kubernetes v1.8 and goes beta in v1.9. IPTABLES mode was added in v1.1 and become the default operating mode since v1.2. Both IPVS and IPTABLES are based on `netfilter`. Differences between IPVS mode and IPTABLES mode are as follows: -1. IPVS provides better scalability and performance for large clusters. +1. IPVS provides better scalability and performance for large clusters. -2. IPVS supports more sophisticated load balancing algorithms than iptables (least load, least connections, locality, weighted, etc.). +2. IPVS supports more sophisticated load balancing algorithms than iptables (least load, least connections, locality, weighted, etc.). 3. IPVS supports server health checking and connection retries, etc. - + ### When ipvs falls back to iptables -IPVS proxier will employ iptables in doing packet filtering, SNAT and supporting NodePort type service. Specifically, ipvs proxier will fall back on iptables in the following 4 scenarios. +IPVS proxier will employ iptables in doing packet filtering, SNAT or masquerade. +Specifically, ipvs proxier will use ipset to store source or destination address of traffics that need DROP or do masquared, to make sure the number of iptables rules be constant, no metter how many services we have. + + +Here is the table of ipset sets that ipvs proxier used. + +| set name | members | usage | +| :----------------------------- | ---------------------------------------- | ---------------------------------------- | +| KUBE-CLUSTER-IP | All service IP + port | Mark-Masq for cases that `masquerade-all=true` or `clusterCIDR` specified | +| KUBE-LOOP-BACK | All service IP + port + IP | masquerade for solving hairpin purpose | +| KUBE-EXTERNAL-IP | service external IP + port | masquerade for packages to external IPs | +| KUBE-LOAD-BALANCER | load balancer ingress IP + port | masquerade for packages to load balancer type service | +| KUBE-LOAD-BALANCER-LOCAL | LB ingress IP + port with `externalTrafficPolicy=local` | accept packages to load balancer with `externalTrafficPolicy=local` | +| KUBE-LOAD-BALANCER-FW | load balancer ingress IP + port with `loadBalancerSourceRanges` | package filter for load balancer with `loadBalancerSourceRanges` specified | +| KUBE-LOAD-BALANCER-SOURCE-CIDR | load balancer ingress IP + port + source CIDR | package filter for load balancer with `loadBalancerSourceRanges` specified | +| KUBE-NODE-PORT-TCP | nodeport type service TCP port | masquerade for packets to nodePort(TCP) | +| KUBE-NODE-PORT-LOCAL-TCP | nodeport type service TCP port with `externalTrafficPolicy=local` | accept packages to nodeport service with `externalTrafficPolicy=local` | +| KUBE-NODE-PORT-UDP | nodeport type service UDP port | masquerade for packets to nodePort(UDP) | +| KUBE-NODE-PORT-LOCAL-UDP | nodeport type service UDP port with `externalTrafficPolicy=local` | accept packages to nodeport service with `externalTrafficPolicy=local` | + + +IPVS proxier will fall back on iptables in the following scenarios. **1. kube-proxy starts with --masquerade-all=true** -If kube-proxy starts with `--masquerade-all=true`, ipvs proxier will masquerade all traffic accessing service Cluster IP, which behaves the same as what iptables proxier. Suppose there is a service with Cluster IP `10.244.5.1` and port `8080`, then the iptables installed by ipvs proxier should be like what is shown below. +If kube-proxy starts with `--masquerade-all=true`, ipvs proxier will masquerade all traffic accessing service Cluster IP, which behaves the same as what iptables proxier. Suppose kube-proxy have flag `--masquerade-all=true` specified, then the iptables installed by ipvs proxier should be like what is shown below. ```shell # iptables -t nat -nL Chain PREROUTING (policy ACCEPT) -target prot opt source destination +target prot opt source destination KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ Chain OUTPUT (policy ACCEPT) -target prot opt source destination +target prot opt source destination KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ Chain POSTROUTING (policy ACCEPT) -target prot opt source destination +target prot opt source destination KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */ -Chain KUBE-POSTROUTING (1 references) -target prot opt source destination -MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 - -Chain KUBE-MARK-DROP (0 references) -target prot opt source destination -MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x8000 - -Chain KUBE-MARK-MASQ (6 references) -target prot opt source destination +Chain KUBE-MARK-MASQ (2 references) +target prot opt source destination MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 +Chain KUBE-POSTROUTING (1 references) +target prot opt source destination +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOOP-BACK dst,dst,src + Chain KUBE-SERVICES (2 references) -target prot opt source destination -KUBE-MARK-MASQ tcp -- 0.0.0.0/0 10.244.5.1 /* default/foo:http cluster IP */ tcp dpt:8080 +target prot opt source destination +KUBE-MARK-MASQ all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-CLUSTER-IP dst,dst +ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-CLUSTER-IP dst,dst ``` **2. Specify cluster CIDR in kube-proxy startup** -If kube-proxy starts with `--cluster-cidr=`, ipvs proxier will masquerade off-cluster traffic accessing service Cluster IP, which behaves the same as what iptables proxier. Suppose kube-proxy is provided with the cluster cidr `10.244.16.0/24`, and service Cluster IP is `10.244.5.1` and port is `8080`, then the iptables installed by ipvs proxier should be like what is shown below. +If kube-proxy starts with `--cluster-cidr=`, ipvs proxier will masquerade off-cluster traffic accessing service Cluster IP, which behaves the same as what iptables proxier. Suppose kube-proxy is provided with the cluster cidr `10.244.16.0/24`, then the iptables installed by ipvs proxier should be like what is shown below. ```shell # iptables -t nat -nL Chain PREROUTING (policy ACCEPT) -target prot opt source destination -KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ - -Chain OUTPUT (policy ACCEPT) -target prot opt source destination -KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ - -Chain POSTROUTING (policy ACCEPT) -target prot opt source destination -KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */ - -Chain KUBE-POSTROUTING (1 references) -target prot opt source destination -MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 - -Chain KUBE-MARK-DROP (0 references) -target prot opt source destination -MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x8000 - -Chain KUBE-MARK-MASQ (6 references) -target prot opt source destination -MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 - -Chain KUBE-SERVICES (2 references) -target prot opt source destination -KUBE-MARK-MASQ tcp -- !10.244.16.0/24 10.244.5.1 /* default/foo:http cluster IP */ tcp dpt:8080 -``` - -**3. Load Balancer Source Ranges is specified for LB type service** - -When service's `LoadBalancerStatus.ingress.IP` is not empty and service's `LoadBalancerSourceRanges` is specified, ipvs proxier will install iptables which looks like what is shown below. - -Suppose service's `LoadBalancerStatus.ingress.IP` is `10.96.1.2` and service's `LoadBalancerSourceRanges` is `10.120.2.0/24`. - -```shell -# iptables -t nat -nL - -Chain PREROUTING (policy ACCEPT) -target prot opt source destination -KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ - -Chain OUTPUT (policy ACCEPT) -target prot opt source destination -KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ - -Chain POSTROUTING (policy ACCEPT) -target prot opt source destination -KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */ - -Chain KUBE-POSTROUTING (1 references) -target prot opt source destination -MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 - -Chain KUBE-MARK-DROP (0 references) -target prot opt source destination -MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x8000 - -Chain KUBE-MARK-MASQ (6 references) -target prot opt source destination -MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 - -Chain KUBE-SERVICES (2 references) -target prot opt source destination -ACCEPT tcp -- 10.120.2.0/24 10.96.1.2 /* default/foo:http loadbalancer IP */ tcp dpt:8080 -DROP tcp -- 0.0.0.0/0 10.96.1.2 /* default/foo:http loadbalancer IP */ tcp dpt:8080 -``` - -**4. Support NodePort type service** - -For supporting NodePort type service, ipvs will recruit the existing implementation in iptables proxier. For example, - -```shell -# kubectl describe svc nginx-service -Name: nginx-service -... -Type: NodePort -IP: 10.101.28.148 -Port: http 3080/TCP -NodePort: http 31604/TCP -Endpoints: 172.17.0.2:80 -Session Affinity: None - -# iptables -t nat -nL - -[root@100-106-179-225 ~]# iptables -t nat -nL -Chain PREROUTING (policy ACCEPT) -target prot opt source destination -KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ - -Chain OUTPUT (policy ACCEPT) -target prot opt source destination -KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ - -Chain KUBE-SERVICES (2 references) -target prot opt source destination -KUBE-MARK-MASQ tcp -- !172.16.0.0/16 10.101.28.148 /* default/nginx-service:http cluster IP */ tcp dpt:3080 -KUBE-SVC-6IM33IEVEEV7U3GP tcp -- 0.0.0.0/0 10.101.28.148 /* default/nginx-service:http cluster IP */ tcp dpt:3080 -KUBE-NODEPORTS all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL - -Chain KUBE-NODEPORTS (1 references) -target prot opt source destination -KUBE-MARK-MASQ tcp -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-service:http */ tcp dpt:31604 -KUBE-SVC-6IM33IEVEEV7U3GP tcp -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-service:http */ tcp dpt:31604 - -Chain KUBE-SVC-6IM33IEVEEV7U3GP (2 references) target prot opt source destination -KUBE-SEP-Q3UCPZ54E6Q2R4UT all -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-service:http */ -Chain KUBE-SEP-Q3UCPZ54E6Q2R4UT (1 references) -target prot opt source destination -KUBE-MARK-MASQ all -- 172.17.0.2 0.0.0.0/0 /* default/nginx-service:http */ -DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-service:http */ tcp to:172.17.0.2:80 +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain OUTPUT (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain POSTROUTING (policy ACCEPT) +target prot opt source destination +KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */ + +Chain KUBE-MARK-MASQ (3 references) +target prot opt source destination +MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 + +Chain KUBE-POSTROUTING (1 references) +target prot opt source destination +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOOP-BACK dst,dst,src + +Chain KUBE-SERVICES (2 references) +target prot opt source destination +KUBE-MARK-MASQ all -- !10.244.16.0/24 0.0.0.0/0 match-set KUBE-CLUSTER-IP dst,dst +ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-CLUSTER-IP dst,dst ``` + +**3. Load Balancer type service** + +For loadBalancer type service, ipvs proxier will install iptables with match of ipset `KUBE-LOAD-BALANCER`. +Specially when service's `LoadBalancerSourceRanges` is specified or specified `externalTrafficPolicy=local`, +ipvs proxier will create ipset sets `KUBE-LOAD-BALANCER-LOCAL`/`KUBE-LOAD-BALANCER-FW`/`KUBE-LOAD-BALANCER-SOURCE-CIDR` +and install iptables accordingly, which should looks like what is shown below. + +```shell +# iptables -t nat -nL + +Chain PREROUTING (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain OUTPUT (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain POSTROUTING (policy ACCEPT) +target prot opt source destination +KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */ + +Chain KUBE-FIREWALL (1 references) +target prot opt source destination +RETURN all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOAD-BALANCER-SOURCE-CIDR dst,dst,src +KUBE-MARK-DROP all -- 0.0.0.0/0 0.0.0.0/0 + +Chain KUBE-LOAD-BALANCER (1 references) +target prot opt source destination +KUBE-FIREWALL all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOAD-BALANCER-FW dst,dst +RETURN all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOAD-BALANCER-LOCAL dst,dst +KUBE-MARK-MASQ all -- 0.0.0.0/0 0.0.0.0/0 + +Chain KUBE-MARK-DROP (1 references) +target prot opt source destination +MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x8000 + +Chain KUBE-MARK-MASQ (2 references) +target prot opt source destination +MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 + +Chain KUBE-POSTROUTING (1 references) +target prot opt source destination +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOOP-BACK dst,dst,src + +Chain KUBE-SERVICES (2 references) +target prot opt source destination +KUBE-LOAD-BALANCER all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOAD-BALANCER dst,dst +ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOAD-BALANCER dst,dst +``` + +**4. NodePort type service** + +For NodePort type service, ipvs proxier will install iptables with match of ipset `KUBE-NODE-PORT-TCP/KUBE-NODE-PORT-UDP`. +When specified `externalTrafficPolicy=local`,ipvs proxier will create ipset sets `KUBE-NODE-PORT-LOCAL-TC/KUBE-NODE-PORT-LOCAL-UDP` +and install iptables accordingly, which should looks like what is shown below. + +Suppose service with TCP type nodePort. + +```shell +Chain PREROUTING (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain OUTPUT (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain POSTROUTING (policy ACCEPT) +target prot opt source destination +KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */ + +Chain KUBE-MARK-MASQ (2 references) +target prot opt source destination +MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 + +Chain KUBE-NODE-PORT (1 references) +target prot opt source destination +RETURN all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-NODE-PORT-LOCAL-TCP dst +KUBE-MARK-MASQ all -- 0.0.0.0/0 0.0.0.0/0 + +Chain KUBE-POSTROUTING (1 references) +target prot opt source destination +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOOP-BACK dst,dst,src + +Chain KUBE-SERVICES (2 references) +target prot opt source destination +KUBE-NODE-PORT all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-NODE-PORT-TCP dst +``` + +**5. Service with externalIPs specified** + +For service with `externalIPs` specified, ipvs proxier will install iptables with match of ipset `KUBE-EXTERNAL-IP`, +Suppose we have service with `externalIPs` specified, iptables rules should looks like what is shown below. + +```shell +Chain PREROUTING (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain OUTPUT (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain POSTROUTING (policy ACCEPT) +target prot opt source destination +KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */ + +Chain KUBE-MARK-MASQ (2 references) +target prot opt source destination +MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 + +Chain KUBE-POSTROUTING (1 references) +target prot opt source destination +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOOP-BACK dst,dst,src + +Chain KUBE-SERVICES (2 references) +target prot opt source destination +KUBE-MARK-MASQ all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-EXTERNAL-IP dst,dst +ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-EXTERNAL-IP dst,dst PHYSDEV match ! --physdev-is-in ADDRTYPE match src-type !LOCAL +ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-EXTERNAL-IP dst,dst ADDRTYPE match dst-type LOCAL +``` + ## Run kube-proxy in ipvs mode -Currently, local-up scripts, GCE scripts and kubeadm support switching IPVS proxy mode via exporting environment variables or specifying flags. +Currently, local-up scripts, GCE scripts and kubeadm support switching IPVS proxy mode via exporting environment variables or specifying flags. ### Prerequisite -Ensure the following kernel modules required by IPVS-based kube-proxy have been compiled into the node kernel (use `lsmod` to check): - +Ensure IPVS required kernel modules ```shell ip_vs ip_vs_rr @@ -209,17 +267,57 @@ ip_vs_wrr ip_vs_sh nf_conntrack_ipv4 ``` -Packages such as `ipset` should also be installed on the node before using IPVS mode. +1. have been compiled into the node kernel. Use + +`grep -e ipvs -e nf_conntrack_ipv4 /lib/modules/$(uname -r)/modules.builtin` + +and get results like the followings if compiled into kernel. +``` +kernel/net/ipv4/netfilter/nf_conntrack_ipv4.ko +kernel/net/netfilter/ipvs/ip_vs.ko +kernel/net/netfilter/ipvs/ip_vs_rr.ko +kernel/net/netfilter/ipvs/ip_vs_wrr.ko +kernel/net/netfilter/ipvs/ip_vs_lc.ko +kernel/net/netfilter/ipvs/ip_vs_wlc.ko +kernel/net/netfilter/ipvs/ip_vs_fo.ko +kernel/net/netfilter/ipvs/ip_vs_ovf.ko +kernel/net/netfilter/ipvs/ip_vs_lblc.ko +kernel/net/netfilter/ipvs/ip_vs_lblcr.ko +kernel/net/netfilter/ipvs/ip_vs_dh.ko +kernel/net/netfilter/ipvs/ip_vs_sh.ko +kernel/net/netfilter/ipvs/ip_vs_sed.ko +kernel/net/netfilter/ipvs/ip_vs_nq.ko +kernel/net/netfilter/ipvs/ip_vs_ftp.ko +``` + +OR + +2. have been loaded. +```shell +# load module +modprobe -- ip_vs +modprobe -- ip_vs_rr +modprobe -- ip_vs_wrr +modprobe -- ip_vs_sh +modprobe -- nf_conntrack_ipv4 + +# to check loaded modules, use +lsmod | grep -e ipvs -e nf_conntrack_ipv4 +# or +cut -f1 -d " " /proc/modules | grep -e ip_vs -e nf_conntrack_ipv4 + ``` + +Packages such as `ipset` should also be installed on the node before using IPVS mode. Kube-proxy will fall back to IPTABLES mode if those requirements are not met. ### Local UP Cluster -Kube-proxy will run in iptables mode by default in a [local-up cluster](https://github.com/kubernetes/community/blob/master/contributors/devel/running-locally.md). +Kube-proxy will run in iptables mode by default in a [local-up cluster](https://github.com/kubernetes/community/blob/master/contributors/devel/running-locally.md). To use IPVS mode, users should export the env `KUBE_PROXY_MODE=ipvs` to specify the ipvs mode before [starting the cluster](https://github.com/kubernetes/community/blob/master/contributors/devel/running-locally.md#starting-the-cluster): ```shell -#before running `hack/local-up-cluster.sh` +# before running `hack/local-up-cluster.sh` export KUBE_PROXY_MODE=ipvs ``` @@ -236,7 +334,7 @@ export KUBE_PROXY_MODE=ipvs ### Cluster Created by Kubeadm -Kube-proxy will run in iptables mode by default in a cluster deployed by [kubeadm](https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/). +Kube-proxy will run in iptables mode by default in a cluster deployed by [kubeadm](https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/). If you are using kubeadm with a [configuration file](https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/#config-file), you can specify the ipvs mode adding `SupportIPVSProxyMode: true` below the `kubeProxy` field. @@ -246,7 +344,6 @@ apiVersion: kubeadm.k8s.io/v1alpha1 ... kubeProxy: config: - featureGates: SupportIPVSProxyMode=true mode: ipvs ... ``` @@ -262,7 +359,7 @@ kubeadm init --feature-gates=SupportIPVSProxyMode=true to specify the ipvs mode before deploying the cluster. -**Notes** +**Notes** If ipvs mode is successfully on, you should see ipvs proxy rules (use `ipvsadm`) like ```shell # ipvsadm -ln @@ -277,7 +374,7 @@ or similar logs occur in kube-proxy logs (for example, `/tmp/kube-proxy.log` for Using ipvs Proxier. ``` -While there is no ipvs proxy rules or the following logs ocuurs indicate that the kube-proxy fails to use ipvs mode: +While there is no ipvs proxy rules or the following logs ocuurs indicate that the kube-proxy fails to use ipvs mode: ``` Can't use ipvs proxier, trying iptables proxier Using iptables Proxier. @@ -313,7 +410,7 @@ UDP 10.0.0.10:53 rr ### Why kube-proxy can't start IPVS mode -Use the following check list to help you solve the problems: +Use the following check list to help you solve the problems: **1. Enable IPVS feature gateway** diff --git a/pkg/proxy/ipvs/proxier.go b/pkg/proxy/ipvs/proxier.go index 9142cbdd38c..caf802133fb 100644 --- a/pkg/proxy/ipvs/proxier.go +++ b/pkg/proxy/ipvs/proxier.go @@ -134,7 +134,7 @@ var ipsetInfo = []struct { // ipsetWithIptablesChain is the ipsets list with iptables source chain and the chain jump to // `iptables -t nat -A -m set --match-set -j ` // example: iptables -t nat -A KUBE-SERVICES -m set --match-set KUBE-NODE-PORT-TCP dst -j KUBE-NODE-PORT -// ipsets with ohter match rules will be create Individually. +// ipsets with other match rules will be created Individually. var ipsetWithIptablesChain = []struct { name string from string @@ -366,6 +366,7 @@ func NewProxier(ipt utiliptables.Interface, endpointsChanges: proxy.NewEndpointChangeTracker(hostname, nil, &isIPv6, recorder), syncPeriod: syncPeriod, minSyncPeriod: minSyncPeriod, + excludeCIDRs: excludeCIDRs, iptables: ipt, masqueradeAll: masqueradeAll, masqueradeMark: masqueradeMark, @@ -547,6 +548,9 @@ func cleanupIptablesLeftovers(ipt utiliptables.Interface) (encounteredError bool // CleanupLeftovers clean up all ipvs and iptables rules created by ipvs Proxier. func CleanupLeftovers(ipvs utilipvs.Interface, ipt utiliptables.Interface, ipset utilipset.Interface, cleanupIPVS bool) (encounteredError bool) { + if canUse, _ := CanUseIPVSProxier(NewLinuxKernelHandler(), ipset); !canUse { + return false + } if cleanupIPVS { // Return immediately when ipvs interface is nil - Probably initialization failed in somewhere. if ipvs == nil { diff --git a/pkg/proxy/ipvs/proxier_test.go b/pkg/proxy/ipvs/proxier_test.go index 4a0543fa294..5b2df80898c 100644 --- a/pkg/proxy/ipvs/proxier_test.go +++ b/pkg/proxy/ipvs/proxier_test.go @@ -23,6 +23,7 @@ import ( "reflect" "strings" "testing" + "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -107,6 +108,24 @@ func (fake *fakeIPSetVersioner) GetVersion() (string, error) { return fake.version, fake.err } +// New returns a new FakeSysctl +func NewFakeSysctl() *FakeSysctl { + return &FakeSysctl{} +} + +type FakeSysctl struct { +} + +// GetSysctl returns the value for the specified sysctl setting +func (fakeSysctl *FakeSysctl) GetSysctl(sysctl string) (int, error) { + return 1, nil +} + +// SetSysctl modifies the specified sysctl flag to the new value +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 { fcmd := fakeexec.FakeCmd{ CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ @@ -805,7 +824,7 @@ func TestLoadBalancer(t *testing.T) { func TestOnlyLocalNodePorts(t *testing.T) { nodeIP := net.ParseIP("100.101.102.103") - ipt, fp := buildFakeProxier([]net.IP{nodeIP}) + ipt, fp := buildFakeProxier() svcIP := "10.20.30.41" svcPort := 80 @@ -889,8 +908,7 @@ func TestOnlyLocalNodePorts(t *testing.T) { checkIptables(t, ipt, epIpt) } func TestLoadBalanceSourceRanges(t *testing.T) { - nodeIP := net.ParseIP("100.101.102.103") - ipt, fp := buildFakeProxier([]net.IP{nodeIP}) + ipt, fp := buildFakeProxier() svcIP := "10.20.30.41" svcPort := 80 @@ -988,7 +1006,7 @@ func TestLoadBalanceSourceRanges(t *testing.T) { } func TestAcceptIPVSTraffic(t *testing.T) { - ipt, fp := buildFakeProxier(nil) + ipt, fp := buildFakeProxier() ingressIP := "1.2.3.4" externalIP := []string{"5.6.7.8"} @@ -1053,7 +1071,7 @@ func TestAcceptIPVSTraffic(t *testing.T) { } func TestOnlyLocalLoadBalancing(t *testing.T) { - ipt, fp := buildFakeProxier(nil) + ipt, fp := buildFakeProxier() svcIP := "10.20.30.41" svcPort := 80 @@ -2467,88 +2485,7 @@ func Test_syncService(t *testing.T) { } } -func Test_cleanLegacyService(t *testing.T) { - // 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("1.1.1.1"), - Protocol: string(api.ProtocolUDP), - Port: 53, - Scheduler: "rr", - Flags: utilipvs.FlagHashed, - }, - // Created by kube-proxy. - "ipvs1": { - Address: net.ParseIP("2.2.2.2"), - Protocol: string(api.ProtocolUDP), - Port: 54, - Scheduler: "rr", - Flags: utilipvs.FlagHashed, - }, - // Created by an external party. - "ipvs2": { - Address: net.ParseIP("3.3.3.3"), - Protocol: string(api.ProtocolUDP), - Port: 55, - Scheduler: "rr", - Flags: utilipvs.FlagHashed, - }, - // Created by an external party. - "ipvs3": { - Address: net.ParseIP("4.4.4.4"), - Protocol: string(api.ProtocolUDP), - Port: 56, - Scheduler: "rr", - Flags: utilipvs.FlagHashed, - }, - // Created by an external party. - "ipvs4": { - Address: net.ParseIP("5.5.5.5"), - Protocol: string(api.ProtocolUDP), - Port: 57, - Scheduler: "rr", - Flags: utilipvs.FlagHashed, - }, - // Created by kube-proxy, but now stale. - "ipvs5": { - Address: net.ParseIP("6.6.6.6"), - Protocol: string(api.ProtocolUDP), - Port: 58, - Scheduler: "rr", - Flags: utilipvs.FlagHashed, - }, - } - - ipt := iptablestest.NewFake() - ipvs := ipvstest.NewFake() - ipset := ipsettest.NewFake(testIPSetVersion) - proxier := NewFakeProxier(ipt, ipvs, ipset, nil) - // These CIDRs cover only ipvs2 and ipvs3. - proxier.excludeCIDRs = []string{"3.3.3.0/24", "4.4.4.0/24"} - for v := range currentServices { - proxier.ipvs.AddVirtualServer(currentServices[v]) - } - proxier.cleanLegacyService(activeServices, currentServices) - // ipvs4 and ipvs5 should have been cleaned. - remainingVirtualServers, _ := proxier.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") - } - } -} - -func buildFakeProxier(nodeIP []net.IP) (*iptablestest.FakeIPTables, *Proxier) { +func buildFakeProxier() (*iptablestest.FakeIPTables, *Proxier) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) @@ -2620,3 +2557,106 @@ 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) + } + + // 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("1.1.1.1"), + Protocol: string(api.ProtocolUDP), + Port: 53, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by kube-proxy. + "ipvs1": { + Address: net.ParseIP("2.2.2.2"), + Protocol: string(api.ProtocolUDP), + Port: 54, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by an external party. + "ipvs2": { + Address: net.ParseIP("3.3.3.3"), + Protocol: string(api.ProtocolUDP), + Port: 55, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by an external party. + "ipvs3": { + Address: net.ParseIP("4.4.4.4"), + Protocol: string(api.ProtocolUDP), + Port: 56, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by an external party. + "ipvs4": { + Address: net.ParseIP("5.5.5.5"), + Protocol: string(api.ProtocolUDP), + Port: 57, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by kube-proxy, but now stale. + "ipvs5": { + Address: net.ParseIP("6.6.6.6"), + Protocol: string(api.ProtocolUDP), + Port: 58, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + } + for v := range currentServices { + proxier.ipvs.AddVirtualServer(currentServices[v]) + } + proxier.cleanLegacyService(activeServices, currentServices) + // ipvs4 and ipvs5 should have been cleaned. + remainingVirtualServers, _ := proxier.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") + } + } +} diff --git a/pkg/quota/evaluator/core/BUILD b/pkg/quota/evaluator/core/BUILD index 8d254028c7c..7a6cbe11cfa 100644 --- a/pkg/quota/evaluator/core/BUILD +++ b/pkg/quota/evaluator/core/BUILD @@ -27,6 +27,7 @@ go_library( "//pkg/quota/generic:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", diff --git a/pkg/quota/evaluator/core/persistent_volume_claims.go b/pkg/quota/evaluator/core/persistent_volume_claims.go index 4547f370d5b..62051e45147 100644 --- a/pkg/quota/evaluator/core/persistent_volume_claims.go +++ b/pkg/quota/evaluator/core/persistent_volume_claims.go @@ -123,6 +123,17 @@ func (p *pvcEvaluator) Matches(resourceQuota *api.ResourceQuota, item runtime.Ob return generic.Matches(resourceQuota, item, p.MatchingResources, generic.MatchesNoScopeFunc) } +// MatchingScopes takes the input specified list of scopes and input object. Returns the set of scopes resource matches. +func (p *pvcEvaluator) MatchingScopes(item runtime.Object, scopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + +// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes. +// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope +func (p *pvcEvaluator) UncoveredQuotaScopes(limitedScopes []api.ScopedResourceSelectorRequirement, matchedQuotaScopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + // MatchingResources takes the input specified list of resources and returns the set of resources it matches. func (p *pvcEvaluator) MatchingResources(items []api.ResourceName) []api.ResourceName { result := []api.ResourceName{} diff --git a/pkg/quota/evaluator/core/pods.go b/pkg/quota/evaluator/core/pods.go index 06aa59e3939..3d1572271af 100644 --- a/pkg/quota/evaluator/core/pods.go +++ b/pkg/quota/evaluator/core/pods.go @@ -23,6 +23,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -117,7 +118,7 @@ type podEvaluator struct { func (p *podEvaluator) Constraints(required []api.ResourceName, item runtime.Object) error { pod, ok := item.(*api.Pod) if !ok { - return fmt.Errorf("Unexpected input object %v", item) + return fmt.Errorf("unexpected input object %v", item) } // BACKWARD COMPATIBILITY REQUIREMENT: if we quota cpu or memory, then each container @@ -181,6 +182,41 @@ func (p *podEvaluator) MatchingResources(input []api.ResourceName) []api.Resourc return result } +// MatchingScopes takes the input specified list of scopes and pod object. Returns the set of scope selectors pod matches. +func (p *podEvaluator) MatchingScopes(item runtime.Object, scopeSelectors []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + matchedScopes := []api.ScopedResourceSelectorRequirement{} + for _, selector := range scopeSelectors { + match, err := podMatchesScopeFunc(selector, item) + if err != nil { + return []api.ScopedResourceSelectorRequirement{}, fmt.Errorf("error on matching scope %v: %v", selector, err) + } + if match { + matchedScopes = append(matchedScopes, selector) + } + } + return matchedScopes, nil +} + +// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes. +// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope +func (p *podEvaluator) UncoveredQuotaScopes(limitedScopes []api.ScopedResourceSelectorRequirement, matchedQuotaScopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + uncoveredScopes := []api.ScopedResourceSelectorRequirement{} + for _, selector := range limitedScopes { + isCovered := false + for _, matchedScopeSelector := range matchedQuotaScopes { + if matchedScopeSelector.ScopeName == selector.ScopeName { + isCovered = true + break + } + } + + if !isCovered { + uncoveredScopes = append(uncoveredScopes, selector) + } + } + return uncoveredScopes, nil +} + // Usage knows how to measure usage associated with pods func (p *podEvaluator) Usage(item runtime.Object) (api.ResourceList, error) { // delegate to normal usage @@ -265,12 +301,12 @@ func toInternalPodOrError(obj runtime.Object) (*api.Pod, error) { } // podMatchesScopeFunc is a function that knows how to evaluate if a pod matches a scope -func podMatchesScopeFunc(scope api.ResourceQuotaScope, object runtime.Object) (bool, error) { +func podMatchesScopeFunc(selector api.ScopedResourceSelectorRequirement, object runtime.Object) (bool, error) { pod, err := toInternalPodOrError(object) if err != nil { return false, err } - switch scope { + switch selector.ScopeName { case api.ResourceQuotaScopeTerminating: return isTerminating(pod), nil case api.ResourceQuotaScopeNotTerminating: @@ -279,6 +315,8 @@ func podMatchesScopeFunc(scope api.ResourceQuotaScope, object runtime.Object) (b return isBestEffort(pod), nil case api.ResourceQuotaScopeNotBestEffort: return !isBestEffort(pod), nil + case api.ResourceQuotaScopePriorityClass: + return podMatchesSelector(pod, selector) } return false, nil } @@ -337,6 +375,18 @@ func isTerminating(pod *api.Pod) bool { return false } +func podMatchesSelector(pod *api.Pod, selector api.ScopedResourceSelectorRequirement) (bool, error) { + labelSelector, err := helper.ScopedResourceSelectorRequirementsAsSelector(selector) + if err != nil { + return false, fmt.Errorf("failed to parse and convert selector: %v", err) + } + m := map[string]string{string(api.ResourceQuotaScopePriorityClass): pod.Spec.PriorityClassName} + if labelSelector.Matches(labels.Set(m)) { + return true, nil + } + return false, nil +} + // QuotaPod returns true if the pod is eligible to track against a quota // A pod is eligible for quota, unless any of the following are true: // - pod has a terminal phase (failed or succeeded) diff --git a/pkg/quota/evaluator/core/services.go b/pkg/quota/evaluator/core/services.go index cdddaf064a8..006c0e9b113 100644 --- a/pkg/quota/evaluator/core/services.go +++ b/pkg/quota/evaluator/core/services.go @@ -82,6 +82,17 @@ func (p *serviceEvaluator) MatchingResources(input []api.ResourceName) []api.Res return quota.Intersection(input, serviceResources) } +// MatchingScopes takes the input specified list of scopes and input object. Returns the set of scopes resource matches. +func (p *serviceEvaluator) MatchingScopes(item runtime.Object, scopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + +// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes. +// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope +func (p *serviceEvaluator) UncoveredQuotaScopes(limitedScopes []api.ScopedResourceSelectorRequirement, matchedQuotaScopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + // convert the input object to an internal service object or error. func toInternalServiceOrError(obj runtime.Object) (*api.Service, error) { svc := &api.Service{} diff --git a/pkg/quota/generic/evaluator.go b/pkg/quota/generic/evaluator.go index 6324ce5ddeb..7df5243e595 100644 --- a/pkg/quota/generic/evaluator.go +++ b/pkg/quota/generic/evaluator.go @@ -67,7 +67,7 @@ func ObjectCountQuotaResourceNameFor(groupResource schema.GroupResource) api.Res type ListFuncByNamespace func(namespace string) ([]runtime.Object, error) // MatchesScopeFunc knows how to evaluate if an object matches a scope -type MatchesScopeFunc func(scope api.ResourceQuotaScope, object runtime.Object) (bool, error) +type MatchesScopeFunc func(scope api.ScopedResourceSelectorRequirement, object runtime.Object) (bool, error) // UsageFunc knows how to measure usage associated with an object type UsageFunc func(object runtime.Object) (api.ResourceList, error) @@ -76,12 +76,14 @@ type UsageFunc func(object runtime.Object) (api.ResourceList, error) type MatchingResourceNamesFunc func(input []api.ResourceName) []api.ResourceName // MatchesNoScopeFunc returns false on all match checks -func MatchesNoScopeFunc(scope api.ResourceQuotaScope, object runtime.Object) (bool, error) { +func MatchesNoScopeFunc(scope api.ScopedResourceSelectorRequirement, object runtime.Object) (bool, error) { return false, nil } // Matches returns true if the quota matches the specified item. -func Matches(resourceQuota *api.ResourceQuota, item runtime.Object, matchFunc MatchingResourceNamesFunc, scopeFunc MatchesScopeFunc) (bool, error) { +func Matches( + resourceQuota *api.ResourceQuota, item runtime.Object, + matchFunc MatchingResourceNamesFunc, scopeFunc MatchesScopeFunc) (bool, error) { if resourceQuota == nil { return false, fmt.Errorf("expected non-nil quota") } @@ -89,7 +91,7 @@ func Matches(resourceQuota *api.ResourceQuota, item runtime.Object, matchFunc Ma matchResource := len(matchFunc(quota.ResourceNames(resourceQuota.Status.Hard))) > 0 // by default, no scopes matches all matchScope := true - for _, scope := range resourceQuota.Spec.Scopes { + for _, scope := range getScopeSelectorsFromQuota(resourceQuota) { innerMatch, err := scopeFunc(scope, item) if err != nil { return false, err @@ -99,6 +101,21 @@ func Matches(resourceQuota *api.ResourceQuota, item runtime.Object, matchFunc Ma return matchResource && matchScope, nil } +func getScopeSelectorsFromQuota(quota *api.ResourceQuota) []api.ScopedResourceSelectorRequirement { + selectors := []api.ScopedResourceSelectorRequirement{} + for _, scope := range quota.Spec.Scopes { + selectors = append(selectors, api.ScopedResourceSelectorRequirement{ + ScopeName: scope, + Operator: api.ScopeSelectorOpExists}) + } + if quota.Spec.ScopeSelector != nil { + for _, scopeSelector := range quota.Spec.ScopeSelector.MatchExpressions { + selectors = append(selectors, scopeSelector) + } + } + return selectors +} + // CalculateUsageStats is a utility function that knows how to calculate aggregate usage. func CalculateUsageStats(options quota.UsageStatsOptions, listFunc ListFuncByNamespace, @@ -117,7 +134,7 @@ func CalculateUsageStats(options quota.UsageStatsOptions, // need to verify that the item matches the set of scopes matchesScopes := true for _, scope := range options.Scopes { - innerMatch, err := scopeFunc(scope, item) + innerMatch, err := scopeFunc(api.ScopedResourceSelectorRequirement{ScopeName: scope}, item) if err != nil { return result, nil } @@ -125,6 +142,15 @@ func CalculateUsageStats(options quota.UsageStatsOptions, matchesScopes = false } } + if options.ScopeSelector != nil { + for _, selector := range options.ScopeSelector.MatchExpressions { + innerMatch, err := scopeFunc(selector, item) + if err != nil { + return result, nil + } + matchesScopes = matchesScopes && innerMatch + } + } // only count usage if there was a match if matchesScopes { usage, err := usageFunc(item) @@ -176,6 +202,17 @@ func (o *objectCountEvaluator) MatchingResources(input []api.ResourceName) []api return quota.Intersection(input, o.resourceNames) } +// MatchingScopes takes the input specified list of scopes and input object. Returns the set of scopes resource matches. +func (o *objectCountEvaluator) MatchingScopes(item runtime.Object, scopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + +// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes. +// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope +func (o *objectCountEvaluator) UncoveredQuotaScopes(limitedScopes []api.ScopedResourceSelectorRequirement, matchedQuotaScopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + // Usage returns the resource usage for the specified object func (o *objectCountEvaluator) Usage(object runtime.Object) (api.ResourceList, error) { quantity := resource.NewQuantity(1, resource.DecimalSI) diff --git a/pkg/quota/interfaces.go b/pkg/quota/interfaces.go index 8d7295ef0c9..e6723b8aef7 100644 --- a/pkg/quota/interfaces.go +++ b/pkg/quota/interfaces.go @@ -31,7 +31,8 @@ type UsageStatsOptions struct { // Scopes that must match counted objects Scopes []api.ResourceQuotaScope // Resources are the set of resources to include in the measurement - Resources []api.ResourceName + Resources []api.ResourceName + ScopeSelector *api.ScopeSelector } // UsageStats is result of measuring observed resource use in the system @@ -51,6 +52,10 @@ type Evaluator interface { Handles(operation admission.Attributes) bool // Matches returns true if the specified quota matches the input item Matches(resourceQuota *api.ResourceQuota, item runtime.Object) (bool, error) + // MatchingScopes takes the input specified list of scopes and input object and returns the set of scopes that matches input object. + MatchingScopes(item runtime.Object, scopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) + // UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes. It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope + UncoveredQuotaScopes(limitedScopes []api.ScopedResourceSelectorRequirement, matchedQuotaScopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) // MatchingResources takes the input specified list of resources and returns the set of resources evaluator matches. MatchingResources(input []api.ResourceName) []api.ResourceName // Usage returns the resource usage for the specified object diff --git a/pkg/quota/resources.go b/pkg/quota/resources.go index a40a81a64c6..f77d2d7428e 100644 --- a/pkg/quota/resources.go +++ b/pkg/quota/resources.go @@ -253,7 +253,7 @@ func ToSet(resourceNames []api.ResourceName) sets.String { } // CalculateUsage calculates and returns the requested ResourceList usage -func CalculateUsage(namespaceName string, scopes []api.ResourceQuotaScope, hardLimits api.ResourceList, registry Registry) (api.ResourceList, error) { +func CalculateUsage(namespaceName string, scopes []api.ResourceQuotaScope, hardLimits api.ResourceList, registry Registry, scopeSelector *api.ScopeSelector) (api.ResourceList, error) { // find the intersection between the hard resources on the quota // and the resources this controller can track to know what we can // look to measure updated usage stats for @@ -275,7 +275,7 @@ func CalculateUsage(namespaceName string, scopes []api.ResourceQuotaScope, hardL continue } - usageStatsOptions := UsageStatsOptions{Namespace: namespaceName, Scopes: scopes, Resources: intersection} + usageStatsOptions := UsageStatsOptions{Namespace: namespaceName, Scopes: scopes, Resources: intersection, ScopeSelector: scopeSelector} stats, err := evaluator.UsageStats(usageStatsOptions) if err != nil { return nil, err diff --git a/pkg/registry/core/pod/storage/storage_test.go b/pkg/registry/core/pod/storage/storage_test.go index 707caceb412..0ea8f0bdd65 100644 --- a/pkg/registry/core/pod/storage/storage_test.go +++ b/pkg/registry/core/pod/storage/storage_test.go @@ -452,7 +452,7 @@ func TestConvertToTableList(t *testing.T) { out: &metav1beta1.Table{ ColumnDefinitions: columns, Rows: []metav1beta1.TableRow{ - {Cells: []interface{}{"", "0/0", "", 0, "", "", ""}, Object: runtime.RawExtension{Object: &api.Pod{}}}, + {Cells: []interface{}{"", "0/0", "", int64(0), "", "", ""}, Object: runtime.RawExtension{Object: &api.Pod{}}}, }, }, }, @@ -461,7 +461,7 @@ func TestConvertToTableList(t *testing.T) { out: &metav1beta1.Table{ ColumnDefinitions: columns, Rows: []metav1beta1.TableRow{ - {Cells: []interface{}{"foo", "1/2", "Pending", 10, "1y", "10.1.2.3", "test-node"}, Object: runtime.RawExtension{Object: pod1}}, + {Cells: []interface{}{"foo", "1/2", "Pending", int64(10), "1y", "10.1.2.3", "test-node"}, Object: runtime.RawExtension{Object: pod1}}, }, }, }, diff --git a/pkg/registry/core/service/portallocator/controller/repair.go b/pkg/registry/core/service/portallocator/controller/repair.go index 1e4dc685c3d..c1a4f0dadbd 100644 --- a/pkg/registry/core/service/portallocator/controller/repair.go +++ b/pkg/registry/core/service/portallocator/controller/repair.go @@ -204,5 +204,10 @@ func collectServiceNodePorts(service *api.Service) []int { servicePorts = append(servicePorts, int(servicePort.NodePort)) } } + + if service.Spec.HealthCheckNodePort != 0 { + servicePorts = append(servicePorts, int(service.Spec.HealthCheckNodePort)) + } + return servicePorts } diff --git a/pkg/registry/core/service/portallocator/controller/repair_test.go b/pkg/registry/core/service/portallocator/controller/repair_test.go index 151c791cc39..48c41aa989a 100644 --- a/pkg/registry/core/service/portallocator/controller/repair_test.go +++ b/pkg/registry/core/service/portallocator/controller/repair_test.go @@ -164,6 +164,12 @@ func TestRepairWithExisting(t *testing.T) { Ports: []api.ServicePort{{NodePort: 111}}, }, }, + &api.Service{ + ObjectMeta: metav1.ObjectMeta{Namespace: "six", Name: "six"}, + Spec: api.ServiceSpec{ + HealthCheckNodePort: 144, + }, + }, ) registry := &mockRangeRegistry{ @@ -183,10 +189,10 @@ func TestRepairWithExisting(t *testing.T) { if err != nil { t.Fatal(err) } - if !after.Has(111) || !after.Has(122) || !after.Has(133) { + if !after.Has(111) || !after.Has(122) || !after.Has(133) || !after.Has(144) { t.Errorf("unexpected portallocator state: %#v", after) } - if free := after.Free(); free != 98 { + if free := after.Free(); free != 97 { t.Errorf("unexpected portallocator state: %d free", free) } } diff --git a/pkg/registry/core/serviceaccount/storage/BUILD b/pkg/registry/core/serviceaccount/storage/BUILD index 1469f663888..d74dcd4db52 100644 --- a/pkg/registry/core/serviceaccount/storage/BUILD +++ b/pkg/registry/core/serviceaccount/storage/BUILD @@ -32,6 +32,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/registry/core/serviceaccount/storage", deps = [ "//pkg/apis/authentication:go_default_library", + "//pkg/apis/authentication/validation:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", diff --git a/pkg/registry/core/serviceaccount/storage/token.go b/pkg/registry/core/serviceaccount/storage/token.go index 32df9503f10..e1a94f6e50f 100644 --- a/pkg/registry/core/serviceaccount/storage/token.go +++ b/pkg/registry/core/serviceaccount/storage/token.go @@ -29,6 +29,7 @@ import ( genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" authenticationapi "k8s.io/kubernetes/pkg/apis/authentication" + authenticationvalidation "k8s.io/kubernetes/pkg/apis/authentication/validation" api "k8s.io/kubernetes/pkg/apis/core" token "k8s.io/kubernetes/pkg/serviceaccount" ) @@ -48,6 +49,12 @@ type TokenREST struct { var _ = rest.NamedCreater(&TokenREST{}) var _ = rest.GroupVersionKindProvider(&TokenREST{}) +var gvk = schema.GroupVersionKind{ + Group: authenticationapiv1.SchemeGroupVersion.Group, + Version: authenticationapiv1.SchemeGroupVersion.Version, + Kind: "TokenRequest", +} + func (r *TokenREST) Create(ctx context.Context, name string, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { if err := createValidation(obj); err != nil { return nil, err @@ -55,6 +62,10 @@ func (r *TokenREST) Create(ctx context.Context, name string, obj runtime.Object, out := obj.(*authenticationapi.TokenRequest) + if errs := authenticationvalidation.ValidateTokenRequest(out); len(errs) != 0 { + return nil, errors.NewInvalid(gvk.GroupKind(), "", errs) + } + svcacctObj, err := r.svcaccts.Get(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, err @@ -113,12 +124,8 @@ func (r *TokenREST) Create(ctx context.Context, name string, obj runtime.Object, return out, nil } -func (r *TokenREST) GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind { - return schema.GroupVersionKind{ - Group: authenticationapiv1.SchemeGroupVersion.Group, - Version: authenticationapiv1.SchemeGroupVersion.Version, - Kind: "TokenRequest", - } +func (r *TokenREST) GroupVersionKind(schema.GroupVersion) schema.GroupVersionKind { + return gvk } type getter interface { diff --git a/pkg/scheduler/BUILD b/pkg/scheduler/BUILD index 0cd00ce3903..1e14062c5aa 100644 --- a/pkg/scheduler/BUILD +++ b/pkg/scheduler/BUILD @@ -15,8 +15,8 @@ go_test( "//pkg/controller/volume/persistentvolume:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/core:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//pkg/scheduler/testing:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", @@ -44,9 +44,9 @@ 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:go_default_library", "//pkg/scheduler/metrics:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//vendor/github.com/golang/glog:go_default_library", @@ -75,10 +75,10 @@ filegroup( "//pkg/scheduler/algorithm:all-srcs", "//pkg/scheduler/algorithmprovider:all-srcs", "//pkg/scheduler/api:all-srcs", + "//pkg/scheduler/cache:all-srcs", "//pkg/scheduler/core:all-srcs", "//pkg/scheduler/factory:all-srcs", "//pkg/scheduler/metrics:all-srcs", - "//pkg/scheduler/schedulercache: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 9d2f4b7021e..37bfb4fb954 100644 --- a/pkg/scheduler/algorithm/BUILD +++ b/pkg/scheduler/algorithm/BUILD @@ -18,7 +18,7 @@ go_library( deps = [ "//pkg/apis/core:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", @@ -34,7 +34,7 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", ], diff --git a/pkg/scheduler/algorithm/predicates/BUILD b/pkg/scheduler/algorithm/predicates/BUILD index 069dac60931..13e216174e6 100644 --- a/pkg/scheduler/algorithm/predicates/BUILD +++ b/pkg/scheduler/algorithm/predicates/BUILD @@ -23,7 +23,7 @@ go_library( "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//pkg/volume/util:go_default_library", @@ -46,6 +46,7 @@ go_library( go_test( name = "go_default_test", srcs = [ + "max_attachable_volume_predicate_test.go", "metadata_test.go", "predicates_test.go", "utils_test.go", @@ -53,10 +54,12 @@ go_test( embed = [":go_default_library"], deps = [ "//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/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/testing:go_default_library", + "//pkg/volume/util:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -64,6 +67,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", ], ) diff --git a/pkg/scheduler/algorithm/predicates/max_attachable_volume_predicate_test.go b/pkg/scheduler/algorithm/predicates/max_attachable_volume_predicate_test.go new file mode 100644 index 00000000000..60aa5879a30 --- /dev/null +++ b/pkg/scheduler/algorithm/predicates/max_attachable_volume_predicate_test.go @@ -0,0 +1,854 @@ +/* +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 predicates + +import ( + "os" + "reflect" + "strconv" + "strings" + "testing" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + 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" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + volumeutil "k8s.io/kubernetes/pkg/volume/util" +) + +func onePVCPod(filterName string) *v1.Pod { + return &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "some" + filterName + "Vol", + }, + }, + }, + }, + }, + } +} + +func splitPVCPod(filterName string) *v1.Pod { + return &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "someNon" + filterName + "Vol", + }, + }, + }, + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "some" + filterName + "Vol", + }, + }, + }, + }, + }, + } +} + +func TestVolumeCountConflicts(t *testing.T) { + oneVolPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp"}, + }, + }, + }, + }, + } + twoVolPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp1"}, + }, + }, + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp2"}, + }, + }, + }, + }, + } + splitVolsPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{}, + }, + }, + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "svp"}, + }, + }, + }, + }, + } + nonApplicablePod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{}, + }, + }, + }, + }, + } + deletedPVCPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "deletedPVC", + }, + }, + }, + }, + }, + } + twoDeletedPVCPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "deletedPVC", + }, + }, + }, + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "anotherDeletedPVC", + }, + }, + }, + }, + }, + } + deletedPVPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "pvcWithDeletedPV", + }, + }, + }, + }, + }, + } + // deletedPVPod2 is a different pod than deletedPVPod but using the same PVC + deletedPVPod2 := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "pvcWithDeletedPV", + }, + }, + }, + }, + }, + } + // anotherDeletedPVPod is a different pod than deletedPVPod and uses another PVC + anotherDeletedPVPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "anotherPVCWithDeletedPV", + }, + }, + }, + }, + }, + } + emptyPod := &v1.Pod{ + Spec: v1.PodSpec{}, + } + unboundPVCPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "unboundPVC", + }, + }, + }, + }, + }, + } + // Different pod than unboundPVCPod, but using the same unbound PVC + unboundPVCPod2 := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "unboundPVC", + }, + }, + }, + }, + }, + } + + // pod with unbound PVC that's different to unboundPVC + anotherUnboundPVCPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "anotherUnboundPVC", + }, + }, + }, + }, + }, + } + + tests := []struct { + newPod *v1.Pod + existingPods []*v1.Pod + filterName string + maxVols int + fits bool + test string + }{ + // filterName:EBSVolumeFilterType + { + newPod: oneVolPod, + existingPods: []*v1.Pod{twoVolPod, oneVolPod}, + filterName: EBSVolumeFilterType, + maxVols: 4, + fits: true, + test: "fits when node capacity >= new pod's EBS volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "doesn't fit when node capacity < new pod's EBS volumes", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{twoVolPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores non-EBS volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "existing pods' counts ignore non-EBS volumes", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count considers PVCs backed by EBS volumes", + }, + { + newPod: splitPVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, oneVolPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores PVCs not backed by EBS volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, onePVCPod(EBSVolumeFilterType)}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: false, + test: "existing pods' counts considers PVCs backed by EBS volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(EBSVolumeFilterType)}, + filterName: EBSVolumeFilterType, + maxVols: 4, + fits: true, + test: "already-mounted EBS volumes are always ok to allow", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(EBSVolumeFilterType)}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "the same EBS volumes are not counted multiple times", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: false, + test: "pod with missing two PVCs is counted towards the PV limit twice", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: deletedPVPod2, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: true, + test: "two pods missing the same PV are counted towards the PV limit only once", + }, + { + newPod: anotherDeletedPVPod, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "two pods missing different PVs are counted towards the PV limit twice", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: unboundPVCPod2, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: true, + test: "the same unbound PVC in multiple pods is counted towards the PV limit only once", + }, + { + newPod: anotherUnboundPVCPod, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "two different unbound PVCs are counted towards the PV limit as two volumes", + }, + // filterName:GCEPDVolumeFilterType + { + newPod: oneVolPod, + existingPods: []*v1.Pod{twoVolPod, oneVolPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 4, + fits: true, + test: "fits when node capacity >= new pod's GCE volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "fit when node capacity < new pod's GCE volumes", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{twoVolPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores non-GCE volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "existing pods' counts ignore non-GCE volumes", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count considers PVCs backed by GCE volumes", + }, + { + newPod: splitPVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, oneVolPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores PVCs not backed by GCE volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, onePVCPod(GCEPDVolumeFilterType)}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "existing pods' counts considers PVCs backed by GCE volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(GCEPDVolumeFilterType)}, + filterName: GCEPDVolumeFilterType, + maxVols: 4, + fits: true, + test: "already-mounted EBS volumes are always ok to allow", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(GCEPDVolumeFilterType)}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "the same GCE volumes are not counted multiple times", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing two PVCs is counted towards the PV limit twice", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: deletedPVPod2, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "two pods missing the same PV are counted towards the PV limit only once", + }, + { + newPod: anotherDeletedPVPod, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "two pods missing different PVs are counted towards the PV limit twice", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: unboundPVCPod2, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "the same unbound PVC in multiple pods is counted towards the PV limit only once", + }, + { + newPod: anotherUnboundPVCPod, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "two different unbound PVCs are counted towards the PV limit as two volumes", + }, + // filterName:AzureDiskVolumeFilterType + { + newPod: oneVolPod, + existingPods: []*v1.Pod{twoVolPod, oneVolPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 4, + fits: true, + test: "fits when node capacity >= new pod's AzureDisk volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "fit when node capacity < new pod's AzureDisk volumes", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{twoVolPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores non-AzureDisk volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "existing pods' counts ignore non-AzureDisk volumes", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count considers PVCs backed by AzureDisk volumes", + }, + { + newPod: splitPVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, oneVolPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores PVCs not backed by AzureDisk volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, onePVCPod(AzureDiskVolumeFilterType)}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "existing pods' counts considers PVCs backed by AzureDisk volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(AzureDiskVolumeFilterType)}, + filterName: AzureDiskVolumeFilterType, + maxVols: 4, + fits: true, + test: "already-mounted AzureDisk volumes are always ok to allow", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(AzureDiskVolumeFilterType)}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "the same AzureDisk volumes are not counted multiple times", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing two PVCs is counted towards the PV limit twice", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: deletedPVPod2, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "two pods missing the same PV are counted towards the PV limit only once", + }, + { + newPod: anotherDeletedPVPod, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "two pods missing different PVs are counted towards the PV limit twice", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: unboundPVCPod2, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "the same unbound PVC in multiple pods is counted towards the PV limit only once", + }, + { + newPod: anotherUnboundPVCPod, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "two different unbound PVCs are counted towards the PV limit as two volumes", + }, + } + + pvInfo := func(filterName string) FakePersistentVolumeInfo { + return FakePersistentVolumeInfo{ + { + ObjectMeta: metav1.ObjectMeta{Name: "some" + filterName + "Vol"}, + Spec: v1.PersistentVolumeSpec{ + PersistentVolumeSource: v1.PersistentVolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: strings.ToLower(filterName) + "Vol"}, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "someNon" + filterName + "Vol"}, + Spec: v1.PersistentVolumeSpec{ + PersistentVolumeSource: v1.PersistentVolumeSource{}, + }, + }, + } + } + + pvcInfo := func(filterName string) FakePersistentVolumeClaimInfo { + return FakePersistentVolumeClaimInfo{ + { + ObjectMeta: metav1.ObjectMeta{Name: "some" + filterName + "Vol"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: "some" + filterName + "Vol"}, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "someNon" + filterName + "Vol"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: "someNon" + filterName + "Vol"}, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "pvcWithDeletedPV"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: "pvcWithDeletedPV"}, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "anotherPVCWithDeletedPV"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: "anotherPVCWithDeletedPV"}, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "unboundPVC"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: ""}, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "anotherUnboundPVC"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: ""}, + }, + } + } + + expectedFailureReasons := []algorithm.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, pvInfo(test.filterName), pvcInfo(test.filterName)) + fits, reasons, err := pred(test.newPod, PredicateMetadata(test.newPod, nil), schedulercache.NewNodeInfo(test.existingPods...)) + if err != nil { + t.Errorf("[%s]%s: unexpected error: %v", test.filterName, test.test, err) + } + if !fits && !reflect.DeepEqual(reasons, expectedFailureReasons) { + t.Errorf("[%s]%s: unexpected failure reasons: %v, want: %v", test.filterName, test.test, reasons, expectedFailureReasons) + } + if fits != test.fits { + t.Errorf("[%s]%s: expected %v, got %v", test.filterName, test.test, test.fits, fits) + } + } + + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AttachVolumeLimit, true)() + + // 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 := NewMaxPDVolumeCountPredicate(test.filterName, pvInfo(test.filterName), pvcInfo(test.filterName)) + fits, reasons, err := pred(test.newPod, PredicateMetadata(test.newPod, nil), node) + if err != nil { + t.Errorf("Using allocatable [%s]%s: unexpected error: %v", test.filterName, test.test, err) + } + if !fits && !reflect.DeepEqual(reasons, expectedFailureReasons) { + t.Errorf("Using allocatable [%s]%s: unexpected failure reasons: %v, want: %v", test.filterName, test.test, reasons, expectedFailureReasons) + } + if fits != test.fits { + t.Errorf("Using allocatable [%s]%s: expected %v, got %v", test.filterName, test.test, test.fits, fits) + } + } +} + +func getNodeWithPodAndVolumeLimits(pods []*v1.Pod, limit int64, filter string) *schedulercache.NodeInfo { + nodeInfo := schedulercache.NewNodeInfo(pods...) + node := &v1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "node-for-max-pd-test-1"}, + Status: v1.NodeStatus{ + Allocatable: v1.ResourceList{ + getVolumeLimitKey(filter): *resource.NewQuantity(limit, resource.DecimalSI), + }, + }, + } + nodeInfo.SetNode(node) + return nodeInfo +} + +func getVolumeLimitKey(filterType string) v1.ResourceName { + switch filterType { + case EBSVolumeFilterType: + return v1.ResourceName(volumeutil.EBSVolumeLimitKey) + case GCEPDVolumeFilterType: + return v1.ResourceName(volumeutil.GCEVolumeLimitKey) + case AzureDiskVolumeFilterType: + return v1.ResourceName(volumeutil.AzureVolumeLimitKey) + default: + return "" + } +} diff --git a/pkg/scheduler/algorithm/predicates/metadata.go b/pkg/scheduler/algorithm/predicates/metadata.go index 27afb175cde..2b276ede617 100644 --- a/pkg/scheduler/algorithm/predicates/metadata.go +++ b/pkg/scheduler/algorithm/predicates/metadata.go @@ -29,7 +29,7 @@ import ( "k8s.io/client-go/util/workqueue" "k8s.io/kubernetes/pkg/scheduler/algorithm" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedutil "k8s.io/kubernetes/pkg/scheduler/util" ) diff --git a/pkg/scheduler/algorithm/predicates/metadata_test.go b/pkg/scheduler/algorithm/predicates/metadata_test.go index b5b450f5d1c..013d546e1f1 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) diff --git a/pkg/scheduler/algorithm/predicates/predicates.go b/pkg/scheduler/algorithm/predicates/predicates.go index 1da525cd429..aaf28f9622e 100644 --- a/pkg/scheduler/algorithm/predicates/predicates.go +++ b/pkg/scheduler/algorithm/predicates/predicates.go @@ -43,7 +43,7 @@ import ( kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/scheduler/algorithm" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedutil "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" volumeutil "k8s.io/kubernetes/pkg/volume/util" @@ -289,10 +289,11 @@ func NoDiskConflict(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *sch // MaxPDVolumeCountChecker contains information to check the max number of volumes for a predicate. type MaxPDVolumeCountChecker struct { - filter VolumeFilter - maxVolumes int - pvInfo PersistentVolumeInfo - pvcInfo PersistentVolumeClaimInfo + filter VolumeFilter + volumeLimitKey v1.ResourceName + maxVolumes int + pvInfo PersistentVolumeInfo + pvcInfo PersistentVolumeClaimInfo // The string below is generated randomly during the struct's initialization. // It is used to prefix volumeID generated inside the predicate() method to @@ -313,21 +314,25 @@ type VolumeFilter struct { // The predicate looks for both volumes used directly, as well as PVC volumes that are backed by relevant volume // 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 { - +func NewMaxPDVolumeCountPredicate( + filterName string, pvInfo PersistentVolumeInfo, pvcInfo PersistentVolumeClaimInfo) algorithm.FitPredicate { var filter VolumeFilter var maxVolumes int + var volumeLimitKey v1.ResourceName switch filterName { case EBSVolumeFilterType: filter = EBSVolumeFilter + volumeLimitKey = v1.ResourceName(volumeutil.EBSVolumeLimitKey) maxVolumes = getMaxVols(DefaultMaxEBSVolumes) case GCEPDVolumeFilterType: filter = GCEPDVolumeFilter + volumeLimitKey = v1.ResourceName(volumeutil.GCEVolumeLimitKey) maxVolumes = getMaxVols(DefaultMaxGCEPDVolumes) case AzureDiskVolumeFilterType: filter = AzureDiskVolumeFilter + volumeLimitKey = v1.ResourceName(volumeutil.AzureVolumeLimitKey) maxVolumes = getMaxVols(DefaultMaxAzureDiskVolumes) default: glog.Fatalf("Wrong filterName, Only Support %v %v %v ", EBSVolumeFilterType, @@ -337,6 +342,7 @@ func NewMaxPDVolumeCountPredicate(filterName string, pvInfo PersistentVolumeInfo } c := &MaxPDVolumeCountChecker{ filter: filter, + volumeLimitKey: volumeLimitKey, maxVolumes: maxVolumes, pvInfo: pvInfo, pvcInfo: pvcInfo, @@ -362,7 +368,6 @@ func getMaxVols(defaultVal int) int { } func (c *MaxPDVolumeCountChecker) filterVolumes(volumes []v1.Volume, namespace string, filteredVolumes map[string]bool) error { - for i := range volumes { vol := &volumes[i] if id, ok := c.filter.FilterVolume(vol); ok { @@ -449,15 +454,23 @@ func (c *MaxPDVolumeCountChecker) predicate(pod *v1.Pod, meta algorithm.Predicat } numNewVolumes := len(newVolumes) + maxAttachLimit := c.maxVolumes - if numExistingVolumes+numNewVolumes > c.maxVolumes { + if utilfeature.DefaultFeatureGate.Enabled(features.AttachVolumeLimit) { + volumeLimits := nodeInfo.VolumeLimits() + if maxAttachLimitFromAllocatable, ok := volumeLimits[c.volumeLimitKey]; ok { + maxAttachLimit = int(maxAttachLimitFromAllocatable) + } + } + + if numExistingVolumes+numNewVolumes > maxAttachLimit { // violates MaxEBSVolumeCount or MaxGCEPDVolumeCount return false, []algorithm.PredicateFailureReason{ErrMaxVolumeCountExceeded}, nil } if nodeInfo != nil && nodeInfo.TransientInfo != nil && utilfeature.DefaultFeatureGate.Enabled(features.BalanceAttachedNodeVolumes) { nodeInfo.TransientInfo.TransientLock.Lock() defer nodeInfo.TransientInfo.TransientLock.Unlock() - nodeInfo.TransientInfo.TransNodeInfo.AllocatableVolumesCount = c.maxVolumes - numExistingVolumes + nodeInfo.TransientInfo.TransNodeInfo.AllocatableVolumesCount = maxAttachLimit - numExistingVolumes nodeInfo.TransientInfo.TransNodeInfo.RequestedVolumes = numNewVolumes } return true, nil, nil diff --git a/pkg/scheduler/algorithm/predicates/predicates_test.go b/pkg/scheduler/algorithm/predicates/predicates_test.go index ab757640b0a..b664590f363 100644 --- a/pkg/scheduler/algorithm/predicates/predicates_test.go +++ b/pkg/scheduler/algorithm/predicates/predicates_test.go @@ -32,7 +32,7 @@ import ( v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/scheduler/algorithm" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -1833,779 +1833,6 @@ func TestServiceAffinity(t *testing.T) { } } -func onePVCPod(filterName string) *v1.Pod { - return &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "some" + filterName + "Vol", - }, - }, - }, - }, - }, - } -} - -func splitPVCPod(filterName string) *v1.Pod { - return &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someNon" + filterName + "Vol", - }, - }, - }, - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "some" + filterName + "Vol", - }, - }, - }, - }, - }, - } -} - -func TestVolumeCountConflicts(t *testing.T) { - oneVolPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp"}, - }, - }, - }, - }, - } - twoVolPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp1"}, - }, - }, - { - VolumeSource: v1.VolumeSource{ - AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp2"}, - }, - }, - }, - }, - } - splitVolsPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - HostPath: &v1.HostPathVolumeSource{}, - }, - }, - { - VolumeSource: v1.VolumeSource{ - AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "svp"}, - }, - }, - }, - }, - } - nonApplicablePod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - HostPath: &v1.HostPathVolumeSource{}, - }, - }, - }, - }, - } - deletedPVCPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "deletedPVC", - }, - }, - }, - }, - }, - } - twoDeletedPVCPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "deletedPVC", - }, - }, - }, - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "anotherDeletedPVC", - }, - }, - }, - }, - }, - } - deletedPVPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "pvcWithDeletedPV", - }, - }, - }, - }, - }, - } - // deletedPVPod2 is a different pod than deletedPVPod but using the same PVC - deletedPVPod2 := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "pvcWithDeletedPV", - }, - }, - }, - }, - }, - } - // anotherDeletedPVPod is a different pod than deletedPVPod and uses another PVC - anotherDeletedPVPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "anotherPVCWithDeletedPV", - }, - }, - }, - }, - }, - } - emptyPod := &v1.Pod{ - Spec: v1.PodSpec{}, - } - unboundPVCPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "unboundPVC", - }, - }, - }, - }, - }, - } - // Different pod than unboundPVCPod, but using the same unbound PVC - unboundPVCPod2 := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "unboundPVC", - }, - }, - }, - }, - }, - } - - // pod with unbound PVC that's different to unboundPVC - anotherUnboundPVCPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "anotherUnboundPVC", - }, - }, - }, - }, - }, - } - - tests := []struct { - newPod *v1.Pod - existingPods []*v1.Pod - filterName string - maxVols int - fits bool - test string - }{ - // filterName:EBSVolumeFilterType - { - newPod: oneVolPod, - existingPods: []*v1.Pod{twoVolPod, oneVolPod}, - filterName: EBSVolumeFilterType, - maxVols: 4, - fits: true, - test: "fits when node capacity >= new pod's EBS volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod}, - filterName: EBSVolumeFilterType, - maxVols: 2, - fits: false, - test: "doesn't fit when node capacity < new pod's EBS volumes", - }, - { - newPod: splitVolsPod, - existingPods: []*v1.Pod{twoVolPod}, - filterName: EBSVolumeFilterType, - maxVols: 3, - fits: true, - test: "new pod's count ignores non-EBS volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, - filterName: EBSVolumeFilterType, - maxVols: 3, - fits: true, - test: "existing pods' counts ignore non-EBS volumes", - }, - { - newPod: onePVCPod(EBSVolumeFilterType), - existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, - filterName: EBSVolumeFilterType, - maxVols: 3, - fits: true, - test: "new pod's count considers PVCs backed by EBS volumes", - }, - { - newPod: splitPVCPod(EBSVolumeFilterType), - existingPods: []*v1.Pod{splitVolsPod, oneVolPod}, - filterName: EBSVolumeFilterType, - maxVols: 3, - fits: true, - test: "new pod's count ignores PVCs not backed by EBS volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod, onePVCPod(EBSVolumeFilterType)}, - filterName: EBSVolumeFilterType, - maxVols: 3, - fits: false, - test: "existing pods' counts considers PVCs backed by EBS volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(EBSVolumeFilterType)}, - filterName: EBSVolumeFilterType, - maxVols: 4, - fits: true, - test: "already-mounted EBS volumes are always ok to allow", - }, - { - newPod: splitVolsPod, - existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(EBSVolumeFilterType)}, - filterName: EBSVolumeFilterType, - maxVols: 3, - fits: true, - test: "the same EBS volumes are not counted multiple times", - }, - { - newPod: onePVCPod(EBSVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, - filterName: EBSVolumeFilterType, - maxVols: 2, - fits: false, - test: "pod with missing PVC is counted towards the PV limit", - }, - { - newPod: onePVCPod(EBSVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, - filterName: EBSVolumeFilterType, - maxVols: 3, - fits: true, - test: "pod with missing PVC is counted towards the PV limit", - }, - { - newPod: onePVCPod(EBSVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod}, - filterName: EBSVolumeFilterType, - maxVols: 3, - fits: false, - test: "pod with missing two PVCs is counted towards the PV limit twice", - }, - { - newPod: onePVCPod(EBSVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: EBSVolumeFilterType, - maxVols: 2, - fits: false, - test: "pod with missing PV is counted towards the PV limit", - }, - { - newPod: onePVCPod(EBSVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: EBSVolumeFilterType, - maxVols: 3, - fits: true, - test: "pod with missing PV is counted towards the PV limit", - }, - { - newPod: deletedPVPod2, - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: EBSVolumeFilterType, - maxVols: 2, - fits: true, - test: "two pods missing the same PV are counted towards the PV limit only once", - }, - { - newPod: anotherDeletedPVPod, - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: EBSVolumeFilterType, - maxVols: 2, - fits: false, - test: "two pods missing different PVs are counted towards the PV limit twice", - }, - { - newPod: onePVCPod(EBSVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: EBSVolumeFilterType, - maxVols: 2, - fits: false, - test: "pod with unbound PVC is counted towards the PV limit", - }, - { - newPod: onePVCPod(EBSVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: EBSVolumeFilterType, - maxVols: 3, - fits: true, - test: "pod with unbound PVC is counted towards the PV limit", - }, - { - newPod: unboundPVCPod2, - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: EBSVolumeFilterType, - maxVols: 2, - fits: true, - test: "the same unbound PVC in multiple pods is counted towards the PV limit only once", - }, - { - newPod: anotherUnboundPVCPod, - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: EBSVolumeFilterType, - maxVols: 2, - fits: false, - test: "two different unbound PVCs are counted towards the PV limit as two volumes", - }, - // filterName:GCEPDVolumeFilterType - { - newPod: oneVolPod, - existingPods: []*v1.Pod{twoVolPod, oneVolPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 4, - fits: true, - test: "fits when node capacity >= new pod's GCE volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 2, - fits: true, - test: "fit when node capacity < new pod's GCE volumes", - }, - { - newPod: splitVolsPod, - existingPods: []*v1.Pod{twoVolPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 3, - fits: true, - test: "new pod's count ignores non-GCE volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 3, - fits: true, - test: "existing pods' counts ignore non-GCE volumes", - }, - { - newPod: onePVCPod(GCEPDVolumeFilterType), - existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 3, - fits: true, - test: "new pod's count considers PVCs backed by GCE volumes", - }, - { - newPod: splitPVCPod(GCEPDVolumeFilterType), - existingPods: []*v1.Pod{splitVolsPod, oneVolPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 3, - fits: true, - test: "new pod's count ignores PVCs not backed by GCE volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod, onePVCPod(GCEPDVolumeFilterType)}, - filterName: GCEPDVolumeFilterType, - maxVols: 3, - fits: true, - test: "existing pods' counts considers PVCs backed by GCE volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(GCEPDVolumeFilterType)}, - filterName: GCEPDVolumeFilterType, - maxVols: 4, - fits: true, - test: "already-mounted EBS volumes are always ok to allow", - }, - { - newPod: splitVolsPod, - existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(GCEPDVolumeFilterType)}, - filterName: GCEPDVolumeFilterType, - maxVols: 3, - fits: true, - test: "the same GCE volumes are not counted multiple times", - }, - { - newPod: onePVCPod(GCEPDVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 2, - fits: true, - test: "pod with missing PVC is counted towards the PV limit", - }, - { - newPod: onePVCPod(GCEPDVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 3, - fits: true, - test: "pod with missing PVC is counted towards the PV limit", - }, - { - newPod: onePVCPod(GCEPDVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 3, - fits: true, - test: "pod with missing two PVCs is counted towards the PV limit twice", - }, - { - newPod: onePVCPod(GCEPDVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 2, - fits: true, - test: "pod with missing PV is counted towards the PV limit", - }, - { - newPod: onePVCPod(GCEPDVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 3, - fits: true, - test: "pod with missing PV is counted towards the PV limit", - }, - { - newPod: deletedPVPod2, - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 2, - fits: true, - test: "two pods missing the same PV are counted towards the PV limit only once", - }, - { - newPod: anotherDeletedPVPod, - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 2, - fits: true, - test: "two pods missing different PVs are counted towards the PV limit twice", - }, - { - newPod: onePVCPod(GCEPDVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 2, - fits: true, - test: "pod with unbound PVC is counted towards the PV limit", - }, - { - newPod: onePVCPod(GCEPDVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 3, - fits: true, - test: "pod with unbound PVC is counted towards the PV limit", - }, - { - newPod: unboundPVCPod2, - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 2, - fits: true, - test: "the same unbound PVC in multiple pods is counted towards the PV limit only once", - }, - { - newPod: anotherUnboundPVCPod, - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: GCEPDVolumeFilterType, - maxVols: 2, - fits: true, - test: "two different unbound PVCs are counted towards the PV limit as two volumes", - }, - // filterName:AzureDiskVolumeFilterType - { - newPod: oneVolPod, - existingPods: []*v1.Pod{twoVolPod, oneVolPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 4, - fits: true, - test: "fits when node capacity >= new pod's AzureDisk volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 2, - fits: true, - test: "fit when node capacity < new pod's AzureDisk volumes", - }, - { - newPod: splitVolsPod, - existingPods: []*v1.Pod{twoVolPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 3, - fits: true, - test: "new pod's count ignores non-AzureDisk volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 3, - fits: true, - test: "existing pods' counts ignore non-AzureDisk volumes", - }, - { - newPod: onePVCPod(AzureDiskVolumeFilterType), - existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 3, - fits: true, - test: "new pod's count considers PVCs backed by AzureDisk volumes", - }, - { - newPod: splitPVCPod(AzureDiskVolumeFilterType), - existingPods: []*v1.Pod{splitVolsPod, oneVolPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 3, - fits: true, - test: "new pod's count ignores PVCs not backed by AzureDisk volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod, onePVCPod(AzureDiskVolumeFilterType)}, - filterName: AzureDiskVolumeFilterType, - maxVols: 3, - fits: true, - test: "existing pods' counts considers PVCs backed by AzureDisk volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(AzureDiskVolumeFilterType)}, - filterName: AzureDiskVolumeFilterType, - maxVols: 4, - fits: true, - test: "already-mounted AzureDisk volumes are always ok to allow", - }, - { - newPod: splitVolsPod, - existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(AzureDiskVolumeFilterType)}, - filterName: AzureDiskVolumeFilterType, - maxVols: 3, - fits: true, - test: "the same AzureDisk volumes are not counted multiple times", - }, - { - newPod: onePVCPod(AzureDiskVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 2, - fits: true, - test: "pod with missing PVC is counted towards the PV limit", - }, - { - newPod: onePVCPod(AzureDiskVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 3, - fits: true, - test: "pod with missing PVC is counted towards the PV limit", - }, - { - newPod: onePVCPod(AzureDiskVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 3, - fits: true, - test: "pod with missing two PVCs is counted towards the PV limit twice", - }, - { - newPod: onePVCPod(AzureDiskVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 2, - fits: true, - test: "pod with missing PV is counted towards the PV limit", - }, - { - newPod: onePVCPod(AzureDiskVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 3, - fits: true, - test: "pod with missing PV is counted towards the PV limit", - }, - { - newPod: deletedPVPod2, - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 2, - fits: true, - test: "two pods missing the same PV are counted towards the PV limit only once", - }, - { - newPod: anotherDeletedPVPod, - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 2, - fits: true, - test: "two pods missing different PVs are counted towards the PV limit twice", - }, - { - newPod: onePVCPod(AzureDiskVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 2, - fits: true, - test: "pod with unbound PVC is counted towards the PV limit", - }, - { - newPod: onePVCPod(AzureDiskVolumeFilterType), - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 3, - fits: true, - test: "pod with unbound PVC is counted towards the PV limit", - }, - { - newPod: unboundPVCPod2, - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 2, - fits: true, - test: "the same unbound PVC in multiple pods is counted towards the PV limit only once", - }, - { - newPod: anotherUnboundPVCPod, - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - filterName: AzureDiskVolumeFilterType, - maxVols: 2, - fits: true, - test: "two different unbound PVCs are counted towards the PV limit as two volumes", - }, - } - - pvInfo := func(filterName string) FakePersistentVolumeInfo { - return FakePersistentVolumeInfo{ - { - ObjectMeta: metav1.ObjectMeta{Name: "some" + filterName + "Vol"}, - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeSource: v1.PersistentVolumeSource{ - AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: strings.ToLower(filterName) + "Vol"}, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "someNon" + filterName + "Vol"}, - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeSource: v1.PersistentVolumeSource{}, - }, - }, - } - } - - pvcInfo := func(filterName string) FakePersistentVolumeClaimInfo { - return FakePersistentVolumeClaimInfo{ - { - ObjectMeta: metav1.ObjectMeta{Name: "some" + filterName + "Vol"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "some" + filterName + "Vol"}, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "someNon" + filterName + "Vol"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "someNon" + filterName + "Vol"}, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "pvcWithDeletedPV"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "pvcWithDeletedPV"}, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "anotherPVCWithDeletedPV"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "anotherPVCWithDeletedPV"}, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "unboundPVC"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: ""}, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "anotherUnboundPVC"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: ""}, - }, - } - } - - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrMaxVolumeCountExceeded} - - for _, test := range tests { - os.Setenv(KubeMaxPDVols, strconv.Itoa(test.maxVols)) - pred := NewMaxPDVolumeCountPredicate(test.filterName, pvInfo(test.filterName), pvcInfo(test.filterName)) - fits, reasons, err := pred(test.newPod, PredicateMetadata(test.newPod, nil), schedulercache.NewNodeInfo(test.existingPods...)) - if err != nil { - t.Errorf("[%s]%s: unexpected error: %v", test.filterName, test.test, err) - } - if !fits && !reflect.DeepEqual(reasons, expectedFailureReasons) { - t.Errorf("[%s]%s: unexpected failure reasons: %v, want: %v", test.filterName, test.test, reasons, expectedFailureReasons) - } - if fits != test.fits { - t.Errorf("[%s]%s: expected %v, got %v", test.filterName, test.test, test.fits, fits) - } - } -} - func newPodWithPort(hostPorts ...int) *v1.Pod { networkPorts := []v1.ContainerPort{} for _, port := range hostPorts { diff --git a/pkg/scheduler/algorithm/priorities/BUILD b/pkg/scheduler/algorithm/priorities/BUILD index b1b84bd57ee..cb8f0e5c0e0 100644 --- a/pkg/scheduler/algorithm/priorities/BUILD +++ b/pkg/scheduler/algorithm/priorities/BUILD @@ -19,6 +19,7 @@ go_library( "node_label.go", "node_prefer_avoid_pods.go", "reduce.go", + "requested_to_capacity_ratio.go", "resource_allocation.go", "resource_limits.go", "selector_spreading.go", @@ -33,8 +34,9 @@ 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/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/util/node:go_default_library", + "//pkg/util/parsers:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", @@ -58,6 +60,7 @@ go_test( "node_affinity_test.go", "node_label_test.go", "node_prefer_avoid_pods_test.go", + "requested_to_capacity_ratio_test.go", "resource_limits_test.go", "selector_spreading_test.go", "taint_toleration_test.go", @@ -68,8 +71,10 @@ go_test( "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/testing:go_default_library", + "//pkg/util/parsers:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", diff --git a/pkg/scheduler/algorithm/priorities/balanced_resource_allocation.go b/pkg/scheduler/algorithm/priorities/balanced_resource_allocation.go index 3d655bdbbba..ec36f1bf757 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) var ( diff --git a/pkg/scheduler/algorithm/priorities/balanced_resource_allocation_test.go b/pkg/scheduler/algorithm/priorities/balanced_resource_allocation_test.go index fae45b1a32c..ae7b601b84a 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 ( utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/features" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // getExistingVolumeCountForNode gets the current number of volumes on node. diff --git a/pkg/scheduler/algorithm/priorities/image_locality.go b/pkg/scheduler/algorithm/priorities/image_locality.go index 06e93c5e8f2..2d399469d61 100644 --- a/pkg/scheduler/algorithm/priorities/image_locality.go +++ b/pkg/scheduler/algorithm/priorities/image_locality.go @@ -18,10 +18,12 @@ package priorities import ( "fmt" + "strings" "k8s.io/api/core/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + "k8s.io/kubernetes/pkg/util/parsers" ) // This is a reasonable size range of all container images. 90%ile of images on dockerhub drops into this range. @@ -74,10 +76,22 @@ func totalImageSize(nodeInfo *schedulercache.NodeInfo, containers []v1.Container imageSizes := nodeInfo.ImageSizes() for _, container := range containers { - if size, ok := imageSizes[container.Image]; ok { + if size, ok := imageSizes[normalizedImageName(container.Image)]; ok { total += size } } return total } + +// normalizedImageName returns the CRI compliant name for a given image. +// TODO: cover the corner cases of missed matches, e.g, +// 1. Using Docker as runtime and docker.io/library/test:tag in pod spec, but only test:tag will present in node status +// 2. Using the implicit registry, i.e., test:tag or library/test:tag in pod spec but only docker.io/library/test:tag +// in node status; note that if users consistently use one registry format, this should not happen. +func normalizedImageName(name string) string { + if strings.LastIndex(name, ":") <= strings.LastIndex(name, "/") { + name = name + ":" + parsers.DefaultImageTag + } + return name +} diff --git a/pkg/scheduler/algorithm/priorities/image_locality_test.go b/pkg/scheduler/algorithm/priorities/image_locality_test.go index d62e1a6036b..a8f76a03d32 100644 --- a/pkg/scheduler/algorithm/priorities/image_locality_test.go +++ b/pkg/scheduler/algorithm/priorities/image_locality_test.go @@ -17,14 +17,17 @@ limitations under the License. package priorities import ( + "crypto/sha256" "reflect" "sort" "testing" + "encoding/hex" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + "k8s.io/kubernetes/pkg/util/parsers" ) func TestImageLocalityPriority(t *testing.T) { @@ -65,7 +68,7 @@ func TestImageLocalityPriority(t *testing.T) { Images: []v1.ContainerImage{ { Names: []string{ - "gcr.io/40", + "gcr.io/40:" + parsers.DefaultImageTag, "gcr.io/40:v1", "gcr.io/40:v1", }, @@ -73,14 +76,14 @@ func TestImageLocalityPriority(t *testing.T) { }, { Names: []string{ - "gcr.io/140", + "gcr.io/140:" + parsers.DefaultImageTag, "gcr.io/140:v1", }, SizeBytes: int64(140 * mb), }, { Names: []string{ - "gcr.io/2000", + "gcr.io/2000:" + parsers.DefaultImageTag, }, SizeBytes: int64(2000 * mb), }, @@ -91,13 +94,13 @@ func TestImageLocalityPriority(t *testing.T) { Images: []v1.ContainerImage{ { Names: []string{ - "gcr.io/250", + "gcr.io/250:" + parsers.DefaultImageTag, }, SizeBytes: int64(250 * mb), }, { Names: []string{ - "gcr.io/10", + "gcr.io/10:" + parsers.DefaultImageTag, "gcr.io/10:v1", }, SizeBytes: int64(10 * mb), @@ -116,11 +119,11 @@ func TestImageLocalityPriority(t *testing.T) { // Pod: gcr.io/40 gcr.io/250 // Node1 - // Image: gcr.io/40 40MB + // Image: gcr.io/40:latest 40MB // Score: (40M-23M)/97.7M + 1 = 1 // Node2 - // Image: gcr.io/250 250MB + // Image: gcr.io/250:latest 250MB // Score: (250M-23M)/97.7M + 1 = 3 pod: &v1.Pod{Spec: test40250}, nodes: []*v1.Node{makeImageNode("machine1", node401402000), makeImageNode("machine2", node25010)}, @@ -131,7 +134,7 @@ func TestImageLocalityPriority(t *testing.T) { // Pod: gcr.io/40 gcr.io/140 // Node1 - // Image: gcr.io/40 40MB, gcr.io/140 140MB + // Image: gcr.io/40:latest 40MB, gcr.io/140:latest 140MB // Score: (40M+140M-23M)/97.7M + 1 = 2 // Node2 @@ -146,11 +149,11 @@ func TestImageLocalityPriority(t *testing.T) { // Pod: gcr.io/2000 gcr.io/10 // Node1 - // Image: gcr.io/2000 2000MB + // Image: gcr.io/2000:latest 2000MB // Score: 2000 > max score = 10 // Node2 - // Image: gcr.io/10 10MB + // Image: gcr.io/10:latest 10MB // Score: 10 < min score = 0 pod: &v1.Pod{Spec: testMinMax}, nodes: []*v1.Node{makeImageNode("machine1", node401402000), makeImageNode("machine2", node25010)}, @@ -177,9 +180,31 @@ func TestImageLocalityPriority(t *testing.T) { } } +func TestNormalizedImageName(t *testing.T) { + for _, testCase := range []struct { + Input string + Output string + }{ + {Input: "root", Output: "root:latest"}, + {Input: "root:tag", Output: "root:tag"}, + {Input: "gcr.io:5000/root", Output: "gcr.io:5000/root:latest"}, + {Input: "root@" + getImageFakeDigest("root"), Output: "root@" + getImageFakeDigest("root")}, + } { + image := normalizedImageName(testCase.Input) + if image != testCase.Output { + t.Errorf("expected image reference: %q, got %q", testCase.Output, image) + } + } +} + func makeImageNode(node string, status v1.NodeStatus) *v1.Node { return &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: node}, Status: status, } } + +func getImageFakeDigest(fakeContent string) string { + hash := sha256.Sum256([]byte(fakeContent)) + return "sha256:" + hex.EncodeToString(hash[:]) +} diff --git a/pkg/scheduler/algorithm/priorities/interpod_affinity.go b/pkg/scheduler/algorithm/priorities/interpod_affinity.go index f3e9c9647b6..6aa5a3896dd 100644 --- a/pkg/scheduler/algorithm/priorities/interpod_affinity.go +++ b/pkg/scheduler/algorithm/priorities/interpod_affinity.go @@ -27,7 +27,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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "github.com/golang/glog" ) diff --git a/pkg/scheduler/algorithm/priorities/interpod_affinity_test.go b/pkg/scheduler/algorithm/priorities/interpod_affinity_test.go index 64f2792fe1e..7f86006d56a 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) diff --git a/pkg/scheduler/algorithm/priorities/least_requested.go b/pkg/scheduler/algorithm/priorities/least_requested.go index b6f096b033a..9f8b78dae64 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) var ( diff --git a/pkg/scheduler/algorithm/priorities/least_requested_test.go b/pkg/scheduler/algorithm/priorities/least_requested_test.go index c272fa34645..ca9d569bfc9 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestLeastRequested(t *testing.T) { diff --git a/pkg/scheduler/algorithm/priorities/metadata.go b/pkg/scheduler/algorithm/priorities/metadata.go index da88a9f3a36..3cb0f2f442a 100644 --- a/pkg/scheduler/algorithm/priorities/metadata.go +++ b/pkg/scheduler/algorithm/priorities/metadata.go @@ -22,7 +22,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/kubernetes/pkg/scheduler/algorithm" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // PriorityMetadataFactory is a factory to produce PriorityMetadata. diff --git a/pkg/scheduler/algorithm/priorities/metadata_test.go b/pkg/scheduler/algorithm/priorities/metadata_test.go index 996993702b5..19bde2d9b7c 100644 --- a/pkg/scheduler/algorithm/priorities/metadata_test.go +++ b/pkg/scheduler/algorithm/priorities/metadata_test.go @@ -26,7 +26,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) diff --git a/pkg/scheduler/algorithm/priorities/most_requested.go b/pkg/scheduler/algorithm/priorities/most_requested.go index 09fd7786d07..ea12e8ef897 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) var ( diff --git a/pkg/scheduler/algorithm/priorities/most_requested_test.go b/pkg/scheduler/algorithm/priorities/most_requested_test.go index aa7afb8a2eb..94262d32cbc 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestMostRequested(t *testing.T) { diff --git a/pkg/scheduler/algorithm/priorities/node_affinity.go b/pkg/scheduler/algorithm/priorities/node_affinity.go index 347f797d776..e274e170921 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // CalculateNodeAffinityPriorityMap prioritizes nodes according to node affinity scheduling preferences diff --git a/pkg/scheduler/algorithm/priorities/node_affinity_test.go b/pkg/scheduler/algorithm/priorities/node_affinity_test.go index 60e49d6fd3e..8ba1cb1e8c0 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestNodeAffinityPriority(t *testing.T) { diff --git a/pkg/scheduler/algorithm/priorities/node_label.go b/pkg/scheduler/algorithm/priorities/node_label.go index ae5d070a12c..82505f788ac 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // NodeLabelPrioritizer contains information to calculate node label priority. diff --git a/pkg/scheduler/algorithm/priorities/node_label_test.go b/pkg/scheduler/algorithm/priorities/node_label_test.go index 48fad6d2d3a..f713d02f34a 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestNewNodeLabelPriority(t *testing.T) { diff --git a/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go b/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go index da27daae8e0..282044de8d3 100644 --- a/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go +++ b/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go @@ -24,7 +24,7 @@ import ( v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // CalculateNodePreferAvoidPodsPriorityMap priorities nodes according to the node annotation 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 1586f393ef1..c9b8c9365e6 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestNodePreferAvoidPriority(t *testing.T) { diff --git a/pkg/scheduler/algorithm/priorities/reduce.go b/pkg/scheduler/algorithm/priorities/reduce.go index 608a83355e9..6a6a7427f1d 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // NormalizeReduce generates a PriorityReduceFunction that can normalize the result diff --git a/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio.go b/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio.go new file mode 100644 index 00000000000..a6ac7a837e8 --- /dev/null +++ b/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio.go @@ -0,0 +1,141 @@ +/* +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 + +import ( + "fmt" + + schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" +) + +// FunctionShape represents shape of scoring function. +// For safety use NewFunctionShape which performs precondition checks for struct creation. +type FunctionShape []FunctionShapePoint + +// FunctionShapePoint represents single point in scoring function shape. +type FunctionShapePoint struct { + // Utilization is function argument. + Utilization int64 + // Score is function value. + Score int64 +} + +var ( + // give priority to least utilized nodes by default + defaultFunctionShape, _ = NewFunctionShape([]FunctionShapePoint{{0, 10}, {100, 0}}) +) + +const ( + minUtilization = 0 + maxUtilization = 100 + minScore = 0 + maxScore = schedulerapi.MaxPriority +) + +// NewFunctionShape creates instance of FunctionShape in a safe way performing all +// necessary sanity checks. +func NewFunctionShape(points []FunctionShapePoint) (FunctionShape, error) { + + n := len(points) + + if n == 0 { + return nil, fmt.Errorf("at least one point must be specified") + } + + for i := 1; i < n; i++ { + if points[i-1].Utilization >= points[i].Utilization { + return nil, fmt.Errorf("utilization values must be sorted. Utilization[%d]==%d >= Utilization[%d]==%d", i-1, points[i-1].Utilization, i, points[i].Utilization) + } + } + + for i, point := range points { + if point.Utilization < minUtilization { + return nil, fmt.Errorf("utilization values must not be less than %d. Utilization[%d]==%d", minUtilization, i, point.Utilization) + } + if point.Utilization > maxUtilization { + return nil, fmt.Errorf("utilization values must not be greater than %d. Utilization[%d]==%d", maxUtilization, i, point.Utilization) + } + if point.Score < minScore { + return nil, fmt.Errorf("score values must not be less than %d. Score[%d]==%d", minScore, i, point.Score) + } + if point.Score > maxScore { + return nil, fmt.Errorf("score valuses not be greater than %d. Score[%d]==%d", maxScore, i, point.Score) + } + } + + // We make defensive copy so we make no assumption if array passed as argument is not changed afterwards + pointsCopy := make(FunctionShape, n) + copy(pointsCopy, points) + return pointsCopy, nil +} + +// RequestedToCapacityRatioResourceAllocationPriorityDefault creates a requestedToCapacity based +// ResourceAllocationPriority using default resource scoring function shape. +// The default function assigns 1.0 to resource when all capacity is available +// and 0.0 when requested amount is equal to capacity. +func RequestedToCapacityRatioResourceAllocationPriorityDefault() *ResourceAllocationPriority { + return RequestedToCapacityRatioResourceAllocationPriority(defaultFunctionShape) +} + +// RequestedToCapacityRatioResourceAllocationPriority creates a requestedToCapacity based +// ResourceAllocationPriority using provided resource scoring function shape. +func RequestedToCapacityRatioResourceAllocationPriority(scoringFunctionShape FunctionShape) *ResourceAllocationPriority { + return &ResourceAllocationPriority{"RequestedToCapacityRatioResourceAllocationPriority", buildRequestedToCapacityRatioScorerFunction(scoringFunctionShape)} +} + +func buildRequestedToCapacityRatioScorerFunction(scoringFunctionShape FunctionShape) func(*schedulercache.Resource, *schedulercache.Resource, bool, int, int) int64 { + rawScoringFunction := buildBrokenLinearFunction(scoringFunctionShape) + + resourceScoringFunction := func(requested, capacity int64) int64 { + if capacity == 0 || requested > capacity { + return rawScoringFunction(maxUtilization) + } + + return rawScoringFunction(maxUtilization - (capacity-requested)*maxUtilization/capacity) + } + + return func(requested, allocable *schedulercache.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { + cpuScore := resourceScoringFunction(requested.MilliCPU, allocable.MilliCPU) + memoryScore := resourceScoringFunction(requested.Memory, allocable.Memory) + return (cpuScore + memoryScore) / 2 + } +} + +// Creates a function which is built using linear segments. Segments are defined via shape array. +// Shape[i].Utilization slice represents points on "utilization" axis where different segments meet. +// Shape[i].Score represents function values at meeting points. +// +// function f(p) is defined as: +// shape[0].Score for p < f[0].Utilization +// shape[i].Score for p == shape[i].Utilization +// shape[n-1].Score for p > shape[n-1].Utilization +// and linear between points (p < shape[i].Utilization) +func buildBrokenLinearFunction(shape FunctionShape) func(int64) int64 { + n := len(shape) + return func(p int64) int64 { + for i := 0; i < n; i++ { + if p <= shape[i].Utilization { + if i == 0 { + return shape[0].Score + } + return shape[i-1].Score + (shape[i].Score-shape[i-1].Score)*(p-shape[i-1].Utilization)/(shape[i].Utilization-shape[i-1].Utilization) + } + } + return shape[n-1].Score + } +} diff --git a/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio_test.go b/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio_test.go new file mode 100644 index 00000000000..f9ecfbd6aea --- /dev/null +++ b/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio_test.go @@ -0,0 +1,241 @@ +/* +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 + +import ( + "reflect" + "sort" + "testing" + + "github.com/stretchr/testify/assert" + "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" +) + +func TestCreatingFunctionShapeErrorsIfEmptyPoints(t *testing.T) { + var err error + _, err = NewFunctionShape([]FunctionShapePoint{}) + assert.Equal(t, "at least one point must be specified", err.Error()) +} + +func TestCreatingFunctionShapeErrorsIfXIsNotSorted(t *testing.T) { + var err error + _, err = NewFunctionShape([]FunctionShapePoint{{10, 1}, {15, 2}, {20, 3}, {19, 4}, {25, 5}}) + assert.Equal(t, "utilization values must be sorted. Utilization[2]==20 >= Utilization[3]==19", err.Error()) + + _, err = NewFunctionShape([]FunctionShapePoint{{10, 1}, {20, 2}, {20, 3}, {22, 4}, {25, 5}}) + assert.Equal(t, "utilization values must be sorted. Utilization[1]==20 >= Utilization[2]==20", err.Error()) +} + +func TestCreatingFunctionPointNotInAllowedRange(t *testing.T) { + var err error + _, err = NewFunctionShape([]FunctionShapePoint{{-1, 0}, {100, 10}}) + assert.Equal(t, "utilization values must not be less than 0. Utilization[0]==-1", err.Error()) + + _, err = NewFunctionShape([]FunctionShapePoint{{0, 0}, {101, 10}}) + assert.Equal(t, "utilization values must not be greater than 100. Utilization[1]==101", err.Error()) + + _, err = NewFunctionShape([]FunctionShapePoint{{0, -1}, {100, 10}}) + assert.Equal(t, "score values must not be less than 0. Score[0]==-1", err.Error()) + + _, err = NewFunctionShape([]FunctionShapePoint{{0, 0}, {100, 11}}) + assert.Equal(t, "score valuses not be greater than 10. Score[1]==11", err.Error()) +} + +func TestBrokenLinearFunction(t *testing.T) { + type Assertion struct { + p int64 + expected int64 + } + type Test struct { + points []FunctionShapePoint + assertions []Assertion + } + + tests := []Test{ + { + points: []FunctionShapePoint{{10, 1}, {90, 9}}, + assertions: []Assertion{ + {p: -10, expected: 1}, + {p: 0, expected: 1}, + {p: 9, expected: 1}, + {p: 10, expected: 1}, + {p: 15, expected: 1}, + {p: 19, expected: 1}, + {p: 20, expected: 2}, + {p: 89, expected: 8}, + {p: 90, expected: 9}, + {p: 99, expected: 9}, + {p: 100, expected: 9}, + {p: 110, expected: 9}, + }, + }, + { + points: []FunctionShapePoint{{0, 2}, {40, 10}, {100, 0}}, + assertions: []Assertion{ + {p: -10, expected: 2}, + {p: 0, expected: 2}, + {p: 20, expected: 6}, + {p: 30, expected: 8}, + {p: 40, expected: 10}, + {p: 70, expected: 5}, + {p: 100, expected: 0}, + {p: 110, expected: 0}, + }, + }, + { + points: []FunctionShapePoint{{0, 2}, {40, 2}, {100, 2}}, + assertions: []Assertion{ + {p: -10, expected: 2}, + {p: 0, expected: 2}, + {p: 20, expected: 2}, + {p: 30, expected: 2}, + {p: 40, expected: 2}, + {p: 70, expected: 2}, + {p: 100, expected: 2}, + {p: 110, expected: 2}, + }, + }, + } + + for _, test := range tests { + functionShape, err := NewFunctionShape(test.points) + assert.Nil(t, err) + function := buildBrokenLinearFunction(functionShape) + for _, assertion := range test.assertions { + assert.InDelta(t, assertion.expected, function(assertion.p), 0.1, "points=%v, p=%f", test.points, assertion.p) + } + } +} + +func TestRequestedToCapacityRatio(t *testing.T) { + type resources struct { + cpu int64 + mem int64 + } + + type nodeResources struct { + capacity resources + used resources + } + + type test struct { + test string + requested resources + nodes map[string]nodeResources + expectedPriorities schedulerapi.HostPriorityList + } + + tests := []test{ + { + test: "nothing scheduled, nothing requested (default - least requested nodes have priority)", + requested: resources{0, 0}, + nodes: map[string]nodeResources{ + "node1": { + capacity: resources{4000, 10000}, + used: resources{0, 0}, + }, + "node2": { + capacity: resources{4000, 10000}, + used: resources{0, 0}, + }, + }, + expectedPriorities: []schedulerapi.HostPriority{{Host: "node1", Score: 10}, {Host: "node2", Score: 10}}, + }, + { + test: "nothing scheduled, resources requested, differently sized machines (default - least requested nodes have priority)", + requested: resources{3000, 5000}, + nodes: map[string]nodeResources{ + "node1": { + capacity: resources{4000, 10000}, + used: resources{0, 0}, + }, + "node2": { + capacity: resources{6000, 10000}, + used: resources{0, 0}, + }, + }, + expectedPriorities: []schedulerapi.HostPriority{{Host: "node1", Score: 4}, {Host: "node2", Score: 5}}, + }, + { + test: "no resources requested, pods scheduled with resources (default - least requested nodes have priority)", + requested: resources{0, 0}, + nodes: map[string]nodeResources{ + "node1": { + capacity: resources{4000, 10000}, + used: resources{3000, 5000}, + }, + "node2": { + capacity: resources{6000, 10000}, + used: resources{3000, 5000}, + }, + }, + expectedPriorities: []schedulerapi.HostPriority{{Host: "node1", Score: 4}, {Host: "node2", Score: 5}}, + }, + } + + buildResourcesPod := func(node string, requestedResources resources) *v1.Pod { + return &v1.Pod{Spec: v1.PodSpec{ + NodeName: node, + Containers: []v1.Container{ + { + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(requestedResources.cpu, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(requestedResources.mem, resource.DecimalSI), + }, + }, + }, + }, + }, + } + } + + for _, test := range tests { + + nodeNames := make([]string, 0) + for nodeName := range test.nodes { + nodeNames = append(nodeNames, nodeName) + } + sort.Strings(nodeNames) + + nodes := make([]*v1.Node, 0) + for _, nodeName := range nodeNames { + node := test.nodes[nodeName] + nodes = append(nodes, makeNode(nodeName, node.capacity.cpu, node.capacity.mem)) + } + + scheduledPods := make([]*v1.Pod, 0) + for name, node := range test.nodes { + scheduledPods = append(scheduledPods, + buildResourcesPod(name, node.used)) + } + + newPod := buildResourcesPod("", test.requested) + + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(scheduledPods, nodes) + list, err := priorityFunction(RequestedToCapacityRatioResourceAllocationPriorityDefault().PriorityMap, nil, nil)(newPod, nodeNameToInfo, nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(test.expectedPriorities, list) { + t.Errorf("%s: expected %#v, got %#v", test.test, test.expectedPriorities, list) + } + } +} diff --git a/pkg/scheduler/algorithm/priorities/resource_allocation.go b/pkg/scheduler/algorithm/priorities/resource_allocation.go index fc01dc11ea5..a3e329df04b 100644 --- a/pkg/scheduler/algorithm/priorities/resource_allocation.go +++ b/pkg/scheduler/algorithm/priorities/resource_allocation.go @@ -23,7 +23,7 @@ import ( "k8s.io/api/core/v1" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // ResourceAllocationPriority contains information to calculate resource allocation priority. diff --git a/pkg/scheduler/algorithm/priorities/resource_limits.go b/pkg/scheduler/algorithm/priorities/resource_limits.go index 5a02ff8dccf..165ac3e3e43 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "github.com/golang/glog" ) diff --git a/pkg/scheduler/algorithm/priorities/resource_limits_test.go b/pkg/scheduler/algorithm/priorities/resource_limits_test.go index bccfdd6161b..86ecd8cca95 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestResourceLimistPriority(t *testing.T) { diff --git a/pkg/scheduler/algorithm/priorities/selector_spreading.go b/pkg/scheduler/algorithm/priorities/selector_spreading.go index 8dd41251a8e..512ec08d7b4 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" utilnode "k8s.io/kubernetes/pkg/util/node" "github.com/golang/glog" diff --git a/pkg/scheduler/algorithm/priorities/selector_spreading_test.go b/pkg/scheduler/algorithm/priorities/selector_spreading_test.go index 71b440755fc..9f2b8dc0339 100644 --- a/pkg/scheduler/algorithm/priorities/selector_spreading_test.go +++ b/pkg/scheduler/algorithm/priorities/selector_spreading_test.go @@ -27,7 +27,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) diff --git a/pkg/scheduler/algorithm/priorities/taint_toleration.go b/pkg/scheduler/algorithm/priorities/taint_toleration.go index c6847c0ea1f..5790a4b091a 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // CountIntolerableTaintsPreferNoSchedule gives the count of intolerable taints of a pod with effect PreferNoSchedule diff --git a/pkg/scheduler/algorithm/priorities/taint_toleration_test.go b/pkg/scheduler/algorithm/priorities/taint_toleration_test.go index 83009c3701a..70b69aed6de 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func nodeWithTaints(nodeName string, taints []v1.Taint) *v1.Node { diff --git a/pkg/scheduler/algorithm/priorities/test_util.go b/pkg/scheduler/algorithm/priorities/test_util.go index d1756c0383c..74ffef34cfb 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func makeNode(node string, milliCPU, memory int64) *v1.Node { diff --git a/pkg/scheduler/algorithm/priorities/util/non_zero_test.go b/pkg/scheduler/algorithm/priorities/util/non_zero_test.go index 8be7e4ac94b..001b65ca195 100644 --- a/pkg/scheduler/algorithm/priorities/util/non_zero_test.go +++ b/pkg/scheduler/algorithm/priorities/util/non_zero_test.go @@ -26,7 +26,7 @@ import ( ) func TestGetNonzeroRequests(t *testing.T) { - tds := []struct { + tests := []struct { name string requests v1.ResourceList expectedCPU int64 @@ -65,9 +65,11 @@ func TestGetNonzeroRequests(t *testing.T) { }, } - for _, td := range tds { - realCPU, realMemory := GetNonzeroRequests(&td.requests) - assert.EqualValuesf(t, td.expectedCPU, realCPU, "Failed to test: %s", td.name) - assert.EqualValuesf(t, td.expectedMemory, realMemory, "Failed to test: %s", td.name) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + realCPU, realMemory := GetNonzeroRequests(&test.requests) + assert.EqualValuesf(t, test.expectedCPU, realCPU, "Failed to test: %s", test.name) + assert.EqualValuesf(t, test.expectedMemory, realMemory, "Failed to test: %s", test.name) + }) } } diff --git a/pkg/scheduler/algorithm/priorities/util/topologies_test.go b/pkg/scheduler/algorithm/priorities/util/topologies_test.go index 25e24299f87..6aee723e468 100644 --- a/pkg/scheduler/algorithm/priorities/util/topologies_test.go +++ b/pkg/scheduler/algorithm/priorities/util/topologies_test.go @@ -59,8 +59,10 @@ func TestGetNamespacesFromPodAffinityTerm(t *testing.T) { } for _, test := range tests { - realValue := GetNamespacesFromPodAffinityTerm(fakePod(), test.podAffinityTerm) - assert.EqualValuesf(t, test.expectedValue, realValue, "Failed to test: %s", test.name) + t.Run(test.name, func(t *testing.T) { + realValue := GetNamespacesFromPodAffinityTerm(fakePod(), test.podAffinityTerm) + assert.EqualValuesf(t, test.expectedValue, realValue, "Failed to test: %s", test.name) + }) } } @@ -96,12 +98,14 @@ func TestPodMatchesTermsNamespaceAndSelector(t *testing.T) { } for _, test := range tests { - fakeTestPod := fakePod() - fakeTestPod.Namespace = test.podNamespaces - fakeTestPod.Labels = test.podLabels + t.Run(test.name, func(t *testing.T) { + fakeTestPod := fakePod() + fakeTestPod.Namespace = test.podNamespaces + fakeTestPod.Labels = test.podLabels - realValue := PodMatchesTermsNamespaceAndSelector(fakeTestPod, fakeNamespaces, fakeSelector) - assert.EqualValuesf(t, test.expectedResult, realValue, "Faild to test: %s", test.name) + realValue := PodMatchesTermsNamespaceAndSelector(fakeTestPod, fakeNamespaces, fakeSelector) + assert.EqualValuesf(t, test.expectedResult, realValue, "Faild to test: %s", test.name) + }) } } @@ -248,7 +252,9 @@ func TestNodesHaveSameTopologyKey(t *testing.T) { } for _, test := range tests { - got := NodesHaveSameTopologyKey(test.nodeA, test.nodeB, test.topologyKey) - assert.Equalf(t, test.expected, got, "Failed to test: %s", test.name) + t.Run(test.name, func(t *testing.T) { + got := NodesHaveSameTopologyKey(test.nodeA, test.nodeB, test.topologyKey) + assert.Equalf(t, test.expected, got, "Failed to test: %s", test.name) + }) } } diff --git a/pkg/scheduler/algorithm/priorities/util/util_test.go b/pkg/scheduler/algorithm/priorities/util/util_test.go index fc79ebbfc4f..b4f0fc0aa52 100644 --- a/pkg/scheduler/algorithm/priorities/util/util_test.go +++ b/pkg/scheduler/algorithm/priorities/util/util_test.go @@ -109,11 +109,13 @@ func TestGetControllerRef(t *testing.T) { } for _, td := range tds { - realOR := GetControllerRef(&td.pod) - if td.expectedNil { - assert.Nilf(t, realOR, "Failed to test: %s", td.name) - } else { - assert.Equalf(t, &td.expectedOR, realOR, "Failed to test: %s", td.name) - } + t.Run(td.name, func(t *testing.T) { + realOR := GetControllerRef(&td.pod) + if td.expectedNil { + assert.Nilf(t, realOR, "Failed to test: %s", td.name) + } else { + assert.Equalf(t, &td.expectedOR, realOR, "Failed to test: %s", td.name) + } + }) } } diff --git a/pkg/scheduler/algorithm/scheduler_interface.go b/pkg/scheduler/algorithm/scheduler_interface.go index e43077151f9..ffa275d45f0 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // SchedulerExtender is an interface for external processes to influence scheduling diff --git a/pkg/scheduler/algorithm/types.go b/pkg/scheduler/algorithm/types.go index e0109d089a8..7bb5eecffc1 100644 --- a/pkg/scheduler/algorithm/types.go +++ b/pkg/scheduler/algorithm/types.go @@ -22,7 +22,7 @@ import ( extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/labels" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // NodeFieldSelectorKeys is a map that: the key are node field selector keys; the values are diff --git a/pkg/scheduler/algorithm/types_test.go b/pkg/scheduler/algorithm/types_test.go index 58ead064d99..e613c8c5028 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // EmptyPriorityMetadataProducer should returns a no-op PriorityMetadataProducer type. diff --git a/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go b/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go index 53a8071e8b1..06e793a518b 100644 --- a/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go +++ b/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go @@ -603,6 +603,103 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { }, }, }, + // Do not change this JSON after the corresponding release has been tagged. + // A failure indicates backwards compatibility with the specified release was broken. + "1.11": { + JSON: `{ + "kind": "Policy", + "apiVersion": "v1", + "predicates": [ + {"name": "MatchNodeSelector"}, + {"name": "PodFitsResources"}, + {"name": "PodFitsHostPorts"}, + {"name": "HostName"}, + {"name": "NoDiskConflict"}, + {"name": "NoVolumeZoneConflict"}, + {"name": "PodToleratesNodeTaints"}, + {"name": "CheckNodeMemoryPressure"}, + {"name": "CheckNodeDiskPressure"}, + {"name": "CheckNodePIDPressure"}, + {"name": "CheckNodeCondition"}, + {"name": "MaxEBSVolumeCount"}, + {"name": "MaxGCEPDVolumeCount"}, + {"name": "MaxAzureDiskVolumeCount"}, + {"name": "MatchInterPodAffinity"}, + {"name": "GeneralPredicates"}, + {"name": "CheckVolumeBinding"}, + {"name": "TestServiceAffinity", "argument": {"serviceAffinity" : {"labels" : ["region"]}}}, + {"name": "TestLabelsPresence", "argument": {"labelsPresence" : {"labels" : ["foo"], "presence":true}}} + ],"priorities": [ + {"name": "EqualPriority", "weight": 2}, + {"name": "ImageLocalityPriority", "weight": 2}, + {"name": "LeastRequestedPriority", "weight": 2}, + {"name": "BalancedResourceAllocation", "weight": 2}, + {"name": "SelectorSpreadPriority", "weight": 2}, + {"name": "NodePreferAvoidPodsPriority", "weight": 2}, + {"name": "NodeAffinityPriority", "weight": 2}, + {"name": "TaintTolerationPriority", "weight": 2}, + {"name": "InterPodAffinityPriority", "weight": 2}, + {"name": "MostRequestedPriority", "weight": 2}, + { + "name": "RequestedToCapacityRatioPriority", + "weight": 2, + "argument": { + "requestedToCapacityRatioArguments": { + "shape": [ + {"utilization": 0, "score": 0}, + {"utilization": 50, "score": 7} + ] + } + }} + ] + }`, + ExpectedPolicy: schedulerapi.Policy{ + Predicates: []schedulerapi.PredicatePolicy{ + {Name: "MatchNodeSelector"}, + {Name: "PodFitsResources"}, + {Name: "PodFitsHostPorts"}, + {Name: "HostName"}, + {Name: "NoDiskConflict"}, + {Name: "NoVolumeZoneConflict"}, + {Name: "PodToleratesNodeTaints"}, + {Name: "CheckNodeMemoryPressure"}, + {Name: "CheckNodeDiskPressure"}, + {Name: "CheckNodePIDPressure"}, + {Name: "CheckNodeCondition"}, + {Name: "MaxEBSVolumeCount"}, + {Name: "MaxGCEPDVolumeCount"}, + {Name: "MaxAzureDiskVolumeCount"}, + {Name: "MatchInterPodAffinity"}, + {Name: "GeneralPredicates"}, + {Name: "CheckVolumeBinding"}, + {Name: "TestServiceAffinity", Argument: &schedulerapi.PredicateArgument{ServiceAffinity: &schedulerapi.ServiceAffinity{Labels: []string{"region"}}}}, + {Name: "TestLabelsPresence", Argument: &schedulerapi.PredicateArgument{LabelsPresence: &schedulerapi.LabelsPresence{Labels: []string{"foo"}, Presence: true}}}, + }, + Priorities: []schedulerapi.PriorityPolicy{ + {Name: "EqualPriority", Weight: 2}, + {Name: "ImageLocalityPriority", Weight: 2}, + {Name: "LeastRequestedPriority", Weight: 2}, + {Name: "BalancedResourceAllocation", Weight: 2}, + {Name: "SelectorSpreadPriority", Weight: 2}, + {Name: "NodePreferAvoidPodsPriority", Weight: 2}, + {Name: "NodeAffinityPriority", Weight: 2}, + {Name: "TaintTolerationPriority", Weight: 2}, + {Name: "InterPodAffinityPriority", Weight: 2}, + {Name: "MostRequestedPriority", Weight: 2}, + { + Name: "RequestedToCapacityRatioPriority", + Weight: 2, + Argument: &schedulerapi.PriorityArgument{ + RequestedToCapacityRatioArguments: &schedulerapi.RequestedToCapacityRatioArguments{ + UtilizationShape: []schedulerapi.UtilizationShapePoint{ + {Utilization: 0, Score: 0}, + {Utilization: 50, Score: 7}, + }}, + }, + }, + }, + }, + }, } registeredPredicates := sets.NewString(factory.ListRegisteredFitPredicates()...) diff --git a/pkg/scheduler/algorithmprovider/defaults/defaults.go b/pkg/scheduler/algorithmprovider/defaults/defaults.go index 267e5d6ba5f..94d73b7e7fa 100644 --- a/pkg/scheduler/algorithmprovider/defaults/defaults.go +++ b/pkg/scheduler/algorithmprovider/defaults/defaults.go @@ -56,7 +56,7 @@ func init() { // 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 his + // 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. @@ -100,6 +100,11 @@ func init() { factory.RegisterPriorityFunction2("ImageLocalityPriority", priorities.ImageLocalityPriorityMap, 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 { diff --git a/pkg/scheduler/api/types.go b/pkg/scheduler/api/types.go index 8ce5d205bb3..4964349ade2 100644 --- a/pkg/scheduler/api/types.go +++ b/pkg/scheduler/api/types.go @@ -109,6 +109,8 @@ type PriorityArgument struct { // The priority function that checks whether a particular node has a certain label // defined or not, regardless of value LabelPreference *LabelPreference + // The RequestedToCapacityRatio priority function is parametrized with function shape. + RequestedToCapacityRatioArguments *RequestedToCapacityRatioArguments } // ServiceAffinity holds the parameters that are used to configure the corresponding predicate in scheduler policy configuration. @@ -143,6 +145,20 @@ type LabelPreference struct { Presence bool } +// RequestedToCapacityRatioArguments holds arguments specific to RequestedToCapacityRatio priority function +type RequestedToCapacityRatioArguments struct { + // Array of point defining priority function shape + UtilizationShape []UtilizationShapePoint +} + +// UtilizationShapePoint represents single point of priority function shape +type UtilizationShapePoint struct { + // Utilization (x axis). Valid values are 0 to 100. Fully utilized node maps to 100. + Utilization int + // Score assigned to given utilization (y axis). Valid values are 0 to 10. + Score int +} + // ExtenderManagedResource describes the arguments of extended resources // managed by an extender. type ExtenderManagedResource struct { diff --git a/pkg/scheduler/api/v1/types.go b/pkg/scheduler/api/v1/types.go index 21412c3ea1e..4058d068893 100644 --- a/pkg/scheduler/api/v1/types.go +++ b/pkg/scheduler/api/v1/types.go @@ -91,6 +91,8 @@ type PriorityArgument struct { // The priority function that checks whether a particular node has a certain label // defined or not, regardless of value LabelPreference *LabelPreference `json:"labelPreference"` + // The RequestedToCapacityRatio priority function is parametrized with function shape. + RequestedToCapacityRatioArguments *RequestedToCapacityRatioArguments `json:"requestedToCapacityRatioArguments"` } // ServiceAffinity holds the parameters that are used to configure the corresponding predicate in scheduler policy configuration. @@ -125,6 +127,20 @@ type LabelPreference struct { Presence bool `json:"presence"` } +// RequestedToCapacityRatioArguments holds arguments specific to RequestedToCapacityRatio priority function +type RequestedToCapacityRatioArguments struct { + // Array of point defining priority function shape + UtilizationShape []UtilizationShapePoint `json:"shape"` +} + +// UtilizationShapePoint represents single point of priority function shape +type UtilizationShapePoint struct { + // Utilization (x axis). Valid values are 0 to 100. Fully utilized node maps to 100. + Utilization int `json:"utilization"` + // Score assigned to given utilization (y axis). Valid values are 0 to 10. + Score int `json:"score"` +} + // ExtenderManagedResource describes the arguments of extended resources // managed by an extender. type ExtenderManagedResource struct { diff --git a/pkg/scheduler/api/v1/zz_generated.deepcopy.go b/pkg/scheduler/api/v1/zz_generated.deepcopy.go index 130637cc038..cbe8dc90c48 100644 --- a/pkg/scheduler/api/v1/zz_generated.deepcopy.go +++ b/pkg/scheduler/api/v1/zz_generated.deepcopy.go @@ -538,6 +538,15 @@ func (in *PriorityArgument) DeepCopyInto(out *PriorityArgument) { **out = **in } } + if in.RequestedToCapacityRatioArguments != nil { + in, out := &in.RequestedToCapacityRatioArguments, &out.RequestedToCapacityRatioArguments + if *in == nil { + *out = nil + } else { + *out = new(RequestedToCapacityRatioArguments) + (*in).DeepCopyInto(*out) + } + } return } @@ -576,6 +585,27 @@ func (in *PriorityPolicy) DeepCopy() *PriorityPolicy { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RequestedToCapacityRatioArguments) DeepCopyInto(out *RequestedToCapacityRatioArguments) { + *out = *in + if in.UtilizationShape != nil { + in, out := &in.UtilizationShape, &out.UtilizationShape + *out = make([]UtilizationShapePoint, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestedToCapacityRatioArguments. +func (in *RequestedToCapacityRatioArguments) DeepCopy() *RequestedToCapacityRatioArguments { + if in == nil { + return nil + } + out := new(RequestedToCapacityRatioArguments) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceAffinity) DeepCopyInto(out *ServiceAffinity) { *out = *in @@ -613,6 +643,22 @@ func (in *ServiceAntiAffinity) DeepCopy() *ServiceAntiAffinity { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UtilizationShapePoint) DeepCopyInto(out *UtilizationShapePoint) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UtilizationShapePoint. +func (in *UtilizationShapePoint) DeepCopy() *UtilizationShapePoint { + if in == nil { + return nil + } + out := new(UtilizationShapePoint) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Victims) DeepCopyInto(out *Victims) { *out = *in diff --git a/pkg/scheduler/api/zz_generated.deepcopy.go b/pkg/scheduler/api/zz_generated.deepcopy.go index 78396741f02..d8654dd27ae 100644 --- a/pkg/scheduler/api/zz_generated.deepcopy.go +++ b/pkg/scheduler/api/zz_generated.deepcopy.go @@ -538,6 +538,15 @@ func (in *PriorityArgument) DeepCopyInto(out *PriorityArgument) { **out = **in } } + if in.RequestedToCapacityRatioArguments != nil { + in, out := &in.RequestedToCapacityRatioArguments, &out.RequestedToCapacityRatioArguments + if *in == nil { + *out = nil + } else { + *out = new(RequestedToCapacityRatioArguments) + (*in).DeepCopyInto(*out) + } + } return } @@ -576,6 +585,27 @@ func (in *PriorityPolicy) DeepCopy() *PriorityPolicy { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RequestedToCapacityRatioArguments) DeepCopyInto(out *RequestedToCapacityRatioArguments) { + *out = *in + if in.UtilizationShape != nil { + in, out := &in.UtilizationShape, &out.UtilizationShape + *out = make([]UtilizationShapePoint, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestedToCapacityRatioArguments. +func (in *RequestedToCapacityRatioArguments) DeepCopy() *RequestedToCapacityRatioArguments { + if in == nil { + return nil + } + out := new(RequestedToCapacityRatioArguments) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceAffinity) DeepCopyInto(out *ServiceAffinity) { *out = *in @@ -613,6 +643,22 @@ func (in *ServiceAntiAffinity) DeepCopy() *ServiceAntiAffinity { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UtilizationShapePoint) DeepCopyInto(out *UtilizationShapePoint) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UtilizationShapePoint. +func (in *UtilizationShapePoint) DeepCopy() *UtilizationShapePoint { + if in == nil { + return nil + } + out := new(UtilizationShapePoint) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Victims) DeepCopyInto(out *Victims) { *out = *in diff --git a/pkg/scheduler/schedulercache/BUILD b/pkg/scheduler/cache/BUILD similarity index 95% rename from pkg/scheduler/schedulercache/BUILD rename to pkg/scheduler/cache/BUILD index 28ca09987f4..eece6843d98 100644 --- a/pkg/scheduler/schedulercache/BUILD +++ b/pkg/scheduler/cache/BUILD @@ -8,7 +8,7 @@ go_library( "node_info.go", "util.go", ], - importpath = "k8s.io/kubernetes/pkg/scheduler/schedulercache", + importpath = "k8s.io/kubernetes/pkg/scheduler/cache", visibility = ["//visibility:public"], deps = [ "//pkg/apis/core/v1/helper:go_default_library", @@ -36,6 +36,7 @@ go_test( "//pkg/features:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", "//pkg/scheduler/util:go_default_library", + "//pkg/util/parsers:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", diff --git a/pkg/scheduler/schedulercache/cache.go b/pkg/scheduler/cache/cache.go similarity index 99% rename from pkg/scheduler/schedulercache/cache.go rename to pkg/scheduler/cache/cache.go index 483558ed1d8..38e26f51bfd 100644 --- a/pkg/scheduler/schedulercache/cache.go +++ b/pkg/scheduler/cache/cache.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package schedulercache +package cache import ( "fmt" diff --git a/pkg/scheduler/schedulercache/cache_test.go b/pkg/scheduler/cache/cache_test.go similarity index 99% rename from pkg/scheduler/schedulercache/cache_test.go rename to pkg/scheduler/cache/cache_test.go index f3a560155ac..59721137788 100644 --- a/pkg/scheduler/schedulercache/cache_test.go +++ b/pkg/scheduler/cache/cache_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package schedulercache +package cache import ( "fmt" diff --git a/pkg/scheduler/schedulercache/interface.go b/pkg/scheduler/cache/interface.go similarity index 99% rename from pkg/scheduler/schedulercache/interface.go rename to pkg/scheduler/cache/interface.go index 475d40fe6ad..336688470c1 100644 --- a/pkg/scheduler/schedulercache/interface.go +++ b/pkg/scheduler/cache/interface.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package schedulercache +package cache import ( "k8s.io/api/core/v1" diff --git a/pkg/scheduler/schedulercache/node_info.go b/pkg/scheduler/cache/node_info.go similarity index 98% rename from pkg/scheduler/schedulercache/node_info.go rename to pkg/scheduler/cache/node_info.go index 3fbcbce8ea1..1479e81c554 100644 --- a/pkg/scheduler/schedulercache/node_info.go +++ b/pkg/scheduler/cache/node_info.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package schedulercache +package cache import ( "errors" @@ -412,6 +412,17 @@ func (n *NodeInfo) Clone() *NodeInfo { return clone } +// VolumeLimits returns volume limits associated with the node +func (n *NodeInfo) VolumeLimits() map[v1.ResourceName]int64 { + volumeLimits := map[v1.ResourceName]int64{} + for k, v := range n.AllocatableResource().ScalarResources { + if v1helper.IsAttachableVolumeResourceName(k) { + volumeLimits[k] = v + } + } + return volumeLimits +} + // String returns representation of human readable format of this NodeInfo. func (n *NodeInfo) String() string { podKeys := make([]string, len(n.pods)) diff --git a/pkg/scheduler/schedulercache/node_info_test.go b/pkg/scheduler/cache/node_info_test.go similarity index 97% rename from pkg/scheduler/schedulercache/node_info_test.go rename to pkg/scheduler/cache/node_info_test.go index 34214d9ef00..4c20f57b1ef 100644 --- a/pkg/scheduler/schedulercache/node_info_test.go +++ b/pkg/scheduler/cache/node_info_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package schedulercache +package cache import ( "fmt" @@ -26,6 +26,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/scheduler/util" + "k8s.io/kubernetes/pkg/util/parsers" ) func TestNewResource(t *testing.T) { @@ -84,7 +85,11 @@ func TestResourceList(t *testing.T) { Memory: 2000, EphemeralStorage: 5000, AllowedPodNumber: 80, - ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 1, "hugepages-test": 2}, + ScalarResources: map[v1.ResourceName]int64{ + "scalar.test/scalar1": 1, + "hugepages-test": 2, + "attachable-volumes-aws-ebs": 39, + }, }, expected: map[v1.ResourceName]resource.Quantity{ v1.ResourceCPU: *resource.NewScaledQuantity(4, -3), @@ -92,6 +97,7 @@ func TestResourceList(t *testing.T) { v1.ResourcePods: *resource.NewQuantity(80, resource.BinarySI), v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), "scalar.test/" + "scalar1": *resource.NewQuantity(1, resource.DecimalSI), + "attachable-volumes-aws-ebs": *resource.NewQuantity(39, resource.DecimalSI), v1.ResourceHugePagesPrefix + "test": *resource.NewQuantity(2, resource.BinarySI), }, }, @@ -245,14 +251,14 @@ func TestImageSizes(t *testing.T) { Images: []v1.ContainerImage{ { Names: []string{ - "gcr.io/10", + "gcr.io/10:" + parsers.DefaultImageTag, "gcr.io/10:v1", }, SizeBytes: int64(10 * 1024 * 1024), }, { Names: []string{ - "gcr.io/50", + "gcr.io/50:" + parsers.DefaultImageTag, "gcr.io/50:v1", }, SizeBytes: int64(50 * 1024 * 1024), @@ -263,10 +269,10 @@ func TestImageSizes(t *testing.T) { ni.updateImageSizes() expected := map[string]int64{ - "gcr.io/10": 10 * 1024 * 1024, - "gcr.io/10:v1": 10 * 1024 * 1024, - "gcr.io/50": 50 * 1024 * 1024, - "gcr.io/50:v1": 50 * 1024 * 1024, + "gcr.io/10:" + parsers.DefaultImageTag: 10 * 1024 * 1024, + "gcr.io/10:v1": 10 * 1024 * 1024, + "gcr.io/50:" + parsers.DefaultImageTag: 50 * 1024 * 1024, + "gcr.io/50:v1": 50 * 1024 * 1024, } imageSizes := ni.ImageSizes() diff --git a/pkg/scheduler/schedulercache/util.go b/pkg/scheduler/cache/util.go similarity index 98% rename from pkg/scheduler/schedulercache/util.go rename to pkg/scheduler/cache/util.go index e2ac2d90777..c3037dcc3d3 100644 --- a/pkg/scheduler/schedulercache/util.go +++ b/pkg/scheduler/cache/util.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package schedulercache +package cache import "k8s.io/api/core/v1" diff --git a/pkg/scheduler/core/BUILD b/pkg/scheduler/core/BUILD index 8068659c199..0e8cd4177c2 100644 --- a/pkg/scheduler/core/BUILD +++ b/pkg/scheduler/core/BUILD @@ -21,7 +21,7 @@ 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/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/testing:go_default_library", "//pkg/scheduler/util:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", @@ -50,8 +50,8 @@ 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/metrics:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//pkg/util/hash:go_default_library", diff --git a/pkg/scheduler/core/equivalence_cache.go b/pkg/scheduler/core/equivalence_cache.go index da50d2a81f7..c845ddbdde6 100644 --- a/pkg/scheduler/core/equivalence_cache.go +++ b/pkg/scheduler/core/equivalence_cache.go @@ -25,28 +25,36 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" hashutil "k8s.io/kubernetes/pkg/util/hash" "github.com/golang/glog" ) -// EquivalenceCache holds: -// 1. a map of AlgorithmCache with node name as key -// 2. function to get equivalence pod +// EquivalenceCache 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 node name, predicate name, and "equivalence +// class". (Equivalence class is defined in the `EquivalenceClassInfo` type.) +// Saved results will be reused until an appropriate invalidation function is +// called. type EquivalenceCache struct { - mu sync.RWMutex - algorithmCache map[string]AlgorithmCache + mu sync.RWMutex + cache nodeMap } -// The AlgorithmCache stores PredicateMap with predicate name as key, PredicateMap as value. -type AlgorithmCache map[string]PredicateMap +// nodeMap stores PredicateCaches with node name as the key. +type nodeMap map[string]predicateMap -// PredicateMap stores HostPrediacte with equivalence hash as key -type PredicateMap map[uint64]HostPredicate +// predicateMap stores resultMaps with predicate name as the key. +type predicateMap map[string]resultMap -// HostPredicate is the cached predicate result -type HostPredicate struct { +// 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 } @@ -55,12 +63,12 @@ type HostPredicate struct { // result from previous scheduling. func NewEquivalenceCache() *EquivalenceCache { return &EquivalenceCache{ - algorithmCache: make(map[string]AlgorithmCache), + cache: make(nodeMap), } } -// RunPredicate will return a cached predicate result. In case of a cache miss, the predicate will -// be run and its results cached for the next call. +// 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 the given NodeInfo is stale. func (ec *EquivalenceCache) RunPredicate( @@ -69,7 +77,7 @@ func (ec *EquivalenceCache) RunPredicate( pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo, - equivClassInfo *equivalenceClassInfo, + equivClassInfo *EquivalenceClassInfo, cache schedulercache.Cache, ) (bool, []algorithm.PredicateFailureReason, error) { if nodeInfo == nil || nodeInfo.Node() == nil { @@ -77,9 +85,9 @@ func (ec *EquivalenceCache) RunPredicate( return false, []algorithm.PredicateFailureReason{}, fmt.Errorf("nodeInfo is nil or node is invalid") } - fit, reasons, invalid := ec.lookupResult(pod.GetName(), nodeInfo.Node().GetName(), predicateKey, equivClassInfo.hash) - if !invalid { - return fit, reasons, nil + result, ok := ec.lookupResult(pod.GetName(), nodeInfo.Node().GetName(), predicateKey, equivClassInfo.hash) + if ok { + return result.Fit, result.FailReasons, nil } fit, reasons, err := pred(pod, meta, nodeInfo) if err != nil { @@ -111,90 +119,84 @@ func (ec *EquivalenceCache) updateResult( return } nodeName := nodeInfo.Node().GetName() - if _, exist := ec.algorithmCache[nodeName]; !exist { - ec.algorithmCache[nodeName] = AlgorithmCache{} + if _, exist := ec.cache[nodeName]; !exist { + ec.cache[nodeName] = make(predicateMap) } - predicateItem := HostPredicate{ + predicateItem := predicateResult{ Fit: fit, FailReasons: reasons, } // if cached predicate map already exists, just update the predicate by key - if predicateMap, ok := ec.algorithmCache[nodeName][predicateKey]; ok { + if predicates, ok := ec.cache[nodeName][predicateKey]; ok { // maps in golang are references, no need to add them back - predicateMap[equivalenceHash] = predicateItem + predicates[equivalenceHash] = predicateItem } else { - ec.algorithmCache[nodeName][predicateKey] = - PredicateMap{ + ec.cache[nodeName][predicateKey] = + resultMap{ equivalenceHash: predicateItem, } } glog.V(5).Infof("Updated cached predicate: %v for pod: %v on node: %s, with item %v", predicateKey, podName, nodeName, predicateItem) } -// lookupResult returns cached predicate results: -// 1. if pod fit -// 2. reasons if pod did not fit -// 3. if cache item is not found +// lookupResult returns cached predicate results and a bool saying whether a +// cache entry was found. func (ec *EquivalenceCache) lookupResult( podName, nodeName, predicateKey string, equivalenceHash uint64, -) (bool, []algorithm.PredicateFailureReason, bool) { +) (value predicateResult, ok bool) { ec.mu.RLock() defer ec.mu.RUnlock() glog.V(5).Infof("Begin to calculate predicate: %v for pod: %s on node: %s based on equivalence cache", predicateKey, podName, nodeName) - if hostPredicate, exist := ec.algorithmCache[nodeName][predicateKey][equivalenceHash]; exist { - if hostPredicate.Fit { - return true, []algorithm.PredicateFailureReason{}, false - } - return false, hostPredicate.FailReasons, false - } - // is invalid - return false, []algorithm.PredicateFailureReason{}, true + value, ok = ec.cache[nodeName][predicateKey][equivalenceHash] + return value, ok } -// InvalidateCachedPredicateItem marks all items of given predicateKeys, of all pods, on the given node as invalid -func (ec *EquivalenceCache) InvalidateCachedPredicateItem(nodeName string, predicateKeys sets.String) { +// InvalidatePredicates clears all cached results for the given predicates. +func (ec *EquivalenceCache) InvalidatePredicates(predicateKeys sets.String) { + if len(predicateKeys) == 0 { + return + } + ec.mu.Lock() + defer ec.mu.Unlock() + // ec.cache uses nodeName as key, so we just iterate it and invalid given predicates + for _, predicates := range ec.cache { + for predicateKey := range predicateKeys { + delete(predicates, predicateKey) + } + } + glog.V(5).Infof("Done invalidating cached predicates: %v on all node", predicateKeys) +} + +// InvalidatePredicatesOnNode clears cached results for the given predicates on one node. +func (ec *EquivalenceCache) InvalidatePredicatesOnNode(nodeName string, predicateKeys sets.String) { if len(predicateKeys) == 0 { return } ec.mu.Lock() defer ec.mu.Unlock() for predicateKey := range predicateKeys { - delete(ec.algorithmCache[nodeName], predicateKey) + delete(ec.cache[nodeName], predicateKey) } glog.V(5).Infof("Done invalidating cached predicates: %v on node: %s", predicateKeys, nodeName) } -// InvalidateCachedPredicateItemOfAllNodes marks all items of given predicateKeys, of all pods, on all node as invalid -func (ec *EquivalenceCache) InvalidateCachedPredicateItemOfAllNodes(predicateKeys sets.String) { - if len(predicateKeys) == 0 { - return - } +// InvalidateAllPredicatesOnNode clears all cached results for one node. +func (ec *EquivalenceCache) InvalidateAllPredicatesOnNode(nodeName string) { ec.mu.Lock() defer ec.mu.Unlock() - // algorithmCache uses nodeName as key, so we just iterate it and invalid given predicates - for _, algorithmCache := range ec.algorithmCache { - for predicateKey := range predicateKeys { - delete(algorithmCache, predicateKey) - } - } - glog.V(5).Infof("Done invalidating cached predicates: %v on all node", predicateKeys) -} - -// InvalidateAllCachedPredicateItemOfNode marks all cached items on given node as invalid -func (ec *EquivalenceCache) InvalidateAllCachedPredicateItemOfNode(nodeName string) { - ec.mu.Lock() - defer ec.mu.Unlock() - delete(ec.algorithmCache, nodeName) + delete(ec.cache, nodeName) glog.V(5).Infof("Done invalidating all cached predicates on node: %s", nodeName) } -// InvalidateCachedPredicateItemForPodAdd is a wrapper of InvalidateCachedPredicateItem for pod add case +// InvalidateCachedPredicateItemForPodAdd is a wrapper of +// InvalidateCachedPredicateItem for pod add case +// TODO: This logic does not belong with the equivalence cache implementation. func (ec *EquivalenceCache) 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. + // 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) @@ -224,25 +226,26 @@ func (ec *EquivalenceCache) InvalidateCachedPredicateItemForPodAdd(pod *v1.Pod, } } } - ec.InvalidateCachedPredicateItem(nodeName, invalidPredicates) + ec.InvalidatePredicatesOnNode(nodeName, invalidPredicates) } -// equivalenceClassInfo holds equivalence hash which is used for checking equivalence cache. -// We will pass this to podFitsOnNode to ensure equivalence hash is only calculated per schedule. -type equivalenceClassInfo struct { +// EquivalenceClassInfo holds equivalence hash which is used for checking +// equivalence cache. We will pass this to podFitsOnNode to ensure equivalence +// hash is only calculated per schedule. +type EquivalenceClassInfo struct { // Equivalence hash. hash uint64 } -// getEquivalenceClassInfo returns a hash of the given pod. -// The hashing function returns the same value for any two pods that are -// equivalent from the perspective of scheduling. -func (ec *EquivalenceCache) getEquivalenceClassInfo(pod *v1.Pod) *equivalenceClassInfo { - equivalencePod := getEquivalenceHash(pod) +// GetEquivalenceClassInfo returns a hash of the given pod. The hashing function +// returns the same value for any two pods that are equivalent from the +// perspective of scheduling. +func (ec *EquivalenceCache) GetEquivalenceClassInfo(pod *v1.Pod) *EquivalenceClassInfo { + equivalencePod := getEquivalencePod(pod) if equivalencePod != nil { hash := fnv.New32a() hashutil.DeepHashObject(hash, equivalencePod) - return &equivalenceClassInfo{ + return &EquivalenceClassInfo{ hash: uint64(hash.Sum32()), } } @@ -254,9 +257,9 @@ func (ec *EquivalenceCache) getEquivalenceClassInfo(pod *v1.Pod) *equivalenceCla // 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. +// 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 @@ -269,8 +272,9 @@ type equivalencePod struct { Volumes []v1.Volume // See note about ordering } -// getEquivalenceHash returns the equivalencePod for a Pod. -func getEquivalenceHash(pod *v1.Pod) *equivalencePod { +// 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, diff --git a/pkg/scheduler/core/equivalence_cache_test.go b/pkg/scheduler/core/equivalence_cache_test.go index 412e258510b..7df8097a170 100644 --- a/pkg/scheduler/core/equivalence_cache_test.go +++ b/pkg/scheduler/core/equivalence_cache_test.go @@ -30,7 +30,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -251,7 +251,7 @@ func TestRunPredicate(t *testing.T) { meta := algorithm.EmptyPredicateMetadataProducer(nil, nil) ecache := NewEquivalenceCache() - equivClass := ecache.getEquivalenceClassInfo(pod) + equivClass := ecache.GetEquivalenceClassInfo(pod) if test.expectCacheHit { ecache.updateResult(pod.Name, "testPredicate", test.expectFit, test.expectedReasons, equivClass.hash, test.cache, node) } @@ -287,14 +287,14 @@ func TestRunPredicate(t *testing.T) { if !test.expectCacheHit && test.pred.callCount == 0 { t.Errorf("Predicate should be called") } - _, _, invalid := ecache.lookupResult(pod.Name, node.Node().Name, "testPredicate", equivClass.hash) - if invalid && test.expectCacheWrite { + _, ok := ecache.lookupResult(pod.Name, node.Node().Name, "testPredicate", equivClass.hash) + if !ok && test.expectCacheWrite { t.Errorf("Cache write should happen") } - if !test.expectCacheHit && test.expectCacheWrite && invalid { + if !test.expectCacheHit && test.expectCacheWrite && !ok { t.Errorf("Cache write should happen") } - if !test.expectCacheHit && !test.expectCacheWrite && !invalid { + if !test.expectCacheHit && !test.expectCacheWrite && ok { t.Errorf("Cache write should not happen") } }) @@ -311,7 +311,7 @@ func TestUpdateResult(t *testing.T) { reasons []algorithm.PredicateFailureReason equivalenceHash uint64 expectPredicateMap bool - expectCacheItem HostPredicate + expectCacheItem predicateResult cache schedulercache.Cache }{ { @@ -322,7 +322,7 @@ func TestUpdateResult(t *testing.T) { fit: true, equivalenceHash: 123, expectPredicateMap: false, - expectCacheItem: HostPredicate{ + expectCacheItem: predicateResult{ Fit: true, }, cache: &upToDateCache{}, @@ -335,7 +335,7 @@ func TestUpdateResult(t *testing.T) { fit: false, equivalenceHash: 123, expectPredicateMap: true, - expectCacheItem: HostPredicate{ + expectCacheItem: predicateResult{ Fit: false, }, cache: &upToDateCache{}, @@ -344,12 +344,12 @@ func TestUpdateResult(t *testing.T) { for _, test := range tests { ecache := NewEquivalenceCache() if test.expectPredicateMap { - ecache.algorithmCache[test.nodeName] = AlgorithmCache{} - predicateItem := HostPredicate{ + ecache.cache[test.nodeName] = make(predicateMap) + predicateItem := predicateResult{ Fit: true, } - ecache.algorithmCache[test.nodeName][test.predicateKey] = - PredicateMap{ + ecache.cache[test.nodeName][test.predicateKey] = + resultMap{ test.equivalenceHash: predicateItem, } } @@ -366,7 +366,7 @@ func TestUpdateResult(t *testing.T) { node, ) - cachedMapItem, ok := ecache.algorithmCache[test.nodeName][test.predicateKey] + cachedMapItem, ok := ecache.cache[test.nodeName][test.predicateKey] if !ok { t.Errorf("Failed: %s, can't find expected cache item: %v", test.name, test.expectCacheItem) @@ -396,8 +396,8 @@ func TestLookupResult(t *testing.T) { equivalenceHashForUpdatePredicate uint64 equivalenceHashForCalPredicate uint64 cachedItem predicateItemType - expectedInvalidPredicateKey bool - expectedInvalidEquivalenceHash bool + expectedPredicateKeyMiss bool + expectedEquivalenceHashMiss bool expectedPredicateItem predicateItemType cache schedulercache.Cache }{ @@ -412,7 +412,7 @@ func TestLookupResult(t *testing.T) { fit: false, reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, }, - expectedInvalidPredicateKey: true, + expectedPredicateKeyMiss: true, expectedPredicateItem: predicateItemType{ fit: false, reasons: []algorithm.PredicateFailureReason{}, @@ -429,7 +429,7 @@ func TestLookupResult(t *testing.T) { cachedItem: predicateItemType{ fit: true, }, - expectedInvalidPredicateKey: false, + expectedPredicateKeyMiss: false, expectedPredicateItem: predicateItemType{ fit: true, reasons: []algorithm.PredicateFailureReason{}, @@ -447,7 +447,7 @@ func TestLookupResult(t *testing.T) { fit: false, reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, }, - expectedInvalidPredicateKey: false, + expectedPredicateKeyMiss: false, expectedPredicateItem: predicateItemType{ fit: false, reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, @@ -465,8 +465,8 @@ func TestLookupResult(t *testing.T) { fit: false, reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, }, - expectedInvalidPredicateKey: false, - expectedInvalidEquivalenceHash: true, + expectedPredicateKeyMiss: false, + expectedEquivalenceHashMiss: true, expectedPredicateItem: predicateItemType{ fit: false, reasons: []algorithm.PredicateFailureReason{}, @@ -490,27 +490,32 @@ func TestLookupResult(t *testing.T) { node, ) // if we want to do invalid, invalid the cached item - if test.expectedInvalidPredicateKey { + if test.expectedPredicateKeyMiss { predicateKeys := sets.NewString() predicateKeys.Insert(test.predicateKey) - ecache.InvalidateCachedPredicateItem(test.nodeName, predicateKeys) + ecache.InvalidatePredicatesOnNode(test.nodeName, predicateKeys) } // calculate predicate with equivalence cache - fit, reasons, invalid := ecache.lookupResult(test.podName, + result, ok := ecache.lookupResult(test.podName, test.nodeName, test.predicateKey, test.equivalenceHashForCalPredicate, ) - // returned invalid should match expectedInvalidPredicateKey or expectedInvalidEquivalenceHash + fit, reasons := result.Fit, result.FailReasons + // returned invalid should match expectedPredicateKeyMiss or expectedEquivalenceHashMiss if test.equivalenceHashForUpdatePredicate != test.equivalenceHashForCalPredicate { - if invalid != test.expectedInvalidEquivalenceHash { - t.Errorf("Failed: %s, expected invalid: %v, but got: %v", - test.name, test.expectedInvalidEquivalenceHash, invalid) + 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 invalid != test.expectedInvalidPredicateKey { - t.Errorf("Failed: %s, expected invalid: %v, but got: %v", - test.name, test.expectedInvalidPredicateKey, invalid) + 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 @@ -618,7 +623,7 @@ func TestGetEquivalenceHash(t *testing.T) { t.Run(test.name, func(t *testing.T) { for i, podInfo := range test.podInfoList { testPod := podInfo.pod - eclassInfo := ecache.getEquivalenceClassInfo(testPod) + eclassInfo := ecache.GetEquivalenceClassInfo(testPod) if eclassInfo == nil && podInfo.hashIsValid { t.Errorf("Failed: pod %v is expected to have valid hash", testPod) } @@ -704,11 +709,11 @@ func TestInvalidateCachedPredicateItemOfAllNodes(t *testing.T) { } // invalidate cached predicate for all nodes - ecache.InvalidateCachedPredicateItemOfAllNodes(sets.NewString(testPredicate)) + ecache.InvalidatePredicates(sets.NewString(testPredicate)) // there should be no cached predicate any more for _, test := range tests { - if algorithmCache, exist := ecache.algorithmCache[test.nodeName]; exist { + if algorithmCache, exist := ecache.cache[test.nodeName]; exist { if _, exist := algorithmCache[testPredicate]; exist { t.Errorf("Failed: cached item for predicate key: %v on node: %v should be invalidated", testPredicate, test.nodeName) @@ -777,8 +782,8 @@ func TestInvalidateAllCachedPredicateItemOfNode(t *testing.T) { for _, test := range tests { // invalidate cached predicate for all nodes - ecache.InvalidateAllCachedPredicateItemOfNode(test.nodeName) - if _, exist := ecache.algorithmCache[test.nodeName]; exist { + ecache.InvalidateAllPredicatesOnNode(test.nodeName) + if _, exist := ecache.cache[test.nodeName]; exist { t.Errorf("Failed: cached item for node: %v should be invalidated", test.nodeName) break } @@ -788,7 +793,7 @@ func TestInvalidateAllCachedPredicateItemOfNode(t *testing.T) { func BenchmarkEquivalenceHash(b *testing.B) { pod := makeBasicPod("test") for i := 0; i < b.N; i++ { - getEquivalenceHash(pod) + getEquivalencePod(pod) } } @@ -852,7 +857,7 @@ func TestEquivalenceCacheInvalidationRace(t *testing.T) { if err := cache.AddPod(pod); err != nil { t.Errorf("Could not add pod to cache: %v", err) } - eCache.InvalidateAllCachedPredicateItemOfNode("machine1") + eCache.InvalidateAllPredicatesOnNode("machine1") mockCache.cacheInvalidated <- struct{}{} }() diff --git a/pkg/scheduler/core/extender.go b/pkg/scheduler/core/extender.go index a654905e287..94d14349365 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) const ( diff --git a/pkg/scheduler/core/extender_test.go b/pkg/scheduler/core/extender_test.go index b0e7489312d..41fe6e91ae9 100644 --- a/pkg/scheduler/core/extender_test.go +++ b/pkg/scheduler/core/extender_test.go @@ -26,7 +26,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" "k8s.io/kubernetes/pkg/scheduler/util" ) @@ -135,7 +135,7 @@ func (f *FakeExtender) ProcessPreemption( nodeToVictimsCopy := map[*v1.Node]*schedulerapi.Victims{} // We don't want to change the original nodeToVictims for k, v := range nodeToVictims { - // In real world implementation, extender's user should have his own way to get node object + // In real world implementation, extender's user should have their own way to get node object // by name if needed (e.g. query kube-apiserver etc). // // For test purpose, we just use node from parameters directly. diff --git a/pkg/scheduler/core/generic_scheduler.go b/pkg/scheduler/core/generic_scheduler.go index 960054b0d14..54d340a8f5a 100644 --- a/pkg/scheduler/core/generic_scheduler.go +++ b/pkg/scheduler/core/generic_scheduler.go @@ -38,8 +38,8 @@ 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/metrics" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" ) @@ -219,7 +219,7 @@ func (g *genericScheduler) Preempt(pod *v1.Pod, nodeLister algorithm.NodeLister, if len(allNodes) == 0 { return nil, nil, nil, ErrNoNodesAvailable } - potentialNodes := nodesWherePreemptionMightHelp(pod, allNodes, fitError.FailedPredicates) + potentialNodes := nodesWherePreemptionMightHelp(allNodes, fitError.FailedPredicates) if len(potentialNodes) == 0 { glog.V(3).Infof("Preemption will not help schedule pod %v on any node.", pod.Name) // In this case, we should clean-up any existing nominated node name of the pod. @@ -342,10 +342,10 @@ 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) - var equivCacheInfo *equivalenceClassInfo + var equivCacheInfo *EquivalenceClassInfo if g.equivalenceCache != nil { // getEquivalenceClassInfo will return immediately if no equivalence pod found - equivCacheInfo = g.equivalenceCache.getEquivalenceClassInfo(pod) + equivCacheInfo = g.equivalenceCache.GetEquivalenceClassInfo(pod) } checkNode := func(i int) { @@ -462,7 +462,7 @@ func podFitsOnNode( ecache *EquivalenceCache, queue SchedulingQueue, alwaysCheckAllPredicates bool, - equivCacheInfo *equivalenceClassInfo, + equivCacheInfo *EquivalenceClassInfo, ) (bool, []algorithm.PredicateFailureReason, error) { var ( eCacheAvailable bool @@ -969,7 +969,7 @@ func selectVictimsOnNode( // nodesWherePreemptionMightHelp returns a list of nodes with failed predicates // that may be satisfied by removing pods from the node. -func nodesWherePreemptionMightHelp(pod *v1.Pod, nodes []*v1.Node, failedPredicatesMap FailedPredicateMap) []*v1.Node { +func nodesWherePreemptionMightHelp(nodes []*v1.Node, failedPredicatesMap FailedPredicateMap) []*v1.Node { potentialNodes := []*v1.Node{} for _, node := range nodes { unresolvableReasonExist := false diff --git a/pkg/scheduler/core/generic_scheduler_test.go b/pkg/scheduler/core/generic_scheduler_test.go index 01c6d331ff5..ce10d9fd3fa 100644 --- a/pkg/scheduler/core/generic_scheduler_test.go +++ b/pkg/scheduler/core/generic_scheduler_test.go @@ -38,7 +38,7 @@ 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" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -1097,7 +1097,6 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) { tests := []struct { name string failedPredMap FailedPredicateMap - pod *v1.Pod expected map[string]bool // set of expected node names. Value is ignored. }{ { @@ -1108,7 +1107,6 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) { "machine3": []algorithm.PredicateFailureReason{algorithmpredicates.ErrTaintsTolerationsNotMatch}, "machine4": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeLabelPresenceViolated}, }, - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", UID: types.UID("pod1")}}, expected: map[string]bool{}, }, { @@ -1118,23 +1116,6 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) { "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrPodNotMatchHostName}, "machine3": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeUnschedulable}, }, - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", UID: types.UID("pod1")}, Spec: v1.PodSpec{Affinity: &v1.Affinity{ - PodAffinity: &v1.PodAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ - { - LabelSelector: &metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{ - { - Key: "service", - Operator: metav1.LabelSelectorOpIn, - Values: []string{"securityscan", "value2"}, - }, - }, - }, - TopologyKey: "hostname", - }, - }, - }}}}, expected: map[string]bool{"machine1": true, "machine4": true}, }, { @@ -1143,40 +1124,6 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) { "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrPodAffinityNotMatch}, "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrPodNotMatchHostName}, }, - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", UID: types.UID("pod1")}, Spec: v1.PodSpec{Affinity: &v1.Affinity{ - PodAffinity: &v1.PodAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ - { - LabelSelector: &metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{ - { - Key: "service", - Operator: metav1.LabelSelectorOpIn, - Values: []string{"securityscan", "value2"}, - }, - }, - }, - TopologyKey: "hostname", - }, - }, - }, - PodAntiAffinity: &v1.PodAntiAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ - { - LabelSelector: &metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{ - { - Key: "service", - Operator: metav1.LabelSelectorOpNotIn, - Values: []string{"blah", "foo"}, - }, - }, - }, - TopologyKey: "region", - }, - }, - }, - }}}, expected: map[string]bool{"machine1": true, "machine3": true, "machine4": true}, }, { @@ -1187,13 +1134,12 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) { "machine3": []algorithm.PredicateFailureReason{algorithmpredicates.NewInsufficientResourceError(v1.ResourceMemory, 1000, 600, 400)}, "machine4": []algorithm.PredicateFailureReason{}, }, - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", UID: types.UID("pod1")}}, expected: map[string]bool{"machine3": true, "machine4": true}, }, } for _, test := range tests { - nodes := nodesWherePreemptionMightHelp(test.pod, makeNodeList(nodeNames), test.failedPredMap) + nodes := nodesWherePreemptionMightHelp(makeNodeList(nodeNames), test.failedPredMap) if len(test.expected) != len(nodes) { t.Errorf("test [%v]:number of nodes is not the same as expected. exptectd: %d, got: %d. Nodes: %v", test.name, len(test.expected), len(nodes), nodes) } diff --git a/pkg/scheduler/factory/BUILD b/pkg/scheduler/factory/BUILD index 0cb8121e261..faf552687c4 100644 --- a/pkg/scheduler/factory/BUILD +++ b/pkg/scheduler/factory/BUILD @@ -60,8 +60,8 @@ go_library( "//pkg/scheduler/algorithm/priorities:go_default_library", "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/api/validation:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/core:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//vendor/github.com/golang/glog:go_default_library", @@ -103,12 +103,14 @@ go_test( "//pkg/api/testing:go_default_library", "//pkg/scheduler:go_default_library", "//pkg/scheduler/algorithm: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/core:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//pkg/scheduler/testing:go_default_library", "//pkg/scheduler/util:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/pkg/scheduler/factory/cache_comparer.go b/pkg/scheduler/factory/cache_comparer.go index e2f3c7cefb7..fadd7be2c99 100644 --- a/pkg/scheduler/factory/cache_comparer.go +++ b/pkg/scheduler/factory/cache_comparer.go @@ -26,8 +26,8 @@ import ( "k8s.io/apimachinery/pkg/labels" corelisters "k8s.io/client-go/listers/core/v1" v1beta1 "k8s.io/client-go/listers/policy/v1beta1" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/core" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" ) type cacheComparer struct { diff --git a/pkg/scheduler/factory/cache_comparer_test.go b/pkg/scheduler/factory/cache_comparer_test.go index 1a525617d13..1741330995b 100644 --- a/pkg/scheduler/factory/cache_comparer_test.go +++ b/pkg/scheduler/factory/cache_comparer_test.go @@ -23,7 +23,7 @@ import ( "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1beta1" "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestCompareNodes(t *testing.T) { diff --git a/pkg/scheduler/factory/factory.go b/pkg/scheduler/factory/factory.go index fb5cc22fcbe..c401f834b34 100644 --- a/pkg/scheduler/factory/factory.go +++ b/pkg/scheduler/factory/factory.go @@ -59,8 +59,8 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" "k8s.io/kubernetes/pkg/scheduler/api/validation" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/core" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" ) @@ -410,7 +410,7 @@ func (c *configFactory) invalidatePredicatesForPvUpdate(oldPV, newPV *v1.Persist break } } - c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(invalidPredicates) + c.equivalencePodCache.InvalidatePredicates(invalidPredicates) } // isZoneRegionLabel check if given key of label is zone or region label. @@ -468,7 +468,7 @@ func (c *configFactory) invalidatePredicatesForPv(pv *v1.PersistentVolume) { invalidPredicates.Insert(predicates.CheckVolumeBindingPred) } - c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(invalidPredicates) + c.equivalencePodCache.InvalidatePredicates(invalidPredicates) } func (c *configFactory) onPvcAdd(obj interface{}) { @@ -538,7 +538,7 @@ func (c *configFactory) invalidatePredicatesForPvc(pvc *v1.PersistentVolumeClaim // Add/delete impacts the available PVs to choose from invalidPredicates.Insert(predicates.CheckVolumeBindingPred) } - c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(invalidPredicates) + c.equivalencePodCache.InvalidatePredicates(invalidPredicates) } func (c *configFactory) invalidatePredicatesForPvcUpdate(old, new *v1.PersistentVolumeClaim) { @@ -553,12 +553,12 @@ func (c *configFactory) invalidatePredicatesForPvcUpdate(old, new *v1.Persistent invalidPredicates.Insert(maxPDVolumeCountPredicateKeys...) } - c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(invalidPredicates) + c.equivalencePodCache.InvalidatePredicates(invalidPredicates) } func (c *configFactory) onServiceAdd(obj interface{}) { if c.enableEquivalenceClassCache { - c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(serviceAffinitySet) + c.equivalencePodCache.InvalidatePredicates(serviceAffinitySet) } c.podQueue.MoveAllToActiveQueue() } @@ -569,7 +569,7 @@ func (c *configFactory) onServiceUpdate(oldObj interface{}, newObj interface{}) oldService := oldObj.(*v1.Service) newService := newObj.(*v1.Service) if !reflect.DeepEqual(oldService.Spec.Selector, newService.Spec.Selector) { - c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(serviceAffinitySet) + c.equivalencePodCache.InvalidatePredicates(serviceAffinitySet) } } c.podQueue.MoveAllToActiveQueue() @@ -577,7 +577,7 @@ func (c *configFactory) onServiceUpdate(oldObj interface{}, newObj interface{}) func (c *configFactory) onServiceDelete(obj interface{}) { if c.enableEquivalenceClassCache { - c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(serviceAffinitySet) + c.equivalencePodCache.InvalidatePredicates(serviceAffinitySet) } c.podQueue.MoveAllToActiveQueue() } @@ -694,13 +694,13 @@ func (c *configFactory) invalidateCachedPredicatesOnUpdatePod(newPod *v1.Pod, ol 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.InvalidateCachedPredicateItemOfAllNodes( + 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.InvalidateCachedPredicateItem( + c.equivalencePodCache.InvalidatePredicatesOnNode( newPod.Spec.NodeName, generalPredicatesSets) } } @@ -741,14 +741,14 @@ func (c *configFactory) invalidateCachedPredicatesOnDeletePod(pod *v1.Pod) { // 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.InvalidateCachedPredicateItemOfAllNodes( + 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.InvalidateCachedPredicateItem( + c.equivalencePodCache.InvalidatePredicatesOnNode( pod.Spec.NodeName, noDiskConflictSet) } } @@ -858,7 +858,7 @@ func (c *configFactory) invalidateCachedPredicatesOnNodeUpdate(newNode *v1.Node, if newNode.Spec.Unschedulable != oldNode.Spec.Unschedulable { invalidPredicates.Insert(predicates.CheckNodeConditionPred) } - c.equivalencePodCache.InvalidateCachedPredicateItem(newNode.GetName(), invalidPredicates) + c.equivalencePodCache.InvalidatePredicatesOnNode(newNode.GetName(), invalidPredicates) } } @@ -885,7 +885,7 @@ func (c *configFactory) deleteNodeFromCache(obj interface{}) { glog.Errorf("scheduler cache RemoveNode failed: %v", err) } if c.enableEquivalenceClassCache { - c.equivalencePodCache.InvalidateAllCachedPredicateItemOfNode(node.GetName()) + c.equivalencePodCache.InvalidateAllPredicatesOnNode(node.GetName()) } } @@ -1315,7 +1315,7 @@ func (c *configFactory) MakeDefaultErrorFunc(backoff *util.PodBackoff, podQueue c.schedulerCache.RemoveNode(&node) // invalidate cached predicate for the node if c.enableEquivalenceClassCache { - c.equivalencePodCache.InvalidateAllCachedPredicateItemOfNode(nodeName) + c.equivalencePodCache.InvalidateAllPredicatesOnNode(nodeName) } } } diff --git a/pkg/scheduler/factory/factory_test.go b/pkg/scheduler/factory/factory_test.go index b83c703ac3d..36ecf26ecb9 100644 --- a/pkg/scheduler/factory/factory_test.go +++ b/pkg/scheduler/factory/factory_test.go @@ -40,8 +40,8 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/core" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" "k8s.io/kubernetes/pkg/scheduler/util" ) diff --git a/pkg/scheduler/factory/plugins.go b/pkg/scheduler/factory/plugins.go index ba481dde93c..f9a668b4a9b 100644 --- a/pkg/scheduler/factory/plugins.go +++ b/pkg/scheduler/factory/plugins.go @@ -322,6 +322,15 @@ func RegisterCustomPriorityFunction(policy schedulerapi.PriorityPolicy) string { }, Weight: policy.Weight, } + } else if policy.Argument.RequestedToCapacityRatioArguments != nil { + pcf = &PriorityConfigFactory{ + MapReduceFunction: func(args PluginFactoryArgs) (algorithm.PriorityMapFunction, algorithm.PriorityReduceFunction) { + scoringFunctionShape := buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(policy.Argument.RequestedToCapacityRatioArguments) + p := priorities.RequestedToCapacityRatioResourceAllocationPriority(scoringFunctionShape) + return p.PriorityMap, nil + }, + Weight: policy.Weight, + } } } else if existingPcf, ok := priorityFunctionMap[policy.Name]; ok { glog.V(2).Infof("Priority type %s already registered, reusing.", policy.Name) @@ -340,6 +349,19 @@ func RegisterCustomPriorityFunction(policy schedulerapi.PriorityPolicy) string { return RegisterPriorityConfigFactory(policy.Name, *pcf) } +func buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(arguments *schedulerapi.RequestedToCapacityRatioArguments) priorities.FunctionShape { + n := len(arguments.UtilizationShape) + points := make([]priorities.FunctionShapePoint, 0, n) + for _, point := range arguments.UtilizationShape { + points = append(points, priorities.FunctionShapePoint{Utilization: int64(point.Utilization), Score: int64(point.Score)}) + } + shape, err := priorities.NewFunctionShape(points) + if err != nil { + glog.Fatalf("invalid RequestedToCapacityRatioPriority arguments: %s", err.Error()) + } + return shape +} + // IsPriorityFunctionRegistered is useful for testing providers. func IsPriorityFunctionRegistered(name string) bool { schedulerFactoryMutex.Lock() @@ -494,6 +516,9 @@ func validatePriorityOrDie(priority schedulerapi.PriorityPolicy) { if priority.Argument.LabelPreference != nil { numArgs++ } + if priority.Argument.RequestedToCapacityRatioArguments != nil { + numArgs++ + } if numArgs != 1 { glog.Fatalf("Exactly 1 priority argument is required, numArgs: %v, Priority: %s", numArgs, priority.Name) } diff --git a/pkg/scheduler/factory/plugins_test.go b/pkg/scheduler/factory/plugins_test.go index a3508c139d2..ee813de97ac 100644 --- a/pkg/scheduler/factory/plugins_test.go +++ b/pkg/scheduler/factory/plugins_test.go @@ -19,7 +19,9 @@ package factory import ( "testing" + "github.com/stretchr/testify/assert" "k8s.io/kubernetes/pkg/scheduler/algorithm" + "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" "k8s.io/kubernetes/pkg/scheduler/api" ) @@ -80,3 +82,19 @@ func TestValidatePriorityConfigOverFlow(t *testing.T) { } } } + +func TestBuildScoringFunctionShapeFromRequestedToCapacityRatioArguments(t *testing.T) { + arguments := api.RequestedToCapacityRatioArguments{ + UtilizationShape: []api.UtilizationShapePoint{ + {Utilization: 10, Score: 1}, + {Utilization: 30, Score: 5}, + {Utilization: 70, Score: 2}, + }} + builtShape := buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(&arguments) + expectedShape, _ := priorities.NewFunctionShape([]priorities.FunctionShapePoint{ + {Utilization: 10, Score: 1}, + {Utilization: 30, Score: 5}, + {Utilization: 70, Score: 2}, + }) + assert.Equal(t, expectedShape, builtShape) +} diff --git a/pkg/scheduler/metrics/metrics.go b/pkg/scheduler/metrics/metrics.go index 4836ac4b93c..2fbba9980c5 100644 --- a/pkg/scheduler/metrics/metrics.go +++ b/pkg/scheduler/metrics/metrics.go @@ -23,13 +23,37 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -const schedulerSubsystem = "scheduler" +const ( + // SchedulerSubsystem - subsystem name used by scheduler + SchedulerSubsystem = "scheduler" + // SchedulingLatencyName - scheduler latency metric name + SchedulingLatencyName = "scheduling_latency_seconds" + + // OperationLabel - operation label name + OperationLabel = "operation" + // Binding - binding operation label value + Binding = "binding" + // SelectingNode - selecting node operation label value + SelectingNode = "selecting_node" + // E2eScheduling - e2e scheduling operation label value +) // All the histogram based metrics have 1ms as size for the smallest bucket. var ( + SchedulingLatency = prometheus.NewSummaryVec( + prometheus.SummaryOpts{ + Subsystem: SchedulerSubsystem, + Name: SchedulingLatencyName, + Help: "Scheduling latency in seconds split by sub-parts of the scheduling operation", + // Make the sliding window of 5h. + // TODO: The value for this should be based on some SLI definition (long term). + MaxAge: 5 * time.Hour, + }, + []string{OperationLabel}, + ) E2eSchedulingLatency = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "e2e_scheduling_latency_microseconds", Help: "E2e scheduling latency (scheduling algorithm + binding)", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -37,7 +61,7 @@ var ( ) SchedulingAlgorithmLatency = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "scheduling_algorithm_latency_microseconds", Help: "Scheduling algorithm latency", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -45,7 +69,7 @@ var ( ) SchedulingAlgorithmPredicateEvaluationDuration = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "scheduling_algorithm_predicate_evaluation", Help: "Scheduling algorithm predicate evaluation duration", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -53,7 +77,7 @@ var ( ) SchedulingAlgorithmPriorityEvaluationDuration = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "scheduling_algorithm_priority_evaluation", Help: "Scheduling algorithm priority evaluation duration", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -61,7 +85,7 @@ var ( ) SchedulingAlgorithmPremptionEvaluationDuration = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "scheduling_algorithm_preemption_evaluation", Help: "Scheduling algorithm preemption evaluation duration", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -69,7 +93,7 @@ var ( ) BindingLatency = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "binding_latency_microseconds", Help: "Binding latency", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -77,16 +101,27 @@ var ( ) PreemptionVictims = prometheus.NewGauge( prometheus.GaugeOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "pod_preemption_victims", Help: "Number of selected preemption victims", }) PreemptionAttempts = prometheus.NewCounter( prometheus.CounterOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "total_preemption_attempts", Help: "Total preemption attempts in the cluster till now", }) + metricsList = []prometheus.Collector{ + SchedulingLatency, + E2eSchedulingLatency, + SchedulingAlgorithmLatency, + BindingLatency, + SchedulingAlgorithmPredicateEvaluationDuration, + SchedulingAlgorithmPriorityEvaluationDuration, + SchedulingAlgorithmPremptionEvaluationDuration, + PreemptionVictims, + PreemptionAttempts, + } ) var registerMetrics sync.Once @@ -95,19 +130,23 @@ var registerMetrics sync.Once func Register() { // Register the metrics. registerMetrics.Do(func() { - prometheus.MustRegister(E2eSchedulingLatency) - prometheus.MustRegister(SchedulingAlgorithmLatency) - prometheus.MustRegister(BindingLatency) - - prometheus.MustRegister(SchedulingAlgorithmPredicateEvaluationDuration) - prometheus.MustRegister(SchedulingAlgorithmPriorityEvaluationDuration) - prometheus.MustRegister(SchedulingAlgorithmPremptionEvaluationDuration) - prometheus.MustRegister(PreemptionVictims) - prometheus.MustRegister(PreemptionAttempts) + for _, metric := range metricsList { + prometheus.MustRegister(metric) + } }) } +// Reset resets metrics +func Reset() { + SchedulingLatency.Reset() +} + // SinceInMicroseconds gets the time since the specified start in microseconds. func SinceInMicroseconds(start time.Time) float64 { return float64(time.Since(start).Nanoseconds() / time.Microsecond.Nanoseconds()) } + +// SinceInSeconds gets the time since the specified start in seconds. +func SinceInSeconds(start time.Time) float64 { + return time.Since(start).Seconds() +} diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go index 98beabe5c57..98b36678abf 100644 --- a/pkg/scheduler/scheduler.go +++ b/pkg/scheduler/scheduler.go @@ -32,9 +32,9 @@ 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" "k8s.io/kubernetes/pkg/scheduler/metrics" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" @@ -284,7 +284,7 @@ func (sched *Scheduler) assumeAndBindVolumes(assumed *v1.Pod, host string) error if bindingRequired { if sched.config.Ecache != nil { invalidPredicates := sets.NewString(predicates.CheckVolumeBindingPred) - sched.config.Ecache.InvalidateCachedPredicateItemOfAllNodes(invalidPredicates) + sched.config.Ecache.InvalidatePredicates(invalidPredicates) } // bindVolumesWorker() will update the Pod object to put it back in the scheduler queue @@ -430,6 +430,7 @@ func (sched *Scheduler) bind(assumed *v1.Pod, b *v1.Binding) error { } metrics.BindingLatency.Observe(metrics.SinceInMicroseconds(bindingStart)) + metrics.SchedulingLatency.WithLabelValues(metrics.Binding).Observe(metrics.SinceInSeconds(bindingStart)) sched.config.Recorder.Eventf(assumed, v1.EventTypeNormal, "Scheduled", "Successfully assigned %v/%v to %v", assumed.Namespace, assumed.Name, b.Target.Name) return nil } @@ -462,6 +463,7 @@ func (sched *Scheduler) scheduleOne() { return } metrics.SchedulingAlgorithmLatency.Observe(metrics.SinceInMicroseconds(start)) + metrics.SchedulingLatency.WithLabelValues(metrics.SelectingNode).Observe(metrics.SinceInSeconds(start)) // Tell the cache to assume that a pod now is running on a given node, even though it hasn't been bound yet. // This allows us to keep scheduling without waiting on binding to occur. assumedPod := pod.DeepCopy() diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go index ebdb5f19937..21a074cff8e 100644 --- a/pkg/scheduler/scheduler_test.go +++ b/pkg/scheduler/scheduler_test.go @@ -37,8 +37,8 @@ import ( "k8s.io/kubernetes/pkg/controller/volume/persistentvolume" "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/core" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" "k8s.io/kubernetes/pkg/scheduler/volumebinder" ) diff --git a/pkg/scheduler/testing/BUILD b/pkg/scheduler/testing/BUILD index 45977993a76..241218afd18 100644 --- a/pkg/scheduler/testing/BUILD +++ b/pkg/scheduler/testing/BUILD @@ -20,7 +20,7 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/apis/core/install:go_default_library", "//pkg/scheduler/algorithm:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", diff --git a/pkg/scheduler/testing/fake_cache.go b/pkg/scheduler/testing/fake_cache.go index 9a78493eed8..65036bd34c0 100644 --- a/pkg/scheduler/testing/fake_cache.go +++ b/pkg/scheduler/testing/fake_cache.go @@ -20,7 +20,7 @@ import ( "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1beta1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // FakeCache is used for testing diff --git a/pkg/scheduler/testing/fake_lister.go b/pkg/scheduler/testing/fake_lister.go index 6cb34a24543..a65c409b3f5 100644 --- a/pkg/scheduler/testing/fake_lister.go +++ b/pkg/scheduler/testing/fake_lister.go @@ -26,7 +26,7 @@ import ( "k8s.io/apimachinery/pkg/labels" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/kubernetes/pkg/scheduler/algorithm" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) var _ algorithm.NodeLister = &FakeNodeLister{} diff --git a/pkg/scheduler/testing/pods_to_cache.go b/pkg/scheduler/testing/pods_to_cache.go index 09053ae8c72..ecb237bfbdb 100644 --- a/pkg/scheduler/testing/pods_to_cache.go +++ b/pkg/scheduler/testing/pods_to_cache.go @@ -19,7 +19,7 @@ package testing import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // PodsToCache is used for testing diff --git a/pkg/security/podsecuritypolicy/factory.go b/pkg/security/podsecuritypolicy/factory.go index a198058e6eb..05c7f0d8bb3 100644 --- a/pkg/security/podsecuritypolicy/factory.go +++ b/pkg/security/podsecuritypolicy/factory.go @@ -77,15 +77,7 @@ func (f *simpleStrategyFactory) CreateStrategies(psp *policy.PodSecurityPolicy, errs = append(errs, err) } - var unsafeSysctls []string - if ann, found := psp.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey]; found { - var err error - unsafeSysctls, err = policy.SysctlsFromPodSecurityPolicyAnnotation(ann) - if err != nil { - errs = append(errs, err) - } - } - sysctlsStrat := createSysctlsStrategy(unsafeSysctls) + sysctlsStrat := createSysctlsStrategy(sysctl.SafeSysctlWhitelist(), psp.Spec.AllowedUnsafeSysctls, psp.Spec.ForbiddenSysctls) if len(errs) > 0 { return nil, errors.NewAggregate(errs) @@ -170,7 +162,7 @@ func createCapabilitiesStrategy(defaultAddCaps, requiredDropCaps, allowedCaps [] return capabilities.NewDefaultCapabilities(defaultAddCaps, requiredDropCaps, allowedCaps) } -// createSysctlsStrategy creates a new unsafe sysctls strategy. -func createSysctlsStrategy(sysctlsPatterns []string) sysctl.SysctlsStrategy { - return sysctl.NewMustMatchPatterns(sysctlsPatterns) +// createSysctlsStrategy creates a new sysctls strategy. +func createSysctlsStrategy(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls []string) sysctl.SysctlsStrategy { + return sysctl.NewMustMatchPatterns(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls) } diff --git a/pkg/security/podsecuritypolicy/provider.go b/pkg/security/podsecuritypolicy/provider.go index 2fe3d96699a..7458eb8a50b 100644 --- a/pkg/security/podsecuritypolicy/provider.go +++ b/pkg/security/podsecuritypolicy/provider.go @@ -227,10 +227,33 @@ func (s *simpleProvider) ValidatePod(pod *api.Pod, fldPath *field.Path) field.Er } if fsType == policy.HostPath { - if !psputil.AllowsHostVolumePath(s.psp, v.HostPath.Path) { + allows, mustBeReadOnly := psputil.AllowsHostVolumePath(s.psp, v.HostPath.Path) + if !allows { allErrs = append(allErrs, field.Invalid( field.NewPath("spec", "volumes").Index(i).Child("hostPath", "pathPrefix"), v.HostPath.Path, fmt.Sprintf("is not allowed to be used"))) + } else if mustBeReadOnly { + // Ensure all the VolumeMounts that use this volume are read-only + for i, c := range pod.Spec.InitContainers { + for j, cv := range c.VolumeMounts { + if cv.Name == v.Name && !cv.ReadOnly { + allErrs = append(allErrs, field.Invalid( + field.NewPath("spec", "initContainers").Index(i).Child("volumeMounts").Index(j).Child("readOnly"), + cv.ReadOnly, "must be read-only"), + ) + } + } + } + for i, c := range pod.Spec.Containers { + for j, cv := range c.VolumeMounts { + if cv.Name == v.Name && !cv.ReadOnly { + allErrs = append(allErrs, field.Invalid( + field.NewPath("spec", "containers").Index(i).Child("volumeMounts").Index(j).Child("readOnly"), + cv.ReadOnly, "must be read-only"), + ) + } + } + } } } diff --git a/pkg/security/podsecuritypolicy/provider_test.go b/pkg/security/podsecuritypolicy/provider_test.go index a6361136349..a7b8174a967 100644 --- a/pkg/security/podsecuritypolicy/provider_test.go +++ b/pkg/security/podsecuritypolicy/provider_test.go @@ -241,17 +241,60 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { {PathPrefix: "/foo/bar"}, } - failOtherSysctlsAllowedPSP := defaultPSP() - failOtherSysctlsAllowedPSP.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "bar,abc" + failHostPathReadOnlyPod := defaultPod() + failHostPathReadOnlyPod.Spec.Containers[0].VolumeMounts = []api.VolumeMount{ + { + Name: "bad volume", + ReadOnly: false, + }, + } + failHostPathReadOnlyPod.Spec.Volumes = []api.Volume{ + { + Name: "bad volume", + VolumeSource: api.VolumeSource{ + HostPath: &api.HostPathVolumeSource{ + Path: "/foo", + }, + }, + }, + } + failHostPathReadOnlyPSP := defaultPSP() + failHostPathReadOnlyPSP.Spec.Volumes = []policy.FSType{policy.HostPath} + failHostPathReadOnlyPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{ + { + PathPrefix: "/foo", + ReadOnly: true, + }, + } - failNoSysctlAllowedPSP := defaultPSP() - failNoSysctlAllowedPSP.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "" + failSysctlDisallowedPSP := defaultPSP() + failSysctlDisallowedPSP.Spec.ForbiddenSysctls = []string{"kernel.shm_rmid_forced"} - failSafeSysctlFooPod := defaultPod() - failSafeSysctlFooPod.Annotations[api.SysctlsPodAnnotationKey] = "foo=1" + failNoSafeSysctlAllowedPSP := defaultPSP() + failNoSafeSysctlAllowedPSP.Spec.ForbiddenSysctls = []string{"*"} - failUnsafeSysctlFooPod := defaultPod() - failUnsafeSysctlFooPod.Annotations[api.UnsafeSysctlsPodAnnotationKey] = "foo=1" + failAllUnsafeSysctlsPSP := defaultPSP() + failAllUnsafeSysctlsPSP.Spec.AllowedUnsafeSysctls = []string{} + + failSafeSysctlKernelPod := defaultPod() + failSafeSysctlKernelPod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: []api.Sysctl{ + { + Name: "kernel.shm_rmid_forced", + Value: "1", + }, + }, + } + + failUnsafeSysctlPod := defaultPod() + failUnsafeSysctlPod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: []api.Sysctl{ + { + Name: "kernel.sem", + Value: "32000", + }, + }, + } failSeccompProfilePod := defaultPod() failSeccompProfilePod.Annotations = map[string]string{api.SeccompPodAnnotationKey: "foo"} @@ -328,25 +371,25 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { psp: failHostPathDirPSP, expectedError: "is not allowed to be used", }, - "failSafeSysctlFooPod with failNoSysctlAllowedSCC": { - pod: failSafeSysctlFooPod, - psp: failNoSysctlAllowedPSP, - expectedError: "sysctls are not allowed", + "failHostPathReadOnlyPSP": { + pod: failHostPathReadOnlyPod, + psp: failHostPathReadOnlyPSP, + expectedError: "must be read-only", }, - "failUnsafeSysctlFooPod with failNoSysctlAllowedSCC": { - pod: failUnsafeSysctlFooPod, - psp: failNoSysctlAllowedPSP, - expectedError: "sysctls are not allowed", + "failSafeSysctlKernelPod with failNoSafeSysctlAllowedPSP": { + pod: failSafeSysctlKernelPod, + psp: failNoSafeSysctlAllowedPSP, + expectedError: "sysctl \"kernel.shm_rmid_forced\" is not allowed", }, - "failSafeSysctlFooPod with failOtherSysctlsAllowedSCC": { - pod: failSafeSysctlFooPod, - psp: failOtherSysctlsAllowedPSP, - expectedError: "sysctl \"foo\" is not allowed", + "failSafeSysctlKernelPod with failSysctlDisallowedPSP": { + pod: failSafeSysctlKernelPod, + psp: failSysctlDisallowedPSP, + expectedError: "sysctl \"kernel.shm_rmid_forced\" is not allowed", }, - "failUnsafeSysctlFooPod with failOtherSysctlsAllowedSCC": { - pod: failUnsafeSysctlFooPod, - psp: failOtherSysctlsAllowedPSP, - expectedError: "sysctl \"foo\" is not allowed", + "failUnsafeSysctlPod with failAllUnsafeSysctlsPSP": { + pod: failUnsafeSysctlPod, + psp: failAllUnsafeSysctlsPSP, + expectedError: "unsafe sysctl \"kernel.sem\" is not allowed", }, "failInvalidSeccomp": { pod: failSeccompProfilePod, @@ -598,38 +641,107 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { Level: "level", } + hostPathDirPodVolumeMounts := []api.VolumeMount{ + { + Name: "writeable /foo/bar", + ReadOnly: false, + }, + { + Name: "read only /foo/bar/baz", + ReadOnly: true, + }, + { + Name: "parent read only volume", + ReadOnly: true, + }, + { + Name: "read only child volume", + ReadOnly: true, + }, + } + hostPathDirPod := defaultPod() + hostPathDirPod.Spec.InitContainers = []api.Container{ + { + Name: defaultContainerName, + VolumeMounts: hostPathDirPodVolumeMounts, + }, + } + + hostPathDirPod.Spec.Containers[0].VolumeMounts = hostPathDirPodVolumeMounts hostPathDirPod.Spec.Volumes = []api.Volume{ { - Name: "good volume", + Name: "writeable /foo/bar", + VolumeSource: api.VolumeSource{ + HostPath: &api.HostPathVolumeSource{ + Path: "/foo/bar", + }, + }, + }, + { + Name: "read only /foo/bar/baz", VolumeSource: api.VolumeSource{ HostPath: &api.HostPathVolumeSource{ Path: "/foo/bar/baz", }, }, }, + { + Name: "parent read only volume", + VolumeSource: api.VolumeSource{ + HostPath: &api.HostPathVolumeSource{ + Path: "/foo/", + }, + }, + }, + { + Name: "read only child volume", + VolumeSource: api.VolumeSource{ + HostPath: &api.HostPathVolumeSource{ + Path: "/foo/readonly/child", + }, + }, + }, } hostPathDirPSP := defaultPSP() hostPathDirPSP.Spec.Volumes = []policy.FSType{policy.HostPath} hostPathDirPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{ - {PathPrefix: "/foo/bar"}, + // overlapping test case where child is different than parent directory. + {PathPrefix: "/foo/bar/baz", ReadOnly: true}, + {PathPrefix: "/foo", ReadOnly: true}, + {PathPrefix: "/foo/bar", ReadOnly: false}, } hostPathDirAsterisksPSP := defaultPSP() hostPathDirAsterisksPSP.Spec.Volumes = []policy.FSType{policy.All} hostPathDirAsterisksPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{ - {PathPrefix: "/foo/bar"}, + {PathPrefix: "/foo"}, } - sysctlAllowFooPSP := defaultPSP() - sysctlAllowFooPSP.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "foo" + sysctlAllowAllPSP := defaultPSP() + sysctlAllowAllPSP.Spec.ForbiddenSysctls = []string{} + sysctlAllowAllPSP.Spec.AllowedUnsafeSysctls = []string{"*"} - safeSysctlFooPod := defaultPod() - safeSysctlFooPod.Annotations[api.SysctlsPodAnnotationKey] = "foo=1" + safeSysctlKernelPod := defaultPod() + safeSysctlKernelPod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: []api.Sysctl{ + { + Name: "kernel.shm_rmid_forced", + Value: "1", + }, + }, + } - unsafeSysctlFooPod := defaultPod() - unsafeSysctlFooPod.Annotations[api.UnsafeSysctlsPodAnnotationKey] = "foo=1" + unsafeSysctlKernelPod := defaultPod() + unsafeSysctlKernelPod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: []api.Sysctl{ + { + Name: "kernel.sem", + Value: "32000", + }, + }, + } seccompPSP := defaultPSP() seccompPSP.Annotations = map[string]string{ @@ -681,21 +793,13 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { pod: seLinuxPod, psp: seLinuxPSP, }, - "pass sysctl specific profile with safe sysctl": { - pod: safeSysctlFooPod, - psp: sysctlAllowFooPSP, + "pass sysctl specific profile with safe kernel sysctl": { + pod: safeSysctlKernelPod, + psp: sysctlAllowAllPSP, }, - "pass sysctl specific profile with unsafe sysctl": { - pod: unsafeSysctlFooPod, - psp: sysctlAllowFooPSP, - }, - "pass empty profile with safe sysctl": { - pod: safeSysctlFooPod, - psp: defaultPSP(), - }, - "pass empty profile with unsafe sysctl": { - pod: unsafeSysctlFooPod, - psp: defaultPSP(), + "pass sysctl specific profile with unsafe kernel sysctl": { + pod: unsafeSysctlKernelPod, + psp: sysctlAllowAllPSP, }, "pass hostDir allowed directory validating PSP": { pod: hostPathDirPod, diff --git a/pkg/security/podsecuritypolicy/sysctl/BUILD b/pkg/security/podsecuritypolicy/sysctl/BUILD index b466cbbeb28..445907ccf35 100644 --- a/pkg/security/podsecuritypolicy/sysctl/BUILD +++ b/pkg/security/podsecuritypolicy/sysctl/BUILD @@ -15,7 +15,6 @@ go_library( importpath = "k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl", deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/core/helper:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", ], ) @@ -24,10 +23,7 @@ go_test( name = "go_default_test", srcs = ["mustmatchpatterns_test.go"], embed = [":go_default_library"], - deps = [ - "//pkg/apis/core:go_default_library", - "//pkg/apis/core/helper:go_default_library", - ], + deps = ["//pkg/apis/core:go_default_library"], ) filegroup( diff --git a/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns.go b/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns.go index b59dd9d3fff..6c33276c563 100644 --- a/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns.go +++ b/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns.go @@ -22,12 +22,26 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/helper" ) +// SafeSysctlWhitelist returns the whitelist of safe sysctls and safe sysctl patterns (ending in *). +// +// A sysctl is called safe iff +// - it is namespaced in the container or the pod +// - it is isolated, i.e. has no influence on any other pod on the same node. +func SafeSysctlWhitelist() []string { + return []string{ + "kernel.shm_rmid_forced", + "net.ipv4.ip_local_port_range", + "net.ipv4.tcp_syncookies", + } +} + // mustMatchPatterns implements the SysctlsStrategy interface type mustMatchPatterns struct { - patterns []string + safeWhitelist []string + allowedUnsafeSysctls []string + forbiddenSysctls []string } var ( @@ -38,56 +52,75 @@ var ( // NewMustMatchPatterns creates a new mustMatchPatterns strategy that will provide validation. // Passing nil means the default pattern, passing an empty list means to disallow all sysctls. -func NewMustMatchPatterns(patterns []string) SysctlsStrategy { - if patterns == nil { - patterns = defaultSysctlsPatterns - } +func NewMustMatchPatterns(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls []string) SysctlsStrategy { return &mustMatchPatterns{ - patterns: patterns, + safeWhitelist: safeWhitelist, + allowedUnsafeSysctls: allowedUnsafeSysctls, + forbiddenSysctls: forbiddenSysctls, } } +func (s *mustMatchPatterns) isForbidden(sysctlName string) bool { + // Is the sysctl forbidden? + for _, s := range s.forbiddenSysctls { + if strings.HasSuffix(s, "*") { + prefix := strings.TrimSuffix(s, "*") + if strings.HasPrefix(sysctlName, prefix) { + return true + } + } else if sysctlName == s { + return true + } + } + return false +} + +func (s *mustMatchPatterns) isSafe(sysctlName string) bool { + for _, ws := range s.safeWhitelist { + if sysctlName == ws { + return true + } + } + return false +} + +func (s *mustMatchPatterns) isAllowedUnsafe(sysctlName string) bool { + for _, s := range s.allowedUnsafeSysctls { + if strings.HasSuffix(s, "*") { + prefix := strings.TrimSuffix(s, "*") + if strings.HasPrefix(sysctlName, prefix) { + return true + } + } else if sysctlName == s { + return true + } + } + return false +} + // Validate ensures that the specified values fall within the range of the strategy. func (s *mustMatchPatterns) Validate(pod *api.Pod) field.ErrorList { allErrs := field.ErrorList{} - allErrs = append(allErrs, s.validateAnnotation(pod, api.SysctlsPodAnnotationKey)...) - allErrs = append(allErrs, s.validateAnnotation(pod, api.UnsafeSysctlsPodAnnotationKey)...) - return allErrs -} -func (s *mustMatchPatterns) validateAnnotation(pod *api.Pod, key string) field.ErrorList { - allErrs := field.ErrorList{} - - fieldPath := field.NewPath("pod", "metadata", "annotations").Key(key) - - sysctls, err := helper.SysctlsFromPodAnnotation(pod.Annotations[key]) - if err != nil { - allErrs = append(allErrs, field.Invalid(fieldPath, pod.Annotations[key], err.Error())) + var sysctls []api.Sysctl + if pod.Spec.SecurityContext != nil { + sysctls = pod.Spec.SecurityContext.Sysctls } - if len(sysctls) > 0 { - if len(s.patterns) == 0 { - allErrs = append(allErrs, field.Invalid(fieldPath, pod.Annotations[key], "sysctls are not allowed")) - } else { - for i, sysctl := range sysctls { - allErrs = append(allErrs, s.ValidateSysctl(sysctl.Name, fieldPath.Index(i))...) - } + fieldPath := field.NewPath("pod", "spec", "securityContext").Child("sysctls") + + for i, sysctl := range sysctls { + switch { + case s.isForbidden(sysctl.Name): + allErrs = append(allErrs, field.ErrorList{field.Forbidden(fieldPath.Index(i), fmt.Sprintf("sysctl %q is not allowed", sysctl.Name))}...) + case s.isSafe(sysctl.Name): + continue + case s.isAllowedUnsafe(sysctl.Name): + continue + default: + allErrs = append(allErrs, field.ErrorList{field.Forbidden(fieldPath.Index(i), fmt.Sprintf("unsafe sysctl %q is not allowed", sysctl.Name))}...) } } return allErrs } - -func (s *mustMatchPatterns) ValidateSysctl(sysctlName string, fldPath *field.Path) field.ErrorList { - for _, s := range s.patterns { - if s[len(s)-1] == '*' { - prefix := s[:len(s)-1] - if strings.HasPrefix(sysctlName, string(prefix)) { - return nil - } - } else if sysctlName == s { - return nil - } - } - return field.ErrorList{field.Forbidden(fldPath, fmt.Sprintf("sysctl %q is not allowed", sysctlName))} -} diff --git a/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns_test.go b/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns_test.go index 7622c826695..9bc7b0c6aff 100644 --- a/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns_test.go +++ b/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns_test.go @@ -17,48 +17,47 @@ limitations under the License. package sysctl import ( - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/helper" "testing" + + api "k8s.io/kubernetes/pkg/apis/core" ) func TestValidate(t *testing.T) { tests := map[string]struct { - patterns []string - allowed []string - disallowed []string + whitelist []string + forbiddenSafe []string + allowedUnsafe []string + allowed []string + disallowed []string }{ // no container requests - "nil": { - patterns: nil, - allowed: []string{"foo"}, + "with allow all": { + whitelist: []string{"foo"}, + allowed: []string{"foo"}, }, "empty": { - patterns: []string{}, - disallowed: []string{"foo"}, + whitelist: []string{"foo"}, + forbiddenSafe: []string{"*"}, + disallowed: []string{"foo"}, }, "without wildcard": { - patterns: []string{"a", "a.b"}, + whitelist: []string{"a", "a.b"}, allowed: []string{"a", "a.b"}, disallowed: []string{"b"}, }, - "with catch-all wildcard": { - patterns: []string{"*"}, - allowed: []string{"a", "a.b"}, - }, "with catch-all wildcard and non-wildcard": { - patterns: []string{"a.b.c", "*"}, - allowed: []string{"a", "a.b", "a.b.c", "b"}, + allowedUnsafe: []string{"a.b.c", "*"}, + allowed: []string{"a", "a.b", "a.b.c", "b"}, }, "without catch-all wildcard": { - patterns: []string{"a.*", "b.*", "c.d.e", "d.e.f.*"}, - allowed: []string{"a.b", "b.c", "c.d.e", "d.e.f.g.h"}, - disallowed: []string{"a", "b", "c", "c.d", "d.e", "d.e.f"}, + allowedUnsafe: []string{"a.*", "b.*", "c.d.e", "d.e.f.*"}, + allowed: []string{"a.b", "b.c", "c.d.e", "d.e.f.g.h"}, + disallowed: []string{"a", "b", "c", "c.d", "d.e", "d.e.f"}, }, } for k, v := range tests { - strategy := NewMustMatchPatterns(v.patterns) + strategy := NewMustMatchPatterns(v.whitelist, v.allowedUnsafe, v.forbiddenSafe) pod := &api.Pod{} errs := strategy.Validate(pod) @@ -66,37 +65,40 @@ func TestValidate(t *testing.T) { t.Errorf("%s: unexpected validaton errors for empty sysctls: %v", k, errs) } - sysctls := []api.Sysctl{} - for _, s := range v.allowed { - sysctls = append(sysctls, api.Sysctl{ - Name: s, - Value: "dummy", - }) - } - testAllowed := func(key string, category string) { - pod.Annotations = map[string]string{ - key: helper.PodAnnotationsFromSysctls(sysctls), + testAllowed := func() { + sysctls := []api.Sysctl{} + for _, s := range v.allowed { + sysctls = append(sysctls, api.Sysctl{ + Name: s, + Value: "dummy", + }) + } + pod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: sysctls, } errs = strategy.Validate(pod) if len(errs) != 0 { - t.Errorf("%s: unexpected validaton errors for %s sysctls: %v", k, category, errs) + t.Errorf("%s: unexpected validaton errors for sysctls: %v", k, errs) } } - testDisallowed := func(key string, category string) { + testDisallowed := func() { for _, s := range v.disallowed { - pod.Annotations = map[string]string{ - key: helper.PodAnnotationsFromSysctls([]api.Sysctl{{Name: s, Value: "dummy"}}), + pod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: []api.Sysctl{ + { + Name: s, + Value: "dummy", + }, + }, } errs = strategy.Validate(pod) if len(errs) == 0 { - t.Errorf("%s: expected error for %s sysctl %q", k, category, s) + t.Errorf("%s: expected error for sysctl %q", k, s) } } } - testAllowed(api.SysctlsPodAnnotationKey, "safe") - testAllowed(api.UnsafeSysctlsPodAnnotationKey, "unsafe") - testDisallowed(api.SysctlsPodAnnotationKey, "safe") - testDisallowed(api.UnsafeSysctlsPodAnnotationKey, "unsafe") + testAllowed() + testDisallowed() } } diff --git a/pkg/security/podsecuritypolicy/util/util.go b/pkg/security/podsecuritypolicy/util/util.go index 67643ccfd2e..3f29f6e7a44 100644 --- a/pkg/security/podsecuritypolicy/util/util.go +++ b/pkg/security/podsecuritypolicy/util/util.go @@ -175,23 +175,27 @@ func GroupFallsInRange(id int64, rng policy.IDRange) bool { // AllowsHostVolumePath is a utility for checking if a PSP allows the host volume path. // This only checks the path. You should still check to make sure the host volume fs type is allowed. -func AllowsHostVolumePath(psp *policy.PodSecurityPolicy, hostPath string) bool { +func AllowsHostVolumePath(psp *policy.PodSecurityPolicy, hostPath string) (pathIsAllowed, mustBeReadOnly bool) { if psp == nil { - return false + return false, false } // If no allowed paths are specified then allow any path if len(psp.Spec.AllowedHostPaths) == 0 { - return true + return true, false } for _, allowedPath := range psp.Spec.AllowedHostPaths { if hasPathPrefix(hostPath, allowedPath.PathPrefix) { - return true + if !allowedPath.ReadOnly { + return true, allowedPath.ReadOnly + } + pathIsAllowed = true + mustBeReadOnly = true } } - return false + return pathIsAllowed, mustBeReadOnly } // hasPathPrefix returns true if the string matches pathPrefix exactly, or if is prefixed with pathPrefix at a path segment boundary diff --git a/pkg/security/podsecuritypolicy/util/util_test.go b/pkg/security/podsecuritypolicy/util/util_test.go index 3f48db6f21b..f3d099d3089 100644 --- a/pkg/security/podsecuritypolicy/util/util_test.go +++ b/pkg/security/podsecuritypolicy/util/util_test.go @@ -17,10 +17,11 @@ limitations under the License. package util import ( - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/policy" "reflect" "testing" + + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/policy" ) // TestVolumeSourceFSTypeDrift ensures that for every known type of volume source (by the fields on @@ -105,41 +106,52 @@ func TestPSPAllowsFSType(t *testing.T) { func TestAllowsHostVolumePath(t *testing.T) { tests := map[string]struct { - psp *policy.PodSecurityPolicy - path string - allows bool + psp *policy.PodSecurityPolicy + path string + allows bool + mustBeReadOnly bool }{ "nil psp": { - psp: nil, - path: "/test", - allows: false, + psp: nil, + path: "/test", + allows: false, + mustBeReadOnly: false, }, "empty allowed paths": { - psp: &policy.PodSecurityPolicy{}, - path: "/test", - allows: true, + psp: &policy.PodSecurityPolicy{}, + path: "/test", + allows: true, + mustBeReadOnly: false, }, "non-matching": { psp: &policy.PodSecurityPolicy{ Spec: policy.PodSecurityPolicySpec{ AllowedHostPaths: []policy.AllowedHostPath{ - {PathPrefix: "/foo"}, + { + PathPrefix: "/foo", + ReadOnly: true, + }, }, }, }, - path: "/foobar", - allows: false, + path: "/foobar", + allows: false, + mustBeReadOnly: false, }, "match on direct match": { psp: &policy.PodSecurityPolicy{ Spec: policy.PodSecurityPolicySpec{ AllowedHostPaths: []policy.AllowedHostPath{ - {PathPrefix: "/foo"}, + { + PathPrefix: "/foo", + ReadOnly: true, + }, }, }, }, - path: "/foo", - allows: true, + path: "/foo", + allows: true, + mustBeReadOnly: true, }, "match with trailing slash on host path": { psp: &policy.PodSecurityPolicy{ @@ -149,8 +161,9 @@ func TestAllowsHostVolumePath(t *testing.T) { }, }, }, - path: "/foo/", - allows: true, + path: "/foo/", + allows: true, + mustBeReadOnly: false, }, "match with trailing slash on allowed path": { psp: &policy.PodSecurityPolicy{ @@ -160,19 +173,24 @@ func TestAllowsHostVolumePath(t *testing.T) { }, }, }, - path: "/foo", - allows: true, + path: "/foo", + allows: true, + mustBeReadOnly: false, }, "match child directory": { psp: &policy.PodSecurityPolicy{ Spec: policy.PodSecurityPolicySpec{ AllowedHostPaths: []policy.AllowedHostPath{ - {PathPrefix: "/foo/"}, + { + PathPrefix: "/foo/", + ReadOnly: true, + }, }, }, }, - path: "/foo/bar", - allows: true, + path: "/foo/bar", + allows: true, + mustBeReadOnly: true, }, "non-matching parent directory": { psp: &policy.PodSecurityPolicy{ @@ -182,15 +200,19 @@ func TestAllowsHostVolumePath(t *testing.T) { }, }, }, - path: "/foo", - allows: false, + path: "/foo", + allows: false, + mustBeReadOnly: false, }, } for k, v := range tests { - allows := AllowsHostVolumePath(v.psp, v.path) + allows, mustBeReadOnly := AllowsHostVolumePath(v.psp, v.path) if v.allows != allows { - t.Errorf("%s expected %t but got %t", k, v.allows, allows) + t.Errorf("allows: %s expected %t but got %t", k, v.allows, allows) + } + if v.mustBeReadOnly != mustBeReadOnly { + t.Errorf("mustBeReadOnly: %s expected %t but got %t", k, v.mustBeReadOnly, mustBeReadOnly) } } } diff --git a/pkg/util/BUILD b/pkg/util/BUILD index 1622fe7150d..27bee9d6cf6 100644 --- a/pkg/util/BUILD +++ b/pkg/util/BUILD @@ -45,6 +45,7 @@ filegroup( "//pkg/util/nsenter:all-srcs", "//pkg/util/oom:all-srcs", "//pkg/util/parsers:all-srcs", + "//pkg/util/pod:all-srcs", "//pkg/util/pointer:all-srcs", "//pkg/util/procfs:all-srcs", "//pkg/util/reflector/prometheus:all-srcs", diff --git a/pkg/util/initsystem/initsystem.go b/pkg/util/initsystem/initsystem.go index aca7a41b860..6638bab5eb2 100644 --- a/pkg/util/initsystem/initsystem.go +++ b/pkg/util/initsystem/initsystem.go @@ -44,15 +44,26 @@ type InitSystem interface { type SystemdInitSystem struct{} +func (sysd SystemdInitSystem) reloadSystemd() error { + if err := exec.Command("systemctl", "daemon-reload").Run(); err != nil { + return fmt.Errorf("failed to reload systemd: %v", err) + } + return nil +} + func (sysd SystemdInitSystem) ServiceStart(service string) error { + // Before we try to start any service, make sure that systemd is ready + if err := sysd.reloadSystemd(); err != nil { + return err + } args := []string{"start", service} - err := exec.Command("systemctl", args...).Run() - return err + return exec.Command("systemctl", args...).Run() } func (sysd SystemdInitSystem) ServiceRestart(service string) error { - if err := exec.Command("systemctl", "daemon-reload").Run(); err != nil { - return fmt.Errorf("failed to reload systemd: %v", err) + // Before we try to restart any service, make sure that systemd is ready + if err := sysd.reloadSystemd(); err != nil { + return err } args := []string{"restart", service} return exec.Command("systemctl", args...).Run() @@ -60,8 +71,7 @@ func (sysd SystemdInitSystem) ServiceRestart(service string) error { func (sysd SystemdInitSystem) ServiceStop(service string) error { args := []string{"stop", service} - err := exec.Command("systemctl", args...).Run() - return err + return exec.Command("systemctl", args...).Run() } func (sysd SystemdInitSystem) ServiceExists(service string) bool { diff --git a/pkg/util/io/writer.go b/pkg/util/io/writer.go index 4c0c1c4b37c..7c457d04a7d 100644 --- a/pkg/util/io/writer.go +++ b/pkg/util/io/writer.go @@ -50,18 +50,24 @@ func (writer *StdWriter) WriteFile(filename string, data []byte, perm os.FileMod // it will not see the mounted device in its own namespace. To work around this // limitation one has to first enter hosts namespace (by using 'nsenter') and // only then write data. -type NsenterWriter struct{} +type NsenterWriter struct { + ne *nsenter.Nsenter +} + +// NewNsenterWriter creates a new Writer that allows writing data to file using +// nsenter command. +func NewNsenterWriter(ne *nsenter.Nsenter) *NsenterWriter { + return &NsenterWriter{ + ne: ne, + } +} // WriteFile calls 'nsenter cat - > ' and 'nsenter chmod' to create a // file on the host. func (writer *NsenterWriter) WriteFile(filename string, data []byte, perm os.FileMode) error { - ne, err := nsenter.NewNsenter() - if err != nil { - return err - } echoArgs := []string{"-c", fmt.Sprintf("cat > %s", filename)} glog.V(5).Infof("nsenter: write data to file %s by nsenter", filename) - command := ne.Exec("sh", echoArgs) + command := writer.ne.Exec("sh", echoArgs) command.SetStdin(bytes.NewBuffer(data)) outputBytes, err := command.CombinedOutput() if err != nil { @@ -71,7 +77,7 @@ func (writer *NsenterWriter) WriteFile(filename string, data []byte, perm os.Fil chmodArgs := []string{fmt.Sprintf("%o", perm), filename} glog.V(5).Infof("nsenter: change permissions of file %s to %s", filename, chmodArgs[0]) - outputBytes, err = ne.Exec("chmod", chmodArgs).CombinedOutput() + outputBytes, err = writer.ne.Exec("chmod", chmodArgs).CombinedOutput() if err != nil { glog.Errorf("Output from chmod command: %v", string(outputBytes)) return err diff --git a/pkg/util/ipset/OWNERS b/pkg/util/ipset/OWNERS index 30a0de33f72..32ba0746b78 100644 --- a/pkg/util/ipset/OWNERS +++ b/pkg/util/ipset/OWNERS @@ -2,6 +2,7 @@ reviewers: - thockin - brendandburns - m1093782566 + - islinwb approvers: - thockin - brendandburns diff --git a/pkg/util/mount/BUILD b/pkg/util/mount/BUILD index 9040cd93b26..6f2df9acae8 100644 --- a/pkg/util/mount/BUILD +++ b/pkg/util/mount/BUILD @@ -71,12 +71,44 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ] + select({ + "@io_bazel_rules_go//go/platform:android": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "//pkg/util/nsenter:go_default_library", + ], "@io_bazel_rules_go//go/platform:linux": [ + "//pkg/util/file:go_default_library", "//pkg/util/io:go_default_library", "//pkg/util/nsenter:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", ], + "@io_bazel_rules_go//go/platform:nacl": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "//pkg/util/file:go_default_library", + "//pkg/util/nsenter:go_default_library", + ], "//conditions:default": [], }), ) @@ -101,7 +133,9 @@ go_test( "//vendor/k8s.io/utils/exec/testing:go_default_library", ] + select({ "@io_bazel_rules_go//go/platform:linux": [ + "//pkg/util/nsenter:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ], "@io_bazel_rules_go//go/platform:windows": [ diff --git a/pkg/util/mount/exec_mount.go b/pkg/util/mount/exec_mount.go index fcb948aa34e..fe7dcbd7ef9 100644 --- a/pkg/util/mount/exec_mount.go +++ b/pkg/util/mount/exec_mount.go @@ -136,7 +136,7 @@ func (m *execMounter) MakeDir(pathname string) error { return m.wrappedMounter.MakeDir(pathname) } -func (m *execMounter) ExistsPath(pathname string) bool { +func (m *execMounter) ExistsPath(pathname string) (bool, error) { return m.wrappedMounter.ExistsPath(pathname) } @@ -163,3 +163,7 @@ func (m *execMounter) GetFSGroup(pathname string) (int64, error) { func (m *execMounter) GetSELinuxSupport(pathname string) (bool, error) { return m.wrappedMounter.GetSELinuxSupport(pathname) } + +func (m *execMounter) GetMode(pathname string) (os.FileMode, error) { + return m.wrappedMounter.GetMode(pathname) +} diff --git a/pkg/util/mount/exec_mount_test.go b/pkg/util/mount/exec_mount_test.go index b3af0a46fbb..d6ccd844895 100644 --- a/pkg/util/mount/exec_mount_test.go +++ b/pkg/util/mount/exec_mount_test.go @@ -19,9 +19,7 @@ limitations under the License. package mount import ( - "errors" "fmt" - "os" "reflect" "strings" "testing" @@ -47,7 +45,7 @@ func TestMount(t *testing.T) { return nil, nil }) - wrappedMounter := &fakeMounter{t} + wrappedMounter := &fakeMounter{FakeMounter: &FakeMounter{}, t: t} mounter := NewExecMounter(exec, wrappedMounter) mounter.Mount(sourcePath, destinationPath, fsType, mountOptions) @@ -75,7 +73,7 @@ func TestBindMount(t *testing.T) { return nil, nil }) - wrappedMounter := &fakeMounter{t} + wrappedMounter := &fakeMounter{FakeMounter: &FakeMounter{}, t: t} mounter := NewExecMounter(exec, wrappedMounter) bindOptions := append(mountOptions, "bind") mounter.Mount(sourcePath, destinationPath, fsType, bindOptions) @@ -94,7 +92,7 @@ func TestUnmount(t *testing.T) { return nil, nil }) - wrappedMounter := &fakeMounter{t} + wrappedMounter := &fakeMounter{&FakeMounter{}, t} mounter := NewExecMounter(exec, wrappedMounter) mounter.Unmount(destinationPath) @@ -102,6 +100,7 @@ func TestUnmount(t *testing.T) { /* Fake wrapped mounter */ type fakeMounter struct { + *FakeMounter t *testing.T } @@ -116,63 +115,3 @@ func (fm *fakeMounter) Unmount(target string) error { fm.t.Errorf("Unexpected wrapped mount call") return fmt.Errorf("Unexpected wrapped mount call") } - -func (fm *fakeMounter) List() ([]MountPoint, error) { - return nil, nil -} -func (fm *fakeMounter) IsMountPointMatch(mp MountPoint, dir string) bool { - return false -} -func (fm *fakeMounter) IsNotMountPoint(file string) (bool, error) { - return false, nil -} -func (fm *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { - return false, nil -} -func (fm *fakeMounter) DeviceOpened(pathname string) (bool, error) { - return false, nil -} -func (fm *fakeMounter) PathIsDevice(pathname string) (bool, error) { - return false, nil -} -func (fm *fakeMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { - return "", nil -} -func (fm *fakeMounter) MakeRShared(path string) error { - return nil -} -func (fm *fakeMounter) MakeFile(pathname string) error { - return nil -} -func (fm *fakeMounter) MakeDir(pathname string) error { - return nil -} -func (fm *fakeMounter) ExistsPath(pathname string) bool { - return false -} -func (fm *fakeMounter) GetFileType(pathname string) (FileType, error) { - return FileTypeFile, nil -} -func (fm *fakeMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { - return subPath.Path, nil, nil -} - -func (fm *fakeMounter) CleanSubPaths(podDir string, volumeName string) error { - return nil -} - -func (fm *fakeMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { - return nil -} - -func (fm *fakeMounter) GetMountRefs(pathname string) ([]string, error) { - return nil, errors.New("not implemented") -} - -func (fm *fakeMounter) GetFSGroup(pathname string) (int64, error) { - return -1, errors.New("not implemented") -} - -func (fm *fakeMounter) GetSELinuxSupport(pathname string) (bool, error) { - return false, errors.New("not implemented") -} diff --git a/pkg/util/mount/exec_mount_unsupported.go b/pkg/util/mount/exec_mount_unsupported.go index cbb5bbc1591..6854b32b26c 100644 --- a/pkg/util/mount/exec_mount_unsupported.go +++ b/pkg/util/mount/exec_mount_unsupported.go @@ -83,8 +83,8 @@ func (mounter *execMounter) MakeFile(pathname string) error { return nil } -func (mounter *execMounter) ExistsPath(pathname string) bool { - return true +func (mounter *execMounter) ExistsPath(pathname string) (bool, error) { + return true, errors.New("not implemented") } func (mounter *execMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { @@ -110,3 +110,7 @@ func (mounter *execMounter) GetFSGroup(pathname string) (int64, error) { func (mounter *execMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } + +func (mounter *execMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/pkg/util/mount/fake.go b/pkg/util/mount/fake.go index f82f669b2eb..55c99c9fe3d 100644 --- a/pkg/util/mount/fake.go +++ b/pkg/util/mount/fake.go @@ -29,6 +29,7 @@ import ( type FakeMounter struct { MountPoints []MountPoint Log []FakeAction + Filesystem map[string]FileType // Some tests run things in parallel, make sure the mounter does not produce // any golang's DATA RACE warnings. mutex sync.Mutex @@ -190,6 +191,9 @@ func (f *FakeMounter) MakeRShared(path string) error { } func (f *FakeMounter) GetFileType(pathname string) (FileType, error) { + if t, ok := f.Filesystem[pathname]; ok { + return t, nil + } return FileType("fake"), nil } @@ -201,8 +205,11 @@ func (f *FakeMounter) MakeFile(pathname string) error { return nil } -func (f *FakeMounter) ExistsPath(pathname string) bool { - return false +func (f *FakeMounter) ExistsPath(pathname string) (bool, error) { + if _, ok := f.Filesystem[pathname]; ok { + return true, nil + } + return false, nil } func (f *FakeMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { @@ -232,3 +239,7 @@ func (f *FakeMounter) GetFSGroup(pathname string) (int64, error) { func (f *FakeMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("GetSELinuxSupport not implemented") } + +func (f *FakeMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/pkg/util/mount/mount.go b/pkg/util/mount/mount.go index 0c59ca9ebb7..f5ce194cac6 100644 --- a/pkg/util/mount/mount.go +++ b/pkg/util/mount/mount.go @@ -84,16 +84,18 @@ type Interface interface { // MakeDir creates a new directory. // Will operate in the host mount namespace if kubelet is running in a container MakeDir(pathname string) error - // SafeMakeDir makes sure that the created directory does not escape given - // base directory mis-using symlinks. The directory is created in the same - // mount namespace as where kubelet is running. Note that the function makes - // sure that it creates the directory somewhere under the base, nothing - // else. E.g. if the directory already exists, it may exists outside of the - // base due to symlinks. - SafeMakeDir(pathname string, base string, perm os.FileMode) error - // ExistsPath checks whether the path exists. - // Will operate in the host mount namespace if kubelet is running in a container - ExistsPath(pathname string) bool + // SafeMakeDir creates subdir within given base. It makes sure that the + // created directory does not escape given base directory mis-using + // symlinks. Note that the function makes sure that it creates the directory + // somewhere under the base, nothing else. E.g. if the directory already + // exists, it may exist outside of the base due to symlinks. + // This method should be used if the directory to create is inside volume + // that's under user control. User must not be able to use symlinks to + // escape the volume to create directories somewhere else. + SafeMakeDir(subdir string, base string, perm os.FileMode) error + // Will operate in the host mount namespace if kubelet is running in a container. + // Error is returned on any other error than "file not found". + ExistsPath(pathname string) (bool, error) // CleanSubPaths removes any bind-mounts created by PrepareSafeSubpath in given // pod volume directory. CleanSubPaths(podDir string, volumeName string) error @@ -117,6 +119,8 @@ type Interface interface { // GetSELinuxSupport returns true if given path is on a mount that supports // SELinux. GetSELinuxSupport(pathname string) (bool, error) + // GetMode returns permissions of the path. + GetMode(pathname string) (os.FileMode, error) } type Subpath struct { @@ -132,8 +136,6 @@ type Subpath struct { PodDir string // Name of the container ContainerName string - // True if the mount needs to be readonly - ReadOnly bool } // Exec executes command where mount utilities are. This can be either the host, diff --git a/pkg/util/mount/mount_linux.go b/pkg/util/mount/mount_linux.go index d60d6527e8e..e80dad590ad 100644 --- a/pkg/util/mount/mount_linux.go +++ b/pkg/util/mount/mount_linux.go @@ -33,6 +33,7 @@ import ( "github.com/golang/glog" "golang.org/x/sys/unix" "k8s.io/apimachinery/pkg/util/sets" + utilfile "k8s.io/kubernetes/pkg/util/file" utilio "k8s.io/kubernetes/pkg/util/io" utilexec "k8s.io/utils/exec" ) @@ -449,12 +450,8 @@ func (mounter *Mounter) MakeFile(pathname string) error { return nil } -func (mounter *Mounter) ExistsPath(pathname string) bool { - _, err := os.Stat(pathname) - if err != nil { - return false - } - return true +func (mounter *Mounter) ExistsPath(pathname string) (bool, error) { + return utilfile.FileExists(pathname) } // formatAndMount uses unix utils to format and mount the given disk @@ -760,7 +757,8 @@ func getSELinuxSupport(path string, mountInfoFilename string) (bool, error) { } func (mounter *Mounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { - newHostPath, err = doBindSubPath(mounter, subPath, os.Getpid()) + newHostPath, err = doBindSubPath(mounter, subPath) + // There is no action when the container starts. Bind-mount will be cleaned // when container stops by CleanSubPaths. cleanupAction = nil @@ -768,30 +766,107 @@ func (mounter *Mounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, } // This implementation is shared between Linux and NsEnterMounter -// kubeletPid is PID of kubelet in the PID namespace where bind-mount is done, -// i.e. pid on the *host* if kubelet runs in a container. -func doBindSubPath(mounter Interface, subpath Subpath, kubeletPid int) (hostPath string, err error) { - // Check early for symlink. This is just a pre-check to avoid bind-mount - // before the final check. - evalSubPath, err := filepath.EvalSymlinks(subpath.Path) +func safeOpenSubPath(mounter Interface, subpath Subpath) (int, error) { + if !pathWithinBase(subpath.Path, subpath.VolumePath) { + return -1, fmt.Errorf("subpath %q not within volume path %q", subpath.Path, subpath.VolumePath) + } + fd, err := doSafeOpen(subpath.Path, subpath.VolumePath) if err != nil { - return "", fmt.Errorf("evalSymlinks %q failed: %v", subpath.Path, err) + return -1, fmt.Errorf("error opening subpath %v: %v", subpath.Path, err) } - glog.V(5).Infof("doBindSubPath %q, full subpath %q for volumepath %q", subpath.Path, evalSubPath, subpath.VolumePath) + return fd, nil +} - evalSubPath = filepath.Clean(evalSubPath) - if !pathWithinBase(evalSubPath, subpath.VolumePath) { - return "", fmt.Errorf("subpath %q not within volume path %q", evalSubPath, subpath.VolumePath) +// prepareSubpathTarget creates target for bind-mount of subpath. It returns +// "true" when the target already exists and something is mounted there. +// Given Subpath must have all paths with already resolved symlinks and with +// paths relevant to kubelet (when it runs in a container). +// This function is called also by NsEnterMounter. It works because +// /var/lib/kubelet is mounted from the host into the container with Kubelet as +// /var/lib/kubelet too. +func prepareSubpathTarget(mounter Interface, subpath Subpath) (bool, string, error) { + // Early check for already bind-mounted subpath. + bindPathTarget := getSubpathBindTarget(subpath) + notMount, err := IsNotMountPoint(mounter, bindPathTarget) + if err != nil { + if !os.IsNotExist(err) { + return false, "", fmt.Errorf("error checking path %s for mount: %s", bindPathTarget, err) + } + // Ignore ErrorNotExist: the file/directory will be created below if it does not exist yet. + notMount = true + } + if !notMount { + // It's already mounted + glog.V(5).Infof("Skipping bind-mounting subpath %s: already mounted", bindPathTarget) + return true, bindPathTarget, nil } - // Prepare directory for bind mounts - // containerName is DNS label, i.e. safe as a directory name. - bindDir := filepath.Join(subpath.PodDir, containerSubPathDirectoryName, subpath.VolumeName, subpath.ContainerName) - err = os.MkdirAll(bindDir, 0750) + // bindPathTarget is in /var/lib/kubelet and thus reachable without any + // translation even to containerized kubelet. + bindParent := filepath.Dir(bindPathTarget) + err = os.MkdirAll(bindParent, 0750) if err != nil && !os.IsExist(err) { - return "", fmt.Errorf("error creating directory %s: %s", bindDir, err) + return false, "", fmt.Errorf("error creating directory %s: %s", bindParent, err) + } + + t, err := os.Lstat(subpath.Path) + if err != nil { + return false, "", fmt.Errorf("lstat %s failed: %s", subpath.Path, err) + } + + if t.Mode()&os.ModeDir > 0 { + if err = os.Mkdir(bindPathTarget, 0750); err != nil && !os.IsExist(err) { + return false, "", fmt.Errorf("error creating directory %s: %s", bindPathTarget, err) + } + } else { + // "/bin/touch ". + // A file is enough for all possible targets (symlink, device, pipe, + // socket, ...), bind-mounting them into a file correctly changes type + // of the target file. + if err = ioutil.WriteFile(bindPathTarget, []byte{}, 0640); err != nil { + return false, "", fmt.Errorf("error creating file %s: %s", bindPathTarget, err) + } + } + return false, bindPathTarget, nil +} + +func getSubpathBindTarget(subpath Subpath) string { + // containerName is DNS label, i.e. safe as a directory name. + return filepath.Join(subpath.PodDir, containerSubPathDirectoryName, subpath.VolumeName, subpath.ContainerName, strconv.Itoa(subpath.VolumeMountIndex)) +} + +func doBindSubPath(mounter Interface, subpath Subpath) (hostPath string, err error) { + // Linux, kubelet runs on the host: + // - safely open the subpath + // - bind-mount /proc//fd/ to subpath target + // User can't change /proc//fd/ to point to a bad place. + + // Evaluate all symlinks here once for all subsequent functions. + newVolumePath, err := filepath.EvalSymlinks(subpath.VolumePath) + if err != nil { + return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.VolumePath, err) + } + newPath, err := filepath.EvalSymlinks(subpath.Path) + if err != nil { + return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.Path, err) + } + glog.V(5).Infof("doBindSubPath %q (%q) for volumepath %q", subpath.Path, newPath, subpath.VolumePath) + subpath.VolumePath = newVolumePath + subpath.Path = newPath + + fd, err := safeOpenSubPath(mounter, subpath) + if err != nil { + return "", err + } + defer syscall.Close(fd) + + alreadyMounted, bindPathTarget, err := prepareSubpathTarget(mounter, subpath) + if err != nil { + return "", err + } + if alreadyMounted { + return bindPathTarget, nil } - bindPathTarget := filepath.Join(bindDir, strconv.Itoa(subpath.VolumeMountIndex)) success := false defer func() { @@ -804,63 +879,17 @@ func doBindSubPath(mounter Interface, subpath Subpath, kubeletPid int) (hostPath } }() - // Check it's not already bind-mounted - notMount, err := IsNotMountPoint(mounter, bindPathTarget) - if err != nil { - if !os.IsNotExist(err) { - return "", fmt.Errorf("error checking path %s for mount: %s", bindPathTarget, err) - } - // Ignore ErrorNotExist: the file/directory will be created below if it does not exist yet. - notMount = true - } - if !notMount { - // It's already mounted - glog.V(5).Infof("Skipping bind-mounting subpath %s: already mounted", bindPathTarget) - success = true - return bindPathTarget, nil - } - - // Create target of the bind mount. A directory for directories, empty file - // for everything else. - t, err := os.Lstat(subpath.Path) - if err != nil { - return "", fmt.Errorf("lstat %s failed: %s", subpath.Path, err) - } - if t.Mode()&os.ModeDir > 0 { - if err = os.Mkdir(bindPathTarget, 0750); err != nil && !os.IsExist(err) { - return "", fmt.Errorf("error creating directory %s: %s", bindPathTarget, err) - } - } else { - // "/bin/touch ". - // A file is enough for all possible targets (symlink, device, pipe, - // socket, ...), bind-mounting them into a file correctly changes type - // of the target file. - if err = ioutil.WriteFile(bindPathTarget, []byte{}, 0640); err != nil { - return "", fmt.Errorf("error creating file %s: %s", bindPathTarget, err) - } - } - - // Safe open subpath and get the fd - fd, err := doSafeOpen(evalSubPath, subpath.VolumePath) - if err != nil { - return "", fmt.Errorf("error opening subpath %v: %v", evalSubPath, err) - } - defer syscall.Close(fd) - + kubeletPid := os.Getpid() mountSource := fmt.Sprintf("/proc/%d/fd/%v", kubeletPid, fd) // Do the bind mount options := []string{"bind"} - if subpath.ReadOnly { - options = append(options, "ro") - } - glog.V(5).Infof("bind mounting %q at %q", mountSource, bindPathTarget) if err = mounter.Mount(mountSource, bindPathTarget, "" /*fstype*/, options); err != nil { return "", fmt.Errorf("error mounting %s: %s", subpath.Path, err) } - success = true + glog.V(3).Infof("Bound SubPath %s into %s", subpath.Path, bindPathTarget) return bindPathTarget, nil } @@ -995,8 +1024,15 @@ func removeEmptyDirs(baseDir, endDir string) error { return nil } -func (mounter *Mounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { - return doSafeMakeDir(pathname, base, perm) +func (mounter *Mounter) SafeMakeDir(subdir string, base string, perm os.FileMode) error { + realBase, err := filepath.EvalSymlinks(base) + if err != nil { + return fmt.Errorf("error resolving symlinks in %s: %s", base, err) + } + + realFullPath := filepath.Join(realBase, subdir) + + return doSafeMakeDir(realFullPath, realBase, perm) } func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) { @@ -1019,6 +1055,10 @@ func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) { return getFSGroup(realpath) } +func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) { + return getMode(pathname) +} + // This implementation is shared between Linux and NsEnterMounter func getFSGroup(pathname string) (int64, error) { info, err := os.Stat(pathname) @@ -1029,6 +1069,17 @@ func getFSGroup(pathname string) (int64, error) { } // This implementation is shared between Linux and NsEnterMounter +func getMode(pathname string) (os.FileMode, error) { + info, err := os.Stat(pathname) + if err != nil { + return 0, err + } + return info.Mode(), nil +} + +// This implementation is shared between Linux and NsEnterMounter. Both pathname +// and base must be either already resolved symlinks or thet will be resolved in +// kubelet's mount namespace (in case it runs containerized). func doSafeMakeDir(pathname string, base string, perm os.FileMode) error { glog.V(4).Infof("Creating directory %q within base %q", pathname, base) @@ -1182,6 +1233,9 @@ func findExistingPrefix(base, pathname string) (string, []string, error) { // Symlinks are disallowed (pathname must already resolve symlinks), // and the path must be within the base directory. func doSafeOpen(pathname string, base string) (int, error) { + pathname = filepath.Clean(pathname) + base = filepath.Clean(base) + // Calculate segments to follow subpath, err := filepath.Rel(base, pathname) if err != nil { diff --git a/pkg/util/mount/mount_linux_test.go b/pkg/util/mount/mount_linux_test.go index b9a1049a4f9..0324bf88d9d 100644 --- a/pkg/util/mount/mount_linux_test.go +++ b/pkg/util/mount/mount_linux_test.go @@ -1009,7 +1009,6 @@ func getTestPaths(base string) (string, string) { func TestBindSubPath(t *testing.T) { defaultPerm := os.FileMode(0750) - readOnlyPerm := os.FileMode(0444) tests := []struct { name string @@ -1017,7 +1016,6 @@ func TestBindSubPath(t *testing.T) { // base. prepare func(base string) ([]string, string, string, error) expectError bool - readOnly bool }{ { name: "subpath-dir", @@ -1193,10 +1191,6 @@ func TestBindSubPath(t *testing.T) { return nil, "", "", err } - if err := os.MkdirAll(subpathMount, defaultPerm); err != nil { - return nil, "", "", err - } - socketFile, socketCreateError := createSocketFile(volpath) return mounts, volpath, socketFile, socketCreateError @@ -1212,65 +1206,12 @@ func TestBindSubPath(t *testing.T) { return nil, "", "", err } - if err := os.MkdirAll(subpathMount, defaultPerm); err != nil { - return nil, "", "", err - } - testFifo := filepath.Join(volpath, "mount_test.fifo") err := syscall.Mkfifo(testFifo, 0) return mounts, volpath, testFifo, err }, expectError: false, }, - { - name: "subpath-dir-readonly", - prepare: func(base string) ([]string, string, string, error) { - volpath, _ := getTestPaths(base) - subpath := filepath.Join(volpath, "dir0") - return nil, volpath, subpath, os.MkdirAll(subpath, defaultPerm) - }, - expectError: false, - readOnly: true, - }, - { - name: "subpath-file-readonly", - prepare: func(base string) ([]string, string, string, error) { - volpath, _ := getTestPaths(base) - subpath := filepath.Join(volpath, "file0") - if err := os.MkdirAll(volpath, defaultPerm); err != nil { - return nil, "", "", err - } - return nil, volpath, subpath, ioutil.WriteFile(subpath, []byte{}, defaultPerm) - }, - expectError: false, - readOnly: true, - }, - { - name: "subpath-dir-and-volume-readonly", - prepare: func(base string) ([]string, string, string, error) { - volpath, _ := getTestPaths(base) - subpath := filepath.Join(volpath, "dir0") - if err := os.MkdirAll(subpath, defaultPerm); err != nil { - return nil, "", "", err - } - return nil, volpath, subpath, os.Chmod(subpath, readOnlyPerm) - }, - expectError: false, - readOnly: true, - }, - { - name: "subpath-file-and-vol-readonly", - prepare: func(base string) ([]string, string, string, error) { - volpath, _ := getTestPaths(base) - subpath := filepath.Join(volpath, "file0") - if err := os.MkdirAll(volpath, defaultPerm); err != nil { - return nil, "", "", err - } - return nil, volpath, subpath, ioutil.WriteFile(subpath, []byte{}, readOnlyPerm) - }, - expectError: false, - readOnly: true, - }, } for _, test := range tests { @@ -1295,11 +1236,10 @@ func TestBindSubPath(t *testing.T) { VolumePath: volPath, PodDir: filepath.Join(base, "pod0"), ContainerName: testContainer, - ReadOnly: test.readOnly, } _, subpathMount := getTestPaths(base) - bindPathTarget, err := doBindSubPath(fm, subpath, 1) + bindPathTarget, err := doBindSubPath(fm, subpath) if test.expectError { if err == nil { t.Errorf("test %q failed: expected error, got success", test.name) @@ -1321,39 +1261,12 @@ func TestBindSubPath(t *testing.T) { if err = validateFileExists(subpathMount); err != nil { t.Errorf("test %q failed: %v", test.name, err) } - if err = validateReadOnlyMount(test.readOnly, bindPathTarget, fm); err != nil { - t.Errorf("test %q failed: %v", test.name, err) - } } os.RemoveAll(base) } } -func validateReadOnlyMount(expectedReadOnly bool, bindPathTarget string, mounter *FakeMounter) error { - mps, err := mounter.List() - if err != nil { - return fmt.Errorf("fakeMounter.List() returned error: %v", err) - } - for _, mp := range mps { - if mp.Path == bindPathTarget { - foundReadOnly := false - for _, opts := range mp.Opts { - if opts == "ro" { - foundReadOnly = true - break - } - } - if expectedReadOnly != foundReadOnly { - return fmt.Errorf("expected readOnly %v, got %v for mount point %v", expectedReadOnly, foundReadOnly, bindPathTarget) - } else { - return nil - } - } - } - return fmt.Errorf("failed to find mountPoint %v", bindPathTarget) -} - func TestParseMountInfo(t *testing.T) { info := `62 0 253:0 / / rw,relatime shared:1 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered diff --git a/pkg/util/mount/mount_unsupported.go b/pkg/util/mount/mount_unsupported.go index 6e268e0f43d..6143aec1827 100644 --- a/pkg/util/mount/mount_unsupported.go +++ b/pkg/util/mount/mount_unsupported.go @@ -21,8 +21,6 @@ package mount import ( "errors" "os" - - "github.com/golang/glog" ) type Mounter struct { @@ -110,9 +108,8 @@ func (mounter *Mounter) MakeFile(pathname string) error { return unsupportedErr } -func (mounter *Mounter) ExistsPath(pathname string) bool { - glog.Errorf("%s", unsupportedErr) - return true +func (mounter *Mounter) ExistsPath(pathname string) (bool, error) { + return true, errors.New("not implemented") } func (mounter *Mounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { @@ -138,3 +135,7 @@ func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) { func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } + +func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/pkg/util/mount/mount_windows.go b/pkg/util/mount/mount_windows.go index f31f99bd66d..5c57a57d064 100644 --- a/pkg/util/mount/mount_windows.go +++ b/pkg/util/mount/mount_windows.go @@ -29,6 +29,8 @@ import ( "syscall" "github.com/golang/glog" + + utilfile "k8s.io/kubernetes/pkg/util/file" ) // Mounter provides the default implementation of mount.Interface @@ -147,9 +149,13 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) { if stat.Mode()&os.ModeSymlink != 0 { target, err := os.Readlink(file) if err != nil { - return true, fmt.Errorf("Readlink error: %v", err) + return true, fmt.Errorf("readlink error: %v", err) } - return !mounter.ExistsPath(target), nil + exists, err := mounter.ExistsPath(target) + if err != nil { + return true, err + } + return !exists, nil } return true, nil @@ -232,12 +238,8 @@ func (mounter *Mounter) MakeFile(pathname string) error { } // ExistsPath checks whether the path exists -func (mounter *Mounter) ExistsPath(pathname string) bool { - _, err := os.Stat(pathname) - if err != nil { - return false - } - return true +func (mounter *Mounter) ExistsPath(pathname string) (bool, error) { + return utilfile.FileExists(pathname) } // check whether hostPath is within volume path @@ -362,10 +364,23 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, glog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, source, target) if err := ValidateDiskNumber(source); err != nil { - glog.Errorf("azureMount: formatAndMount failed, err: %v\n", err) + glog.Errorf("diskMount: formatAndMount failed, err: %v", err) return err } + if len(fstype) == 0 { + // Use 'NTFS' as the default + fstype = "NTFS" + } + + // format disk if it is unformatted(raw) + cmd := fmt.Sprintf("Get-Disk -Number %s | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru"+ + " | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false", source, fstype) + if output, err := mounter.Exec.Run("powershell", "/c", cmd); err != nil { + return fmt.Errorf("diskMount: format disk failed, error: %v, output: %q", err, string(output)) + } + glog.V(4).Infof("diskMount: Disk successfully formatted, disk: %q, fstype: %q", source, fstype) + driveLetter, err := getDriveLetterByDiskNumber(source, mounter.Exec) if err != nil { return err @@ -461,9 +476,23 @@ func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) { return false, nil } +func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) { + info, err := os.Stat(pathname) + if err != nil { + return 0, err + } + return info.Mode(), nil +} + // SafeMakeDir makes sure that the created directory does not escape given base directory mis-using symlinks. -func (mounter *Mounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { - return doSafeMakeDir(pathname, base, perm) +func (mounter *Mounter) SafeMakeDir(subdir string, base string, perm os.FileMode) error { + realBase, err := filepath.EvalSymlinks(base) + if err != nil { + return fmt.Errorf("error resolving symlinks in %s: %s", base, err) + } + + realFullPath := filepath.Join(realBase, subdir) + return doSafeMakeDir(realFullPath, realBase, perm) } func doSafeMakeDir(pathname string, base string, perm os.FileMode) error { diff --git a/pkg/util/mount/mount_windows_test.go b/pkg/util/mount/mount_windows_test.go index 32b0903f183..a6e26bec8a6 100644 --- a/pkg/util/mount/mount_windows_test.go +++ b/pkg/util/mount/mount_windows_test.go @@ -24,6 +24,7 @@ import ( "os" "os/exec" "path/filepath" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -720,3 +721,75 @@ func TestIsLikelyNotMountPoint(t *testing.T) { } } } + +func TestFormatAndMount(t *testing.T) { + fakeMounter := ErrorMounter{&FakeMounter{}, 0, nil} + execCallback := func(cmd string, args ...string) ([]byte, error) { + for j := range args { + if strings.Contains(args[j], "Get-Disk -Number") { + return []byte("0"), nil + } + + if strings.Contains(args[j], "Get-Partition -DiskNumber") { + return []byte("0"), nil + } + + if strings.Contains(args[j], "mklink") { + return nil, nil + } + } + return nil, fmt.Errorf("Unexpected cmd %s, args %v", cmd, args) + } + fakeExec := NewFakeExec(execCallback) + + mounter := SafeFormatAndMount{ + Interface: &fakeMounter, + Exec: fakeExec, + } + + tests := []struct { + device string + target string + fstype string + mountOptions []string + expectError bool + }{ + { + "0", + "disk", + "NTFS", + []string{}, + false, + }, + { + "0", + "disk", + "", + []string{}, + false, + }, + { + "invalidDevice", + "disk", + "NTFS", + []string{}, + true, + }, + } + + for _, test := range tests { + base, err := ioutil.TempDir("", test.device) + if err != nil { + t.Fatalf(err.Error()) + } + defer os.RemoveAll(base) + + target := filepath.Join(base, test.target) + err = mounter.FormatAndMount(test.device, target, test.fstype, test.mountOptions) + if test.expectError { + assert.NotNil(t, err, "Expect error during FormatAndMount(%s, %s, %s, %v)", test.device, test.target, test.fstype, test.mountOptions) + } else { + assert.Nil(t, err, "Expect error is nil during FormatAndMount(%s, %s, %s, %v)", test.device, test.target, test.fstype, test.mountOptions) + } + } +} diff --git a/pkg/util/mount/nsenter_mount.go b/pkg/util/mount/nsenter_mount.go index 9b0464c329a..a122411cec2 100644 --- a/pkg/util/mount/nsenter_mount.go +++ b/pkg/util/mount/nsenter_mount.go @@ -22,12 +22,12 @@ import ( "fmt" "os" "path/filepath" - "regexp" - "strconv" "strings" + "syscall" "github.com/golang/glog" - utilio "k8s.io/kubernetes/pkg/util/io" + "golang.org/x/sys/unix" + utilfile "k8s.io/kubernetes/pkg/util/file" "k8s.io/kubernetes/pkg/util/nsenter" ) @@ -36,13 +36,6 @@ const ( hostProcMountsPath = "/rootfs/proc/1/mounts" // hostProcMountinfoPath is the default mount info path for rootfs hostProcMountinfoPath = "/rootfs/proc/1/mountinfo" - // hostProcSelfStatusPath is the default path to /proc/self/status on the host - hostProcSelfStatusPath = "/rootfs/proc/self/status" -) - -var ( - // pidRegExp matches "Pid: " in /proc/self/status - pidRegExp = regexp.MustCompile(`\nPid:\t([0-9]*)\n`) ) // Currently, all docker containers receive their own mount namespaces. @@ -50,14 +43,16 @@ var ( // the host's mount namespace. type NsenterMounter struct { ne *nsenter.Nsenter + // rootDir is location of /var/lib/kubelet directory. + rootDir string } -func NewNsenterMounter() (*NsenterMounter, error) { - ne, err := nsenter.NewNsenter() - if err != nil { - return nil, err +// NewNsenterMounter creates a new mounter for kubelet that runs as a container. +func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter { + return &NsenterMounter{ + rootDir: rootDir, + ne: ne, } - return &NsenterMounter{ne: ne}, nil } // NsenterMounter implements mount.Interface @@ -281,42 +276,24 @@ func (mounter *NsenterMounter) MakeFile(pathname string) error { return nil } -func (mounter *NsenterMounter) ExistsPath(pathname string) bool { - args := []string{pathname} - _, err := mounter.ne.Exec("ls", args).CombinedOutput() - if err == nil { - return true +func (mounter *NsenterMounter) ExistsPath(pathname string) (bool, error) { + // Resolve the symlinks but allow the target not to exist. EvalSymlinks + // would return an generic error when the target does not exist. + hostPath, err := mounter.ne.EvalSymlinks(pathname, false /* mustExist */) + if err != nil { + return false, err } - return false + kubeletpath := mounter.ne.KubeletPath(hostPath) + return utilfile.FileExists(kubeletpath) } func (mounter *NsenterMounter) CleanSubPaths(podDir string, volumeName string) error { return doCleanSubPaths(mounter, podDir, volumeName) } -// getPidOnHost returns kubelet's pid in the host pid namespace -func (mounter *NsenterMounter) getPidOnHost(procStatusPath string) (int, error) { - // Get the PID from /rootfs/proc/self/status - statusBytes, err := utilio.ConsistentRead(procStatusPath, maxListTries) - if err != nil { - return 0, fmt.Errorf("error reading %s: %s", procStatusPath, err) - } - matches := pidRegExp.FindSubmatch(statusBytes) - if len(matches) < 2 { - return 0, fmt.Errorf("cannot parse %s: no Pid:", procStatusPath) - } - return strconv.Atoi(string(matches[1])) -} - func (mounter *NsenterMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { - hostPid, err := mounter.getPidOnHost(hostProcSelfStatusPath) - if err != nil { - return "", nil, err - } - glog.V(4).Infof("Kubelet's PID on the host is %d", hostPid) - // Bind-mount the subpath to avoid using symlinks in subpaths. - newHostPath, err = doBindSubPath(mounter, subPath, hostPid) + newHostPath, err = doNsEnterBindSubPath(mounter, subPath) // There is no action when the container starts. Bind-mount will be cleaned // when container stops by CleanSubPaths. @@ -324,26 +301,152 @@ func (mounter *NsenterMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath return newHostPath, cleanupAction, err } -func (mounter *NsenterMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { - return doSafeMakeDir(pathname, base, perm) +func (mounter *NsenterMounter) SafeMakeDir(subdir string, base string, perm os.FileMode) error { + fullSubdirPath := filepath.Join(base, subdir) + evaluatedSubdirPath, err := mounter.ne.EvalSymlinks(fullSubdirPath, false /* mustExist */) + if err != nil { + return fmt.Errorf("error resolving symlinks in %s: %s", fullSubdirPath, err) + } + evaluatedSubdirPath = filepath.Clean(evaluatedSubdirPath) + + evaluatedBase, err := mounter.ne.EvalSymlinks(base, true /* mustExist */) + if err != nil { + return fmt.Errorf("error resolving symlinks in %s: %s", base, err) + } + evaluatedBase = filepath.Clean(evaluatedBase) + + rootDir := filepath.Clean(mounter.rootDir) + if pathWithinBase(evaluatedBase, rootDir) { + // Base is in /var/lib/kubelet. This directory is shared between the + // container with kubelet and the host. We don't need to add '/rootfs'. + // This is useful when /rootfs is mounted as read-only - we can still + // create subpaths for paths in /var/lib/kubelet. + return doSafeMakeDir(evaluatedSubdirPath, evaluatedBase, perm) + } + + // Base is somewhere on the host's filesystem. Add /rootfs and try to make + // the directory there. + // This requires /rootfs to be writable. + kubeletSubdirPath := mounter.ne.KubeletPath(evaluatedSubdirPath) + kubeletBase := mounter.ne.KubeletPath(evaluatedBase) + return doSafeMakeDir(kubeletSubdirPath, kubeletBase, perm) } func (mounter *NsenterMounter) GetMountRefs(pathname string) ([]string, error) { - hostpath, err := mounter.ne.EvalSymlinks(pathname) + hostpath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) if err != nil { return nil, err } - return searchMountPoints(hostpath, procMountInfoPath) + return searchMountPoints(hostpath, hostProcMountinfoPath) +} + +func doNsEnterBindSubPath(mounter *NsenterMounter, subpath Subpath) (hostPath string, err error) { + // Linux, kubelet runs in a container: + // - safely open the subpath + // - bind-mount the subpath to target (this can be unsafe) + // - check that we mounted the right thing by comparing device ID and inode + // of the subpath (via safely opened fd) and the target (that's under our + // control) + + // Evaluate all symlinks here once for all subsequent functions. + evaluatedHostVolumePath, err := mounter.ne.EvalSymlinks(subpath.VolumePath, true /*mustExist*/) + if err != nil { + return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.VolumePath, err) + } + evaluatedHostSubpath, err := mounter.ne.EvalSymlinks(subpath.Path, true /*mustExist*/) + if err != nil { + return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.Path, err) + } + glog.V(5).Infof("doBindSubPath %q (%q) for volumepath %q", subpath.Path, evaluatedHostSubpath, subpath.VolumePath) + subpath.VolumePath = mounter.ne.KubeletPath(evaluatedHostVolumePath) + subpath.Path = mounter.ne.KubeletPath(evaluatedHostSubpath) + + // Check the subpath is correct and open it + fd, err := safeOpenSubPath(mounter, subpath) + if err != nil { + return "", err + } + defer syscall.Close(fd) + + alreadyMounted, bindPathTarget, err := prepareSubpathTarget(mounter, subpath) + if err != nil { + return "", err + } + if alreadyMounted { + return bindPathTarget, nil + } + + success := false + defer func() { + // Cleanup subpath on error + if !success { + glog.V(4).Infof("doNsEnterBindSubPath() failed for %q, cleaning up subpath", bindPathTarget) + if cleanErr := cleanSubPath(mounter, subpath); cleanErr != nil { + glog.Errorf("Failed to clean subpath %q: %v", bindPathTarget, cleanErr) + } + } + }() + + // Leap of faith: optimistically expect that nobody has modified previously + // expanded evalSubPath with evil symlinks and bind-mount it. + // Mount is done on the host! don't use kubelet path! + glog.V(5).Infof("bind mounting %q at %q", evaluatedHostSubpath, bindPathTarget) + if err = mounter.Mount(evaluatedHostSubpath, bindPathTarget, "" /*fstype*/, []string{"bind"}); err != nil { + return "", fmt.Errorf("error mounting %s: %s", evaluatedHostSubpath, err) + } + + // Check that the bind-mount target is the same inode and device as the + // source that we keept open, i.e. we mounted the right thing. + err = checkDeviceInode(fd, bindPathTarget) + if err != nil { + return "", fmt.Errorf("error checking bind mount for subpath %s: %s", subpath.VolumePath, err) + } + + success = true + glog.V(3).Infof("Bound SubPath %s into %s", subpath.Path, bindPathTarget) + return bindPathTarget, nil +} + +// checkDeviceInode checks that opened file and path represent the same file. +func checkDeviceInode(fd int, path string) error { + var srcStat, dstStat unix.Stat_t + err := unix.Fstat(fd, &srcStat) + if err != nil { + return fmt.Errorf("error running fstat on subpath FD: %v", err) + } + + err = unix.Stat(path, &dstStat) + if err != nil { + return fmt.Errorf("error running fstat on %s: %v", path, err) + } + + if srcStat.Dev != dstStat.Dev { + return fmt.Errorf("different device number") + } + if srcStat.Ino != dstStat.Ino { + return fmt.Errorf("different inode") + } + return nil } func (mounter *NsenterMounter) GetFSGroup(pathname string) (int64, error) { - kubeletpath, err := mounter.ne.KubeletPath(pathname) + hostPath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) if err != nil { - return 0, err + return -1, err } + kubeletpath := mounter.ne.KubeletPath(hostPath) return getFSGroup(kubeletpath) } func (mounter *NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) { - return getSELinuxSupport(pathname, procMountInfoPath) + return getSELinuxSupport(pathname, hostProcMountsPath) +} + +func (mounter *NsenterMounter) GetMode(pathname string) (os.FileMode, error) { + hostPath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) + if err != nil { + return 0, err + } + kubeletpath := mounter.ne.KubeletPath(hostPath) + return getMode(kubeletpath) } diff --git a/pkg/util/mount/nsenter_mount_test.go b/pkg/util/mount/nsenter_mount_test.go index 2aee4ad5f9d..c541a4cdf74 100644 --- a/pkg/util/mount/nsenter_mount_test.go +++ b/pkg/util/mount/nsenter_mount_test.go @@ -21,9 +21,12 @@ package mount import ( "io/ioutil" "os" - "path" - "strconv" + "path/filepath" + "strings" "testing" + + "golang.org/x/sys/unix" + "k8s.io/kubernetes/pkg/util/nsenter" ) func TestParseFindMnt(t *testing.T) { @@ -72,120 +75,635 @@ func TestParseFindMnt(t *testing.T) { } } -func TestGetPidOnHost(t *testing.T) { - tempDir, err := ioutil.TempDir("", "get_pid_on_host_tests") +func TestCheckDeviceInode(t *testing.T) { + testDir, err := ioutil.TempDir("", "nsenter-mounter-device-") if err != nil { - t.Fatalf(err.Error()) + t.Fatalf("Cannot create temporary directory: %s", err) } - defer os.RemoveAll(tempDir) + defer os.RemoveAll(testDir) tests := []struct { name string - procFile string - expectedPid int - expectError bool + srcPath string + dstPath string + expectError string }{ { - name: "valid status file", - procFile: `Name: cat -Umask: 0002 -State: R (running) -Tgid: 15041 -Ngid: 0 -Pid: 15041 -PPid: 22699 -TracerPid: 0 -Uid: 1000 1000 1000 1000 -Gid: 1000 1000 1000 1000 -FDSize: 256 -Groups: 10 135 156 157 158 973 984 1000 1001 -NStgid: 15041 -NSpid: 15041 -NSpgid: 15041 -NSsid: 22699 -VmPeak: 115016 kB -VmSize: 115016 kB -VmLck: 0 kB -VmPin: 0 kB -VmHWM: 816 kB -VmRSS: 816 kB -RssAnon: 64 kB -RssFile: 752 kB -RssShmem: 0 kB -VmData: 312 kB -VmStk: 136 kB -VmExe: 32 kB -VmLib: 2060 kB -VmPTE: 44 kB -VmPMD: 12 kB -VmSwap: 0 kB -HugetlbPages: 0 kB -Threads: 1 -SigQ: 2/60752 -SigPnd: 0000000000000000 -ShdPnd: 0000000000000000 -SigBlk: 0000000000000000 -SigIgn: 0000000000000000 -SigCgt: 0000000000000000 -CapInh: 0000000000000000 -CapPrm: 0000000000000000 -CapEff: 0000000000000000 -CapBnd: 0000003fffffffff -CapAmb: 0000000000000000 -NoNewPrivs: 0 -Seccomp: 0 -Cpus_allowed: ff -Cpus_allowed_list: 0-7 -Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001 -Mems_allowed_list: 0 -voluntary_ctxt_switches: 0 -nonvoluntary_ctxt_switches: 0 -`, - expectedPid: 15041, + name: "the same file", + srcPath: filepath.Join(testDir, "1"), + dstPath: filepath.Join(testDir, "1"), + expectError: "", }, { - name: "no Pid:", - procFile: `Name: cat -Umask: 0002 -State: R (running) -Tgid: 15041 -Ngid: 0 -PPid: 22699 -`, - expectedPid: 0, - expectError: true, + name: "different file on the same FS", + srcPath: filepath.Join(testDir, "2.1"), + dstPath: filepath.Join(testDir, "2.2"), + expectError: "different inode", }, { - name: "invalid Pid:", - procFile: `Name: cat -Umask: 0002 -State: R (running) -Tgid: 15041 -Ngid: 0 -Pid: invalid -PPid: 22699 -`, - expectedPid: 0, - expectError: true, + name: "different file on different device", + srcPath: filepath.Join(testDir, "3"), + // /proc is always on a different "device" than /tmp (or $TEMP) + dstPath: "/proc/self/status", + expectError: "different device", }, } - for i, test := range tests { - filename := path.Join(tempDir, strconv.Itoa(i)) - err := ioutil.WriteFile(filename, []byte(test.procFile), 0666) - if err != nil { - t.Fatalf(err.Error()) + for _, test := range tests { + if err := ioutil.WriteFile(test.srcPath, []byte{}, 0644); err != nil { + t.Errorf("Test %q: cannot create srcPath %s: %s", test.name, test.srcPath, err) + continue } - mounter := NsenterMounter{} - pid, err := mounter.getPidOnHost(filename) + + // Don't create dst if it exists + if _, err := os.Stat(test.dstPath); os.IsNotExist(err) { + if err := ioutil.WriteFile(test.dstPath, []byte{}, 0644); err != nil { + t.Errorf("Test %q: cannot create dstPath %s: %s", test.name, test.dstPath, err) + continue + } + } else if err != nil { + t.Errorf("Test %q: cannot check existence of dstPath %s: %s", test.name, test.dstPath, err) + continue + } + + fd, err := unix.Open(test.srcPath, unix.O_CREAT, 0644) + if err != nil { + t.Errorf("Test %q: cannot open srcPath %s: %s", test.name, test.srcPath, err) + continue + } + + err = checkDeviceInode(fd, test.dstPath) + + if test.expectError == "" && err != nil { + t.Errorf("Test %q: expected no error, got %s", test.name, err) + } + if test.expectError != "" { + if err == nil { + t.Errorf("Test %q: expected error, got none", test.name) + } else { + if !strings.Contains(err.Error(), test.expectError) { + t.Errorf("Test %q: expected error %q, got %q", test.name, test.expectError, err) + } + } + } + } +} + +func newFakeNsenterMounter(tmpdir string, t *testing.T) (mounter *NsenterMounter, rootfsPath string, varlibPath string, err error) { + rootfsPath = filepath.Join(tmpdir, "rootfs") + if err := os.Mkdir(rootfsPath, 0755); err != nil { + return nil, "", "", err + } + ne, err := nsenter.NewFakeNsenter(rootfsPath) + if err != nil { + return nil, "", "", err + } + + varlibPath = filepath.Join(tmpdir, "/var/lib/kubelet") + if err := os.MkdirAll(varlibPath, 0755); err != nil { + return nil, "", "", err + } + + return NewNsenterMounter(varlibPath, ne), rootfsPath, varlibPath, nil +} + +func TestNsenterExistsFile(t *testing.T) { + tests := []struct { + name string + prepare func(base, rootfs string) (string, error) + expectedOutput bool + expectError bool + }{ + { + name: "simple existing file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/file + path := filepath.Join(base, "file") + if err := ioutil.WriteFile(path, []byte{}, 0644); err != nil { + return "", err + } + // In kubelet: /rootfs/base/file + if _, err := writeRootfsFile(rootfs, path, 0644); err != nil { + return "", err + } + return path, nil + }, + expectedOutput: true, + }, + { + name: "simple non-existing file", + prepare: func(base, rootfs string) (string, error) { + path := filepath.Join(base, "file") + return path, nil + }, + expectedOutput: false, + }, + { + name: "simple non-accessible file", + prepare: func(base, rootfs string) (string, error) { + // On the host: + // create /base/dir/file, then make the dir inaccessible + dir := filepath.Join(base, "dir") + if err := os.MkdirAll(dir, 0755); err != nil { + return "", err + } + path := filepath.Join(dir, "file") + if err := ioutil.WriteFile(path, []byte{}, 0); err != nil { + return "", err + } + if err := os.Chmod(dir, 0644); err != nil { + return "", err + } + + // In kubelet: do the same with /rootfs/base/dir/file + rootfsPath, err := writeRootfsFile(rootfs, path, 0777) + if err != nil { + return "", err + } + rootfsDir := filepath.Dir(rootfsPath) + if err := os.Chmod(rootfsDir, 0644); err != nil { + return "", err + } + + return path, nil + }, + expectedOutput: false, + expectError: true, + }, + { + name: "relative symlink to existing file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/link -> file + file := filepath.Join(base, "file") + if err := ioutil.WriteFile(file, []byte{}, 0); err != nil { + return "", err + } + path := filepath.Join(base, "link") + if err := os.Symlink("file", path); err != nil { + return "", err + } + // In kubelet: /rootfs/base/file + if _, err := writeRootfsFile(rootfs, file, 0644); err != nil { + return "", err + } + return path, nil + }, + expectedOutput: true, + }, + { + name: "absolute symlink to existing file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/link -> /base/file + file := filepath.Join(base, "file") + if err := ioutil.WriteFile(file, []byte{}, 0); err != nil { + return "", err + } + path := filepath.Join(base, "link") + if err := os.Symlink(file, path); err != nil { + return "", err + } + // In kubelet: /rootfs/base/file + if _, err := writeRootfsFile(rootfs, file, 0644); err != nil { + return "", err + } + + return path, nil + }, + expectedOutput: true, + }, + { + name: "relative symlink to non-existing file", + prepare: func(base, rootfs string) (string, error) { + path := filepath.Join(base, "link") + if err := os.Symlink("file", path); err != nil { + return "", err + } + return path, nil + }, + expectedOutput: false, + }, + { + name: "absolute symlink to non-existing file", + prepare: func(base, rootfs string) (string, error) { + file := filepath.Join(base, "file") + path := filepath.Join(base, "link") + if err := os.Symlink(file, path); err != nil { + return "", err + } + return path, nil + }, + expectedOutput: false, + }, + { + name: "symlink loop", + prepare: func(base, rootfs string) (string, error) { + path := filepath.Join(base, "link") + if err := os.Symlink(path, path); err != nil { + return "", err + } + return path, nil + }, + expectedOutput: false, + // TODO: realpath -m is not able to detect symlink loop. Should we care? + expectError: false, + }, + } + + for _, test := range tests { + tmpdir, err := ioutil.TempDir("", "nsenter-exists-file") + if err != nil { + t.Error(err) + continue + } + defer os.RemoveAll(tmpdir) + + testBase := filepath.Join(tmpdir, "base") + if err := os.Mkdir(testBase, 0755); err != nil { + t.Error(err) + continue + } + + mounter, rootfs, _, err := newFakeNsenterMounter(tmpdir, t) + if err != nil { + t.Error(err) + continue + } + + path, err := test.prepare(testBase, rootfs) + if err != nil { + t.Error(err) + continue + } + + out, err := mounter.ExistsPath(path) if err != nil && !test.expectError { t.Errorf("Test %q: unexpected error: %s", test.name, err) } if err == nil && test.expectError { t.Errorf("Test %q: expected error, got none", test.name) } - if pid != test.expectedPid { - t.Errorf("Test %q: expected pid %d, got %d", test.name, test.expectedPid, pid) + + if out != test.expectedOutput { + t.Errorf("Test %q: expected return value %v, got %v", test.name, test.expectedOutput, out) + } + } +} + +func TestNsenterGetMode(t *testing.T) { + tests := []struct { + name string + prepare func(base, rootfs string) (string, error) + expectedMode os.FileMode + expectError bool + }{ + { + name: "simple file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/file + path := filepath.Join(base, "file") + if err := ioutil.WriteFile(path, []byte{}, 0644); err != nil { + return "", err + } + + // Prepare a different file as /rootfs/base/file (="the host + // visible from container") to check that NsEnterMounter calls + // stat on this file and not on /base/file. + // Visible from kubelet: /rootfs/base/file + if _, err := writeRootfsFile(rootfs, path, 0777); err != nil { + return "", err + } + + return path, nil + }, + expectedMode: 0777, + }, + { + name: "non-existing file", + prepare: func(base, rootfs string) (string, error) { + path := filepath.Join(base, "file") + return path, nil + }, + expectedMode: 0, + expectError: true, + }, + { + name: "absolute symlink to existing file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/link -> /base/file + file := filepath.Join(base, "file") + if err := ioutil.WriteFile(file, []byte{}, 0644); err != nil { + return "", err + } + path := filepath.Join(base, "link") + if err := os.Symlink(file, path); err != nil { + return "", err + } + + // Visible from kubelet: + // /rootfs/base/file + if _, err := writeRootfsFile(rootfs, file, 0747); err != nil { + return "", err + } + + return path, nil + }, + expectedMode: 0747, + }, + { + name: "relative symlink to existing file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/link -> file + file := filepath.Join(base, "file") + if err := ioutil.WriteFile(file, []byte{}, 0741); err != nil { + return "", err + } + path := filepath.Join(base, "link") + if err := os.Symlink("file", path); err != nil { + return "", err + } + + // Visible from kubelet: + // /rootfs/base/file + if _, err := writeRootfsFile(rootfs, file, 0647); err != nil { + return "", err + } + + return path, nil + }, + expectedMode: 0647, + }, + } + + for _, test := range tests { + tmpdir, err := ioutil.TempDir("", "nsenter-get-mode-") + if err != nil { + t.Error(err) + continue + } + defer os.RemoveAll(tmpdir) + + testBase := filepath.Join(tmpdir, "base") + if err := os.Mkdir(testBase, 0755); err != nil { + t.Error(err) + continue + } + + mounter, rootfs, _, err := newFakeNsenterMounter(tmpdir, t) + if err != nil { + t.Error(err) + continue + } + + path, err := test.prepare(testBase, rootfs) + if err != nil { + t.Error(err) + continue + } + + mode, err := mounter.GetMode(path) + if err != nil && !test.expectError { + t.Errorf("Test %q: unexpected error: %s", test.name, err) + } + if err == nil && test.expectError { + t.Errorf("Test %q: expected error, got none", test.name) + } + + if mode != test.expectedMode { + t.Errorf("Test %q: expected return value %v, got %v", test.name, test.expectedMode, mode) + } + } +} + +func writeRootfsFile(rootfs, path string, mode os.FileMode) (string, error) { + fullPath := filepath.Join(rootfs, path) + dir := filepath.Dir(fullPath) + if err := os.MkdirAll(dir, 0755); err != nil { + return "", err + } + if err := ioutil.WriteFile(fullPath, []byte{}, mode); err != nil { + return "", err + } + // Use chmod, io.WriteFile is affected by umask + if err := os.Chmod(fullPath, mode); err != nil { + return "", err + } + return fullPath, nil +} + +func TestNsenterSafeMakeDir(t *testing.T) { + tests := []struct { + name string + prepare func(base, rootfs, varlib string) (expectedDir string, err error) + subdir string + expectError bool + // If true, "base" directory for SafeMakeDir will be /var/lib/kubelet + baseIsVarLib bool + }{ + { + name: "simple directory", + // evaluated in base + subdir: "some/subdirectory/structure", + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // expected to be created in /roots/ + expectedDir = filepath.Join(rootfs, base, "some/subdirectory/structure") + return expectedDir, nil + }, + }, + { + name: "simple existing directory", + // evaluated in base + subdir: "some/subdirectory/structure", + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: directory exists + hostPath := filepath.Join(base, "some/subdirectory/structure") + if err := os.MkdirAll(hostPath, 0755); err != nil { + return "", err + } + // In rootfs: directory exists + kubeletPath := filepath.Join(rootfs, hostPath) + if err := os.MkdirAll(kubeletPath, 0755); err != nil { + return "", err + } + // expected to be created in /roots/ + expectedDir = kubeletPath + return expectedDir, nil + }, + }, + { + name: "absolute symlink into safe place", + // evaluated in base + subdir: "some/subdirectory/structure", + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: /base/other/subdirectory exists, /base/some is link to /base/other + hostPath := filepath.Join(base, "other/subdirectory") + if err := os.MkdirAll(hostPath, 0755); err != nil { + return "", err + } + somePath := filepath.Join(base, "some") + otherPath := filepath.Join(base, "other") + if err := os.Symlink(otherPath, somePath); err != nil { + return "", err + } + + // In rootfs: /base/other/subdirectory exists + kubeletPath := filepath.Join(rootfs, hostPath) + if err := os.MkdirAll(kubeletPath, 0755); err != nil { + return "", err + } + // expected 'structure' to be created + expectedDir = filepath.Join(rootfs, hostPath, "structure") + return expectedDir, nil + }, + }, + { + name: "relative symlink into safe place", + // evaluated in base + subdir: "some/subdirectory/structure", + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: /base/other/subdirectory exists, /base/some is link to other + hostPath := filepath.Join(base, "other/subdirectory") + if err := os.MkdirAll(hostPath, 0755); err != nil { + return "", err + } + somePath := filepath.Join(base, "some") + if err := os.Symlink("other", somePath); err != nil { + return "", err + } + + // In rootfs: /base/other/subdirectory exists + kubeletPath := filepath.Join(rootfs, hostPath) + if err := os.MkdirAll(kubeletPath, 0755); err != nil { + return "", err + } + // expected 'structure' to be created + expectedDir = filepath.Join(rootfs, hostPath, "structure") + return expectedDir, nil + }, + }, + { + name: "symlink into unsafe place", + // evaluated in base + subdir: "some/subdirectory/structure", + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: /base/some is link to /bin/other + somePath := filepath.Join(base, "some") + if err := os.Symlink("/bin", somePath); err != nil { + return "", err + } + return "", nil + }, + expectError: true, + }, + { + name: "simple directory in /var/lib/kubelet", + // evaluated in varlib + subdir: "some/subdirectory/structure", + baseIsVarLib: true, + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // expected to be created in /base/var/lib/kubelet, not in /rootfs! + expectedDir = filepath.Join(varlib, "some/subdirectory/structure") + return expectedDir, nil + }, + }, + { + name: "safe symlink in /var/lib/kubelet", + // evaluated in varlib + subdir: "some/subdirectory/structure", + baseIsVarLib: true, + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: /varlib/kubelet/other/subdirectory exists, /varlib/some is link to other + hostPath := filepath.Join(varlib, "other/subdirectory") + if err := os.MkdirAll(hostPath, 0755); err != nil { + return "", err + } + somePath := filepath.Join(varlib, "some") + if err := os.Symlink("other", somePath); err != nil { + return "", err + } + + // expected to be created in /base/var/lib/kubelet, not in /rootfs! + expectedDir = filepath.Join(varlib, "other/subdirectory/structure") + return expectedDir, nil + }, + }, + { + name: "unsafe symlink in /var/lib/kubelet", + // evaluated in varlib + subdir: "some/subdirectory/structure", + baseIsVarLib: true, + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: /varlib/some is link to /bin + somePath := filepath.Join(varlib, "some") + if err := os.Symlink("/bin", somePath); err != nil { + return "", err + } + + return "", nil + }, + expectError: true, + }, + } + for _, test := range tests { + tmpdir, err := ioutil.TempDir("", "nsenter-get-mode-") + if err != nil { + t.Error(err) + continue + } + defer os.RemoveAll(tmpdir) + + mounter, rootfs, varlib, err := newFakeNsenterMounter(tmpdir, t) + if err != nil { + t.Error(err) + continue + } + // Prepare base directory for the test + testBase := filepath.Join(tmpdir, "base") + if err := os.Mkdir(testBase, 0755); err != nil { + t.Error(err) + continue + } + // Prepare base directory also in /rootfs + rootfsBase := filepath.Join(rootfs, testBase) + if err := os.MkdirAll(rootfsBase, 0755); err != nil { + t.Error(err) + continue + } + + expectedDir := "" + if test.prepare != nil { + expectedDir, err = test.prepare(testBase, rootfs, varlib) + if err != nil { + t.Error(err) + continue + } + } + + if test.baseIsVarLib { + // use /var/lib/kubelet as the test base so we can test creating + // subdirs there directly in /var/lib/kubenet and not in + // /rootfs/var/lib/kubelet + testBase = varlib + } + + err = mounter.SafeMakeDir(test.subdir, testBase, 0755) + if err != nil && !test.expectError { + t.Errorf("Test %q: unexpected error: %s", test.name, err) + } + if test.expectError { + if err == nil { + t.Errorf("Test %q: expected error, got none", test.name) + } else { + if !strings.Contains(err.Error(), "is outside of allowed base") { + t.Errorf("Test %q: expected error to contain \"is outside of allowed base\", got this one instead: %s", test.name, err) + } + } + } + + if expectedDir != "" { + _, err := os.Stat(expectedDir) + if err != nil { + t.Errorf("Test %q: expected %q to exist, got error: %s", test.name, expectedDir, err) + } } } } diff --git a/pkg/util/mount/nsenter_mount_unsupported.go b/pkg/util/mount/nsenter_mount_unsupported.go index 8cf79de472c..f417ba9bc15 100644 --- a/pkg/util/mount/nsenter_mount_unsupported.go +++ b/pkg/util/mount/nsenter_mount_unsupported.go @@ -21,12 +21,14 @@ package mount import ( "errors" "os" + + "k8s.io/kubernetes/pkg/util/nsenter" ) type NsenterMounter struct{} -func NewNsenterMounter() (*NsenterMounter, error) { - return &NsenterMounter{}, nil +func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter { + return &NsenterMounter{} } var _ = Interface(&NsenterMounter{}) @@ -83,8 +85,8 @@ func (*NsenterMounter) MakeFile(pathname string) error { return nil } -func (*NsenterMounter) ExistsPath(pathname string) bool { - return true +func (*NsenterMounter) ExistsPath(pathname string) (bool, error) { + return true, errors.New("not implemented") } func (*NsenterMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { @@ -110,3 +112,7 @@ func (*NsenterMounter) GetFSGroup(pathname string) (int64, error) { func (*NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } + +func (*NsenterMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/pkg/util/nsenter/BUILD b/pkg/util/nsenter/BUILD index 988fef01b59..286b8882773 100644 --- a/pkg/util/nsenter/BUILD +++ b/pkg/util/nsenter/BUILD @@ -1,4 +1,4 @@ -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", @@ -92,3 +92,20 @@ filegroup( tags = ["automanaged"], visibility = ["//visibility:public"], ) + +go_test( + name = "go_default_test", + srcs = select({ + "@io_bazel_rules_go//go/platform:linux": [ + "nsenter_test.go", + ], + "//conditions:default": [], + }), + embed = [":go_default_library"], + deps = select({ + "@io_bazel_rules_go//go/platform:linux": [ + "//vendor/k8s.io/utils/exec:go_default_library", + ], + "//conditions:default": [], + }), +) diff --git a/pkg/util/nsenter/OWNERS b/pkg/util/nsenter/OWNERS new file mode 100644 index 00000000000..c4f27cb4381 --- /dev/null +++ b/pkg/util/nsenter/OWNERS @@ -0,0 +1,8 @@ +reviewers: + - jsafrane + - msau42 + - cofyc +approvers: + - jsafrane + - msau42 + - cofyc diff --git a/pkg/util/nsenter/nsenter.go b/pkg/util/nsenter/nsenter.go index 11e9fe4a6dc..e928a57ac9f 100644 --- a/pkg/util/nsenter/nsenter.go +++ b/pkg/util/nsenter/nsenter.go @@ -19,6 +19,8 @@ limitations under the License. package nsenter import ( + "context" + "errors" "fmt" "os" "path/filepath" @@ -30,9 +32,11 @@ import ( ) const ( - hostRootFsPath = "/rootfs" - // hostProcMountNsPath is the default mount namespace for rootfs - hostProcMountNsPath = "/rootfs/proc/1/ns/mnt" + // DefaultHostRootFsPath is path to host's filesystem mounted into container + // with kubelet. + DefaultHostRootFsPath = "/rootfs" + // mountNsPath is the default mount namespace of the host + mountNsPath = "/proc/1/ns/mnt" // nsenterPath is the default nsenter command nsenterPath = "nsenter" ) @@ -65,30 +69,46 @@ const ( type Nsenter struct { // a map of commands to their paths on the host filesystem paths map[string]string + + // Path to the host filesystem, typically "/rootfs". Used only for testing. + hostRootFsPath string + + // Exec implementation, used only for testing + executor exec.Interface } // NewNsenter constructs a new instance of Nsenter -func NewNsenter() (*Nsenter, error) { +func NewNsenter(hostRootFsPath string, executor exec.Interface) (*Nsenter, error) { ne := &Nsenter{ - paths: map[string]string{ - "mount": "", - "findmnt": "", - "umount": "", - "systemd-run": "", - "stat": "", - "touch": "", - "mkdir": "", - "ls": "", - "sh": "", - "chmod": "", - }, + hostRootFsPath: hostRootFsPath, + executor: executor, + } + if err := ne.initPaths(); err != nil { + return nil, err + } + return ne, nil +} + +func (ne *Nsenter) initPaths() error { + ne.paths = map[string]string{} + binaries := []string{ + "mount", + "findmnt", + "umount", + "systemd-run", + "stat", + "touch", + "mkdir", + "sh", + "chmod", + "realpath", } // search for the required commands in other locations besides /usr/bin - for binary := range ne.paths { + for _, binary := range binaries { // check for binary under the following directories for _, path := range []string{"/", "/bin", "/usr/sbin", "/usr/bin"} { binPath := filepath.Join(path, binary) - if _, err := os.Stat(filepath.Join(hostRootFsPath, binPath)); err != nil { + if _, err := os.Stat(filepath.Join(ne.hostRootFsPath, binPath)); err != nil { continue } ne.paths[binary] = binPath @@ -96,19 +116,19 @@ func NewNsenter() (*Nsenter, error) { } // systemd-run is optional, bailout if we don't find any of the other binaries if ne.paths[binary] == "" && binary != "systemd-run" { - return nil, fmt.Errorf("unable to find %v", binary) + return fmt.Errorf("unable to find %v", binary) } } - return ne, nil + return nil } // Exec executes nsenter commands in hostProcMountNsPath mount namespace func (ne *Nsenter) Exec(cmd string, args []string) exec.Cmd { + hostProcMountNsPath := filepath.Join(ne.hostRootFsPath, mountNsPath) fullArgs := append([]string{fmt.Sprintf("--mount=%s", hostProcMountNsPath), "--"}, append([]string{ne.AbsHostPath(cmd)}, args...)...) glog.V(5).Infof("Running nsenter command: %v %v", nsenterPath, fullArgs) - exec := exec.New() - return exec.Command(nsenterPath, fullArgs...) + return ne.executor.Command(nsenterPath, fullArgs...) } // AbsHostPath returns the absolute runnable path for a specified command @@ -128,8 +148,26 @@ func (ne *Nsenter) SupportsSystemd() (string, bool) { // EvalSymlinks returns the path name on the host after evaluating symlinks on the // host. -func (ne *Nsenter) EvalSymlinks(pathname string) (string, error) { - args := []string{"-m", pathname} +// mustExist makes EvalSymlinks to return error when the path does not +// exist. When it's false, it evaluates symlinks of the existing part and +// blindly adds the non-existing part: +// pathname: /mnt/volume/non/existing/directory +// /mnt/volume exists +// non/existing/directory does not exist +// -> It resolves symlinks in /mnt/volume to say /mnt/foo and returns +// /mnt/foo/non/existing/directory. +// +// BEWARE! EvalSymlinks is not able to detect symlink looks with mustExist=false! +// If /tmp/link is symlink to /tmp/link, EvalSymlinks(/tmp/link/foo) returns /tmp/link/foo. +func (ne *Nsenter) EvalSymlinks(pathname string, mustExist bool) (string, error) { + var args []string + if mustExist { + // "realpath -e: all components of the path must exist" + args = []string{"-e", pathname} + } else { + // "realpath -m: no path components need exist or be a directory" + args = []string{"-m", pathname} + } outBytes, err := ne.Exec("realpath", args).CombinedOutput() if err != nil { glog.Infof("failed to resolve symbolic links on %s: %v", pathname, err) @@ -139,11 +177,60 @@ func (ne *Nsenter) EvalSymlinks(pathname string) (string, error) { } // KubeletPath returns the path name that can be accessed by containerized -// kubelet, after evaluating symlinks on the host. -func (ne *Nsenter) KubeletPath(pathname string) (string, error) { - hostpath, err := ne.EvalSymlinks(pathname) - if err != nil { - return "", err - } - return filepath.Join(hostRootFsPath, hostpath), nil +// kubelet. It is recommended to resolve symlinks on the host by EvalSymlinks +// before calling this function +func (ne *Nsenter) KubeletPath(pathname string) string { + return filepath.Join(ne.hostRootFsPath, pathname) } + +// NewFakeNsenter returns a Nsenter that does not run "nsenter --mount=... --", +// but runs everything in the same mount namespace as the unit test binary. +// rootfsPath is supposed to be a symlink, e.g. /tmp/xyz/rootfs -> /. +// This fake Nsenter is enough for most operations, e.g. to resolve symlinks, +// but it's not enough to call /bin/mount - unit tests don't run as root. +func NewFakeNsenter(rootfsPath string) (*Nsenter, error) { + executor := &fakeExec{ + rootfsPath: rootfsPath, + } + // prepare /rootfs/bin, usr/bin and usr/sbin + bin := filepath.Join(rootfsPath, "bin") + if err := os.Symlink("/bin", bin); err != nil { + return nil, err + } + + usr := filepath.Join(rootfsPath, "usr") + if err := os.Mkdir(usr, 0755); err != nil { + return nil, err + } + usrbin := filepath.Join(usr, "bin") + if err := os.Symlink("/usr/bin", usrbin); err != nil { + return nil, err + } + usrsbin := filepath.Join(usr, "sbin") + if err := os.Symlink("/usr/sbin", usrsbin); err != nil { + return nil, err + } + + return NewNsenter(rootfsPath, executor) +} + +type fakeExec struct { + rootfsPath string +} + +func (f fakeExec) Command(cmd string, args ...string) exec.Cmd { + // This will intentionaly panic if Nsenter does not provide enough arguments. + realCmd := args[2] + realArgs := args[3:] + return exec.New().Command(realCmd, realArgs...) +} + +func (fakeExec) LookPath(file string) (string, error) { + return "", errors.New("not implemented") +} + +func (fakeExec) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd { + return nil +} + +var _ exec.Interface = fakeExec{} diff --git a/pkg/util/nsenter/nsenter_test.go b/pkg/util/nsenter/nsenter_test.go new file mode 100644 index 00000000000..3158a55bbec --- /dev/null +++ b/pkg/util/nsenter/nsenter_test.go @@ -0,0 +1,311 @@ +// +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 nsenter + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "k8s.io/utils/exec" +) + +func TestExec(t *testing.T) { + tests := []struct { + name string + command string + args []string + expectedOutput string + expectError bool + }{ + { + name: "simple command", + command: "echo", + args: []string{"hello", "world"}, + expectedOutput: "hello world\n", + }, + { + name: "nozero exit code", + command: "false", + expectError: true, + }, + } + + executor := fakeExec{ + rootfsPath: "/rootfs", + } + for _, test := range tests { + ns := Nsenter{ + hostRootFsPath: "/rootfs", + executor: executor, + } + cmd := ns.Exec(test.command, test.args) + outBytes, err := cmd.CombinedOutput() + out := string(outBytes) + if err != nil && !test.expectError { + t.Errorf("Test %q: unexpected error: %s", test.name, err) + } + if err == nil && test.expectError { + t.Errorf("Test %q: expected error, got none", test.name) + } + if test.expectedOutput != out { + t.Errorf("test %q: expected output %q, got %q", test.name, test.expectedOutput, out) + } + } +} + +func TestKubeletPath(t *testing.T) { + tests := []struct { + rootfs string + hostpath string + expectedKubeletPath string + }{ + { + // simple join + "/rootfs", + "/some/path", + "/rootfs/some/path", + }, + { + // squash slashes + "/rootfs/", + "//some/path", + "/rootfs/some/path", + }, + } + + for _, test := range tests { + ns := Nsenter{ + hostRootFsPath: test.rootfs, + } + out := ns.KubeletPath(test.hostpath) + if out != test.expectedKubeletPath { + t.Errorf("Expected path %q, got %q", test.expectedKubeletPath, out) + } + + } +} + +func TestEvalSymlinks(t *testing.T) { + tests := []struct { + name string + mustExist bool + prepare func(tmpdir string) (src string, expectedDst string, err error) + expectError bool + }{ + { + name: "simple file /src", + mustExist: true, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + src = filepath.Join(tmpdir, "src") + err = ioutil.WriteFile(src, []byte{}, 0644) + return src, src, err + }, + }, + { + name: "non-existing file /src", + mustExist: true, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + src = filepath.Join(tmpdir, "src") + return src, "", nil + }, + expectError: true, + }, + { + name: "non-existing file /src/ with mustExist=false", + mustExist: false, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + src = filepath.Join(tmpdir, "src") + return src, src, nil + }, + }, + { + name: "non-existing file /existing/path/src with mustExist=false with existing directories", + mustExist: false, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + src = filepath.Join(tmpdir, "existing/path") + if err := os.MkdirAll(src, 0755); err != nil { + return "", "", err + } + src = filepath.Join(src, "src") + return src, src, nil + }, + }, + { + name: "simple symlink /src -> /dst", + mustExist: false, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "dst") + if err = ioutil.WriteFile(dst, []byte{}, 0644); err != nil { + return "", "", err + } + src = filepath.Join(tmpdir, "src") + err = os.Symlink(dst, src) + return src, dst, err + }, + }, + { + name: "dangling symlink /src -> /non-existing-path", + mustExist: true, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "non-existing-path") + src = filepath.Join(tmpdir, "src") + err = os.Symlink(dst, src) + return src, "", err + }, + expectError: true, + }, + { + name: "dangling symlink /src -> /non-existing-path with mustExist=false", + mustExist: false, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "non-existing-path") + src = filepath.Join(tmpdir, "src") + err = os.Symlink(dst, src) + return src, dst, err + }, + }, + { + name: "symlink to directory /src/file, where /src is link to /dst", + mustExist: true, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "dst") + if err = os.Mkdir(dst, 0755); err != nil { + return "", "", err + } + dstFile := filepath.Join(dst, "file") + if err = ioutil.WriteFile(dstFile, []byte{}, 0644); err != nil { + return "", "", err + } + + src = filepath.Join(tmpdir, "src") + if err = os.Symlink(dst, src); err != nil { + return "", "", err + } + srcFile := filepath.Join(src, "file") + return srcFile, dstFile, nil + }, + }, + { + name: "symlink to non-existing directory: /src/file, where /src is link to /dst and dst does not exist", + mustExist: true, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "dst") + + src = filepath.Join(tmpdir, "src") + if err = os.Symlink(dst, src); err != nil { + return "", "", err + } + srcFile := filepath.Join(src, "file") + return srcFile, "", nil + }, + expectError: true, + }, + { + name: "symlink to non-existing directory: /src/file, where /src is link to /dst and dst does not exist with mustExist=false", + mustExist: false, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "dst") + dstFile := filepath.Join(dst, "file") + + src = filepath.Join(tmpdir, "src") + if err = os.Symlink(dst, src); err != nil { + return "", "", err + } + srcFile := filepath.Join(src, "file") + return srcFile, dstFile, nil + }, + }, + } + + for _, test := range tests { + ns := Nsenter{ + hostRootFsPath: "/rootfs", + executor: fakeExec{ + rootfsPath: "/rootfs", + }, + } + + tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + src, expectedDst, err := test.prepare(tmpdir) + if err != nil { + t.Error(err) + continue + } + + dst, err := ns.EvalSymlinks(src, test.mustExist) + if err != nil && !test.expectError { + t.Errorf("Test %q: unexpected error: %s", test.name, err) + } + if err == nil && test.expectError { + t.Errorf("Test %q: expected error, got none", test.name) + } + if dst != expectedDst { + t.Errorf("Test %q: expected destination %q, got %q", test.name, expectedDst, dst) + } + } +} + +func TestNewNsenter(t *testing.T) { + // Create a symlink /tmp/xyz/rootfs -> / and use it as rootfs path + // It should resolve all binaries correctly, the test runs on Linux + + tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + rootfs := filepath.Join(tmpdir, "rootfs") + if err = os.Symlink("/", rootfs); err != nil { + t.Fatal(err) + } + + _, err = NewNsenter(rootfs, exec.New()) + if err != nil { + t.Errorf("Error: %s", err) + } +} + +func TestNewNsenterError(t *testing.T) { + // Create empty dir /tmp/xyz/rootfs and use it as rootfs path + // It should resolve all binaries correctly, the test runs on Linux + + tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + rootfs := filepath.Join(tmpdir, "rootfs") + if err = os.MkdirAll(rootfs, 0755); err != nil { + t.Fatal(err) + } + + _, err = NewNsenter(rootfs, exec.New()) + if err == nil { + t.Errorf("Expected error, got none") + } +} diff --git a/pkg/util/nsenter/nsenter_unsupported.go b/pkg/util/nsenter/nsenter_unsupported.go index 842cf046731..0618b9da469 100644 --- a/pkg/util/nsenter/nsenter_unsupported.go +++ b/pkg/util/nsenter/nsenter_unsupported.go @@ -22,6 +22,12 @@ import ( "k8s.io/utils/exec" ) +const ( + // DefaultHostRootFsPath is path to host's filesystem mounted into container + // with kubelet. + DefaultHostRootFsPath = "/rootfs" +) + // Nsenter is part of experimental support for running the kubelet // in a container. type Nsenter struct { @@ -30,7 +36,7 @@ type Nsenter struct { } // NewNsenter constructs a new instance of Nsenter -func NewNsenter() (*Nsenter, error) { +func NewNsenter(hostRootFsPath string, executor exec.Interface) (*Nsenter, error) { return &Nsenter{}, nil } diff --git a/pkg/util/pod/BUILD b/pkg/util/pod/BUILD new file mode 100644 index 00000000000..57a081ab7c6 --- /dev/null +++ b/pkg/util/pod/BUILD @@ -0,0 +1,39 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["pod.go"], + importpath = "k8s.io/kubernetes/pkg/util/pod", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["pod_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake: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/util/pod/pod.go b/pkg/util/pod/pod.go new file mode 100644 index 00000000000..81d4304fa2b --- /dev/null +++ b/pkg/util/pod/pod.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. +*/ + +package pod + +import ( + "encoding/json" + "fmt" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/strategicpatch" + clientset "k8s.io/client-go/kubernetes" +) + +// PatchPodStatus patches pod status. +func PatchPodStatus(c clientset.Interface, namespace, name string, oldPodStatus, newPodStatus v1.PodStatus) (*v1.Pod, []byte, error) { + patchBytes, err := preparePatchBytesforPodStatus(namespace, name, oldPodStatus, newPodStatus) + if err != nil { + return nil, nil, err + } + + updatedPod, err := c.CoreV1().Pods(namespace).Patch(name, types.StrategicMergePatchType, patchBytes, "status") + if err != nil { + return nil, nil, fmt.Errorf("failed to patch status %q for pod %q/%q: %v", patchBytes, namespace, name, err) + } + return updatedPod, patchBytes, nil +} + +func preparePatchBytesforPodStatus(namespace, name string, oldPodStatus, newPodStatus v1.PodStatus) ([]byte, error) { + oldData, err := json.Marshal(v1.Pod{ + Status: oldPodStatus, + }) + if err != nil { + return nil, fmt.Errorf("failed to Marshal oldData for pod %q/%q: %v", namespace, name, err) + } + + newData, err := json.Marshal(v1.Pod{ + Status: newPodStatus, + }) + if err != nil { + return nil, fmt.Errorf("failed to Marshal newData for pod %q/%q: %v", namespace, name, err) + } + + patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Pod{}) + if err != nil { + return nil, fmt.Errorf("failed to CreateTwoWayMergePatch for pod %q/%q: %v", namespace, name, err) + } + return patchBytes, nil +} diff --git a/pkg/util/pod/pod_test.go b/pkg/util/pod/pod_test.go new file mode 100644 index 00000000000..af0278fa090 --- /dev/null +++ b/pkg/util/pod/pod_test.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 pod + +import ( + "testing" + + "fmt" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" + "reflect" +) + +func TestPatchPodStatus(t *testing.T) { + ns := "ns" + name := "name" + client := &fake.Clientset{} + client.CoreV1().Pods(ns).Create(&v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns, + Name: name, + }, + }) + + testCases := []struct { + description string + mutate func(input v1.PodStatus) v1.PodStatus + expectedPatchBytes []byte + }{ + { + "no change", + func(input v1.PodStatus) v1.PodStatus { return input }, + []byte(fmt.Sprintf(`{}`)), + }, + { + "message change", + func(input v1.PodStatus) v1.PodStatus { + input.Message = "random message" + return input + }, + []byte(fmt.Sprintf(`{"status":{"message":"random message"}}`)), + }, + { + "pod condition change", + func(input v1.PodStatus) v1.PodStatus { + input.Conditions[0].Status = v1.ConditionFalse + return input + }, + []byte(fmt.Sprintf(`{"status":{"$setElementOrder/conditions":[{"type":"Ready"},{"type":"PodScheduled"}],"conditions":[{"status":"False","type":"Ready"}]}}`)), + }, + { + "additional init container condition", + func(input v1.PodStatus) v1.PodStatus { + input.InitContainerStatuses = []v1.ContainerStatus{ + { + Name: "init-container", + Ready: true, + }, + } + return input + }, + []byte(fmt.Sprintf(`{"status":{"initContainerStatuses":[{"image":"","imageID":"","lastState":{},"name":"init-container","ready":true,"restartCount":0,"state":{}}]}}`)), + }, + } + for _, tc := range testCases { + _, patchBytes, err := PatchPodStatus(client, ns, name, getPodStatus(), tc.mutate(getPodStatus())) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(patchBytes, tc.expectedPatchBytes) { + t.Errorf("for test case %q, expect patchBytes: %q, got: %q\n", tc.description, tc.expectedPatchBytes, patchBytes) + } + } +} + +func getPodStatus() v1.PodStatus { + return v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + }, + ContainerStatuses: []v1.ContainerStatus{ + { + Name: "container1", + Ready: true, + }, + { + Name: "container2", + Ready: true, + }, + }, + Message: "Message", + } +} diff --git a/pkg/util/removeall/removeall_test.go b/pkg/util/removeall/removeall_test.go index 134326369ff..07db7718ed0 100644 --- a/pkg/util/removeall/removeall_test.go +++ b/pkg/util/removeall/removeall_test.go @@ -27,83 +27,12 @@ import ( "k8s.io/kubernetes/pkg/util/mount" ) -type fakeMounter struct{} - -var _ mount.Interface = &fakeMounter{} - -func (mounter *fakeMounter) Mount(source string, target string, fstype string, options []string) error { - return errors.New("not implemented") +type fakeMounter struct { + mount.FakeMounter } -func (mounter *fakeMounter) Unmount(target string) error { - return errors.New("not implemented") -} - -func (mounter *fakeMounter) List() ([]mount.MountPoint, error) { - return nil, errors.New("not implemented") -} - -func (mounter fakeMounter) DeviceOpened(pathname string) (bool, error) { - return false, errors.New("not implemented") -} - -func (mounter *fakeMounter) PathIsDevice(pathname string) (bool, error) { - return false, errors.New("not implemented") -} - -func (mounter *fakeMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { - return "", errors.New("not implemented") -} - -func (mounter *fakeMounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool { - return mp.Path == dir -} - -func (mounter *fakeMounter) IsNotMountPoint(dir string) (bool, error) { - return mount.IsNotMountPoint(mounter, dir) -} - -func (mounter *fakeMounter) GetFileType(pathname string) (mount.FileType, error) { - return mount.FileType("fake"), errors.New("not implemented") -} - -func (mounter *fakeMounter) MakeDir(pathname string) error { - return nil -} - -func (mounter *fakeMounter) MakeFile(pathname string) error { - return nil -} - -func (mounter *fakeMounter) ExistsPath(pathname string) bool { - return true -} - -func (mounter *fakeMounter) PrepareSafeSubpath(subPath mount.Subpath) (newHostPath string, cleanupAction func(), err error) { - return "", nil, nil -} - -func (mounter *fakeMounter) CleanSubPaths(_, _ string) error { - return nil -} - -func (mounter *fakeMounter) SafeMakeDir(_, _ string, _ os.FileMode) error { - return nil -} - -func (mounter *fakeMounter) GetMountRefs(pathname string) ([]string, error) { - return nil, errors.New("not implemented") -} - -func (mounter *fakeMounter) GetFSGroup(pathname string) (int64, error) { - return -1, errors.New("not implemented") -} - -func (mounter *fakeMounter) GetSELinuxSupport(pathname string) (bool, error) { - return false, errors.New("not implemented") -} - -func (mounter *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { +// IsLikelyNotMountPoint overrides mount.FakeMounter.IsLikelyNotMountPoint for our use. +func (f *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { name := path.Base(file) if strings.HasPrefix(name, "mount") { return false, nil @@ -114,10 +43,6 @@ func (mounter *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { return true, nil } -func (mounter *fakeMounter) MakeRShared(path string) error { - return nil -} - func TestRemoveAllOneFilesystem(t *testing.T) { tests := []struct { name string diff --git a/pkg/volume/BUILD b/pkg/volume/BUILD index 097a994f8a1..28c8c8a68d8 100644 --- a/pkg/volume/BUILD +++ b/pkg/volume/BUILD @@ -56,6 +56,7 @@ go_library( "//pkg/volume/util/fs:go_default_library", "//pkg/volume/util/recyclerclient:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/pkg/volume/aws_ebs/BUILD b/pkg/volume/aws_ebs/BUILD index 5354b9e31b1..506240f6764 100644 --- a/pkg/volume/aws_ebs/BUILD +++ b/pkg/volume/aws_ebs/BUILD @@ -19,6 +19,7 @@ go_library( deps = [ "//pkg/cloudprovider:go_default_library", "//pkg/cloudprovider/providers/aws:go_default_library", + "//pkg/features:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/strings:go_default_library", "//pkg/volume:go_default_library", @@ -29,6 +30,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/pkg/volume/aws_ebs/attacher.go b/pkg/volume/aws_ebs/attacher.go index 059431e1661..ac716ed1b0d 100644 --- a/pkg/volume/aws_ebs/attacher.go +++ b/pkg/volume/aws_ebs/attacher.go @@ -59,7 +59,7 @@ func (plugin *awsElasticBlockStorePlugin) GetDeviceMountRefs(deviceMountPath str } func (attacher *awsElasticBlockStoreAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) { - volumeSource, readOnly, err := getVolumeSource(spec) + volumeSource, _, err := getVolumeSource(spec) if err != nil { return "", err } @@ -68,7 +68,7 @@ func (attacher *awsElasticBlockStoreAttacher) Attach(spec *volume.Spec, nodeName // awsCloud.AttachDisk checks if disk is already attached to node and // succeeds in that case, so no need to do that separately. - devicePath, err := attacher.awsVolumes.AttachDisk(volumeID, nodeName, readOnly) + devicePath, err := attacher.awsVolumes.AttachDisk(volumeID, nodeName) if err != nil { glog.Errorf("Error attaching volume %q to node %q: %+v", volumeID, nodeName, err) return "", err diff --git a/pkg/volume/aws_ebs/attacher_test.go b/pkg/volume/aws_ebs/attacher_test.go index 1076d06910e..36ed854d1a4 100644 --- a/pkg/volume/aws_ebs/attacher_test.go +++ b/pkg/volume/aws_ebs/attacher_test.go @@ -76,15 +76,14 @@ type testcase struct { func TestAttachDetach(t *testing.T) { diskName := aws.KubernetesVolumeID("disk") nodeName := types.NodeName("instance") - readOnly := false - spec := createVolSpec(diskName, readOnly) + spec := createVolSpec(diskName, false) attachError := errors.New("Fake attach error") detachError := errors.New("Fake detach error") tests := []testcase{ // Successful Attach call { name: "Attach_Positive", - attach: attachCall{diskName, nodeName, readOnly, "/dev/sda", nil}, + attach: attachCall{diskName, nodeName, "/dev/sda", nil}, test: func(testcase *testcase) (string, error) { attacher := newAttacher(testcase) return attacher.Attach(spec, nodeName) @@ -95,7 +94,7 @@ func TestAttachDetach(t *testing.T) { // Attach call fails { name: "Attach_Negative", - attach: attachCall{diskName, nodeName, readOnly, "", attachError}, + attach: attachCall{diskName, nodeName, "", attachError}, test: func(testcase *testcase) (string, error) { attacher := newAttacher(testcase) return attacher.Attach(spec, nodeName) @@ -195,7 +194,6 @@ func createPVSpec(name aws.KubernetesVolumeID, readOnly bool) *volume.Spec { type attachCall struct { diskName aws.KubernetesVolumeID nodeName types.NodeName - readOnly bool retDeviceName string ret error } @@ -214,7 +212,7 @@ type diskIsAttachedCall struct { ret error } -func (testcase *testcase) AttachDisk(diskName aws.KubernetesVolumeID, nodeName types.NodeName, readOnly bool) (string, error) { +func (testcase *testcase) AttachDisk(diskName aws.KubernetesVolumeID, nodeName types.NodeName) (string, error) { expected := &testcase.attach if expected.diskName == "" && expected.nodeName == "" { @@ -234,12 +232,7 @@ func (testcase *testcase) AttachDisk(diskName aws.KubernetesVolumeID, nodeName t return "", errors.New("Unexpected AttachDisk call: wrong nodeName") } - if expected.readOnly != readOnly { - testcase.t.Errorf("Unexpected AttachDisk call: expected readOnly %v, got %v", expected.readOnly, readOnly) - return "", errors.New("Unexpected AttachDisk call: wrong readOnly") - } - - glog.V(4).Infof("AttachDisk call: %s, %s, %v, returning %q, %v", diskName, nodeName, readOnly, expected.retDeviceName, expected.ret) + glog.V(4).Infof("AttachDisk call: %s, %s, returning %q, %v", diskName, nodeName, expected.retDeviceName, expected.ret) return expected.retDeviceName, expected.ret } diff --git a/pkg/volume/aws_ebs/aws_ebs.go b/pkg/volume/aws_ebs/aws_ebs.go index 71531245371..4ba24bd6ffb 100644 --- a/pkg/volume/aws_ebs/aws_ebs.go +++ b/pkg/volume/aws_ebs/aws_ebs.go @@ -17,9 +17,11 @@ limitations under the License. package aws_ebs import ( + "context" "fmt" "os" "path/filepath" + "regexp" "strconv" "strings" @@ -28,7 +30,9 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/cloudprovider/providers/aws" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/util/mount" kstrings "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" @@ -93,6 +97,47 @@ func (plugin *awsElasticBlockStorePlugin) SupportsBulkVolumeVerification() bool return true } +func (plugin *awsElasticBlockStorePlugin) GetVolumeLimits() (map[string]int64, error) { + volumeLimits := map[string]int64{ + util.EBSVolumeLimitKey: 39, + } + cloud := plugin.host.GetCloudProvider() + + // if we can't fetch cloudprovider we return an error + // hoping external CCM or admin can set it. Returning + // default values from here will mean, no one can + // override them. + if cloud == nil { + return nil, fmt.Errorf("No cloudprovider present") + } + + if cloud.ProviderName() != aws.ProviderName { + return nil, fmt.Errorf("Expected aws cloud, found %s", cloud.ProviderName()) + } + + instances, ok := cloud.Instances() + if !ok { + glog.V(3).Infof("Failed to get instances from cloud provider") + return volumeLimits, nil + } + + instanceType, err := instances.InstanceType(context.TODO(), plugin.host.GetNodeName()) + if err != nil { + glog.Errorf("Failed to get instance type from AWS cloud provider") + return volumeLimits, nil + } + + if ok, _ := regexp.MatchString("^[cm]5.*", instanceType); ok { + volumeLimits[util.EBSVolumeLimitKey] = 25 + } + + return volumeLimits, nil +} + +func (plugin *awsElasticBlockStorePlugin) VolumeLimitKey(spec *volume.Spec) string { + return util.EBSVolumeLimitKey +} + func (plugin *awsElasticBlockStorePlugin) GetAccessModes() []v1.PersistentVolumeAccessMode { return []v1.PersistentVolumeAccessMode{ v1.ReadWriteOnce, @@ -265,6 +310,7 @@ func (plugin *awsElasticBlockStorePlugin) ExpandVolumeDevice( } var _ volume.ExpandableVolumePlugin = &awsElasticBlockStorePlugin{} +var _ volume.VolumePluginWithAttachLimits = &awsElasticBlockStorePlugin{} // Abstract interface to PD operations. type ebsManager interface { @@ -453,7 +499,7 @@ type awsElasticBlockStoreProvisioner struct { var _ volume.Provisioner = &awsElasticBlockStoreProvisioner{} -func (c *awsElasticBlockStoreProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *awsElasticBlockStoreProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } @@ -507,5 +553,9 @@ func (c *awsElasticBlockStoreProvisioner) Provision() (*v1.PersistentVolume, err } } + if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { + pv.Spec.VolumeMode = c.options.PVC.Spec.VolumeMode + } + return pv, nil } diff --git a/pkg/volume/aws_ebs/aws_ebs_block.go b/pkg/volume/aws_ebs/aws_ebs_block.go index 37e748707c6..5eaefb23f61 100644 --- a/pkg/volume/aws_ebs/aws_ebs_block.go +++ b/pkg/volume/aws_ebs/aws_ebs_block.go @@ -29,6 +29,7 @@ import ( "k8s.io/kubernetes/pkg/util/mount" kstrings "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util/volumepathhandler" ) @@ -155,6 +156,10 @@ func (b *awsElasticBlockStoreMapper) SetUpDevice() (string, error) { return "", nil } +func (b *awsElasticBlockStoreMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + // GetGlobalMapPath returns global map path and error // path: plugins/kubernetes.io/{PluginName}/volumeDevices/volumeID // plugins/kubernetes.io/aws-ebs/volumeDevices/vol-XXXXXX diff --git a/pkg/volume/aws_ebs/aws_ebs_test.go b/pkg/volume/aws_ebs/aws_ebs_test.go index 72438e379b7..f5ceb20f116 100644 --- a/pkg/volume/aws_ebs/aws_ebs_test.go +++ b/pkg/volume/aws_ebs/aws_ebs_test.go @@ -173,7 +173,7 @@ func TestPlugin(t *testing.T) { if err != nil { t.Errorf("Error creating new provisioner:%v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } diff --git a/pkg/volume/azure_dd/BUILD b/pkg/volume/azure_dd/BUILD index c4913bfba6e..cb1ccc3bf09 100644 --- a/pkg/volume/azure_dd/BUILD +++ b/pkg/volume/azure_dd/BUILD @@ -56,6 +56,7 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/cloudprovider:go_default_library", "//pkg/cloudprovider/providers/azure:go_default_library", + "//pkg/features:go_default_library", "//pkg/util/keymutex:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/strings:go_default_library", @@ -71,6 +72,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/pkg/volume/azure_dd/attacher.go b/pkg/volume/azure_dd/attacher.go index 4f7b50f378a..adfd1ab72c3 100644 --- a/pkg/volume/azure_dd/attacher.go +++ b/pkg/volume/azure_dd/attacher.go @@ -185,10 +185,6 @@ func (a *azureDiskAttacher) WaitForAttach(spec *volume.Spec, devicePath string, // did we find it? if newDevicePath != "" { - // the current sequence k8s uses for unformated disk (check-disk, mount, fail, mkfs.extX) hangs on - // Azure Managed disk scsi interface. this is a hack and will be replaced once we identify and solve - // the root case on Azure. - formatIfNotFormatted(newDevicePath, *volumeSource.FSType, exec) return true, nil } diff --git a/pkg/volume/azure_dd/azure_common_linux.go b/pkg/volume/azure_dd/azure_common_linux.go index 806e27e0e94..383b46f4687 100644 --- a/pkg/volume/azure_dd/azure_common_linux.go +++ b/pkg/volume/azure_dd/azure_common_linux.go @@ -178,45 +178,3 @@ func findDiskByLunWithConstraint(lun int, io ioHandler, azureDisks []string) (st } return "", err } - -func formatIfNotFormatted(disk string, fstype string, exec mount.Exec) { - notFormatted, err := diskLooksUnformatted(disk, exec) - if err == nil && notFormatted { - args := []string{disk} - // Disk is unformatted so format it. - // Use 'ext4' as the default - if len(fstype) == 0 { - fstype = "ext4" - } - if fstype == "ext4" || fstype == "ext3" { - args = []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", disk} - } - glog.Infof("azureDisk - Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", disk, fstype, args) - - _, err := exec.Run("mkfs."+fstype, args...) - if err == nil { - // the disk has been formatted successfully try to mount it again. - glog.Infof("azureDisk - Disk successfully formatted with 'mkfs.%s %v'", fstype, args) - } else { - glog.Warningf("azureDisk - Error formatting volume with 'mkfs.%s %v': %v", fstype, args, err) - } - } else { - if err != nil { - glog.Warningf("azureDisk - Failed to check if the disk %s formatted with error %s, will attach anyway", disk, err) - } else { - glog.Infof("azureDisk - Disk %s already formatted, will not format", disk) - } - } -} - -func diskLooksUnformatted(disk string, exec mount.Exec) (bool, error) { - args := []string{"-nd", "-o", "FSTYPE", disk} - glog.V(4).Infof("Attempting to determine if disk %q is formatted using lsblk with args: (%v)", disk, args) - dataOut, err := exec.Run("lsblk", args...) - if err != nil { - glog.Errorf("Could not determine if disk %q is formatted (%v)", disk, err) - return false, err - } - output := libstrings.TrimSpace(string(dataOut)) - return output == "", nil -} diff --git a/pkg/volume/azure_dd/azure_common_unsupported.go b/pkg/volume/azure_dd/azure_common_unsupported.go index 6710af8fcb0..ba938ccc28a 100644 --- a/pkg/volume/azure_dd/azure_common_unsupported.go +++ b/pkg/volume/azure_dd/azure_common_unsupported.go @@ -26,6 +26,3 @@ func scsiHostRescan(io ioHandler, exec mount.Exec) { func findDiskByLun(lun int, io ioHandler, exec mount.Exec) (string, error) { return "", nil } - -func formatIfNotFormatted(disk string, fstype string, exec mount.Exec) { -} diff --git a/pkg/volume/azure_dd/azure_dd.go b/pkg/volume/azure_dd/azure_dd.go index ec7ab8debf5..8310e0ab00c 100644 --- a/pkg/volume/azure_dd/azure_dd.go +++ b/pkg/volume/azure_dd/azure_dd.go @@ -17,13 +17,18 @@ limitations under the License. package azure_dd import ( + "fmt" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" "github.com/golang/glog" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/cloudprovider/providers/azure" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/util" ) // interface exposed by the cloud provider implementing Disk functionality @@ -51,6 +56,9 @@ type DiskController interface { CreateVolume(name, storageAccount, storageAccountType, location string, requestGB int) (string, string, int, error) // Delete a VHD blob DeleteVolume(diskURI string) error + + // Expand the disk to new size + ResizeDisk(diskName string, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error) } type azureDataDiskPlugin struct { @@ -62,6 +70,8 @@ var _ volume.PersistentVolumePlugin = &azureDataDiskPlugin{} var _ volume.DeletableVolumePlugin = &azureDataDiskPlugin{} var _ volume.ProvisionableVolumePlugin = &azureDataDiskPlugin{} var _ volume.AttachableVolumePlugin = &azureDataDiskPlugin{} +var _ volume.VolumePluginWithAttachLimits = &azureDataDiskPlugin{} +var _ volume.ExpandableVolumePlugin = &azureDataDiskPlugin{} const ( azureDataDiskPluginName = "kubernetes.io/azure-disk" @@ -106,6 +116,32 @@ func (plugin *azureDataDiskPlugin) SupportsBulkVolumeVerification() bool { return false } +func (plugin *azureDataDiskPlugin) GetVolumeLimits() (map[string]int64, error) { + volumeLimits := map[string]int64{ + util.AzureVolumeLimitKey: 16, + } + + cloud := plugin.host.GetCloudProvider() + + // if we can't fetch cloudprovider we return an error + // hoping external CCM or admin can set it. Returning + // default values from here will mean, no one can + // override them. + if cloud == nil { + return nil, fmt.Errorf("No cloudprovider present") + } + + if cloud.ProviderName() != azure.CloudProviderName { + return nil, fmt.Errorf("Expected Azure cloudprovider, got %s", cloud.ProviderName()) + } + + return volumeLimits, nil +} + +func (plugin *azureDataDiskPlugin) VolumeLimitKey(spec *volume.Spec) string { + return util.AzureVolumeLimitKey +} + func (plugin *azureDataDiskPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode { return []v1.PersistentVolumeAccessMode{ v1.ReadWriteOnce, @@ -189,6 +225,26 @@ func (plugin *azureDataDiskPlugin) NewUnmounter(volName string, podUID types.UID }, nil } +func (plugin *azureDataDiskPlugin) RequiresFSResize() bool { + return true +} + +func (plugin *azureDataDiskPlugin) ExpandVolumeDevice( + spec *volume.Spec, + newSize resource.Quantity, + oldSize resource.Quantity) (resource.Quantity, error) { + if spec.PersistentVolume == nil || spec.PersistentVolume.Spec.AzureDisk == nil { + return oldSize, fmt.Errorf("invalid PV spec") + } + + diskController, err := getDiskController(plugin.host) + if err != nil { + return oldSize, err + } + + return diskController.ResizeDisk(spec.PersistentVolume.Spec.AzureDisk.DiskName, oldSize, newSize) +} + func (plugin *azureDataDiskPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) { mounter := plugin.host.GetMounter(plugin.GetPluginName()) pluginDir := plugin.host.GetPluginDir(plugin.GetPluginName()) diff --git a/pkg/volume/azure_dd/azure_dd_block.go b/pkg/volume/azure_dd/azure_dd_block.go index 9ded780ef46..af1d195047e 100644 --- a/pkg/volume/azure_dd/azure_dd_block.go +++ b/pkg/volume/azure_dd/azure_dd_block.go @@ -27,6 +27,7 @@ import ( "k8s.io/kubernetes/pkg/util/mount" kstrings "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util/volumepathhandler" ) @@ -137,6 +138,10 @@ func (b *azureDataDiskMapper) SetUpDevice() (string, error) { return "", nil } +func (b *azureDataDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + // GetGlobalMapPath returns global map path and error // path: plugins/kubernetes.io/{PluginName}/volumeDevices/volumeID // plugins/kubernetes.io/azure-disk/volumeDevices/vol-XXXXXX diff --git a/pkg/volume/azure_dd/azure_provision.go b/pkg/volume/azure_dd/azure_provision.go index bf7eae37db4..ee7aa78f66f 100644 --- a/pkg/volume/azure_dd/azure_provision.go +++ b/pkg/volume/azure_dd/azure_provision.go @@ -23,6 +23,8 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/util" ) @@ -65,7 +67,7 @@ func (d *azureDiskDeleter) Delete() error { return diskController.DeleteBlobDisk(volumeSource.DataDiskURI) } -func (p *azureDiskProvisioner) Provision() (*v1.PersistentVolume, error) { +func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(p.plugin.GetAccessModes(), p.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", p.options.PVC.Spec.AccessModes, p.plugin.GetAccessModes()) } @@ -187,5 +189,10 @@ func (p *azureDiskProvisioner) Provision() (*v1.PersistentVolume, error) { MountOptions: p.options.MountOptions, }, } + + if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { + pv.Spec.VolumeMode = p.options.PVC.Spec.VolumeMode + } + return pv, nil } diff --git a/pkg/volume/azure_file/azure_file.go b/pkg/volume/azure_file/azure_file.go index b7efb940d0b..f36b47cb3ee 100644 --- a/pkg/volume/azure_file/azure_file.go +++ b/pkg/volume/azure_file/azure_file.go @@ -150,7 +150,7 @@ func (plugin *azureFilePlugin) ExpandVolumeDevice( newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error) { - if spec.PersistentVolume != nil || spec.PersistentVolume.Spec.AzureFile == nil { + if spec.PersistentVolume == nil || spec.PersistentVolume.Spec.AzureFile == nil { return oldSize, fmt.Errorf("invalid PV spec") } shareName := spec.PersistentVolume.Spec.AzureFile.ShareName diff --git a/pkg/volume/azure_file/azure_provision.go b/pkg/volume/azure_file/azure_provision.go index dc155334ff9..891f2d69582 100644 --- a/pkg/volume/azure_file/azure_provision.go +++ b/pkg/volume/azure_file/azure_provision.go @@ -131,10 +131,13 @@ type azureFileProvisioner struct { var _ volume.Provisioner = &azureFileProvisioner{} -func (a *azureFileProvisioner) Provision() (*v1.PersistentVolume, error) { +func (a *azureFileProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(a.plugin.GetAccessModes(), a.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", a.options.PVC.Spec.AccessModes, a.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(a.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", a.plugin.GetPluginName()) + } var sku, location, account string diff --git a/pkg/volume/cephfs/OWNERS b/pkg/volume/cephfs/OWNERS index 35dc489f905..5562ca53f16 100644 --- a/pkg/volume/cephfs/OWNERS +++ b/pkg/volume/cephfs/OWNERS @@ -1,5 +1,6 @@ approvers: - rootfs +- jsafrane - saad-ali reviewers: - rootfs @@ -7,3 +8,4 @@ reviewers: - jsafrane - jingxu97 - msau42 +- cofyc diff --git a/pkg/volume/cinder/attacher.go b/pkg/volume/cinder/attacher.go index bfe66d56603..fff3efd5573 100644 --- a/pkg/volume/cinder/attacher.go +++ b/pkg/volume/cinder/attacher.go @@ -120,13 +120,11 @@ func (attacher *cinderDiskAttacher) waitDiskAttached(instanceID, volumeID string } func (attacher *cinderDiskAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) { - volumeSource, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { return "", err } - volumeID := volumeSource.VolumeID - instanceID, err := attacher.nodeInstanceID(nodeName) if err != nil { return "", err @@ -175,15 +173,15 @@ func (attacher *cinderDiskAttacher) VolumesAreAttached(specs []*volume.Spec, nod volumeSpecMap := make(map[string]*volume.Spec) volumeIDList := []string{} for _, spec := range specs { - volumeSource, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { glog.Errorf("Error getting volume (%q) source : %v", spec.Name(), err) continue } - volumeIDList = append(volumeIDList, volumeSource.VolumeID) + volumeIDList = append(volumeIDList, volumeID) volumesAttachedCheck[spec] = true - volumeSpecMap[volumeSource.VolumeID] = spec + volumeSpecMap[volumeID] = spec } attachedResult, err := attacher.cinderProvider.DisksAreAttachedByName(nodeName, volumeIDList) @@ -207,13 +205,11 @@ func (attacher *cinderDiskAttacher) VolumesAreAttached(specs []*volume.Spec, nod func (attacher *cinderDiskAttacher) WaitForAttach(spec *volume.Spec, devicePath string, _ *v1.Pod, timeout time.Duration) (string, error) { // NOTE: devicePath is is path as reported by Cinder, which may be incorrect and should not be used. See Issue #33128 - volumeSource, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { return "", err } - volumeID := volumeSource.VolumeID - if devicePath == "" { return "", fmt.Errorf("WaitForAttach failed for Cinder disk %q: devicePath is empty", volumeID) } @@ -252,12 +248,12 @@ func (attacher *cinderDiskAttacher) WaitForAttach(spec *volume.Spec, devicePath func (attacher *cinderDiskAttacher) GetDeviceMountPath( spec *volume.Spec) (string, error) { - volumeSource, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { return "", err } - return makeGlobalPDName(attacher.host, volumeSource.VolumeID), nil + return makeGlobalPDName(attacher.host, volumeID), nil } // FIXME: this method can be further pruned. @@ -275,7 +271,7 @@ func (attacher *cinderDiskAttacher) MountDevice(spec *volume.Spec, devicePath st } } - volumeSource, readOnly, err := getVolumeSource(spec) + _, volumeFSType, readOnly, err := getVolumeInfo(spec) if err != nil { return err } @@ -287,7 +283,7 @@ func (attacher *cinderDiskAttacher) MountDevice(spec *volume.Spec, devicePath st if notMnt { diskMounter := volumeutil.NewSafeFormatAndMountFromHost(cinderVolumePluginName, attacher.host) mountOptions := volumeutil.MountOptionFromSpec(spec, options...) - err = diskMounter.FormatAndMount(devicePath, deviceMountPath, volumeSource.FSType, mountOptions) + err = diskMounter.FormatAndMount(devicePath, deviceMountPath, volumeFSType, mountOptions) if err != nil { os.Remove(deviceMountPath) return err diff --git a/pkg/volume/cinder/attacher_test.go b/pkg/volume/cinder/attacher_test.go index e7961d9b72f..6acb573a51b 100644 --- a/pkg/volume/cinder/attacher_test.go +++ b/pkg/volume/cinder/attacher_test.go @@ -393,7 +393,7 @@ func createPVSpec(name string, readOnly bool) *volume.Spec { PersistentVolume: &v1.PersistentVolume{ Spec: v1.PersistentVolumeSpec{ PersistentVolumeSource: v1.PersistentVolumeSource{ - Cinder: &v1.CinderVolumeSource{ + Cinder: &v1.CinderPersistentVolumeSource{ VolumeID: name, ReadOnly: readOnly, }, diff --git a/pkg/volume/cinder/cinder.go b/pkg/volume/cinder/cinder.go index 121972c4613..55aec4586c4 100644 --- a/pkg/volume/cinder/cinder.go +++ b/pkg/volume/cinder/cinder.go @@ -94,12 +94,12 @@ func (plugin *cinderPlugin) GetPluginName() string { } func (plugin *cinderPlugin) GetVolumeName(spec *volume.Spec) (string, error) { - volumeSource, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { return "", err } - return volumeSource.VolumeID, nil + return volumeID, nil } func (plugin *cinderPlugin) CanSupport(spec *volume.Spec) bool { @@ -129,14 +129,11 @@ func (plugin *cinderPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume. } func (plugin *cinderPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager cdManager, mounter mount.Interface) (volume.Mounter, error) { - cinder, readOnly, err := getVolumeSource(spec) + pdName, fsType, readOnly, err := getVolumeInfo(spec) if err != nil { return nil, err } - pdName := cinder.VolumeID - fsType := cinder.FSType - return &cinderVolumeMounter{ cinderVolume: &cinderVolume{ podUID: podUID, @@ -248,7 +245,7 @@ func (plugin *cinderPlugin) ConstructVolumeSpec(volumeName, mountPath string) (* var _ volume.ExpandableVolumePlugin = &cinderPlugin{} func (plugin *cinderPlugin) ExpandVolumeDevice(spec *volume.Spec, newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error) { - cinder, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { return oldSize, err } @@ -257,12 +254,12 @@ func (plugin *cinderPlugin) ExpandVolumeDevice(spec *volume.Spec, newSize resour return oldSize, err } - expandedSize, err := cloud.ExpandVolume(cinder.VolumeID, oldSize, newSize) + expandedSize, err := cloud.ExpandVolume(volumeID, oldSize, newSize) if err != nil { return oldSize, err } - glog.V(2).Infof("volume %s expanded to new size %d successfully", cinder.VolumeID, int(newSize.Value())) + glog.V(2).Infof("volume %s expanded to new size %d successfully", volumeID, int(newSize.Value())) return expandedSize, nil } @@ -503,11 +500,15 @@ type cinderVolumeProvisioner struct { var _ volume.Provisioner = &cinderVolumeProvisioner{} -func (c *cinderVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *cinderVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(c.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", c.plugin.GetPluginName()) + } + volumeID, sizeGB, labels, fstype, err := c.manager.CreateVolume(c) if err != nil { return nil, err @@ -528,7 +529,7 @@ func (c *cinderVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)), }, PersistentVolumeSource: v1.PersistentVolumeSource{ - Cinder: &v1.CinderVolumeSource{ + Cinder: &v1.CinderPersistentVolumeSource{ VolumeID: volumeID, FSType: fstype, ReadOnly: false, @@ -544,13 +545,13 @@ func (c *cinderVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { return pv, nil } -func getVolumeSource(spec *volume.Spec) (*v1.CinderVolumeSource, bool, error) { +func getVolumeInfo(spec *volume.Spec) (string, string, bool, error) { if spec.Volume != nil && spec.Volume.Cinder != nil { - return spec.Volume.Cinder, spec.Volume.Cinder.ReadOnly, nil + return spec.Volume.Cinder.VolumeID, spec.Volume.Cinder.FSType, spec.Volume.Cinder.ReadOnly, nil } else if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Cinder != nil { - return spec.PersistentVolume.Spec.Cinder, spec.ReadOnly, nil + return spec.PersistentVolume.Spec.Cinder.VolumeID, spec.PersistentVolume.Spec.Cinder.FSType, spec.ReadOnly, nil } - return nil, false, fmt.Errorf("Spec does not reference a Cinder volume type") + return "", "", false, fmt.Errorf("Spec does not reference a Cinder volume type") } diff --git a/pkg/volume/cinder/cinder_test.go b/pkg/volume/cinder/cinder_test.go index f0f1db7065a..d16b3d09c9f 100644 --- a/pkg/volume/cinder/cinder_test.go +++ b/pkg/volume/cinder/cinder_test.go @@ -51,7 +51,7 @@ func TestCanSupport(t *testing.T) { t.Errorf("Expected true") } - if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{Cinder: &v1.CinderVolumeSource{}}}}}) { + if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{Cinder: &v1.CinderPersistentVolumeSource{}}}}}) { t.Errorf("Expected true") } } @@ -196,7 +196,7 @@ func TestPlugin(t *testing.T) { PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete, } provisioner, err := plug.(*cinderPlugin).newProvisionerInternal(options, &fakePDManager{0}) - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } diff --git a/pkg/volume/configmap/configmap.go b/pkg/volume/configmap/configmap.go index ff041c0ac0c..2f108bb72cd 100644 --- a/pkg/volume/configmap/configmap.go +++ b/pkg/volume/configmap/configmap.go @@ -191,12 +191,6 @@ func (b *configMapVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { if err != nil { return err } - if err := wrapped.SetUpAt(dir, fsGroup); err != nil { - return err - } - if err := volumeutil.MakeNestedMountpoints(b.volName, dir, b.pod); err != nil { - return err - } optional := b.source.Optional != nil && *b.source.Optional configMap, err := b.getConfigMap(b.pod.Namespace, b.source.Name) @@ -213,6 +207,13 @@ func (b *configMapVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { } } + if err := wrapped.SetUpAt(dir, fsGroup); err != nil { + return err + } + if err := volumeutil.MakeNestedMountpoints(b.volName, dir, b.pod); err != nil { + return err + } + totalBytes := totalBytes(configMap) glog.V(3).Infof("Received configMap %v/%v containing (%v) pieces of data, %v total bytes", b.pod.Namespace, @@ -243,7 +244,6 @@ func (b *configMapVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { glog.Errorf("Error applying volume ownership settings for group: %v", fsGroup) return err } - return nil } diff --git a/pkg/volume/csi/BUILD b/pkg/volume/csi/BUILD index 2067ebfeb9d..54a2574eb77 100644 --- a/pkg/volume/csi/BUILD +++ b/pkg/volume/csi/BUILD @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "csi_attacher.go", + "csi_block.go", "csi_client.go", "csi_mounter.go", "csi_plugin.go", @@ -12,9 +13,11 @@ go_library( importpath = "k8s.io/kubernetes/pkg/volume/csi", visibility = ["//visibility:public"], deps = [ + "//pkg/features:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/strings:go_default_library", "//pkg/volume:go_default_library", + "//pkg/volume/csi/labelmanager:go_default_library", "//pkg/volume/util:go_default_library", "//vendor/github.com/container-storage-interface/spec/lib/go/csi/v0:go_default_library", "//vendor/github.com/golang/glog:go_default_library", @@ -25,6 +28,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], ) @@ -33,6 +37,7 @@ go_test( name = "go_default_test", srcs = [ "csi_attacher_test.go", + "csi_block_test.go", "csi_client_test.go", "csi_mounter_test.go", "csi_plugin_test.go", @@ -42,7 +47,8 @@ go_test( "//pkg/volume:go_default_library", "//pkg/volume/csi/fake:go_default_library", "//pkg/volume/testing:go_default_library", - "//vendor/google.golang.org/grpc:go_default_library", + "//pkg/volume/util:go_default_library", + "//vendor/github.com/container-storage-interface/spec/lib/go/csi/v0:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/storage/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", @@ -51,6 +57,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", "//vendor/k8s.io/client-go/testing:go_default_library", "//vendor/k8s.io/client-go/util/testing:go_default_library", @@ -69,6 +76,7 @@ filegroup( srcs = [ ":package-srcs", "//pkg/volume/csi/fake:all-srcs", + "//pkg/volume/csi/labelmanager:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/pkg/volume/csi/csi_attacher.go b/pkg/volume/csi/csi_attacher.go index 8c280d86ddd..82fb8e6620c 100644 --- a/pkg/volume/csi/csi_attacher.go +++ b/pkg/volume/csi/csi_attacher.go @@ -270,11 +270,7 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo } if c.csiClient == nil { - if csiSource.Driver == "" { - return fmt.Errorf("attacher.MountDevice failed, driver name is empty") - } - addr := fmt.Sprintf(csiAddrTemplate, csiSource.Driver) - c.csiClient = newCsiDriverClient("unix", addr) + c.csiClient = newCsiDriverClient(csiSource.Driver) } csi := c.csiClient @@ -472,8 +468,7 @@ func (c *csiAttacher) UnmountDevice(deviceMountPath string) error { } if c.csiClient == nil { - addr := fmt.Sprintf(csiAddrTemplate, driverName) - c.csiClient = newCsiDriverClient("unix", addr) + c.csiClient = newCsiDriverClient(driverName) } csi := c.csiClient diff --git a/pkg/volume/csi/csi_attacher_test.go b/pkg/volume/csi/csi_attacher_test.go index dda1a1a66af..83703ddd491 100644 --- a/pkg/volume/csi/csi_attacher_test.go +++ b/pkg/volume/csi/csi_attacher_test.go @@ -33,7 +33,6 @@ import ( core "k8s.io/client-go/testing" utiltesting "k8s.io/client-go/util/testing" "k8s.io/kubernetes/pkg/volume" - "k8s.io/kubernetes/pkg/volume/csi/fake" volumetest "k8s.io/kubernetes/pkg/volume/testing" ) @@ -583,8 +582,8 @@ func TestAttacherMountDevice(t *testing.T) { numStaged = 0 } - cdc := csiAttacher.csiClient.(*csiDriverClient) - staged := cdc.nodeClient.(*fake.NodeClient).GetNodeStagedVolumes() + cdc := csiAttacher.csiClient.(*fakeCsiDriverClient) + staged := cdc.nodeClient.GetNodeStagedVolumes() if len(staged) != numStaged { t.Errorf("got wrong number of staged volumes, expecting %v got: %v", numStaged, len(staged)) } @@ -668,8 +667,8 @@ func TestAttacherUnmountDevice(t *testing.T) { csiAttacher.csiClient = setupClient(t, tc.stageUnstageSet) // Add the volume to NodeStagedVolumes - cdc := csiAttacher.csiClient.(*csiDriverClient) - cdc.nodeClient.(*fake.NodeClient).AddNodeStagedVolume(tc.volID, tc.deviceMountPath) + cdc := csiAttacher.csiClient.(*fakeCsiDriverClient) + cdc.nodeClient.AddNodeStagedVolume(tc.volID, tc.deviceMountPath) // Make the PV for this object dir := filepath.Dir(tc.deviceMountPath) @@ -700,7 +699,7 @@ func TestAttacherUnmountDevice(t *testing.T) { if !tc.stageUnstageSet { expectedSet = 1 } - staged := cdc.nodeClient.(*fake.NodeClient).GetNodeStagedVolumes() + staged := cdc.nodeClient.GetNodeStagedVolumes() if len(staged) != expectedSet { t.Errorf("got wrong number of staged volumes, expecting %v got: %v", expectedSet, len(staged)) } diff --git a/pkg/volume/csi/csi_block.go b/pkg/volume/csi/csi_block.go new file mode 100644 index 00000000000..502747d28c4 --- /dev/null +++ b/pkg/volume/csi/csi_block.go @@ -0,0 +1,283 @@ +/* +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 csi + +import ( + "context" + "errors" + "fmt" + "os" + "path/filepath" + + "github.com/golang/glog" + + "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/pkg/volume" +) + +type csiBlockMapper struct { + k8s kubernetes.Interface + csiClient csiClient + plugin *csiPlugin + driverName string + specName string + volumeID string + readOnly bool + spec *volume.Spec + podUID types.UID + volumeInfo map[string]string +} + +var _ volume.BlockVolumeMapper = &csiBlockMapper{} + +// GetGlobalMapPath returns a path (on the node) where the devicePath will be symlinked to +// Example: plugins/kubernetes.io/csi/volumeDevices/{volumeID} +func (m *csiBlockMapper) GetGlobalMapPath(spec *volume.Spec) (string, error) { + dir := getVolumeDevicePluginDir(spec.Name(), m.plugin.host) + glog.V(4).Infof(log("blockMapper.GetGlobalMapPath = %s", dir)) + return dir, nil +} + +// GetPodDeviceMapPath returns pod's device map path and volume name +// path: pods/{podUid}/volumeDevices/kubernetes.io~csi/, {volumeID} +func (m *csiBlockMapper) GetPodDeviceMapPath() (string, string) { + path, specName := m.plugin.host.GetPodVolumeDeviceDir(m.podUID, csiPluginName), m.specName + glog.V(4).Infof(log("blockMapper.GetPodDeviceMapPath = %s", path)) + return path, specName +} + +// SetUpDevice ensures the device is attached returns path where the device is located. +func (m *csiBlockMapper) SetUpDevice() (string, error) { + if !m.plugin.blockEnabled { + return "", errors.New("CSIBlockVolume feature not enabled") + } + + glog.V(4).Infof(log("blockMapper.SetupDevice called")) + + if m.spec == nil { + glog.Error(log("blockMapper.Map spec is nil")) + return "", fmt.Errorf("spec is nil") + } + csiSource, err := getCSISourceFromSpec(m.spec) + if err != nil { + glog.Error(log("blockMapper.SetupDevice failed to get CSI persistent source: %v", err)) + return "", err + } + + globalMapPath, err := m.GetGlobalMapPath(m.spec) + if err != nil { + glog.Error(log("blockMapper.SetupDevice failed to get global map path: %v", err)) + return "", err + } + + csi := m.csiClient + ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) + defer cancel() + + // Check whether "STAGE_UNSTAGE_VOLUME" is set + stageUnstageSet, err := hasStageUnstageCapability(ctx, csi) + if err != nil { + glog.Error(log("blockMapper.SetupDevice failed to check STAGE_UNSTAGE_VOLUME capability: %v", err)) + return "", err + } + if !stageUnstageSet { + glog.Infof(log("blockMapper.SetupDevice STAGE_UNSTAGE_VOLUME capability not set. Skipping MountDevice...")) + return "", nil + } + + // Start MountDevice + nodeName := string(m.plugin.host.GetNodeName()) + attachID := getAttachmentName(csiSource.VolumeHandle, csiSource.Driver, nodeName) + + // search for attachment by VolumeAttachment.Spec.Source.PersistentVolumeName + attachment, err := m.k8s.StorageV1beta1().VolumeAttachments().Get(attachID, meta.GetOptions{}) + if err != nil { + glog.Error(log("blockMapper.SetupDevice failed to get volume attachment [id=%v]: %v", attachID, err)) + return "", err + } + + if attachment == nil { + glog.Error(log("blockMapper.SetupDevice unable to find VolumeAttachment [id=%s]", attachID)) + return "", errors.New("no existing VolumeAttachment found") + } + publishVolumeInfo := attachment.Status.AttachmentMetadata + + nodeStageSecrets := map[string]string{} + if csiSource.NodeStageSecretRef != nil { + nodeStageSecrets, err = getCredentialsFromSecret(m.k8s, csiSource.NodeStageSecretRef) + if err != nil { + return "", fmt.Errorf("failed to get NodeStageSecretRef %s/%s: %v", + csiSource.NodeStageSecretRef.Namespace, csiSource.NodeStageSecretRef.Name, err) + } + } + + // create globalMapPath before call to NodeStageVolume + if err := os.MkdirAll(globalMapPath, 0750); err != nil { + glog.Error(log("blockMapper.SetupDevice failed to create dir %s: %v", globalMapPath, err)) + return "", err + } + glog.V(4).Info(log("blockMapper.SetupDevice created global device map path successfully [%s]", globalMapPath)) + + //TODO (vladimirvivien) implement better AccessModes mapping between k8s and CSI + accessMode := v1.ReadWriteOnce + if m.spec.PersistentVolume.Spec.AccessModes != nil { + accessMode = m.spec.PersistentVolume.Spec.AccessModes[0] + } + + err = csi.NodeStageVolume(ctx, + csiSource.VolumeHandle, + publishVolumeInfo, + globalMapPath, + fsTypeBlockName, + accessMode, + nodeStageSecrets, + csiSource.VolumeAttributes) + + if err != nil { + glog.Error(log("blockMapper.SetupDevice failed: %v", err)) + if err := os.RemoveAll(globalMapPath); err != nil { + glog.Error(log("blockMapper.SetupDevice failed to remove dir after a NodeStageVolume() error [%s]: %v", globalMapPath, err)) + } + return "", err + } + + glog.V(4).Infof(log("blockMapper.SetupDevice successfully requested NodeStageVolume [%s]", globalMapPath)) + return globalMapPath, nil +} + +func (m *csiBlockMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + if !m.plugin.blockEnabled { + return errors.New("CSIBlockVolume feature not enabled") + } + + glog.V(4).Infof(log("blockMapper.MapDevice mapping block device %s", devicePath)) + + if m.spec == nil { + glog.Error(log("blockMapper.MapDevice spec is nil")) + return fmt.Errorf("spec is nil") + } + + csiSource, err := getCSISourceFromSpec(m.spec) + if err != nil { + glog.Error(log("blockMapper.Map failed to get CSI persistent source: %v", err)) + return err + } + + dir := filepath.Join(volumeMapPath, volumeMapName) + csi := m.csiClient + + ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) + defer cancel() + + nodeName := string(m.plugin.host.GetNodeName()) + attachID := getAttachmentName(csiSource.VolumeHandle, csiSource.Driver, nodeName) + + // search for attachment by VolumeAttachment.Spec.Source.PersistentVolumeName + attachment, err := m.k8s.StorageV1beta1().VolumeAttachments().Get(attachID, meta.GetOptions{}) + if err != nil { + glog.Error(log("blockMapper.MapDevice failed to get volume attachment [id=%v]: %v", attachID, err)) + return err + } + + if attachment == nil { + glog.Error(log("blockMapper.MapDevice unable to find VolumeAttachment [id=%s]", attachID)) + return errors.New("no existing VolumeAttachment found") + } + publishVolumeInfo := attachment.Status.AttachmentMetadata + + nodePublishSecrets := map[string]string{} + if csiSource.NodePublishSecretRef != nil { + nodePublishSecrets, err = getCredentialsFromSecret(m.k8s, csiSource.NodePublishSecretRef) + if err != nil { + glog.Errorf("blockMapper.MapDevice failed to get NodePublishSecretRef %s/%s: %v", + csiSource.NodePublishSecretRef.Namespace, csiSource.NodePublishSecretRef.Name, err) + return err + } + } + + if err := os.MkdirAll(dir, 0750); err != nil { + glog.Error(log("blockMapper.MapDevice failed to create dir %#v: %v", dir, err)) + return err + } + glog.V(4).Info(log("blockMapper.MapDevice created NodePublish path [%s]", dir)) + + //TODO (vladimirvivien) implement better AccessModes mapping between k8s and CSI + accessMode := v1.ReadWriteOnce + if m.spec.PersistentVolume.Spec.AccessModes != nil { + accessMode = m.spec.PersistentVolume.Spec.AccessModes[0] + } + + err = csi.NodePublishVolume( + ctx, + m.volumeID, + m.readOnly, + globalMapPath, + dir, + accessMode, + publishVolumeInfo, + csiSource.VolumeAttributes, + nodePublishSecrets, + fsTypeBlockName, + ) + + if err != nil { + glog.Errorf(log("blockMapper.MapDevice failed: %v", err)) + if err := os.RemoveAll(dir); err != nil { + glog.Error(log("blockMapper.MapDevice failed to remove mount dir after a NodePublish() error [%s]: %v", dir, err)) + } + return err + } + + return nil +} + +var _ volume.BlockVolumeUnmapper = &csiBlockMapper{} + +// TearDownDevice removes traces of the SetUpDevice. +func (m *csiBlockMapper) TearDownDevice(globalMapPath, devicePath string) error { + if !m.plugin.blockEnabled { + return errors.New("CSIBlockVolume feature not enabled") + } + + glog.V(4).Infof(log("unmapper.TearDownDevice(globalMapPath=%s; devicePath=%s)", globalMapPath, devicePath)) + + csi := m.csiClient + ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) + defer cancel() + + // unmap global device map path + if err := csi.NodeUnstageVolume(ctx, m.volumeID, globalMapPath); err != nil { + glog.Errorf(log("blockMapper.TearDownDevice failed: %v", err)) + return err + } + glog.V(4).Infof(log("blockMapper.TearDownDevice NodeUnstageVolume successfully [%s]", globalMapPath)) + + // request to remove pod volume map path also + podVolumePath, volumeName := m.GetPodDeviceMapPath() + podVolumeMapPath := filepath.Join(podVolumePath, volumeName) + if err := csi.NodeUnpublishVolume(ctx, m.volumeID, podVolumeMapPath); err != nil { + glog.Error(log("blockMapper.TearDownDevice failed: %v", err)) + return err + } + + glog.V(4).Infof(log("blockMapper.TearDownDevice NodeUnpublished successfully [%s]", podVolumeMapPath)) + + return nil +} diff --git a/pkg/volume/csi/csi_block_test.go b/pkg/volume/csi/csi_block_test.go new file mode 100644 index 00000000000..af340147884 --- /dev/null +++ b/pkg/volume/csi/csi_block_test.go @@ -0,0 +1,264 @@ +/* +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 csi + +import ( + "fmt" + "os" + "path" + "path/filepath" + "testing" + + api "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + fakeclient "k8s.io/client-go/kubernetes/fake" + "k8s.io/kubernetes/pkg/volume" + volumetest "k8s.io/kubernetes/pkg/volume/testing" +) + +func TestBlockMapperGetGlobalMapPath(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + // TODO (vladimirvivien) specName with slashes will not work + testCases := []struct { + name string + specVolumeName string + path string + }{ + { + name: "simple specName", + specVolumeName: "spec-0", + path: path.Join(tmpDir, fmt.Sprintf("plugins/kubernetes.io/csi/volumeDevices/%s/%s", "spec-0", "dev")), + }, + { + name: "specName with dots", + specVolumeName: "test.spec.1", + path: path.Join(tmpDir, fmt.Sprintf("plugins/kubernetes.io/csi/volumeDevices/%s/%s", "test.spec.1", "dev")), + }, + } + for _, tc := range testCases { + t.Logf("test case: %s", tc.name) + pv := makeTestPV(tc.specVolumeName, 10, testDriver, testVol) + spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly) + mapper, err := plug.NewBlockVolumeMapper( + spec, + &api.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}}, + volume.VolumeOptions{}, + ) + if err != nil { + t.Fatalf("Failed to make a new Mapper: %v", err) + } + csiMapper := mapper.(*csiBlockMapper) + + path, err := csiMapper.GetGlobalMapPath(spec) + if err != nil { + t.Errorf("mapper GetGlobalMapPath failed: %v", err) + } + + if tc.path != path { + t.Errorf("expecting path %s, got %s", tc.path, path) + } + } +} + +func TestBlockMapperSetupDevice(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + fakeClient := fakeclient.NewSimpleClientset() + host := volumetest.NewFakeVolumeHostWithNodeName( + tmpDir, + fakeClient, + nil, + "fakeNode", + ) + plug.host = host + pv := makeTestPV("test-pv", 10, testDriver, testVol) + pvName := pv.GetName() + nodeName := string(plug.host.GetNodeName()) + spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly) + + // MapDevice + mapper, err := plug.NewBlockVolumeMapper( + spec, + &api.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}}, + volume.VolumeOptions{}, + ) + if err != nil { + t.Fatalf("failed to create new mapper: %v", err) + } + csiMapper := mapper.(*csiBlockMapper) + csiMapper.csiClient = setupClient(t, true) + + attachID := getAttachmentName(csiMapper.volumeID, csiMapper.driverName, string(nodeName)) + attachment := makeTestAttachment(attachID, nodeName, pvName) + attachment.Status.Attached = true + _, err = csiMapper.k8s.StorageV1beta1().VolumeAttachments().Create(attachment) + if err != nil { + t.Fatalf("failed to setup VolumeAttachment: %v", err) + } + t.Log("created attachement ", attachID) + + devicePath, err := csiMapper.SetUpDevice() + if err != nil { + t.Fatalf("mapper failed to SetupDevice: %v", err) + } + + globalMapPath, err := csiMapper.GetGlobalMapPath(spec) + if err != nil { + t.Fatalf("mapper failed to GetGlobalMapPath: %v", err) + } + + if devicePath != globalMapPath { + t.Fatalf("mapper.SetupDevice returned unexpected path %s instead of %v", devicePath, globalMapPath) + } + + vols := csiMapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodeStagedVolumes() + if vols[csiMapper.volumeID] != devicePath { + t.Error("csi server may not have received NodePublishVolume call") + } +} + +func TestBlockMapperMapDevice(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + fakeClient := fakeclient.NewSimpleClientset() + host := volumetest.NewFakeVolumeHostWithNodeName( + tmpDir, + fakeClient, + nil, + "fakeNode", + ) + plug.host = host + pv := makeTestPV("test-pv", 10, testDriver, testVol) + pvName := pv.GetName() + nodeName := string(plug.host.GetNodeName()) + spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly) + + // MapDevice + mapper, err := plug.NewBlockVolumeMapper( + spec, + &api.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}}, + volume.VolumeOptions{}, + ) + if err != nil { + t.Fatalf("failed to create new mapper: %v", err) + } + csiMapper := mapper.(*csiBlockMapper) + csiMapper.csiClient = setupClient(t, true) + + attachID := getAttachmentName(csiMapper.volumeID, csiMapper.driverName, string(nodeName)) + attachment := makeTestAttachment(attachID, nodeName, pvName) + attachment.Status.Attached = true + _, err = csiMapper.k8s.StorageV1beta1().VolumeAttachments().Create(attachment) + if err != nil { + t.Fatalf("failed to setup VolumeAttachment: %v", err) + } + t.Log("created attachement ", attachID) + + devicePath, err := csiMapper.SetUpDevice() + if err != nil { + t.Fatalf("mapper failed to SetupDevice: %v", err) + } + globalMapPath, err := csiMapper.GetGlobalMapPath(csiMapper.spec) + if err != nil { + t.Fatalf("mapper failed to GetGlobalMapPath: %v", err) + } + + // Map device to global and pod device map path + volumeMapPath, volName := csiMapper.GetPodDeviceMapPath() + err = csiMapper.MapDevice(devicePath, globalMapPath, volumeMapPath, volName, csiMapper.podUID) + if err != nil { + t.Fatalf("mapper failed to GetGlobalMapPath: %v", err) + } + + if _, err := os.Stat(filepath.Join(volumeMapPath, volName)); err != nil { + if os.IsNotExist(err) { + t.Errorf("mapper.MapDevice failed, volume path not created: %s", volumeMapPath) + } else { + t.Errorf("mapper.MapDevice failed: %v", err) + } + } + + pubs := csiMapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes() + if pubs[csiMapper.volumeID] != volumeMapPath { + t.Error("csi server may not have received NodePublishVolume call") + } +} + +func TestBlockMapperTearDownDevice(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + fakeClient := fakeclient.NewSimpleClientset() + host := volumetest.NewFakeVolumeHostWithNodeName( + tmpDir, + fakeClient, + nil, + "fakeNode", + ) + plug.host = host + pv := makeTestPV("test-pv", 10, testDriver, testVol) + spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly) + + // save volume data + dir := getVolumeDeviceDataDir(pv.ObjectMeta.Name, plug.host) + if err := os.MkdirAll(dir, 0755); err != nil && !os.IsNotExist(err) { + t.Errorf("failed to create dir [%s]: %v", dir, err) + } + + if err := saveVolumeData( + dir, + volDataFileName, + map[string]string{ + volDataKey.specVolID: pv.ObjectMeta.Name, + volDataKey.driverName: testDriver, + volDataKey.volHandle: testVol, + }, + ); err != nil { + t.Fatalf("failed to save volume data: %v", err) + } + + unmapper, err := plug.NewBlockVolumeUnmapper(pv.ObjectMeta.Name, testPodUID) + if err != nil { + t.Fatalf("failed to make a new Unmapper: %v", err) + } + + csiUnmapper := unmapper.(*csiBlockMapper) + csiUnmapper.csiClient = setupClient(t, true) + + globalMapPath, err := csiUnmapper.GetGlobalMapPath(spec) + if err != nil { + t.Fatalf("unmapper failed to GetGlobalMapPath: %v", err) + } + + err = csiUnmapper.TearDownDevice(globalMapPath, "/dev/test") + if err != nil { + t.Fatal(err) + } + + // ensure csi client call and node unstaged + vols := csiUnmapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodeStagedVolumes() + if _, ok := vols[csiUnmapper.volumeID]; ok { + t.Error("csi server may not have received NodeUnstageVolume call") + } + + // ensure csi client call and node unpblished + pubs := csiUnmapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes() + if _, ok := pubs[csiUnmapper.volumeID]; ok { + t.Error("csi server may not have received NodeUnpublishVolume call") + } +} diff --git a/pkg/volume/csi/csi_client.go b/pkg/volume/csi/csi_client.go index e9283efbf18..e12772d7a91 100644 --- a/pkg/volume/csi/csi_client.go +++ b/pkg/volume/csi/csi_client.go @@ -19,6 +19,7 @@ package csi import ( "context" "errors" + "fmt" "net" "time" @@ -26,6 +27,8 @@ import ( "github.com/golang/glog" "google.golang.org/grpc" api "k8s.io/api/core/v1" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" ) type csiClient interface { @@ -61,45 +64,15 @@ type csiClient interface { // csiClient encapsulates all csi-plugin methods type csiDriverClient struct { - network string - addr string - conn *grpc.ClientConn - idClient csipb.IdentityClient - nodeClient csipb.NodeClient - ctrlClient csipb.ControllerClient - versionAsserted bool - versionSupported bool - publishAsserted bool - publishCapable bool + driverName string + nodeClient csipb.NodeClient } -func newCsiDriverClient(network, addr string) *csiDriverClient { - return &csiDriverClient{network: network, addr: addr} -} +var _ csiClient = &csiDriverClient{} -// assertConnection ensures a valid connection has been established -// if not, it creates a new connection and associated clients -func (c *csiDriverClient) assertConnection() error { - if c.conn == nil { - conn, err := grpc.Dial( - c.addr, - grpc.WithInsecure(), - grpc.WithDialer(func(target string, timeout time.Duration) (net.Conn, error) { - return net.Dial(c.network, target) - }), - ) - if err != nil { - return err - } - c.conn = conn - c.idClient = csipb.NewIdentityClient(conn) - c.nodeClient = csipb.NewNodeClient(conn) - c.ctrlClient = csipb.NewControllerClient(conn) - - // set supported version - } - - return nil +func newCsiDriverClient(driverName string) *csiDriverClient { + c := &csiDriverClient{driverName: driverName} + return c } func (c *csiDriverClient) NodePublishVolume( @@ -121,10 +94,13 @@ func (c *csiDriverClient) NodePublishVolume( if targetPath == "" { return errors.New("missing target path") } - if err := c.assertConnection(); err != nil { - glog.Errorf("%v: failed to assert a connection: %v", csiPluginName, err) + + conn, err := newGrpcConn(c.driverName) + if err != nil { return err } + defer conn.Close() + nodeClient := csipb.NewNodeClient(conn) req := &csipb.NodePublishVolumeRequest{ VolumeId: volID, @@ -137,18 +113,25 @@ func (c *csiDriverClient) NodePublishVolume( AccessMode: &csipb.VolumeCapability_AccessMode{ Mode: asCSIAccessMode(accessMode), }, - AccessType: &csipb.VolumeCapability_Mount{ - Mount: &csipb.VolumeCapability_MountVolume{ - FsType: fsType, - }, - }, }, } if stagingTargetPath != "" { req.StagingTargetPath = stagingTargetPath } - _, err := c.nodeClient.NodePublishVolume(ctx, req) + if fsType == fsTypeBlockName { + req.VolumeCapability.AccessType = &csipb.VolumeCapability_Block{ + Block: &csipb.VolumeCapability_BlockVolume{}, + } + } else { + req.VolumeCapability.AccessType = &csipb.VolumeCapability_Mount{ + Mount: &csipb.VolumeCapability_MountVolume{ + FsType: fsType, + }, + } + } + + _, err = nodeClient.NodePublishVolume(ctx, req) return err } @@ -160,17 +143,20 @@ func (c *csiDriverClient) NodeUnpublishVolume(ctx context.Context, volID string, if targetPath == "" { return errors.New("missing target path") } - if err := c.assertConnection(); err != nil { - glog.Error(log("failed to assert a connection: %v", err)) + + conn, err := newGrpcConn(c.driverName) + if err != nil { return err } + defer conn.Close() + nodeClient := csipb.NewNodeClient(conn) req := &csipb.NodeUnpublishVolumeRequest{ VolumeId: volID, TargetPath: targetPath, } - _, err := c.nodeClient.NodeUnpublishVolume(ctx, req) + _, err = nodeClient.NodeUnpublishVolume(ctx, req) return err } @@ -190,10 +176,13 @@ func (c *csiDriverClient) NodeStageVolume(ctx context.Context, if stagingTargetPath == "" { return errors.New("missing staging target path") } - if err := c.assertConnection(); err != nil { - glog.Errorf("%v: failed to assert a connection: %v", csiPluginName, err) + + conn, err := newGrpcConn(c.driverName) + if err != nil { return err } + defer conn.Close() + nodeClient := csipb.NewNodeClient(conn) req := &csipb.NodeStageVolumeRequest{ VolumeId: volID, @@ -203,17 +192,24 @@ func (c *csiDriverClient) NodeStageVolume(ctx context.Context, AccessMode: &csipb.VolumeCapability_AccessMode{ Mode: asCSIAccessMode(accessMode), }, - AccessType: &csipb.VolumeCapability_Mount{ - Mount: &csipb.VolumeCapability_MountVolume{ - FsType: fsType, - }, - }, }, NodeStageSecrets: nodeStageSecrets, VolumeAttributes: volumeAttribs, } - _, err := c.nodeClient.NodeStageVolume(ctx, req) + if fsType == fsTypeBlockName { + req.VolumeCapability.AccessType = &csipb.VolumeCapability_Block{ + Block: &csipb.VolumeCapability_BlockVolume{}, + } + } else { + req.VolumeCapability.AccessType = &csipb.VolumeCapability_Mount{ + Mount: &csipb.VolumeCapability_MountVolume{ + FsType: fsType, + }, + } + } + + _, err = nodeClient.NodeStageVolume(ctx, req) return err } @@ -225,27 +221,34 @@ func (c *csiDriverClient) NodeUnstageVolume(ctx context.Context, volID, stagingT if stagingTargetPath == "" { return errors.New("missing staging target path") } - if err := c.assertConnection(); err != nil { - glog.Errorf("%v: failed to assert a connection: %v", csiPluginName, err) + + conn, err := newGrpcConn(c.driverName) + if err != nil { return err } + defer conn.Close() + nodeClient := csipb.NewNodeClient(conn) req := &csipb.NodeUnstageVolumeRequest{ VolumeId: volID, StagingTargetPath: stagingTargetPath, } - _, err := c.nodeClient.NodeUnstageVolume(ctx, req) + _, err = nodeClient.NodeUnstageVolume(ctx, req) return err } func (c *csiDriverClient) NodeGetCapabilities(ctx context.Context) ([]*csipb.NodeServiceCapability, error) { glog.V(4).Info(log("calling NodeGetCapabilities rpc")) - if err := c.assertConnection(); err != nil { - glog.Errorf("%v: failed to assert a connection: %v", csiPluginName, err) + + conn, err := newGrpcConn(c.driverName) + if err != nil { return nil, err } + defer conn.Close() + nodeClient := csipb.NewNodeClient(conn) + req := &csipb.NodeGetCapabilitiesRequest{} - resp, err := c.nodeClient.NodeGetCapabilities(ctx, req) + resp, err := nodeClient.NodeGetCapabilities(ctx, req) if err != nil { return nil, err } @@ -263,3 +266,28 @@ func asCSIAccessMode(am api.PersistentVolumeAccessMode) csipb.VolumeCapability_A } return csipb.VolumeCapability_AccessMode_UNKNOWN } + +func newGrpcConn(driverName string) (*grpc.ClientConn, error) { + if driverName == "" { + return nil, fmt.Errorf("driver name is empty") + } + addr := fmt.Sprintf(csiAddrTemplate, driverName) + // TODO once KubeletPluginsWatcher graduates to beta, remove FeatureGate check + if utilfeature.DefaultFeatureGate.Enabled(features.KubeletPluginsWatcher) { + driver, ok := csiDrivers.driversMap[driverName] + if !ok { + return nil, fmt.Errorf("driver name %s not found in the list of registered CSI drivers", driverName) + } + addr = driver.driverEndpoint + } + network := "unix" + glog.V(4).Infof(log("creating new gRPC connection for [%s://%s]", network, addr)) + + return grpc.Dial( + addr, + grpc.WithInsecure(), + grpc.WithDialer(func(target string, timeout time.Duration) (net.Conn, error) { + return net.Dial(network, target) + }), + ) +} diff --git a/pkg/volume/csi/csi_client_test.go b/pkg/volume/csi/csi_client_test.go index d4c843ef1bf..c5b8cf01f78 100644 --- a/pkg/volume/csi/csi_client_test.go +++ b/pkg/volume/csi/csi_client_test.go @@ -21,21 +21,124 @@ import ( "errors" "testing" - "google.golang.org/grpc" + csipb "github.com/container-storage-interface/spec/lib/go/csi/v0" api "k8s.io/api/core/v1" "k8s.io/kubernetes/pkg/volume/csi/fake" ) -func setupClient(t *testing.T, stageUnstageSet bool) *csiDriverClient { - client := newCsiDriverClient("unix", "/tmp/test.sock") - client.conn = new(grpc.ClientConn) //avoids creating conn object +type fakeCsiDriverClient struct { + t *testing.T + nodeClient *fake.NodeClient +} - // setup mock grpc clients - client.idClient = fake.NewIdentityClient() - client.nodeClient = fake.NewNodeClient(stageUnstageSet) - client.ctrlClient = fake.NewControllerClient() +func newFakeCsiDriverClient(t *testing.T, stagingCapable bool) *fakeCsiDriverClient { + return &fakeCsiDriverClient{ + t: t, + nodeClient: fake.NewNodeClient(stagingCapable), + } +} - return client +func (c *fakeCsiDriverClient) NodePublishVolume( + ctx context.Context, + volID string, + readOnly bool, + stagingTargetPath string, + targetPath string, + accessMode api.PersistentVolumeAccessMode, + volumeInfo map[string]string, + volumeAttribs map[string]string, + nodePublishSecrets map[string]string, + fsType string, +) error { + c.t.Log("calling fake.NodePublishVolume...") + req := &csipb.NodePublishVolumeRequest{ + VolumeId: volID, + TargetPath: targetPath, + Readonly: readOnly, + PublishInfo: volumeInfo, + VolumeAttributes: volumeAttribs, + NodePublishSecrets: nodePublishSecrets, + VolumeCapability: &csipb.VolumeCapability{ + AccessMode: &csipb.VolumeCapability_AccessMode{ + Mode: asCSIAccessMode(accessMode), + }, + AccessType: &csipb.VolumeCapability_Mount{ + Mount: &csipb.VolumeCapability_MountVolume{ + FsType: fsType, + }, + }, + }, + } + + _, err := c.nodeClient.NodePublishVolume(ctx, req) + return err +} + +func (c *fakeCsiDriverClient) NodeUnpublishVolume(ctx context.Context, volID string, targetPath string) error { + c.t.Log("calling fake.NodeUnpublishVolume...") + req := &csipb.NodeUnpublishVolumeRequest{ + VolumeId: volID, + TargetPath: targetPath, + } + + _, err := c.nodeClient.NodeUnpublishVolume(ctx, req) + return err +} + +func (c *fakeCsiDriverClient) NodeStageVolume(ctx context.Context, + volID string, + publishInfo map[string]string, + stagingTargetPath string, + fsType string, + accessMode api.PersistentVolumeAccessMode, + nodeStageSecrets map[string]string, + volumeAttribs map[string]string, +) error { + c.t.Log("calling fake.NodeStageVolume...") + req := &csipb.NodeStageVolumeRequest{ + VolumeId: volID, + PublishInfo: publishInfo, + StagingTargetPath: stagingTargetPath, + VolumeCapability: &csipb.VolumeCapability{ + AccessMode: &csipb.VolumeCapability_AccessMode{ + Mode: asCSIAccessMode(accessMode), + }, + AccessType: &csipb.VolumeCapability_Mount{ + Mount: &csipb.VolumeCapability_MountVolume{ + FsType: fsType, + }, + }, + }, + NodeStageSecrets: nodeStageSecrets, + VolumeAttributes: volumeAttribs, + } + + _, err := c.nodeClient.NodeStageVolume(ctx, req) + return err +} + +func (c *fakeCsiDriverClient) NodeUnstageVolume(ctx context.Context, volID, stagingTargetPath string) error { + c.t.Log("calling fake.NodeUnstageVolume...") + req := &csipb.NodeUnstageVolumeRequest{ + VolumeId: volID, + StagingTargetPath: stagingTargetPath, + } + _, err := c.nodeClient.NodeUnstageVolume(ctx, req) + return err +} + +func (c *fakeCsiDriverClient) NodeGetCapabilities(ctx context.Context) ([]*csipb.NodeServiceCapability, error) { + c.t.Log("calling fake.NodeGetCapabilities...") + req := &csipb.NodeGetCapabilitiesRequest{} + resp, err := c.nodeClient.NodeGetCapabilities(ctx, req) + if err != nil { + return nil, err + } + return resp.GetCapabilities(), nil +} + +func setupClient(t *testing.T, stageUnstageSet bool) csiClient { + return newFakeCsiDriverClient(t, stageUnstageSet) } func TestClientNodePublishVolume(t *testing.T) { @@ -58,7 +161,7 @@ func TestClientNodePublishVolume(t *testing.T) { for _, tc := range testCases { t.Logf("test case: %s", tc.name) - client.nodeClient.(*fake.NodeClient).SetNextError(tc.err) + client.(*fakeCsiDriverClient).nodeClient.SetNextError(tc.err) err := client.NodePublishVolume( context.Background(), tc.volID, @@ -96,7 +199,7 @@ func TestClientNodeUnpublishVolume(t *testing.T) { for _, tc := range testCases { t.Logf("test case: %s", tc.name) - client.nodeClient.(*fake.NodeClient).SetNextError(tc.err) + client.(*fakeCsiDriverClient).nodeClient.SetNextError(tc.err) err := client.NodeUnpublishVolume(context.Background(), tc.volID, tc.targetPath) if tc.mustFail && err == nil { t.Error("test must fail, but err is nil") @@ -125,7 +228,7 @@ func TestClientNodeStageVolume(t *testing.T) { for _, tc := range testCases { t.Logf("Running test case: %s", tc.name) - client.nodeClient.(*fake.NodeClient).SetNextError(tc.err) + client.(*fakeCsiDriverClient).nodeClient.SetNextError(tc.err) err := client.NodeStageVolume( context.Background(), tc.volID, @@ -161,7 +264,7 @@ func TestClientNodeUnstageVolume(t *testing.T) { for _, tc := range testCases { t.Logf("Running test case: %s", tc.name) - client.nodeClient.(*fake.NodeClient).SetNextError(tc.err) + client.(*fakeCsiDriverClient).nodeClient.SetNextError(tc.err) err := client.NodeUnstageVolume( context.Background(), tc.volID, tc.stagingTargetPath, diff --git a/pkg/volume/csi/csi_mounter.go b/pkg/volume/csi/csi_mounter.go index 53908c76b93..b6d86956d15 100644 --- a/pkg/volume/csi/csi_mounter.go +++ b/pkg/volume/csi/csi_mounter.go @@ -18,7 +18,6 @@ package csi import ( "context" - "encoding/json" "errors" "fmt" "os" @@ -55,8 +54,8 @@ var ( ) type csiMountMgr struct { - k8s kubernetes.Interface csiClient csiClient + k8s kubernetes.Interface plugin *csiPlugin driverName string volumeID string @@ -121,6 +120,7 @@ func (c *csiMountMgr) SetUpAt(dir string, fsGroup *int64) error { ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) defer cancel() + // Check for STAGE_UNSTAGE_VOLUME set and populate deviceMountPath if so deviceMountPath := "" stageUnstageSet, err := hasStageUnstageCapability(ctx, csi) @@ -170,24 +170,6 @@ func (c *csiMountMgr) SetUpAt(dir string, fsGroup *int64) error { } glog.V(4).Info(log("created target path successfully [%s]", dir)) - // persist volume info data for teardown - volData := map[string]string{ - volDataKey.specVolID: c.spec.Name(), - volDataKey.volHandle: csiSource.VolumeHandle, - volDataKey.driverName: csiSource.Driver, - volDataKey.nodeName: nodeName, - volDataKey.attachmentID: attachID, - } - - if err := saveVolumeData(c.plugin, c.podUID, c.spec.Name(), volData); err != nil { - glog.Error(log("mounter.SetUpAt failed to save volume info data: %v", err)) - if err := removeMountDir(c.plugin, dir); err != nil { - glog.Error(log("mounter.SetUpAt failed to remove mount dir after a saveVolumeData() error [%s]: %v", dir, err)) - return err - } - return err - } - //TODO (vladimirvivien) implement better AccessModes mapping between k8s and CSI accessMode := api.ReadWriteOnce if c.spec.PersistentVolume.Spec.AccessModes != nil { @@ -290,29 +272,12 @@ func (c *csiMountMgr) TearDownAt(dir string) error { return nil } - // load volume info from file - dataDir := path.Dir(dir) // dropoff /mount at end - data, err := loadVolumeData(dataDir, volDataFileName) - if err != nil { - glog.Error(log("unmounter.Teardown failed to load volume data file using dir [%s]: %v", dir, err)) - return err - } - - volID := data[volDataKey.volHandle] - driverName := data[volDataKey.driverName] - - if c.csiClient == nil { - addr := fmt.Sprintf(csiAddrTemplate, driverName) - client := newCsiDriverClient("unix", addr) - glog.V(4).Infof(log("unmounter csiClient setup [volume=%v,driver=%v]", volID, driverName)) - c.csiClient = client - } + volID := c.volumeID + csi := c.csiClient ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) defer cancel() - csi := c.csiClient - if err := csi.NodeUnpublishVolume(ctx, volID, dir); err != nil { glog.Errorf(log("mounter.TearDownAt failed: %v", err)) return err @@ -328,50 +293,6 @@ func (c *csiMountMgr) TearDownAt(dir string) error { return nil } -// saveVolumeData persists parameter data as json file using the location -// generated by /var/lib/kubelet/pods//volumes/kubernetes.io~csi//volume_data.json -func saveVolumeData(p *csiPlugin, podUID types.UID, specVolID string, data map[string]string) error { - dir := getTargetPath(podUID, specVolID, p.host) - dataFilePath := path.Join(dir, volDataFileName) - - file, err := os.Create(dataFilePath) - if err != nil { - glog.Error(log("failed to save volume data file %s: %v", dataFilePath, err)) - return err - } - defer file.Close() - if err := json.NewEncoder(file).Encode(data); err != nil { - glog.Error(log("failed to save volume data file %s: %v", dataFilePath, err)) - return err - } - glog.V(4).Info(log("volume data file saved successfully [%s]", dataFilePath)) - return nil -} - -// loadVolumeData uses the directory returned by mounter.GetPath with value -// /var/lib/kubelet/pods//volumes/kubernetes.io~csi//mount. -// The function extracts specVolumeID and uses it to load the json data file from dir -// /var/lib/kubelet/pods//volumes/kubernetes.io~csi//volume_data.json -func loadVolumeData(dir string, fileName string) (map[string]string, error) { - // remove /mount at the end - dataFileName := path.Join(dir, fileName) - glog.V(4).Info(log("loading volume data file [%s]", dataFileName)) - - file, err := os.Open(dataFileName) - if err != nil { - glog.Error(log("failed to open volume data file [%s]: %v", dataFileName, err)) - return nil, err - } - defer file.Close() - data := map[string]string{} - if err := json.NewDecoder(file).Decode(&data); err != nil { - glog.Error(log("failed to parse volume data file [%s]: %v", dataFileName, err)) - return nil, err - } - - return data, nil -} - // isDirMounted returns the !notMounted result from IsLikelyNotMountPoint check func isDirMounted(plug *csiPlugin, dir string) (bool, error) { mounter := plug.host.GetMounter(plug.GetPluginName()) diff --git a/pkg/volume/csi/csi_mounter_test.go b/pkg/volume/csi/csi_mounter_test.go index c64792c5d11..d1e942871d0 100644 --- a/pkg/volume/csi/csi_mounter_test.go +++ b/pkg/volume/csi/csi_mounter_test.go @@ -31,8 +31,8 @@ import ( "k8s.io/apimachinery/pkg/types" fakeclient "k8s.io/client-go/kubernetes/fake" "k8s.io/kubernetes/pkg/volume" - "k8s.io/kubernetes/pkg/volume/csi/fake" volumetest "k8s.io/kubernetes/pkg/volume/testing" + "k8s.io/kubernetes/pkg/volume/util" ) var ( @@ -78,7 +78,6 @@ func TestMounterGetPath(t *testing.T) { csiMounter := mounter.(*csiMountMgr) path := csiMounter.GetPath() - t.Logf("*** GetPath: %s", path) if tc.path != path { t.Errorf("expecting path %s, got %s", tc.path, path) @@ -114,7 +113,7 @@ func TestMounterSetUp(t *testing.T) { } csiMounter := mounter.(*csiMountMgr) - csiMounter.csiClient = setupClient(t, false) + csiMounter.csiClient = setupClient(t, true) attachID := getAttachmentName(csiMounter.volumeID, csiMounter.driverName, string(plug.host.GetNodeName())) @@ -155,7 +154,7 @@ func TestMounterSetUp(t *testing.T) { } // ensure call went all the way - pubs := csiMounter.csiClient.(*csiDriverClient).nodeClient.(*fake.NodeClient).GetNodePublishedVolumes() + pubs := csiMounter.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes() if pubs[csiMounter.volumeID] != csiMounter.GetPath() { t.Error("csi server may not have received NodePublishVolume call") } @@ -164,39 +163,46 @@ func TestMounterSetUp(t *testing.T) { func TestUnmounterTeardown(t *testing.T) { plug, tmpDir := newTestPlugin(t) defer os.RemoveAll(tmpDir) - pv := makeTestPV("test-pv", 10, testDriver, testVol) + // save the data file prior to unmount + dir := path.Join(getTargetPath(testPodUID, pv.ObjectMeta.Name, plug.host), "/mount") + if err := os.MkdirAll(dir, 0755); err != nil && !os.IsNotExist(err) { + t.Errorf("failed to create dir [%s]: %v", dir, err) + } + + // do a fake local mount + diskMounter := util.NewSafeFormatAndMountFromHost(plug.GetPluginName(), plug.host) + if err := diskMounter.FormatAndMount("/fake/device", dir, "testfs", nil); err != nil { + t.Errorf("failed to mount dir [%s]: %v", dir, err) + } + + if err := saveVolumeData( + path.Dir(dir), + volDataFileName, + map[string]string{ + volDataKey.specVolID: pv.ObjectMeta.Name, + volDataKey.driverName: testDriver, + volDataKey.volHandle: testVol, + }, + ); err != nil { + t.Fatalf("failed to save volume data: %v", err) + } + unmounter, err := plug.NewUnmounter(pv.ObjectMeta.Name, testPodUID) if err != nil { t.Fatalf("failed to make a new Unmounter: %v", err) } csiUnmounter := unmounter.(*csiMountMgr) - csiUnmounter.csiClient = setupClient(t, false) - - dir := csiUnmounter.GetPath() - - // save the data file prior to unmount - if err := os.MkdirAll(dir, 0755); err != nil && !os.IsNotExist(err) { - t.Errorf("failed to create dir [%s]: %v", dir, err) - } - if err := saveVolumeData( - plug, - testPodUID, - "test-pv", - map[string]string{volDataKey.specVolID: "test-pv", volDataKey.driverName: "driver", volDataKey.volHandle: "vol-handle"}, - ); err != nil { - t.Fatalf("failed to save volume data: %v", err) - } - + csiUnmounter.csiClient = setupClient(t, true) err = csiUnmounter.TearDownAt(dir) if err != nil { t.Fatal(err) } // ensure csi client call - pubs := csiUnmounter.csiClient.(*csiDriverClient).nodeClient.(*fake.NodeClient).GetNodePublishedVolumes() + pubs := csiUnmounter.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes() if _, ok := pubs[csiUnmounter.volumeID]; ok { t.Error("csi server may not have received NodeUnpublishVolume call") } @@ -223,7 +229,7 @@ func TestSaveVolumeData(t *testing.T) { t.Errorf("failed to create dir [%s]: %v", mountDir, err) } - err := saveVolumeData(plug, testPodUID, specVolID, tc.data) + err := saveVolumeData(path.Dir(mountDir), volDataFileName, tc.data) if !tc.shouldFail && err != nil { t.Errorf("unexpected failure: %v", err) diff --git a/pkg/volume/csi/csi_plugin.go b/pkg/volume/csi/csi_plugin.go index d63296877d0..d10457686a7 100644 --- a/pkg/volume/csi/csi_plugin.go +++ b/pkg/volume/csi/csi_plugin.go @@ -19,14 +19,21 @@ package csi import ( "errors" "fmt" + "os" + "path" + "strings" + "sync" "time" "github.com/golang/glog" api "k8s.io/api/core/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/csi/labelmanager" ) const ( @@ -40,16 +47,19 @@ const ( csiTimeout = 15 * time.Second volNameSep = "^" volDataFileName = "vol_data.json" + fsTypeBlockName = "block" ) type csiPlugin struct { - host volume.VolumeHost + host volume.VolumeHost + blockEnabled bool } // ProbeVolumePlugins returns implemented plugins func ProbeVolumePlugins() []volume.VolumePlugin { p := &csiPlugin{ - host: nil, + host: nil, + blockEnabled: utilfeature.DefaultFeatureGate.Enabled(features.CSIBlockVolume), } return []volume.VolumePlugin{p} } @@ -57,9 +67,54 @@ func ProbeVolumePlugins() []volume.VolumePlugin { // volume.VolumePlugin methods var _ volume.VolumePlugin = &csiPlugin{} +type csiDriver struct { + driverName string + driverEndpoint string +} + +type csiDriversStore struct { + driversMap map[string]csiDriver + sync.RWMutex +} + +// csiDrivers map keep track of all registered CSI drivers on the node and their +// corresponding sockets +var csiDrivers csiDriversStore + +var lm labelmanager.Interface + +// RegistrationCallback is called by kubelet's plugin watcher upon detection +// of a new registration socket opened by CSI Driver registrar side car. +func RegistrationCallback(pluginName string, endpoint string, versions []string, socketPath string) (error, chan bool) { + + glog.Infof(log("Callback from kubelet with plugin name: %s endpoint: %s versions: %s socket path: %s", + pluginName, endpoint, strings.Join(versions, ","), socketPath)) + + if endpoint == "" { + endpoint = socketPath + } + // Calling nodeLabelManager to update label for newly registered CSI driver + err := lm.AddLabels(pluginName) + if err != nil { + return err, nil + } + // Storing endpoint of newly registered CSI driver into the map, where CSI driver name will be the key + // all other CSI components will be able to get the actual socket of CSI drivers by its name. + csiDrivers.Lock() + defer csiDrivers.Unlock() + csiDrivers.driversMap[pluginName] = csiDriver{driverName: pluginName, driverEndpoint: endpoint} + + return nil, nil +} + func (p *csiPlugin) Init(host volume.VolumeHost) error { glog.Info(log("plugin initializing...")) p.host = host + + // Initializing csiDrivers map and label management channels + csiDrivers = csiDriversStore{driversMap: map[string]csiDriver{}} + lm = labelmanager.NewLabelManager(host.GetNodeName(), host.GetKubeClient()) + return nil } @@ -103,17 +158,14 @@ func (p *csiPlugin) NewMounter( return nil, err } - // before it is used in any paths such as socket etc - addr := fmt.Sprintf(csiAddrTemplate, pvSource.Driver) - glog.V(4).Infof(log("setting up mounter for [volume=%v,driver=%v]", pvSource.VolumeHandle, pvSource.Driver)) - client := newCsiDriverClient("unix", addr) - k8s := p.host.GetKubeClient() if k8s == nil { glog.Error(log("failed to get a kubernetes client")) return nil, errors.New("failed to get a Kubernetes client") } + csi := newCsiDriverClient(pvSource.Driver) + mounter := &csiMountMgr{ plugin: p, k8s: k8s, @@ -123,19 +175,66 @@ func (p *csiPlugin) NewMounter( driverName: pvSource.Driver, volumeID: pvSource.VolumeHandle, specVolumeID: spec.Name(), - csiClient: client, + csiClient: csi, readOnly: readOnly, } + + // Save volume info in pod dir + dir := mounter.GetPath() + dataDir := path.Dir(dir) // dropoff /mount at end + + if err := os.MkdirAll(dataDir, 0750); err != nil { + glog.Error(log("failed to create dir %#v: %v", dataDir, err)) + return nil, err + } + glog.V(4).Info(log("created path successfully [%s]", dataDir)) + + // persist volume info data for teardown + node := string(p.host.GetNodeName()) + attachID := getAttachmentName(pvSource.VolumeHandle, pvSource.Driver, node) + volData := map[string]string{ + volDataKey.specVolID: spec.Name(), + volDataKey.volHandle: pvSource.VolumeHandle, + volDataKey.driverName: pvSource.Driver, + volDataKey.nodeName: node, + volDataKey.attachmentID: attachID, + } + + if err := saveVolumeData(dataDir, volDataFileName, volData); err != nil { + glog.Error(log("failed to save volume info data: %v", err)) + if err := os.RemoveAll(dataDir); err != nil { + glog.Error(log("failed to remove dir after error [%s]: %v", dataDir, err)) + return nil, err + } + return nil, err + } + + glog.V(4).Info(log("mounter created successfully")) + return mounter, nil } func (p *csiPlugin) NewUnmounter(specName string, podUID types.UID) (volume.Unmounter, error) { glog.V(4).Infof(log("setting up unmounter for [name=%v, podUID=%v]", specName, podUID)) + unmounter := &csiMountMgr{ plugin: p, podUID: podUID, specVolumeID: specName, } + + // load volume info from file + dir := unmounter.GetPath() + dataDir := path.Dir(dir) // dropoff /mount at end + data, err := loadVolumeData(dataDir, volDataFileName) + if err != nil { + glog.Error(log("unmounter failed to load volume data file [%s]: %v", dir, err)) + return nil, err + } + unmounter.driverName = data[volDataKey.driverName] + unmounter.volumeID = data[volDataKey.volHandle] + unmounter.csiClient = newCsiDriverClient(unmounter.driverName) + return unmounter, nil } @@ -213,25 +312,132 @@ func (p *csiPlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) return mount.GetMountRefs(m, deviceMountPath) } -func getCSISourceFromSpec(spec *volume.Spec) (*api.CSIPersistentVolumeSource, error) { - if spec.PersistentVolume != nil && - spec.PersistentVolume.Spec.CSI != nil { - return spec.PersistentVolume.Spec.CSI, nil +// BlockVolumePlugin methods +var _ volume.BlockVolumePlugin = &csiPlugin{} + +func (p *csiPlugin) NewBlockVolumeMapper(spec *volume.Spec, podRef *api.Pod, opts volume.VolumeOptions) (volume.BlockVolumeMapper, error) { + if !p.blockEnabled { + return nil, errors.New("CSIBlockVolume feature not enabled") } - return nil, fmt.Errorf("CSIPersistentVolumeSource not defined in spec") -} - -func getReadOnlyFromSpec(spec *volume.Spec) (bool, error) { - if spec.PersistentVolume != nil && - spec.PersistentVolume.Spec.CSI != nil { - return spec.ReadOnly, nil + pvSource, err := getCSISourceFromSpec(spec) + if err != nil { + return nil, err + } + readOnly, err := getReadOnlyFromSpec(spec) + if err != nil { + return nil, err } - return false, fmt.Errorf("CSIPersistentVolumeSource not defined in spec") + glog.V(4).Info(log("setting up block mapper for [volume=%v,driver=%v]", pvSource.VolumeHandle, pvSource.Driver)) + client := newCsiDriverClient(pvSource.Driver) + + k8s := p.host.GetKubeClient() + if k8s == nil { + glog.Error(log("failed to get a kubernetes client")) + return nil, errors.New("failed to get a Kubernetes client") + } + + mapper := &csiBlockMapper{ + csiClient: client, + k8s: k8s, + plugin: p, + volumeID: pvSource.VolumeHandle, + driverName: pvSource.Driver, + readOnly: readOnly, + spec: spec, + podUID: podRef.UID, + } + + // Save volume info in pod dir + dataDir := getVolumeDeviceDataDir(spec.Name(), p.host) + + if err := os.MkdirAll(dataDir, 0750); err != nil { + glog.Error(log("failed to create data dir %s: %v", dataDir, err)) + return nil, err + } + glog.V(4).Info(log("created path successfully [%s]", dataDir)) + + // persist volume info data for teardown + node := string(p.host.GetNodeName()) + attachID := getAttachmentName(pvSource.VolumeHandle, pvSource.Driver, node) + volData := map[string]string{ + volDataKey.specVolID: spec.Name(), + volDataKey.volHandle: pvSource.VolumeHandle, + volDataKey.driverName: pvSource.Driver, + volDataKey.nodeName: node, + volDataKey.attachmentID: attachID, + } + + if err := saveVolumeData(dataDir, volDataFileName, volData); err != nil { + glog.Error(log("failed to save volume info data: %v", err)) + if err := os.RemoveAll(dataDir); err != nil { + glog.Error(log("failed to remove dir after error [%s]: %v", dataDir, err)) + return nil, err + } + return nil, err + } + + return mapper, nil } -// log prepends log string with `kubernetes.io/csi` -func log(msg string, parts ...interface{}) string { - return fmt.Sprintf(fmt.Sprintf("%s: %s", csiPluginName, msg), parts...) +func (p *csiPlugin) NewBlockVolumeUnmapper(volName string, podUID types.UID) (volume.BlockVolumeUnmapper, error) { + if !p.blockEnabled { + return nil, errors.New("CSIBlockVolume feature not enabled") + } + + glog.V(4).Infof(log("setting up block unmapper for [Spec=%v, podUID=%v]", volName, podUID)) + unmapper := &csiBlockMapper{ + plugin: p, + podUID: podUID, + specName: volName, + } + + // load volume info from file + dataDir := getVolumeDeviceDataDir(unmapper.specName, p.host) + data, err := loadVolumeData(dataDir, volDataFileName) + if err != nil { + glog.Error(log("unmapper failed to load volume data file [%s]: %v", dataDir, err)) + return nil, err + } + unmapper.driverName = data[volDataKey.driverName] + unmapper.volumeID = data[volDataKey.volHandle] + unmapper.csiClient = newCsiDriverClient(unmapper.driverName) + + return unmapper, nil +} + +func (p *csiPlugin) ConstructBlockVolumeSpec(podUID types.UID, specVolName, mapPath string) (*volume.Spec, error) { + if !p.blockEnabled { + return nil, errors.New("CSIBlockVolume feature not enabled") + } + + glog.V(4).Infof("plugin.ConstructBlockVolumeSpec [podUID=%s, specVolName=%s, path=%s]", string(podUID), specVolName, mapPath) + + dataDir := getVolumeDeviceDataDir(specVolName, p.host) + volData, err := loadVolumeData(dataDir, volDataFileName) + if err != nil { + glog.Error(log("plugin.ConstructBlockVolumeSpec failed loading volume data using [%s]: %v", mapPath, err)) + return nil, err + } + + glog.V(4).Info(log("plugin.ConstructBlockVolumeSpec extracted [%#v]", volData)) + + blockMode := api.PersistentVolumeBlock + pv := &api.PersistentVolume{ + ObjectMeta: meta.ObjectMeta{ + Name: volData[volDataKey.specVolID], + }, + Spec: api.PersistentVolumeSpec{ + PersistentVolumeSource: api.PersistentVolumeSource{ + CSI: &api.CSIPersistentVolumeSource{ + Driver: volData[volDataKey.driverName], + VolumeHandle: volData[volDataKey.volHandle], + }, + }, + VolumeMode: &blockMode, + }, + } + + return volume.NewSpecFromPersistentVolume(pv, false), nil } diff --git a/pkg/volume/csi/csi_plugin_test.go b/pkg/volume/csi/csi_plugin_test.go index 66151e0ac7d..ce76592e4e3 100644 --- a/pkg/volume/csi/csi_plugin_test.go +++ b/pkg/volume/csi/csi_plugin_test.go @@ -20,12 +20,14 @@ import ( "fmt" "os" "path" + "path/filepath" "testing" api "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" fakeclient "k8s.io/client-go/kubernetes/fake" utiltesting "k8s.io/client-go/util/testing" "k8s.io/kubernetes/pkg/volume" @@ -34,6 +36,11 @@ import ( // create a plugin mgr to load plugins and setup a fake client func newTestPlugin(t *testing.T) (*csiPlugin, string) { + err := utilfeature.DefaultFeatureGate.Set("CSIBlockVolume=true") + if err != nil { + t.Fatalf("Failed to enable feature gate for CSIBlockVolume: %v", err) + } + tmpDir, err := utiltesting.MkTmpdir("csi-test") if err != nil { t.Fatalf("can't create temp dir: %v", err) @@ -160,7 +167,7 @@ func TestPluginConstructVolumeSpec(t *testing.T) { if err := os.MkdirAll(mountDir, 0755); err != nil && !os.IsNotExist(err) { t.Errorf("failed to create dir [%s]: %v", mountDir, err) } - if err := saveVolumeData(plug, testPodUID, tc.specVolID, tc.data); err != nil { + if err := saveVolumeData(path.Dir(mountDir), volDataFileName, tc.data); err != nil { t.Fatal(err) } } @@ -215,7 +222,21 @@ func TestPluginNewMounter(t *testing.T) { t.Error("mounter pod not set") } if csiMounter.podUID == types.UID("") { - t.Error("mounter podUID mot set") + t.Error("mounter podUID not set") + } + if csiMounter.csiClient == nil { + t.Error("mounter csiClient is nil") + } + + // ensure data file is created + dataDir := path.Dir(mounter.GetPath()) + dataFile := filepath.Join(dataDir, volDataFileName) + if _, err := os.Stat(dataFile); err != nil { + if os.IsNotExist(err) { + t.Errorf("data file not created %s", dataFile) + } else { + t.Fatal(err) + } } } @@ -225,6 +246,25 @@ func TestPluginNewUnmounter(t *testing.T) { pv := makeTestPV("test-pv", 10, testDriver, testVol) + // save the data file to re-create client + dir := path.Join(getTargetPath(testPodUID, pv.ObjectMeta.Name, plug.host), "/mount") + if err := os.MkdirAll(dir, 0755); err != nil && !os.IsNotExist(err) { + t.Errorf("failed to create dir [%s]: %v", dir, err) + } + + if err := saveVolumeData( + path.Dir(dir), + volDataFileName, + map[string]string{ + volDataKey.specVolID: pv.ObjectMeta.Name, + volDataKey.driverName: testDriver, + volDataKey.volHandle: testVol, + }, + ); err != nil { + t.Fatalf("failed to save volume data: %v", err) + } + + // test unmounter unmounter, err := plug.NewUnmounter(pv.ObjectMeta.Name, testPodUID) csiUnmounter := unmounter.(*csiMountMgr) @@ -240,6 +280,9 @@ func TestPluginNewUnmounter(t *testing.T) { t.Error("podUID not set") } + if csiUnmounter.csiClient == nil { + t.Error("unmounter csiClient is nil") + } } func TestPluginNewAttacher(t *testing.T) { @@ -277,3 +320,156 @@ func TestPluginNewDetacher(t *testing.T) { t.Error("Kubernetes client not set for detacher") } } + +func TestPluginNewBlockMapper(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + pv := makeTestPV("test-block-pv", 10, testDriver, testVol) + mounter, err := plug.NewBlockVolumeMapper( + volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly), + &api.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}}, + volume.VolumeOptions{}, + ) + if err != nil { + t.Fatalf("Failed to make a new BlockMapper: %v", err) + } + + if mounter == nil { + t.Fatal("failed to create CSI BlockMapper, mapper is nill") + } + csiMapper := mounter.(*csiBlockMapper) + + // validate mounter fields + if csiMapper.driverName != testDriver { + t.Error("CSI block mapper missing driver name") + } + if csiMapper.volumeID != testVol { + t.Error("CSI block mapper missing volumeID") + } + + if csiMapper.podUID == types.UID("") { + t.Error("CSI block mapper missing pod.UID") + } + if csiMapper.csiClient == nil { + t.Error("mapper csiClient is nil") + } + + // ensure data file is created + dataFile := getVolumeDeviceDataDir(csiMapper.spec.Name(), plug.host) + if _, err := os.Stat(dataFile); err != nil { + if os.IsNotExist(err) { + t.Errorf("data file not created %s", dataFile) + } else { + t.Fatal(err) + } + } +} + +func TestPluginNewUnmapper(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + pv := makeTestPV("test-pv", 10, testDriver, testVol) + + // save the data file to re-create client + dir := getVolumeDeviceDataDir(pv.ObjectMeta.Name, plug.host) + if err := os.MkdirAll(dir, 0755); err != nil && !os.IsNotExist(err) { + t.Errorf("failed to create dir [%s]: %v", dir, err) + } + + if err := saveVolumeData( + dir, + volDataFileName, + map[string]string{ + volDataKey.specVolID: pv.ObjectMeta.Name, + volDataKey.driverName: testDriver, + volDataKey.volHandle: testVol, + }, + ); err != nil { + t.Fatalf("failed to save volume data: %v", err) + } + + // test unmounter + unmapper, err := plug.NewBlockVolumeUnmapper(pv.ObjectMeta.Name, testPodUID) + csiUnmapper := unmapper.(*csiBlockMapper) + + if err != nil { + t.Fatalf("Failed to make a new Unmounter: %v", err) + } + + if csiUnmapper == nil { + t.Fatal("failed to create CSI Unmounter") + } + + if csiUnmapper.podUID != testPodUID { + t.Error("podUID not set") + } + + if csiUnmapper.specName != pv.ObjectMeta.Name { + t.Error("specName not set") + } + + if csiUnmapper.csiClient == nil { + t.Error("unmapper csiClient is nil") + } + + // test loaded vol data + if csiUnmapper.driverName != testDriver { + t.Error("unmapper driverName not set") + } + if csiUnmapper.volumeID != testVol { + t.Error("unmapper volumeHandle not set") + } +} + +func TestPluginConstructBlockVolumeSpec(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + testCases := []struct { + name string + specVolID string + data map[string]string + shouldFail bool + }{ + { + name: "valid spec name", + specVolID: "test.vol.id", + data: map[string]string{volDataKey.specVolID: "test.vol.id", volDataKey.volHandle: "test-vol0", volDataKey.driverName: "test-driver0"}, + }, + } + + for _, tc := range testCases { + t.Logf("test case: %s", tc.name) + deviceDataDir := getVolumeDeviceDataDir(tc.specVolID, plug.host) + + // create data file in csi plugin dir + if tc.data != nil { + if err := os.MkdirAll(deviceDataDir, 0755); err != nil && !os.IsNotExist(err) { + t.Errorf("failed to create dir [%s]: %v", deviceDataDir, err) + } + if err := saveVolumeData(deviceDataDir, volDataFileName, tc.data); err != nil { + t.Fatal(err) + } + } + + // rebuild spec + spec, err := plug.ConstructBlockVolumeSpec("test-podUID", tc.specVolID, getVolumeDevicePluginDir(tc.specVolID, plug.host)) + if tc.shouldFail { + if err == nil { + t.Fatal("expecting ConstructVolumeSpec to fail, but got nil error") + } + continue + } + + volHandle := spec.PersistentVolume.Spec.CSI.VolumeHandle + if volHandle != tc.data[volDataKey.volHandle] { + t.Errorf("expected volID %s, got volID %s", tc.data[volDataKey.volHandle], volHandle) + } + + if spec.Name() != tc.specVolID { + t.Errorf("Unexpected spec name %s", spec.Name()) + } + } +} diff --git a/pkg/volume/csi/csi_util.go b/pkg/volume/csi/csi_util.go index 81a973e44db..6a0b67212e5 100644 --- a/pkg/volume/csi/csi_util.go +++ b/pkg/volume/csi/csi_util.go @@ -17,10 +17,17 @@ limitations under the License. package csi import ( + "encoding/json" + "fmt" + "os" + "path" + "github.com/golang/glog" api "k8s.io/api/core/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" + kstrings "k8s.io/kubernetes/pkg/util/strings" + "k8s.io/kubernetes/pkg/volume" ) func getCredentialsFromSecret(k8s kubernetes.Interface, secretRef *api.SecretReference) (map[string]string, error) { @@ -36,3 +43,81 @@ func getCredentialsFromSecret(k8s kubernetes.Interface, secretRef *api.SecretRef return credentials, nil } + +// saveVolumeData persists parameter data as json file at the provided location +func saveVolumeData(dir string, fileName string, data map[string]string) error { + dataFilePath := path.Join(dir, fileName) + glog.V(4).Info(log("saving volume data file [%s]", dataFilePath)) + file, err := os.Create(dataFilePath) + if err != nil { + glog.Error(log("failed to save volume data file %s: %v", dataFilePath, err)) + return err + } + defer file.Close() + if err := json.NewEncoder(file).Encode(data); err != nil { + glog.Error(log("failed to save volume data file %s: %v", dataFilePath, err)) + return err + } + glog.V(4).Info(log("volume data file saved successfully [%s]", dataFilePath)) + return nil +} + +// loadVolumeData loads volume info from specified json file/location +func loadVolumeData(dir string, fileName string) (map[string]string, error) { + // remove /mount at the end + dataFileName := path.Join(dir, fileName) + glog.V(4).Info(log("loading volume data file [%s]", dataFileName)) + + file, err := os.Open(dataFileName) + if err != nil { + glog.Error(log("failed to open volume data file [%s]: %v", dataFileName, err)) + return nil, err + } + defer file.Close() + data := map[string]string{} + if err := json.NewDecoder(file).Decode(&data); err != nil { + glog.Error(log("failed to parse volume data file [%s]: %v", dataFileName, err)) + return nil, err + } + + return data, nil +} + +func getCSISourceFromSpec(spec *volume.Spec) (*api.CSIPersistentVolumeSource, error) { + if spec.PersistentVolume != nil && + spec.PersistentVolume.Spec.CSI != nil { + return spec.PersistentVolume.Spec.CSI, nil + } + + return nil, fmt.Errorf("CSIPersistentVolumeSource not defined in spec") +} + +func getReadOnlyFromSpec(spec *volume.Spec) (bool, error) { + if spec.PersistentVolume != nil && + spec.PersistentVolume.Spec.CSI != nil { + return spec.ReadOnly, nil + } + + return false, fmt.Errorf("CSIPersistentVolumeSource not defined in spec") +} + +// log prepends log string with `kubernetes.io/csi` +func log(msg string, parts ...interface{}) string { + return fmt.Sprintf(fmt.Sprintf("%s: %s", csiPluginName, msg), parts...) +} + +// getVolumeDevicePluginDir returns the path where the CSI plugin keeps the +// symlink for a block device associated with a given specVolumeID. +// path: plugins/kubernetes.io/csi/volumeDevices/{specVolumeID}/dev +func getVolumeDevicePluginDir(specVolID string, host volume.VolumeHost) string { + sanitizedSpecVolID := kstrings.EscapeQualifiedNameForDisk(specVolID) + return path.Join(host.GetVolumeDevicePluginDir(csiPluginName), sanitizedSpecVolID, "dev") +} + +// getVolumeDeviceDataDir returns the path where the CSI plugin keeps the +// volume data for a block device associated with a given specVolumeID. +// path: plugins/kubernetes.io/csi/volumeDevices/{specVolumeID}/data +func getVolumeDeviceDataDir(specVolID string, host volume.VolumeHost) string { + sanitizedSpecVolID := kstrings.EscapeQualifiedNameForDisk(specVolID) + return path.Join(host.GetVolumeDevicePluginDir(csiPluginName), sanitizedSpecVolID, "data") +} diff --git a/pkg/volume/csi/fake/fake_client.go b/pkg/volume/csi/fake/fake_client.go index 805f73ca20b..b4341e71514 100644 --- a/pkg/volume/csi/fake/fake_client.go +++ b/pkg/volume/csi/fake/fake_client.go @@ -105,7 +105,7 @@ func (f *NodeClient) NodePublishVolume(ctx context.Context, req *csipb.NodePubli if req.GetTargetPath() == "" { return nil, errors.New("missing target path") } - fsTypes := "ext4|xfs|zfs" + fsTypes := "block|ext4|xfs|zfs" fsType := req.GetVolumeCapability().GetMount().GetFsType() if !strings.Contains(fsTypes, fsType) { return nil, errors.New("invalid fstype") @@ -144,7 +144,7 @@ func (f *NodeClient) NodeStageVolume(ctx context.Context, req *csipb.NodeStageVo } fsType := "" - fsTypes := "ext4|xfs|zfs" + fsTypes := "block|ext4|xfs|zfs" mounted := req.GetVolumeCapability().GetMount() if mounted != nil { fsType = mounted.GetFsType() diff --git a/pkg/volume/csi/labelmanager/BUILD b/pkg/volume/csi/labelmanager/BUILD new file mode 100644 index 00000000000..1fed8335642 --- /dev/null +++ b/pkg/volume/csi/labelmanager/BUILD @@ -0,0 +1,30 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["labelmanager.go"], + importpath = "k8s.io/kubernetes/pkg/volume/csi/labelmanager", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/util/retry: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/volume/csi/labelmanager/labelmanager.go b/pkg/volume/csi/labelmanager/labelmanager.go new file mode 100644 index 00000000000..162d7d3dc84 --- /dev/null +++ b/pkg/volume/csi/labelmanager/labelmanager.go @@ -0,0 +1,251 @@ +/* +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 labelmanager includes internal functions used to add/delete labels to +// kubernetes nodes for corresponding CSI drivers +package labelmanager // import "k8s.io/kubernetes/pkg/volume/csi/labelmanager" + +import ( + "encoding/json" + "fmt" + + "github.com/golang/glog" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/util/retry" +) + +const ( + // Name of node annotation that contains JSON map of driver names to node + // names + annotationKey = "csi.volume.kubernetes.io/nodeid" + csiPluginName = "kubernetes.io/csi" +) + +// labelManagementStruct is struct of channels used for communication between the driver registration +// code and the go routine responsible for managing the node's labels +type labelManagerStruct struct { + nodeName types.NodeName + k8s kubernetes.Interface +} + +// Interface implements an interface for managing labels of a node +type Interface interface { + AddLabels(driverName string) error +} + +// NewLabelManager initializes labelManagerStruct and returns available interfaces +func NewLabelManager(nodeName types.NodeName, kubeClient kubernetes.Interface) Interface { + return labelManagerStruct{ + nodeName: nodeName, + k8s: kubeClient, + } +} + +// nodeLabelManager waits for labeling requests initiated by the driver's registration +// process. +func (lm labelManagerStruct) AddLabels(driverName string) error { + err := verifyAndAddNodeId(string(lm.nodeName), lm.k8s.CoreV1().Nodes(), driverName, string(lm.nodeName)) + if err != nil { + return fmt.Errorf("failed to update node %s's annotation with error: %+v", lm.nodeName, err) + } + return nil +} + +// Clones the given map and returns a new map with the given key and value added. +// Returns the given map, if annotationKey is empty. +func cloneAndAddAnnotation( + annotations map[string]string, + annotationKey, + annotationValue string) map[string]string { + if annotationKey == "" { + // Don't need to add an annotation. + return annotations + } + // Clone. + newAnnotations := map[string]string{} + for key, value := range annotations { + newAnnotations[key] = value + } + newAnnotations[annotationKey] = annotationValue + return newAnnotations +} + +func verifyAndAddNodeId( + k8sNodeName string, + k8sNodesClient corev1.NodeInterface, + csiDriverName string, + csiDriverNodeId string) error { + // Add or update annotation on Node object + retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { + // Retrieve the latest version of Node before attempting update, so that + // existing changes are not overwritten. RetryOnConflict uses + // exponential backoff to avoid exhausting the apiserver. + result, getErr := k8sNodesClient.Get(k8sNodeName, metav1.GetOptions{}) + if getErr != nil { + glog.Errorf("Failed to get latest version of Node: %v", getErr) + return getErr // do not wrap error + } + + var previousAnnotationValue string + if result.ObjectMeta.Annotations != nil { + previousAnnotationValue = + result.ObjectMeta.Annotations[annotationKey] + glog.V(3).Infof( + "previousAnnotationValue=%q", previousAnnotationValue) + } + + existingDriverMap := map[string]string{} + if previousAnnotationValue != "" { + // Parse previousAnnotationValue as JSON + if err := json.Unmarshal([]byte(previousAnnotationValue), &existingDriverMap); err != nil { + return fmt.Errorf( + "failed to parse node's %q annotation value (%q) err=%v", + annotationKey, + previousAnnotationValue, + err) + } + } + + if val, ok := existingDriverMap[csiDriverName]; ok { + if val == csiDriverNodeId { + // Value already exists in node annotation, nothing more to do + glog.V(1).Infof( + "The key value {%q: %q} alredy eixst in node %q annotation, no need to update: %v", + csiDriverName, + csiDriverNodeId, + annotationKey, + previousAnnotationValue) + return nil + } + } + + // Add/update annotation value + existingDriverMap[csiDriverName] = csiDriverNodeId + jsonObj, err := json.Marshal(existingDriverMap) + if err != nil { + return fmt.Errorf( + "failed while trying to add key value {%q: %q} to node %q annotation. Existing value: %v", + csiDriverName, + csiDriverNodeId, + annotationKey, + previousAnnotationValue) + } + + result.ObjectMeta.Annotations = cloneAndAddAnnotation( + result.ObjectMeta.Annotations, + annotationKey, + string(jsonObj)) + _, updateErr := k8sNodesClient.Update(result) + if updateErr == nil { + fmt.Printf( + "Updated node %q successfully for CSI driver %q and CSI node name %q", + k8sNodeName, + csiDriverName, + csiDriverNodeId) + } + return updateErr // do not wrap error + }) + if retryErr != nil { + return fmt.Errorf("node update failed: %v", retryErr) + } + return nil +} + +// Fetches Kubernetes node API object corresponding to k8sNodeName. +// If the csiDriverName is present in the node annotation, it is removed. +func verifyAndDeleteNodeId( + k8sNodeName string, + k8sNodesClient corev1.NodeInterface, + csiDriverName string) error { + retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { + // Retrieve the latest version of Node before attempting update, so that + // existing changes are not overwritten. RetryOnConflict uses + // exponential backoff to avoid exhausting the apiserver. + result, getErr := k8sNodesClient.Get(k8sNodeName, metav1.GetOptions{}) + if getErr != nil { + glog.Errorf("failed to get latest version of Node: %v", getErr) + return getErr // do not wrap error + } + + var previousAnnotationValue string + if result.ObjectMeta.Annotations != nil { + previousAnnotationValue = + result.ObjectMeta.Annotations[annotationKey] + glog.V(3).Infof( + "previousAnnotationValue=%q", previousAnnotationValue) + } + + existingDriverMap := map[string]string{} + if previousAnnotationValue == "" { + // Value already exists in node annotation, nothing more to do + glog.V(1).Infof( + "The key %q does not exist in node %q annotation, no need to cleanup.", + csiDriverName, + annotationKey) + return nil + } + + // Parse previousAnnotationValue as JSON + if err := json.Unmarshal([]byte(previousAnnotationValue), &existingDriverMap); err != nil { + return fmt.Errorf( + "failed to parse node's %q annotation value (%q) err=%v", + annotationKey, + previousAnnotationValue, + err) + } + + if _, ok := existingDriverMap[csiDriverName]; !ok { + // Value already exists in node annotation, nothing more to do + glog.V(1).Infof( + "The key %q does not eixst in node %q annotation, no need to cleanup: %v", + csiDriverName, + annotationKey, + previousAnnotationValue) + return nil + } + + // Add/update annotation value + delete(existingDriverMap, csiDriverName) + jsonObj, err := json.Marshal(existingDriverMap) + if err != nil { + return fmt.Errorf( + "failed while trying to remove key %q from node %q annotation. Existing data: %v", + csiDriverName, + annotationKey, + previousAnnotationValue) + } + + result.ObjectMeta.Annotations = cloneAndAddAnnotation( + result.ObjectMeta.Annotations, + annotationKey, + string(jsonObj)) + _, updateErr := k8sNodesClient.Update(result) + if updateErr == nil { + fmt.Printf( + "Updated node %q annotation to remove CSI driver %q.", + k8sNodeName, + csiDriverName) + } + return updateErr // do not wrap error + }) + if retryErr != nil { + return fmt.Errorf("node update failed: %v", retryErr) + } + return nil +} diff --git a/pkg/volume/downwardapi/downwardapi.go b/pkg/volume/downwardapi/downwardapi.go index e1c1c536eeb..b8a2c8ec575 100644 --- a/pkg/volume/downwardapi/downwardapi.go +++ b/pkg/volume/downwardapi/downwardapi.go @@ -180,13 +180,6 @@ func (b *downwardAPIVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { glog.Errorf("Couldn't setup downwardAPI volume %v for pod %v/%v: %s", b.volName, b.pod.Namespace, b.pod.Name, err.Error()) return err } - if err := wrapped.SetUpAt(dir, fsGroup); err != nil { - glog.Errorf("Unable to setup downwardAPI volume %v for pod %v/%v: %s", b.volName, b.pod.Namespace, b.pod.Name, err.Error()) - return err - } - if err := volumeutil.MakeNestedMountpoints(b.volName, dir, *b.pod); err != nil { - return err - } data, err := CollectData(b.source.Items, b.pod, b.plugin.host, b.source.DefaultMode) if err != nil { @@ -194,6 +187,15 @@ func (b *downwardAPIVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { return err } + if err := wrapped.SetUpAt(dir, fsGroup); err != nil { + glog.Errorf("Unable to setup downwardAPI volume %v for pod %v/%v: %s", b.volName, b.pod.Namespace, b.pod.Name, err.Error()) + return err + } + + if err := volumeutil.MakeNestedMountpoints(b.volName, dir, *b.pod); err != nil { + return err + } + writerContext := fmt.Sprintf("pod %v/%v volume %v", b.pod.Namespace, b.pod.Name, b.volName) writer, err := volumeutil.NewAtomicWriter(dir, writerContext) if err != nil { diff --git a/pkg/volume/fc/fc.go b/pkg/volume/fc/fc.go index fb7a570155e..4160fe055c4 100644 --- a/pkg/volume/fc/fc.go +++ b/pkg/volume/fc/fc.go @@ -443,6 +443,10 @@ func (b *fcDiskMapper) SetUpDevice() (string, error) { return "", nil } +func (b *fcDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + type fcDiskUnmapper struct { *fcDisk deviceUtil util.DeviceUtil diff --git a/pkg/volume/flocker/flocker_volume.go b/pkg/volume/flocker/flocker_volume.go index d7f245d15a2..e25e2d2fdcb 100644 --- a/pkg/volume/flocker/flocker_volume.go +++ b/pkg/volume/flocker/flocker_volume.go @@ -54,7 +54,7 @@ type flockerVolumeProvisioner struct { var _ volume.Provisioner = &flockerVolumeProvisioner{} -func (c *flockerVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *flockerVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } @@ -67,6 +67,10 @@ func (c *flockerVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { return nil, fmt.Errorf("Provisioning failed: Specified unsupported selector") } + if util.CheckPersistentVolumeClaimModeBlock(c.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", c.plugin.GetPluginName()) + } + datasetUUID, sizeGB, labels, err := c.manager.CreateVolume(c) if err != nil { return nil, err diff --git a/pkg/volume/flocker/flocker_volume_test.go b/pkg/volume/flocker/flocker_volume_test.go index db24c348ba2..7a46232d412 100644 --- a/pkg/volume/flocker/flocker_volume_test.go +++ b/pkg/volume/flocker/flocker_volume_test.go @@ -57,7 +57,7 @@ func TestProvision(t *testing.T) { dir, provisioner := newTestableProvisioner(assert, options) defer os.RemoveAll(dir) - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) assert.NoError(err, "Provision() failed: ", err) cap := persistentSpec.Spec.Capacity[v1.ResourceStorage] @@ -85,7 +85,7 @@ func TestProvision(t *testing.T) { dir, provisioner = newTestableProvisioner(assert, options) defer os.RemoveAll(dir) - persistentSpec, err = provisioner.Provision() + persistentSpec, err = provisioner.Provision(nil, nil) assert.Error(err, "Provision() did not fail with Parameters specified") // selectors are not supported @@ -97,6 +97,6 @@ func TestProvision(t *testing.T) { dir, provisioner = newTestableProvisioner(assert, options) defer os.RemoveAll(dir) - persistentSpec, err = provisioner.Provision() + persistentSpec, err = provisioner.Provision(nil, nil) assert.Error(err, "Provision() did not fail with Selector specified") } diff --git a/pkg/volume/gce_pd/gce_pd.go b/pkg/volume/gce_pd/gce_pd.go index 8c78c6754af..18e040433a6 100644 --- a/pkg/volume/gce_pd/gce_pd.go +++ b/pkg/volume/gce_pd/gce_pd.go @@ -17,16 +17,21 @@ limitations under the License. package gce_pd import ( + "context" "fmt" "os" "path" "strconv" + "strings" "github.com/golang/glog" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" + gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/util/mount" kstrings "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" @@ -47,11 +52,24 @@ var _ volume.PersistentVolumePlugin = &gcePersistentDiskPlugin{} var _ volume.DeletableVolumePlugin = &gcePersistentDiskPlugin{} var _ volume.ProvisionableVolumePlugin = &gcePersistentDiskPlugin{} var _ volume.ExpandableVolumePlugin = &gcePersistentDiskPlugin{} +var _ volume.VolumePluginWithAttachLimits = &gcePersistentDiskPlugin{} const ( gcePersistentDiskPluginName = "kubernetes.io/gce-pd" ) +// The constants are used to map from the machine type (number of CPUs) to the limit of +// persistent disks that can be attached to an instance. Please refer to gcloud doc +// https://cloud.google.com/compute/docs/disks/#increased_persistent_disk_limits +const ( + OneCPU = 1 + EightCPUs = 8 + VolumeLimit16 = 16 + VolumeLimit32 = 32 + VolumeLimit64 = 64 + VolumeLimit128 = 128 +) + func getPath(uid types.UID, volName string, host volume.VolumeHost) string { return host.GetPodVolumeDir(uid, kstrings.EscapeQualifiedNameForDisk(gcePersistentDiskPluginName), volName) } @@ -98,6 +116,58 @@ func (plugin *gcePersistentDiskPlugin) GetAccessModes() []v1.PersistentVolumeAcc } } +func (plugin *gcePersistentDiskPlugin) GetVolumeLimits() (map[string]int64, error) { + volumeLimits := map[string]int64{ + util.GCEVolumeLimitKey: VolumeLimit16, + } + cloud := plugin.host.GetCloudProvider() + + // if we can't fetch cloudprovider we return an error + // hoping external CCM or admin can set it. Returning + // default values from here will mean, no one can + // override them. + if cloud == nil { + return nil, fmt.Errorf("No cloudprovider present") + } + + if cloud.ProviderName() != gcecloud.ProviderName { + return nil, fmt.Errorf("Expected gce cloud got %s", cloud.ProviderName()) + } + + instances, ok := cloud.Instances() + if !ok { + glog.Warning("Failed to get instances from cloud provider") + return volumeLimits, nil + } + + instanceType, err := instances.InstanceType(context.TODO(), plugin.host.GetNodeName()) + if err != nil { + glog.Errorf("Failed to get instance type from GCE cloud provider") + return volumeLimits, nil + } + if strings.HasPrefix(instanceType, "n1-") { + splits := strings.Split(instanceType, "-") + if len(splits) < 3 { + return volumeLimits, nil + } + last := splits[2] + if num, err := strconv.Atoi(last); err == nil { + if num == OneCPU { + volumeLimits[util.GCEVolumeLimitKey] = VolumeLimit32 + } else if num < EightCPUs { + volumeLimits[util.GCEVolumeLimitKey] = VolumeLimit64 + } else { + volumeLimits[util.GCEVolumeLimitKey] = VolumeLimit128 + } + } + } + return volumeLimits, nil +} + +func (plugin *gcePersistentDiskPlugin) VolumeLimitKey(spec *volume.Spec) string { + return util.GCEVolumeLimitKey +} + func (plugin *gcePersistentDiskPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) { // Inject real implementations here, test through the internal function. return plugin.newMounterInternal(spec, pod.UID, &GCEDiskUtil{}, plugin.host.GetMounter(plugin.GetPluginName())) @@ -396,7 +466,7 @@ type gcePersistentDiskProvisioner struct { var _ volume.Provisioner = &gcePersistentDiskProvisioner{} -func (c *gcePersistentDiskProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *gcePersistentDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } @@ -448,5 +518,9 @@ func (c *gcePersistentDiskProvisioner) Provision() (*v1.PersistentVolume, error) } } + if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { + pv.Spec.VolumeMode = c.options.PVC.Spec.VolumeMode + } + return pv, nil } diff --git a/pkg/volume/gce_pd/gce_pd_block.go b/pkg/volume/gce_pd/gce_pd_block.go index f4398d13b59..24dcfce731f 100644 --- a/pkg/volume/gce_pd/gce_pd_block.go +++ b/pkg/volume/gce_pd/gce_pd_block.go @@ -28,6 +28,7 @@ import ( "k8s.io/kubernetes/pkg/util/mount" kstrings "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util/volumepathhandler" ) @@ -151,6 +152,10 @@ func (b *gcePersistentDiskMapper) SetUpDevice() (string, error) { return "", nil } +func (b *gcePersistentDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + // GetGlobalMapPath returns global map path and error // path: plugins/kubernetes.io/{PluginName}/volumeDevices/pdName func (pd *gcePersistentDisk) GetGlobalMapPath(spec *volume.Spec) (string, error) { diff --git a/pkg/volume/gce_pd/gce_pd_test.go b/pkg/volume/gce_pd/gce_pd_test.go index 2f22a204f43..54a1de07f11 100644 --- a/pkg/volume/gce_pd/gce_pd_test.go +++ b/pkg/volume/gce_pd/gce_pd_test.go @@ -167,7 +167,7 @@ func TestPlugin(t *testing.T) { if err != nil { t.Errorf("Error creating new provisioner:%v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } diff --git a/pkg/volume/git_repo/git_repo.go b/pkg/volume/git_repo/git_repo.go index 94f174862b5..332f33e5ab1 100644 --- a/pkg/volume/git_repo/git_repo.go +++ b/pkg/volume/git_repo/git_repo.go @@ -20,6 +20,7 @@ import ( "fmt" "io/ioutil" "path" + "path/filepath" "strings" "k8s.io/api/core/v1" @@ -90,6 +91,10 @@ func (plugin *gitRepoPlugin) SupportsBulkVolumeVerification() bool { } func (plugin *gitRepoPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) { + if err := validateVolume(spec.Volume.GitRepo); err != nil { + return nil, err + } + return &gitRepoVolumeMounter{ gitRepoVolume: &gitRepoVolume{ volName: spec.Name(), @@ -190,7 +195,7 @@ func (b *gitRepoVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { return err } - args := []string{"clone", b.source} + args := []string{"clone", "--", b.source} if len(b.target) != 0 { args = append(args, b.target) @@ -214,7 +219,7 @@ func (b *gitRepoVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { var subdir string switch { - case b.target == ".": + case len(b.target) != 0 && filepath.Clean(b.target) == ".": // if target dir is '.', use the current dir subdir = path.Join(dir) case len(files) == 1: @@ -248,6 +253,19 @@ func (b *gitRepoVolumeMounter) execCommand(command string, args []string, dir st return cmd.CombinedOutput() } +func validateVolume(src *v1.GitRepoVolumeSource) error { + if err := validateNonFlagArgument(src.Repository, "repository"); err != nil { + return err + } + if err := validateNonFlagArgument(src.Revision, "revision"); err != nil { + return err + } + if err := validateNonFlagArgument(src.Directory, "directory"); err != nil { + return err + } + return nil +} + // gitRepoVolumeUnmounter cleans git repo volumes. type gitRepoVolumeUnmounter struct { *gitRepoVolume @@ -276,3 +294,10 @@ func getVolumeSource(spec *volume.Spec) (*v1.GitRepoVolumeSource, bool) { return volumeSource, readOnly } + +func validateNonFlagArgument(arg, argName string) error { + if len(arg) > 0 && arg[0] == '-' { + return fmt.Errorf("%q is an invalid value for %s", arg, argName) + } + return nil +} diff --git a/pkg/volume/git_repo/git_repo_test.go b/pkg/volume/git_repo/git_repo_test.go index 8c6a41a1c1e..601ce9f664e 100644 --- a/pkg/volume/git_repo/git_repo_test.go +++ b/pkg/volume/git_repo/git_repo_test.go @@ -93,7 +93,7 @@ func TestPlugin(t *testing.T) { }, expecteds: []expectedCommand{ { - cmd: []string{"git", "clone", gitUrl, "target_dir"}, + cmd: []string{"git", "clone", "--", gitUrl, "target_dir"}, dir: "", }, { @@ -120,7 +120,7 @@ func TestPlugin(t *testing.T) { }, expecteds: []expectedCommand{ { - cmd: []string{"git", "clone", gitUrl, "target_dir"}, + cmd: []string{"git", "clone", "--", gitUrl, "target_dir"}, dir: "", }, }, @@ -138,7 +138,7 @@ func TestPlugin(t *testing.T) { }, expecteds: []expectedCommand{ { - cmd: []string{"git", "clone", gitUrl}, + cmd: []string{"git", "clone", "--", gitUrl}, dir: "", }, }, @@ -158,7 +158,7 @@ func TestPlugin(t *testing.T) { }, expecteds: []expectedCommand{ { - cmd: []string{"git", "clone", gitUrl}, + cmd: []string{"git", "clone", "--", gitUrl}, dir: "", }, { @@ -186,7 +186,7 @@ func TestPlugin(t *testing.T) { }, expecteds: []expectedCommand{ { - cmd: []string{"git", "clone", gitUrl, "."}, + cmd: []string{"git", "clone", "--", gitUrl, "."}, dir: "", }, { @@ -200,6 +200,72 @@ func TestPlugin(t *testing.T) { }, isExpectedFailure: false, }, + { + name: "current-dir-mess", + vol: &v1.Volume{ + Name: "vol1", + VolumeSource: v1.VolumeSource{ + GitRepo: &v1.GitRepoVolumeSource{ + Repository: gitUrl, + Revision: revision, + Directory: "./.", + }, + }, + }, + expecteds: []expectedCommand{ + { + cmd: []string{"git", "clone", "--", gitUrl, "./."}, + dir: "", + }, + { + cmd: []string{"git", "checkout", revision}, + dir: "", + }, + { + cmd: []string{"git", "reset", "--hard"}, + dir: "", + }, + }, + isExpectedFailure: false, + }, + { + name: "invalid-repository", + vol: &v1.Volume{ + Name: "vol1", + VolumeSource: v1.VolumeSource{ + GitRepo: &v1.GitRepoVolumeSource{ + Repository: "--foo", + }, + }, + }, + isExpectedFailure: true, + }, + { + name: "invalid-revision", + vol: &v1.Volume{ + Name: "vol1", + VolumeSource: v1.VolumeSource{ + GitRepo: &v1.GitRepoVolumeSource{ + Repository: gitUrl, + Revision: "--bar", + }, + }, + }, + isExpectedFailure: true, + }, + { + name: "invalid-directory", + vol: &v1.Volume{ + Name: "vol1", + VolumeSource: v1.VolumeSource{ + GitRepo: &v1.GitRepoVolumeSource{ + Repository: gitUrl, + Directory: "-b", + }, + }, + }, + isExpectedFailure: true, + }, } for _, scenario := range scenarios { diff --git a/pkg/volume/glusterfs/glusterfs.go b/pkg/volume/glusterfs/glusterfs.go index 28a7104aa1d..a2d200d216a 100644 --- a/pkg/volume/glusterfs/glusterfs.go +++ b/pkg/volume/glusterfs/glusterfs.go @@ -664,7 +664,7 @@ func (d *glusterfsVolumeDeleter) Delete() error { return nil } -func (p *glusterfsVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (p *glusterfsVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !volutil.AccessModesContainedInAll(p.plugin.GetAccessModes(), p.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", p.options.PVC.Spec.AccessModes, p.plugin.GetAccessModes()) } @@ -673,6 +673,11 @@ func (p *glusterfsVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { glog.V(4).Infof("not able to parse your claim Selector") return nil, fmt.Errorf("not able to parse your claim Selector") } + + if volutil.CheckPersistentVolumeClaimModeBlock(p.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", p.plugin.GetPluginName()) + } + glog.V(4).Infof("Provision VolumeOptions %v", p.options) scName := v1helper.GetPersistentVolumeClaimClass(p.options.PVC) cfg, err := parseClassParameters(p.options.Parameters, p.plugin.host.GetKubeClient()) diff --git a/pkg/volume/host_path/host_path.go b/pkg/volume/host_path/host_path.go index 4a3cb76b6af..a2cac9d0635 100644 --- a/pkg/volume/host_path/host_path.go +++ b/pkg/volume/host_path/host_path.go @@ -265,7 +265,11 @@ type hostPathProvisioner struct { // Create for hostPath simply creates a local /tmp/hostpath_pv/%s directory as a new PersistentVolume. // This Provisioner is meant for development and testing only and WILL NOT WORK in a multi-node cluster. -func (r *hostPathProvisioner) Provision() (*v1.PersistentVolume, error) { +func (r *hostPathProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { + if util.CheckPersistentVolumeClaimModeBlock(r.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", r.plugin.GetPluginName()) + } + fullpath := fmt.Sprintf("/tmp/hostpath_pv/%s", uuid.NewUUID()) capacity := r.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] @@ -350,7 +354,8 @@ type fileTypeChecker struct { } func (ftc *fileTypeChecker) Exists() bool { - return ftc.mounter.ExistsPath(ftc.path) + exists, err := ftc.mounter.ExistsPath(ftc.path) + return exists && err == nil } func (ftc *fileTypeChecker) IsFile() bool { diff --git a/pkg/volume/host_path/host_path_test.go b/pkg/volume/host_path/host_path_test.go index 199880c247e..3824acede12 100644 --- a/pkg/volume/host_path/host_path_test.go +++ b/pkg/volume/host_path/host_path_test.go @@ -17,7 +17,6 @@ limitations under the License. package host_path import ( - "errors" "fmt" "os" "testing" @@ -178,7 +177,7 @@ func TestProvisioner(t *testing.T) { if err != nil { t.Errorf("Failed to make a new Provisioner: %v", err) } - pv, err := creater.Provision() + pv, err := creater.Provision(nil, nil) if err != nil { t.Errorf("Unexpected error creating volume: %v", err) } @@ -319,88 +318,6 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { } } -type fakeFileTypeChecker struct { - desiredType string -} - -func (fftc *fakeFileTypeChecker) Mount(source string, target string, fstype string, options []string) error { - return nil -} - -func (fftc *fakeFileTypeChecker) Unmount(target string) error { - return nil -} - -func (fftc *fakeFileTypeChecker) List() ([]utilmount.MountPoint, error) { - return nil, nil -} -func (fftc *fakeFileTypeChecker) IsMountPointMatch(mp utilmount.MountPoint, dir string) bool { - return false -} - -func (fftc *fakeFileTypeChecker) IsNotMountPoint(file string) (bool, error) { - return false, nil -} - -func (fftc *fakeFileTypeChecker) IsLikelyNotMountPoint(file string) (bool, error) { - return false, nil -} - -func (fftc *fakeFileTypeChecker) DeviceOpened(pathname string) (bool, error) { - return false, nil -} -func (fftc *fakeFileTypeChecker) PathIsDevice(pathname string) (bool, error) { - return false, nil -} - -func (fftc *fakeFileTypeChecker) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { - return "fake", nil -} - -func (fftc *fakeFileTypeChecker) MakeRShared(path string) error { - return nil -} - -func (fftc *fakeFileTypeChecker) MakeFile(pathname string) error { - return nil -} - -func (fftc *fakeFileTypeChecker) MakeDir(pathname string) error { - return nil -} - -func (fftc *fakeFileTypeChecker) ExistsPath(pathname string) bool { - return true -} - -func (fftc *fakeFileTypeChecker) GetFileType(_ string) (utilmount.FileType, error) { - return utilmount.FileType(fftc.desiredType), nil -} - -func (fftc *fakeFileTypeChecker) PrepareSafeSubpath(subPath utilmount.Subpath) (newHostPath string, cleanupAction func(), err error) { - return "", nil, nil -} - -func (fftc *fakeFileTypeChecker) CleanSubPaths(_, _ string) error { - return nil -} - -func (fftc *fakeFileTypeChecker) SafeMakeDir(_, _ string, _ os.FileMode) error { - return nil -} - -func (fftc *fakeFileTypeChecker) GetMountRefs(pathname string) ([]string, error) { - return nil, errors.New("not implemented") -} - -func (fftc *fakeFileTypeChecker) GetFSGroup(pathname string) (int64, error) { - return -1, errors.New("not implemented") -} - -func (fftc *fakeFileTypeChecker) GetSELinuxSupport(pathname string) (bool, error) { - return false, errors.New("not implemented") -} - func setUp() error { err := os.MkdirAll("/tmp/ExistingFolder", os.FileMode(0755)) if err != nil { @@ -469,7 +386,11 @@ func TestOSFileTypeChecker(t *testing.T) { } for i, tc := range testCases { - fakeFTC := &fakeFileTypeChecker{desiredType: tc.desiredType} + fakeFTC := &utilmount.FakeMounter{ + Filesystem: map[string]utilmount.FileType{ + tc.path: utilmount.FileType(tc.desiredType), + }, + } oftc := newFileTypeChecker(tc.path, fakeFTC) path := oftc.GetPath() diff --git a/pkg/volume/iscsi/iscsi.go b/pkg/volume/iscsi/iscsi.go index 22f3fe81c69..687f2cc6a37 100644 --- a/pkg/volume/iscsi/iscsi.go +++ b/pkg/volume/iscsi/iscsi.go @@ -367,6 +367,10 @@ func (b *iscsiDiskMapper) SetUpDevice() (string, error) { return "", nil } +func (b *iscsiDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return ioutil.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + type iscsiDiskUnmapper struct { *iscsiDisk exec mount.Exec diff --git a/pkg/volume/local/local.go b/pkg/volume/local/local.go index 618adea56b3..854c6d96822 100644 --- a/pkg/volume/local/local.go +++ b/pkg/volume/local/local.go @@ -390,6 +390,10 @@ func (m *localVolumeMapper) SetUpDevice() (string, error) { return globalPath, nil } +func (m *localVolumeMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + // localVolumeUnmapper implements the BlockVolumeUnmapper interface for local volumes. type localVolumeUnmapper struct { *localVolume diff --git a/pkg/volume/metrics_du.go b/pkg/volume/metrics_du.go index 88a985d5ac2..1cae99c1073 100644 --- a/pkg/volume/metrics_du.go +++ b/pkg/volume/metrics_du.go @@ -25,7 +25,7 @@ import ( var _ MetricsProvider = &metricsDu{} // metricsDu represents a MetricsProvider that calculates the used and -// available Volume space by executing the "du" command and gathering +// available Volume space by calling fs.DiskUsage() and gathering // filesystem info for the Volume path. type metricsDu struct { // the directory path the volume is mounted to. @@ -46,7 +46,7 @@ func (md *metricsDu) GetMetrics() (*Metrics, error) { return metrics, NewNoPathDefinedError() } - err := md.runDu(metrics) + err := md.runDiskUsage(metrics) if err != nil { return metrics, err } @@ -64,9 +64,9 @@ func (md *metricsDu) GetMetrics() (*Metrics, error) { return metrics, nil } -// runDu executes the "du" command and writes the results to metrics.Used -func (md *metricsDu) runDu(metrics *Metrics) error { - used, err := fs.Du(md.path) +// runDiskUsage gets disk usage of md.path and writes the results to metrics.Used +func (md *metricsDu) runDiskUsage(metrics *Metrics) error { + used, err := fs.DiskUsage(md.path) if err != nil { return err } diff --git a/pkg/volume/photon_pd/photon_pd.go b/pkg/volume/photon_pd/photon_pd.go index 25ca23928d0..89c385fdb73 100644 --- a/pkg/volume/photon_pd/photon_pd.go +++ b/pkg/volume/photon_pd/photon_pd.go @@ -340,11 +340,15 @@ func (plugin *photonPersistentDiskPlugin) newProvisionerInternal(options volume. }, nil } -func (p *photonPersistentDiskProvisioner) Provision() (*v1.PersistentVolume, error) { +func (p *photonPersistentDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(p.plugin.GetAccessModes(), p.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", p.options.PVC.Spec.AccessModes, p.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(p.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", p.plugin.GetPluginName()) + } + pdID, sizeGB, fstype, err := p.manager.CreateVolume(p) if err != nil { return nil, err diff --git a/pkg/volume/photon_pd/photon_pd_test.go b/pkg/volume/photon_pd/photon_pd_test.go index 4ad52b095ab..d3c14a229db 100644 --- a/pkg/volume/photon_pd/photon_pd_test.go +++ b/pkg/volume/photon_pd/photon_pd_test.go @@ -166,7 +166,7 @@ func TestPlugin(t *testing.T) { if err != nil { t.Fatalf("Error creating new provisioner:%v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } diff --git a/pkg/volume/plugins.go b/pkg/volume/plugins.go index 5ed32f4be92..fbe0bd4c6d0 100644 --- a/pkg/volume/plugins.go +++ b/pkg/volume/plugins.go @@ -23,6 +23,7 @@ import ( "sync" "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -216,6 +217,32 @@ type ExpandableVolumePlugin interface { RequiresFSResize() bool } +// VolumePluginWithAttachLimits is an extended interface of VolumePlugin that restricts number of +// volumes that can be attached to a node. +type VolumePluginWithAttachLimits interface { + VolumePlugin + // Return maximum number of volumes that can be attached to a node for this plugin. + // The key must be same as string returned by VolumeLimitKey function. The returned + // map may look like: + // - { "storage-limits-aws-ebs": 39 } + // - { "storage-limits-gce-pd": 10 } + // A volume plugin may return error from this function - if it can not be used on a given node or not + // applicable in given environment (where environment could be cloudprovider or any other dependency) + // For example - calling this function for EBS volume plugin on a GCE node should + // result in error. + // The returned values are stored in node allocatable property and will be used + // by scheduler to determine how many pods with volumes can be scheduled on given node. + GetVolumeLimits() (map[string]int64, error) + // Return volume limit key string to be used in node capacity constraints + // The key must start with prefix storage-limits-. For example: + // - storage-limits-aws-ebs + // - storage-limits-csi-cinder + // The key should respect character limit of ResourceName type + // This function may be called by kubelet or scheduler to identify node allocatable property + // which stores volumes limits. + VolumeLimitKey(spec *Spec) string +} + // BlockVolumePlugin is an extend interface of VolumePlugin and is used for block volumes support. type BlockVolumePlugin interface { VolumePlugin @@ -310,6 +337,8 @@ type VolumeHost interface { // Returns a function that returns a configmap. GetConfigMapFunc() func(namespace, name string) (*v1.ConfigMap, error) + GetServiceAccountTokenFunc() func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) + // Returns an interface that should be used to execute any utilities in volume plugins GetExec(pluginName string) mount.Exec @@ -584,6 +613,17 @@ func (pm *VolumePluginMgr) refreshProbedPlugins() { } } +// ListVolumePluginWithLimits returns plugins that have volume limits on nodes +func (pm *VolumePluginMgr) ListVolumePluginWithLimits() []VolumePluginWithAttachLimits { + matchedPlugins := []VolumePluginWithAttachLimits{} + for _, v := range pm.plugins { + if plugin, ok := v.(VolumePluginWithAttachLimits); ok { + matchedPlugins = append(matchedPlugins, plugin) + } + } + return matchedPlugins +} + // FindPersistentPluginBySpec looks for a persistent volume plugin that can // support a given volume specification. If no plugin is found, return an // error @@ -598,6 +638,20 @@ func (pm *VolumePluginMgr) FindPersistentPluginBySpec(spec *Spec) (PersistentVol return nil, fmt.Errorf("no persistent volume plugin matched") } +// FindVolumePluginWithLimitsBySpec returns volume plugin that has a limit on how many +// of them can be attached to a node +func (pm *VolumePluginMgr) FindVolumePluginWithLimitsBySpec(spec *Spec) (VolumePluginWithAttachLimits, error) { + volumePlugin, err := pm.FindPluginBySpec(spec) + if err != nil { + return nil, fmt.Errorf("Could not find volume plugin for spec : %#v", spec) + } + + if limitedPlugin, ok := volumePlugin.(VolumePluginWithAttachLimits); ok { + return limitedPlugin, nil + } + return nil, fmt.Errorf("no plugin with limits found") +} + // FindPersistentPluginByName fetches a persistent volume plugin by name. If // no plugin is found, returns error. func (pm *VolumePluginMgr) FindPersistentPluginByName(name string) (PersistentVolumePlugin, error) { diff --git a/pkg/volume/portworx/portworx.go b/pkg/volume/portworx/portworx.go index c0cde9fde9e..1edb0bacac3 100644 --- a/pkg/volume/portworx/portworx.go +++ b/pkg/volume/portworx/portworx.go @@ -378,11 +378,15 @@ type portworxVolumeProvisioner struct { var _ volume.Provisioner = &portworxVolumeProvisioner{} -func (c *portworxVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *portworxVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(c.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", c.plugin.GetPluginName()) + } + volumeID, sizeGiB, labels, err := c.manager.CreateVolume(c) if err != nil { return nil, err diff --git a/pkg/volume/portworx/portworx_test.go b/pkg/volume/portworx/portworx_test.go index 8757dff2551..72be62500fe 100644 --- a/pkg/volume/portworx/portworx_test.go +++ b/pkg/volume/portworx/portworx_test.go @@ -204,7 +204,7 @@ func TestPlugin(t *testing.T) { if err != nil { t.Errorf("Error creating a new provisioner:%v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } diff --git a/pkg/volume/projected/BUILD b/pkg/volume/projected/BUILD index a8d0ce63461..2f3b388d431 100644 --- a/pkg/volume/projected/BUILD +++ b/pkg/volume/projected/BUILD @@ -28,6 +28,7 @@ go_library( srcs = ["projected.go"], importpath = "k8s.io/kubernetes/pkg/volume/projected", deps = [ + "//pkg/features:go_default_library", "//pkg/util/strings:go_default_library", "//pkg/volume:go_default_library", "//pkg/volume/configmap:go_default_library", @@ -35,11 +36,13 @@ go_library( "//pkg/volume/secret:go_default_library", "//pkg/volume/util:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/pkg/volume/projected/projected.go b/pkg/volume/projected/projected.go index e75f10af5f3..c17ba4c19ff 100644 --- a/pkg/volume/projected/projected.go +++ b/pkg/volume/projected/projected.go @@ -21,18 +21,22 @@ import ( "sort" "strings" - "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" utilstrings "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/configmap" "k8s.io/kubernetes/pkg/volume/downwardapi" "k8s.io/kubernetes/pkg/volume/secret" volumeutil "k8s.io/kubernetes/pkg/volume/util" + + "github.com/golang/glog" ) // ProbeVolumePlugins is the entry point for plugin detection in a package. @@ -45,9 +49,10 @@ const ( ) type projectedPlugin struct { - host volume.VolumeHost - getSecret func(namespace, name string) (*v1.Secret, error) - getConfigMap func(namespace, name string) (*v1.ConfigMap, error) + host volume.VolumeHost + getSecret func(namespace, name string) (*v1.Secret, error) + getConfigMap func(namespace, name string) (*v1.ConfigMap, error) + getServiceAccountToken func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) } var _ volume.VolumePlugin = &projectedPlugin{} @@ -70,6 +75,7 @@ func (plugin *projectedPlugin) Init(host volume.VolumeHost) error { plugin.host = host plugin.getSecret = host.GetSecretFunc() plugin.getConfigMap = host.GetConfigMapFunc() + plugin.getServiceAccountToken = host.GetServiceAccountTokenFunc() return nil } @@ -188,18 +194,19 @@ func (s *projectedVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { if err != nil { return err } - if err := wrapped.SetUpAt(dir, fsGroup); err != nil { - return err - } - if err := volumeutil.MakeNestedMountpoints(s.volName, dir, *s.pod); err != nil { - return err - } data, err := s.collectData() if err != nil { glog.Errorf("Error preparing data for projected volume %v for pod %v/%v: %s", s.volName, s.pod.Namespace, s.pod.Name, err.Error()) return err } + if err := wrapped.SetUpAt(dir, fsGroup); err != nil { + return err + } + + if err := volumeutil.MakeNestedMountpoints(s.volName, dir, *s.pod); err != nil { + return err + } writerContext := fmt.Sprintf("pod %v/%v volume %v", s.pod.Namespace, s.pod.Name, s.volName) writer, err := volumeutil.NewAtomicWriter(dir, writerContext) @@ -219,7 +226,6 @@ func (s *projectedVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { glog.Errorf("Error applying volume ownership settings for group: %v", fsGroup) return err } - return nil } @@ -236,7 +242,8 @@ func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjec errlist := []error{} payload := make(map[string]volumeutil.FileProjection) for _, source := range s.source.Sources { - if source.Secret != nil { + switch { + case source.Secret != nil: optional := source.Secret.Optional != nil && *source.Secret.Optional secretapi, err := s.plugin.getSecret(s.pod.Namespace, source.Secret.Name) if err != nil { @@ -261,7 +268,7 @@ func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjec for k, v := range secretPayload { payload[k] = v } - } else if source.ConfigMap != nil { + case source.ConfigMap != nil: optional := source.ConfigMap.Optional != nil && *source.ConfigMap.Optional configMap, err := s.plugin.getConfigMap(s.pod.Namespace, source.ConfigMap.Name) if err != nil { @@ -286,7 +293,7 @@ func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjec for k, v := range configMapPayload { payload[k] = v } - } else if source.DownwardAPI != nil { + case source.DownwardAPI != nil: downwardAPIPayload, err := downwardapi.CollectData(source.DownwardAPI.Items, s.pod, s.plugin.host, s.source.DefaultMode) if err != nil { errlist = append(errlist, err) @@ -295,6 +302,34 @@ func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjec for k, v := range downwardAPIPayload { payload[k] = v } + case source.ServiceAccountToken != nil: + if !utilfeature.DefaultFeatureGate.Enabled(features.TokenRequestProjection) { + errlist = append(errlist, fmt.Errorf("pod request ServiceAccountToken projection but the TokenRequestProjection feature was not enabled")) + continue + } + tp := source.ServiceAccountToken + tr, err := s.plugin.getServiceAccountToken(s.pod.Namespace, s.pod.Spec.ServiceAccountName, &authenticationv1.TokenRequest{ + Spec: authenticationv1.TokenRequestSpec{ + Audiences: []string{ + tp.Audience, + }, + ExpirationSeconds: tp.ExpirationSeconds, + BoundObjectRef: &authenticationv1.BoundObjectReference{ + APIVersion: "v1", + Kind: "Pod", + Name: s.pod.Name, + UID: s.pod.UID, + }, + }, + }) + if err != nil { + errlist = append(errlist, err) + continue + } + payload[tp.Path] = volumeutil.FileProjection{ + Data: []byte(tr.Status.Token), + Mode: 0600, + } } } return payload, utilerrors.NewAggregate(errlist) diff --git a/pkg/volume/quobyte/quobyte.go b/pkg/volume/quobyte/quobyte.go index 0a5990b2900..524a4924896 100644 --- a/pkg/volume/quobyte/quobyte.go +++ b/pkg/volume/quobyte/quobyte.go @@ -354,11 +354,15 @@ type quobyteVolumeProvisioner struct { options volume.VolumeOptions } -func (provisioner *quobyteVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (provisioner *quobyteVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(provisioner.plugin.GetAccessModes(), provisioner.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", provisioner.options.PVC.Spec.AccessModes, provisioner.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(provisioner.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", provisioner.plugin.GetPluginName()) + } + if provisioner.options.PVC.Spec.Selector != nil { return nil, fmt.Errorf("claim Selector is not supported") } diff --git a/pkg/volume/rbd/BUILD b/pkg/volume/rbd/BUILD index 65042418cd4..e6b7fe8aead 100644 --- a/pkg/volume/rbd/BUILD +++ b/pkg/volume/rbd/BUILD @@ -17,6 +17,7 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/volume/rbd", deps = [ + "//pkg/features:go_default_library", "//pkg/util/file:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/node:go_default_library", @@ -33,6 +34,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], ) diff --git a/pkg/volume/rbd/OWNERS b/pkg/volume/rbd/OWNERS index a700b703ce8..9e353b18127 100644 --- a/pkg/volume/rbd/OWNERS +++ b/pkg/volume/rbd/OWNERS @@ -1,5 +1,6 @@ approvers: - rootfs +- jsafrane reviewers: - sjenning - saad-ali @@ -7,3 +8,4 @@ reviewers: - rootfs - jingxu97 - msau42 +- cofyc diff --git a/pkg/volume/rbd/rbd.go b/pkg/volume/rbd/rbd.go index 615b89554ab..89b9cd045ef 100644 --- a/pkg/volume/rbd/rbd.go +++ b/pkg/volume/rbd/rbd.go @@ -30,7 +30,9 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" + utilfeature "k8s.io/apiserver/pkg/util/feature" clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" @@ -577,7 +579,7 @@ type rbdVolumeProvisioner struct { var _ volume.Provisioner = &rbdVolumeProvisioner{} -func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (r *rbdVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !volutil.AccessModesContainedInAll(r.plugin.GetAccessModes(), r.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", r.options.PVC.Spec.AccessModes, r.plugin.GetAccessModes()) } @@ -698,6 +700,11 @@ func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dMi", sizeMB)), } pv.Spec.MountOptions = r.options.MountOptions + + if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { + pv.Spec.VolumeMode = r.options.PVC.Spec.VolumeMode + } + return pv, nil } @@ -871,6 +878,10 @@ func (rbd *rbdDiskMapper) SetUpDevice() (string, error) { return "", nil } +func (rbd *rbdDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return volutil.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + func (rbd *rbd) rbdGlobalMapPath(spec *volume.Spec) (string, error) { mon, err := getVolumeSourceMonitors(spec) if err != nil { diff --git a/pkg/volume/scaleio/sio_volume.go b/pkg/volume/scaleio/sio_volume.go index b7f02701118..0f10dfa1e83 100644 --- a/pkg/volume/scaleio/sio_volume.go +++ b/pkg/volume/scaleio/sio_volume.go @@ -252,13 +252,17 @@ func (v *sioVolume) Delete() error { // ************************ var _ volume.Provisioner = &sioVolume{} -func (v *sioVolume) Provision() (*api.PersistentVolume, error) { +func (v *sioVolume) Provision(selectedNode *api.Node, allowedTopologies []api.TopologySelectorTerm) (*api.PersistentVolume, error) { glog.V(4).Info(log("attempting to dynamically provision pvc %v", v.options.PVC.Name)) if !util.AccessModesContainedInAll(v.plugin.GetAccessModes(), v.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", v.options.PVC.Spec.AccessModes, v.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(v.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", v.plugin.GetPluginName()) + } + // setup volume attrributes genName := v.generateName("k8svol", 11) var oneGig int64 = 1024 * 1024 * 1024 diff --git a/pkg/volume/scaleio/sio_volume_test.go b/pkg/volume/scaleio/sio_volume_test.go index bdc13045d9e..8d725af8647 100644 --- a/pkg/volume/scaleio/sio_volume_test.go +++ b/pkg/volume/scaleio/sio_volume_test.go @@ -296,7 +296,7 @@ func TestVolumeProvisioner(t *testing.T) { } sioVol.sioMgr.client = sio - spec, err := provisioner.Provision() + spec, err := provisioner.Provision(nil, nil) if err != nil { t.Fatalf("call to Provision() failed: %v", err) } @@ -467,7 +467,7 @@ func TestVolumeProvisionerWithZeroCapacity(t *testing.T) { } sioVol.sioMgr.client = sio - _, err = provisioner.Provision() + _, err = provisioner.Provision(nil, nil) if err == nil { t.Fatalf("call to Provision() should fail with invalid capacity") } @@ -516,7 +516,7 @@ func TestVolumeProvisionerWithSecretNamespace(t *testing.T) { } sioVol.sioMgr.client = sio - spec, err := sioVol.Provision() + spec, err := sioVol.Provision(nil, nil) if err != nil { t.Fatalf("call to Provision() failed: %v", err) } diff --git a/pkg/volume/secret/secret.go b/pkg/volume/secret/secret.go index c8146d84422..3ab27c77c42 100644 --- a/pkg/volume/secret/secret.go +++ b/pkg/volume/secret/secret.go @@ -190,12 +190,6 @@ func (b *secretVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { if err != nil { return err } - if err := wrapped.SetUpAt(dir, fsGroup); err != nil { - return err - } - if err := volumeutil.MakeNestedMountpoints(b.volName, dir, b.pod); err != nil { - return err - } optional := b.source.Optional != nil && *b.source.Optional secret, err := b.getSecret(b.pod.Namespace, b.source.SecretName) @@ -212,6 +206,13 @@ func (b *secretVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { } } + if err := wrapped.SetUpAt(dir, fsGroup); err != nil { + return err + } + if err := volumeutil.MakeNestedMountpoints(b.volName, dir, b.pod); err != nil { + return err + } + totalBytes := totalSecretBytes(secret) glog.V(3).Infof("Received secret %v/%v containing (%v) pieces of data, %v total bytes", b.pod.Namespace, @@ -242,7 +243,6 @@ func (b *secretVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { glog.Errorf("Error applying volume ownership settings for group: %v", fsGroup) return err } - return nil } diff --git a/pkg/volume/storageos/storageos.go b/pkg/volume/storageos/storageos.go index a814c438dd1..8b5c2311c9f 100644 --- a/pkg/volume/storageos/storageos.go +++ b/pkg/volume/storageos/storageos.go @@ -560,10 +560,13 @@ type storageosProvisioner struct { var _ volume.Provisioner = &storageosProvisioner{} -func (c *storageosProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *storageosProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(c.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", c.plugin.GetPluginName()) + } var adminSecretName, adminSecretNamespace string diff --git a/pkg/volume/storageos/storageos_test.go b/pkg/volume/storageos/storageos_test.go index 9d03ab235ac..a5732fff7a1 100644 --- a/pkg/volume/storageos/storageos_test.go +++ b/pkg/volume/storageos/storageos_test.go @@ -269,7 +269,7 @@ func TestPlugin(t *testing.T) { t.Errorf("newProvisionerInternal() failed: %v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Fatalf("Provision() failed: %v", err) } diff --git a/pkg/volume/testing/BUILD b/pkg/volume/testing/BUILD index edd95307657..6cbd8230c75 100644 --- a/pkg/volume/testing/BUILD +++ b/pkg/volume/testing/BUILD @@ -22,6 +22,7 @@ go_library( "//pkg/volume/util/recyclerclient:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library", "//vendor/github.com/stretchr/testify/mock:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/pkg/volume/testing/testing.go b/pkg/volume/testing/testing.go index 1cfe6dddc1a..9192dd0e99b 100644 --- a/pkg/volume/testing/testing.go +++ b/pkg/volume/testing/testing.go @@ -27,6 +27,7 @@ import ( "testing" "time" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -183,6 +184,12 @@ func (f *fakeVolumeHost) GetConfigMapFunc() func(namespace, name string) (*v1.Co } } +func (f *fakeVolumeHost) GetServiceAccountTokenFunc() func(string, string, *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return f.kubeClient.CoreV1().ServiceAccounts(namespace).CreateToken(name, tr) + } +} + func (f *fakeVolumeHost) GetNodeLabels() (map[string]string, error) { if f.nodeLabels == nil { f.nodeLabels = map[string]string{"test-label": "test-value"} @@ -439,6 +446,15 @@ func (plugin *FakeVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]st return []string{}, nil } +// Expandable volume support +func (plugin *FakeVolumePlugin) ExpandVolumeDevice(spec *Spec, newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error) { + return resource.Quantity{}, nil +} + +func (plugin *FakeVolumePlugin) RequiresFSResize() bool { + return true +} + type FakeFileVolumePlugin struct { } @@ -503,6 +519,7 @@ type FakeVolume struct { GetDeviceMountPathCallCount int SetUpDeviceCallCount int TearDownDeviceCallCount int + MapDeviceCallCount int GlobalMapPathCallCount int PodDeviceMapPathCallCount int } @@ -633,6 +650,21 @@ func (fv *FakeVolume) GetTearDownDeviceCallCount() int { return fv.TearDownDeviceCallCount } +// Block volume support +func (fv *FakeVolume) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, pod types.UID) error { + fv.Lock() + defer fv.Unlock() + fv.MapDeviceCallCount++ + return nil +} + +// Block volume support +func (fv *FakeVolume) GetMapDeviceCallCount() int { + fv.RLock() + defer fv.RUnlock() + return fv.MapDeviceCallCount +} + func (fv *FakeVolume) Attach(spec *Spec, nodeName types.NodeName) (string, error) { fv.Lock() defer fv.Unlock() @@ -724,7 +756,7 @@ type FakeProvisioner struct { Host VolumeHost } -func (fc *FakeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (fc *FakeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { fullpath := fmt.Sprintf("/tmp/hostpath_pv/%s", uuid.NewUUID()) pv := &v1.PersistentVolume{ @@ -1112,6 +1144,24 @@ func VerifyGetPodDeviceMapPathCallCount( expectedPodDeviceMapPathCallCount) } +// VerifyGetMapDeviceCallCount ensures that at least one of the Mappers for this +// plugin has the expectedMapDeviceCallCount number of calls. Otherwise it +// returns an error. +func VerifyGetMapDeviceCallCount( + expectedMapDeviceCallCount int, + fakeVolumePlugin *FakeVolumePlugin) error { + for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() { + actualCallCount := mapper.GetMapDeviceCallCount() + if actualCallCount >= expectedMapDeviceCallCount { + return nil + } + } + + return fmt.Errorf( + "No Mapper have expected MapdDeviceCallCount. Expected: <%v>.", + expectedMapDeviceCallCount) +} + // GetTestVolumePluginMgr creates, initializes, and returns a test volume plugin // manager and fake volume plugin using a fake volume host. func GetTestVolumePluginMgr( diff --git a/pkg/volume/util/BUILD b/pkg/volume/util/BUILD index 1002d7eeecf..08d5c3ef033 100644 --- a/pkg/volume/util/BUILD +++ b/pkg/volume/util/BUILD @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "atomic_writer.go", + "attach_limit.go", "device_util.go", "doc.go", "error.go", @@ -59,6 +60,7 @@ go_library( "//pkg/util/mount:go_default_library", "//pkg/volume:go_default_library", "//pkg/volume/util/types:go_default_library", + "//pkg/volume/util/volumepathhandler:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", diff --git a/pkg/volume/util/attach_limit.go b/pkg/volume/util/attach_limit.go new file mode 100644 index 00000000000..610f5f5b2cc --- /dev/null +++ b/pkg/volume/util/attach_limit.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 util + +// This file is a common place holder for volume limit utility constants +// shared between volume package and scheduler + +const ( + // EBSVolumeLimitKey resource name that will store volume limits for EBS + EBSVolumeLimitKey = "attachable-volumes-aws-ebs" + // AzureVolumeLimitKey stores resource name that will store volume limits for Azure + AzureVolumeLimitKey = "attachable-volumes-azure-disk" + // GCEVolumeLimitKey stores resource name that will store volume limits for GCE node + GCEVolumeLimitKey = "attachable-volumes-gce-pd" +) diff --git a/pkg/volume/util/fs/BUILD b/pkg/volume/util/fs/BUILD index 205ddaaaeb0..0e9be3016b6 100644 --- a/pkg/volume/util/fs/BUILD +++ b/pkg/volume/util/fs/BUILD @@ -34,7 +34,7 @@ go_library( "fs_unsupported.go", ], "@io_bazel_rules_go//go/platform:windows": [ - "fs_unsupported.go", + "fs_windows.go", ], "//conditions:default": [], }), @@ -74,6 +74,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", ], "@io_bazel_rules_go//go/platform:windows": [ + "//vendor/golang.org/x/sys/windows:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", ], "//conditions:default": [], diff --git a/pkg/volume/util/fs/fs.go b/pkg/volume/util/fs/fs.go index bbb4b0105c5..a80a167eea7 100644 --- a/pkg/volume/util/fs/fs.go +++ b/pkg/volume/util/fs/fs.go @@ -54,7 +54,8 @@ func FsInfo(path string) (int64, int64, int64, int64, int64, int64, error) { return available, capacity, usage, inodes, inodesFree, inodesUsed, nil } -func Du(path string) (*resource.Quantity, error) { +// DiskUsage gets disk usage of specified path. +func DiskUsage(path string) (*resource.Quantity, error) { // Uses the same niceness level as cadvisor.fs does when running du // Uses -B 1 to always scale to a blocksize of 1 byte out, err := exec.Command("nice", "-n", "19", "du", "-s", "-B", "1", path).CombinedOutput() diff --git a/pkg/volume/util/fs/fs_unsupported.go b/pkg/volume/util/fs/fs_unsupported.go index da41fc8eee5..340b4fdc225 100644 --- a/pkg/volume/util/fs/fs_unsupported.go +++ b/pkg/volume/util/fs/fs_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!darwin +// +build !linux,!darwin,!windows /* Copyright 2014 The Kubernetes Authors. @@ -29,7 +29,8 @@ func FsInfo(path string) (int64, int64, int64, int64, int64, int64, error) { return 0, 0, 0, 0, 0, 0, fmt.Errorf("FsInfo not supported for this build.") } -func Du(path string) (*resource.Quantity, error) { +// DiskUsage gets disk usage of specified path. +func DiskUsage(path string) (*resource.Quantity, error) { return nil, fmt.Errorf("Du not supported for this build.") } diff --git a/pkg/volume/util/fs/fs_windows.go b/pkg/volume/util/fs/fs_windows.go new file mode 100644 index 00000000000..ea8c4784ae9 --- /dev/null +++ b/pkg/volume/util/fs/fs_windows.go @@ -0,0 +1,77 @@ +// +build windows + +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" + + "k8s.io/apimachinery/pkg/api/resource" +) + +var ( + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + procGetDiskFreeSpaceEx = modkernel32.NewProc("GetDiskFreeSpaceExW") +) + +// FSInfo returns (available bytes, byte capacity, byte usage, total inodes, inodes free, inode usage, error) +// for the filesystem that path resides upon. +func FsInfo(path string) (int64, int64, int64, int64, int64, int64, error) { + var freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes int64 + var err error + + ret, _, err := syscall.Syscall6( + procGetDiskFreeSpaceEx.Addr(), + 4, + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), + uintptr(unsafe.Pointer(&freeBytesAvailable)), + uintptr(unsafe.Pointer(&totalNumberOfBytes)), + uintptr(unsafe.Pointer(&totalNumberOfFreeBytes)), + 0, + 0, + ) + if ret == 0 { + return 0, 0, 0, 0, 0, 0, err + } + + return freeBytesAvailable, totalNumberOfBytes, totalNumberOfBytes - freeBytesAvailable, 0, 0, 0, nil +} + +// DiskUsage gets disk usage of specified path. +func DiskUsage(path string) (*resource.Quantity, error) { + _, _, usage, _, _, _, err := FsInfo(path) + if err != nil { + return nil, err + } + + used, err := resource.ParseQuantity(fmt.Sprintf("%d", usage)) + if err != nil { + return nil, fmt.Errorf("failed to parse fs usage %d due to %v", usage, err) + } + used.Format = resource.BinarySI + return &used, nil +} + +// Always return zero since inodes is not supported on Windows. +func Find(path string) (int64, error) { + return 0, nil +} diff --git a/pkg/volume/util/operationexecutor/operation_executor.go b/pkg/volume/util/operationexecutor/operation_executor.go index c065ace25e1..283a322259f 100644 --- a/pkg/volume/util/operationexecutor/operation_executor.go +++ b/pkg/volume/util/operationexecutor/operation_executor.go @@ -142,6 +142,8 @@ type OperationExecutor interface { IsOperationPending(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) bool // Expand Volume will grow size available to PVC ExpandVolume(*expandcache.PVCWithResizeRequest, expandcache.VolumeResizeMap) error + // ExpandVolumeFSWithoutUnmounting will resize volume's file system to expected size without unmounting the volume. + ExpandVolumeFSWithoutUnmounting(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) error // ReconstructVolumeOperation construct a new volumeSpec and returns it created by plugin ReconstructVolumeOperation(volumeMode v1.PersistentVolumeMode, plugin volume.VolumePlugin, mapperPlugin volume.BlockVolumePlugin, uid types.UID, podName volumetypes.UniquePodName, volumeSpecName string, mountPath string, pluginName string) (*volume.Spec, error) // CheckVolumeExistenceOperation checks volume existence @@ -173,6 +175,9 @@ type ActualStateOfWorldMounterUpdater interface { // Marks the specified volume as having its global mount unmounted. MarkDeviceAsUnmounted(volumeName v1.UniqueVolumeName) error + + // Marks the specified volume's file system resize request is finished. + MarkVolumeAsResized(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) error } // ActualStateOfWorldAttacherUpdater defines a set of operations updating the @@ -817,6 +822,14 @@ func (oe *operationExecutor) ExpandVolume(pvcWithResizeRequest *expandcache.PVCW return oe.pendingOperations.Run(uniqueVolumeKey, "", generatedOperations) } +func (oe *operationExecutor) ExpandVolumeFSWithoutUnmounting(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) error { + generatedOperations, err := oe.operationGenerator.GenerateExpandVolumeFSWithoutUnmountingFunc(volumeToMount, actualStateOfWorld) + if err != nil { + return err + } + return oe.pendingOperations.Run(volumeToMount.VolumeName, "", generatedOperations) +} + func (oe *operationExecutor) VerifyControllerAttachedVolume( volumeToMount VolumeToMount, nodeName types.NodeName, diff --git a/pkg/volume/util/operationexecutor/operation_executor_test.go b/pkg/volume/util/operationexecutor/operation_executor_test.go index 0551c4733fb..7d427e48f0f 100644 --- a/pkg/volume/util/operationexecutor/operation_executor_test.go +++ b/pkg/volume/util/operationexecutor/operation_executor_test.go @@ -438,6 +438,16 @@ func (fopg *fakeOperationGenerator) GenerateExpandVolumeFunc(pvcWithResizeReques }, nil } +func (fopg *fakeOperationGenerator) GenerateExpandVolumeFSWithoutUnmountingFunc(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) { + opFunc := func() (error, error) { + startOperationAndBlock(fopg.ch, fopg.quit) + return nil, nil + } + return volumetypes.GeneratedOperations{ + OperationFunc: opFunc, + }, nil +} + func (fopg *fakeOperationGenerator) GenerateBulkVolumeVerifyFunc( pluginNodeVolumes map[types.NodeName][]*volume.Spec, pluginNane string, diff --git a/pkg/volume/util/operationexecutor/operation_generator.go b/pkg/volume/util/operationexecutor/operation_generator.go index a9312fe7fcf..51f321ae9d4 100644 --- a/pkg/volume/util/operationexecutor/operation_generator.go +++ b/pkg/volume/util/operationexecutor/operation_generator.go @@ -121,6 +121,9 @@ type OperationGenerator interface { map[*volume.Spec]v1.UniqueVolumeName, ActualStateOfWorldAttacherUpdater) (volumetypes.GeneratedOperations, error) GenerateExpandVolumeFunc(*expandcache.PVCWithResizeRequest, expandcache.VolumeResizeMap) (volumetypes.GeneratedOperations, error) + + // Generates the volume file system resize function, which can resize volume's file system to expected size without unmounting the volume. + GenerateExpandVolumeFSWithoutUnmountingFunc(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) } func (og *operationGenerator) GenerateVolumesAreAttachedFunc( @@ -853,37 +856,19 @@ func (og *operationGenerator) GenerateMapVolumeFunc( // On failure, return error. Caller will log and retry. return volumeToMount.GenerateError("MapVolume.SetUp failed", mapErr) } - // Update devicePath for none attachable plugin case + + // if pluginDevicePath is provided, assume attacher may not provide device + // or attachment flow uses SetupDevice to get device path + if len(pluginDevicePath) != 0 { + devicePath = pluginDevicePath + } if len(devicePath) == 0 { - if len(pluginDevicePath) != 0 { - devicePath = pluginDevicePath - } else { - return volumeToMount.GenerateError("MapVolume failed", fmt.Errorf("Device path of the volume is empty")) - } - } - // Update actual state of world to reflect volume is globally mounted - markDeviceMappedErr := actualStateOfWorld.MarkDeviceAsMounted( - volumeToMount.VolumeName, devicePath, globalMapPath) - if markDeviceMappedErr != nil { - // On failure, return error. Caller will log and retry. - return volumeToMount.GenerateError("MapVolume.MarkDeviceAsMounted failed", markDeviceMappedErr) + return volumeToMount.GenerateError("MapVolume failed", fmt.Errorf("Device path of the volume is empty")) } - mapErr = og.blkUtil.MapDevice(devicePath, globalMapPath, string(volumeToMount.Pod.UID)) - if mapErr != nil { - // On failure, return error. Caller will log and retry. - return volumeToMount.GenerateError("MapVolume.MapDevice failed", mapErr) - } - - // Device mapping for global map path succeeded - simpleMsg, detailedMsg := volumeToMount.GenerateMsg("MapVolume.MapDevice succeeded", fmt.Sprintf("globalMapPath %q", globalMapPath)) - verbosity := glog.Level(4) - og.recorder.Eventf(volumeToMount.Pod, v1.EventTypeNormal, kevents.SuccessfulMountVolume, simpleMsg) - glog.V(verbosity).Infof(detailedMsg) - - // Map device to pod device map path under the given pod directory using symbolic link + // Map device to global and pod device map path volumeMapPath, volName := blockVolumeMapper.GetPodDeviceMapPath() - mapErr = og.blkUtil.MapDevice(devicePath, volumeMapPath, volName) + mapErr = blockVolumeMapper.MapDevice(devicePath, globalMapPath, volumeMapPath, volName, volumeToMount.Pod.UID) if mapErr != nil { // On failure, return error. Caller will log and retry. return volumeToMount.GenerateError("MapVolume.MapDevice failed", mapErr) @@ -898,6 +883,20 @@ func (og *operationGenerator) GenerateMapVolumeFunc( return volumeToMount.GenerateError("MapVolume.AttachFileDevice failed", err) } + // Update actual state of world to reflect volume is globally mounted + markDeviceMappedErr := actualStateOfWorld.MarkDeviceAsMounted( + volumeToMount.VolumeName, devicePath, globalMapPath) + if markDeviceMappedErr != nil { + // On failure, return error. Caller will log and retry. + return volumeToMount.GenerateError("MapVolume.MarkDeviceAsMounted failed", markDeviceMappedErr) + } + + // Device mapping for global map path succeeded + simpleMsg, detailedMsg := volumeToMount.GenerateMsg("MapVolume.MapDevice succeeded", fmt.Sprintf("globalMapPath %q", globalMapPath)) + verbosity := glog.Level(4) + og.recorder.Eventf(volumeToMount.Pod, v1.EventTypeNormal, kevents.SuccessfulMountVolume, simpleMsg) + glog.V(verbosity).Infof(detailedMsg) + // Device mapping for pod device map path succeeded simpleMsg, detailedMsg = volumeToMount.GenerateMsg("MapVolume.MapDevice succeeded", fmt.Sprintf("volumeMapPath %q", volumeMapPath)) verbosity = glog.Level(1) @@ -1306,6 +1305,62 @@ func (og *operationGenerator) GenerateExpandVolumeFunc( }, nil } +func (og *operationGenerator) GenerateExpandVolumeFSWithoutUnmountingFunc( + volumeToMount VolumeToMount, + actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) { + volumePlugin, err := + og.volumePluginMgr.FindPluginBySpec(volumeToMount.VolumeSpec) + if err != nil || volumePlugin == nil { + return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("VolumeFSResize.FindPluginBySpec failed", err) + } + + attachableVolumePlugin, err := + og.volumePluginMgr.FindAttachablePluginBySpec(volumeToMount.VolumeSpec) + if err != nil || attachableVolumePlugin == nil { + if attachableVolumePlugin == nil { + err = fmt.Errorf("AttachableVolumePlugin is nil") + } + return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("VolumeFSResize.FindAttachablePluginBySpec failed", err) + } + + volumeAttacher, err := attachableVolumePlugin.NewAttacher() + if err != nil || volumeAttacher == nil { + if volumeAttacher == nil { + err = fmt.Errorf("VolumeAttacher is nil") + } + return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("VolumeFSResize.NewAttacher failed", err) + } + + deviceMountPath, err := volumeAttacher.GetDeviceMountPath(volumeToMount.VolumeSpec) + if err != nil { + return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("VolumeFSResize.GetDeviceMountPath failed", err) + } + + fsResizeFunc := func() (error, error) { + resizeSimpleError, resizeDetailedError := og.resizeFileSystem(volumeToMount, volumeToMount.DevicePath, deviceMountPath, volumePlugin.GetPluginName()) + if resizeSimpleError != nil || resizeDetailedError != nil { + return resizeSimpleError, resizeDetailedError + } + markFSResizedErr := actualStateOfWorld.MarkVolumeAsResized(volumeToMount.PodName, volumeToMount.VolumeName) + if markFSResizedErr != nil { + // On failure, return error. Caller will log and retry. + return volumeToMount.GenerateError("VolumeFSResize.MarkVolumeAsResized failed", markFSResizedErr) + } + return nil, nil + } + eventRecorderFunc := func(err *error) { + if *err != nil { + og.recorder.Eventf(volumeToMount.Pod, v1.EventTypeWarning, kevents.VolumeResizeFailed, (*err).Error()) + } + } + + return volumetypes.GeneratedOperations{ + OperationFunc: fsResizeFunc, + EventRecorderFunc: eventRecorderFunc, + CompleteFunc: util.OperationCompleteHook(volumePlugin.GetPluginName(), "volume_fs_resize"), + }, nil +} + func checkMountOptionSupport(og *operationGenerator, volumeToMount VolumeToMount, plugin volume.VolumePlugin) error { mountOptions := util.MountOptionFromSpec(volumeToMount.VolumeSpec) diff --git a/pkg/volume/util/util.go b/pkg/volume/util/util.go index 663d8d62946..1e7b7093406 100644 --- a/pkg/volume/util/util.go +++ b/pkg/volume/util/util.go @@ -50,6 +50,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" utypes "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/volume/util/types" + "k8s.io/kubernetes/pkg/volume/util/volumepathhandler" ) const ( @@ -718,6 +719,12 @@ func CheckVolumeModeFilesystem(volumeSpec *volume.Spec) (bool, error) { return true, nil } +// CheckPersistentVolumeClaimModeBlock checks VolumeMode. +// If the mode is Block, return true otherwise return false. +func CheckPersistentVolumeClaimModeBlock(pvc *v1.PersistentVolumeClaim) bool { + return utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == v1.PersistentVolumeBlock +} + // MakeAbsolutePath convert path to absolute path according to GOOS func MakeAbsolutePath(goos, path string) string { if goos != "windows" { @@ -735,3 +742,30 @@ func MakeAbsolutePath(goos, path string) string { // Otherwise, add 'c:\' return "c:\\" + path } + +// MapBlockVolume is a utility function to provide a common way of mounting +// block device path for a specified volume and pod. This function should be +// called by volume plugins that implements volume.BlockVolumeMapper.Map() method. +func MapBlockVolume( + devicePath, + globalMapPath, + podVolumeMapPath, + volumeMapName string, + podUID utypes.UID, +) error { + blkUtil := volumepathhandler.NewBlockVolumePathHandler() + + // map devicePath to global node path + mapErr := blkUtil.MapDevice(devicePath, globalMapPath, string(podUID)) + if mapErr != nil { + return mapErr + } + + // map devicePath to pod volume path + mapErr = blkUtil.MapDevice(devicePath, podVolumeMapPath, volumeMapName) + if mapErr != nil { + return mapErr + } + + return nil +} diff --git a/pkg/volume/volume.go b/pkg/volume/volume.go index 161d84faf49..5f633214fcc 100644 --- a/pkg/volume/volume.go +++ b/pkg/volume/volume.go @@ -162,6 +162,9 @@ type BlockVolumeMapper interface { // at attacher.Attach() and attacher.WaitForAttach(). // This may be called more than once, so implementations must be idempotent. SetUpDevice() (string, error) + + // Map maps the block device path for the specified spec and pod. + MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error } // BlockVolumeUnmapper interface provides methods to cleanup/unmap the volumes. @@ -180,7 +183,7 @@ type Provisioner interface { // Provision creates the resource by allocating the underlying volume in a // storage system. This method should block until completion and returns // PersistentVolume representing the created storage resource. - Provision() (*v1.PersistentVolume, error) + Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) } // Deleter removes the resource from the underlying storage provider. Calls diff --git a/pkg/volume/vsphere_volume/vsphere_volume.go b/pkg/volume/vsphere_volume/vsphere_volume.go index 7b1e611df54..0cd3014feeb 100644 --- a/pkg/volume/vsphere_volume/vsphere_volume.go +++ b/pkg/volume/vsphere_volume/vsphere_volume.go @@ -348,10 +348,13 @@ func (plugin *vsphereVolumePlugin) newProvisionerInternal(options volume.VolumeO }, nil } -func (v *vsphereVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (v *vsphereVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(v.plugin.GetAccessModes(), v.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", v.options.PVC.Spec.AccessModes, v.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(v.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", v.plugin.GetPluginName()) + } volSpec, err := v.manager.CreateVolume(v) if err != nil { diff --git a/pkg/volume/vsphere_volume/vsphere_volume_test.go b/pkg/volume/vsphere_volume/vsphere_volume_test.go index 34fec92d618..848d6848d3a 100644 --- a/pkg/volume/vsphere_volume/vsphere_volume_test.go +++ b/pkg/volume/vsphere_volume/vsphere_volume_test.go @@ -156,7 +156,7 @@ func TestPlugin(t *testing.T) { if err != nil { t.Errorf("newProvisionerInternal() failed: %v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } diff --git a/plugin/pkg/admission/resourcequota/admission_test.go b/plugin/pkg/admission/resourcequota/admission_test.go index d94acdf2a31..d51ac501269 100644 --- a/plugin/pkg/admission/resourcequota/admission_test.go +++ b/plugin/pkg/admission/resourcequota/admission_test.go @@ -17,6 +17,7 @@ limitations under the License. package resourcequota import ( + "fmt" "strconv" "strings" "testing" @@ -73,6 +74,14 @@ func validPod(name string, numContainers int, resources api.ResourceRequirements return pod } +func validPodWithPriority(name string, numContainers int, resources api.ResourceRequirements, priorityClass string) *api.Pod { + pod := validPod(name, numContainers, resources) + if priorityClass != "" { + pod.Spec.PriorityClassName = priorityClass + } + return pod +} + func validPersistentVolumeClaim(name string, resources api.ResourceRequirements) *api.PersistentVolumeClaim { return &api.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: "test"}, @@ -1445,3 +1454,672 @@ func TestAdmitLimitedResourceWithQuotaThatDoesNotCover(t *testing.T) { t.Fatalf("Expected an error since the quota did not cover cpu") } } + +// TestAdmitLimitedScopeWithQuota verifies if a limited scope is configured the quota must cover the resource. +func TestAdmitLimitedScopeWithCoverQuota(t *testing.T) { + testCases := []struct { + description string + testPod *api.Pod + quota *api.ResourceQuota + anotherQuota *api.ResourceQuota + config *resourcequotaapi.Configuration + expErr string + }{ + { + description: "Covering quota exists for configured limited scope PriorityClassNameExists.", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists}, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "configured limited scope PriorityClassNameExists and limited cpu resource. No covering quota for cpu and pod admit fails.", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists}, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists, + }, + }, + MatchContains: []string{"requests.cpu"}, // match on "requests.cpu" only + }, + }, + }, + expErr: "insufficient quota to consume: requests.cpu", + }, + { + description: "Covering quota does not exist for configured limited scope PriorityClassNameExists.", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{PriorityClass Exists []}]", + }, + { + description: "Covering quota does not exist for configured limited scope resourceQuotaBestEffort", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{BestEffort Exists []}]", + }, + { + description: "Covering quota exist for configured limited scope resourceQuotaBestEffort", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota-besteffort", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeBestEffort}, + }, + Status: api.ResourceQuotaStatus{ + Hard: api.ResourceList{ + api.ResourcePods: resource.MustParse("5"), + }, + Used: api.ResourceList{ + api.ResourcePods: resource.MustParse("3"), + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Neither matches pod. Pod allowed", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("100m", "1Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Only BestEffort scope matches pod. Pod admit fails because covering quota is missing for BestEffort scope", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{BestEffort Exists []}]", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Only PriorityClass scope matches pod. Pod admit fails because covering quota is missing for PriorityClass scope", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("100m", "1Gi"), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{PriorityClass In [cluster-services]}]", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Both the scopes matches pod. Pod admit fails because covering quota is missing for PriorityClass scope and BestEffort scope", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{BestEffort Exists []} {PriorityClass In [cluster-services]}]", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Both the scopes matches pod. Quota available only for BestEffort scope. Pod admit fails because covering quota is missing for PriorityClass scope", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota-besteffort", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeBestEffort}, + }, + Status: api.ResourceQuotaStatus{ + Hard: api.ResourceList{ + api.ResourcePods: resource.MustParse("5"), + }, + Used: api.ResourceList{ + api.ResourcePods: resource.MustParse("3"), + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{PriorityClass In [cluster-services]}]", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Both the scopes matches pod. Quota available only for PriorityClass scope. Pod admit fails because covering quota is missing for BestEffort scope", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{BestEffort Exists []}]", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Both the scopes matches pod. Quota available only for both the scopes. Pod admit success. No Error", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota-besteffort", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeBestEffort}, + }, + Status: api.ResourceQuotaStatus{ + Hard: api.ResourceList{ + api.ResourcePods: resource.MustParse("5"), + }, + Used: api.ResourceList{ + api.ResourcePods: resource.MustParse("3"), + }, + }, + }, + anotherQuota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Pod allowed with priorityclass if limited scope PriorityClassNameExists not configured.", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{}, + expErr: "", + }, + { + description: "quota fails, though covering quota for configured limited scope PriorityClassNameExists exists.", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "20Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists}, + }, + }, + }, + Status: api.ResourceQuotaStatus{ + Hard: api.ResourceList{ + api.ResourceMemory: resource.MustParse("10Gi"), + }, + Used: api.ResourceList{ + api.ResourceMemory: resource.MustParse("1Gi"), + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + }, + }, + expErr: "forbidden: exceeded quota: quota, requested: memory=20Gi, used: memory=1Gi, limited: memory=10Gi", + }, + { + description: "Pod has different priorityclass than configured limited. Covering quota exists for configured limited scope PriorityClassIn.", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Pod has limited priorityclass. Covering quota exists for configured limited scope PriorityClassIn.", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name", "cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Pod has limited priorityclass. Covering quota does not exist for configured limited scope PriorityClassIn.", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name", "cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{PriorityClass In [another-priorityclass-name cluster-services]}]", + }, + { + description: "From the above test case, just changing pod priority from cluster-services to another-priorityclass-name. expecting no error", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "another-priorityclass-name"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name", "cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Pod has limited priorityclass. Covering quota does NOT exists for configured limited scope PriorityClassIn.", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name", "cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{PriorityClass In [another-priorityclass-name cluster-services]}]", + }, + { + description: "Pod has limited priorityclass. Covering quota exists for configured limited scope PriorityClassIn through PriorityClassNameExists", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists}, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name", "cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + } + + for _, testCase := range testCases { + newPod := testCase.testPod + config := testCase.config + resourceQuota := testCase.quota + kubeClient := fake.NewSimpleClientset(resourceQuota) + if testCase.anotherQuota != nil { + kubeClient = fake.NewSimpleClientset(resourceQuota, testCase.anotherQuota) + } + indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}) + stopCh := make(chan struct{}) + defer close(stopCh) + + informerFactory := informers.NewSharedInformerFactory(kubeClient, controller.NoResyncPeriodFunc()) + quotaAccessor, _ := newQuotaAccessor() + quotaAccessor.client = kubeClient + quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister() + + quotaConfiguration := install.NewQuotaConfigurationForAdmission() + evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh) + + handler := &QuotaAdmission{ + Handler: admission.NewHandler(admission.Create, admission.Update), + evaluator: evaluator, + } + indexer.Add(resourceQuota) + if testCase.anotherQuota != nil { + indexer.Add(testCase.anotherQuota) + } + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) + if testCase.expErr == "" { + if err != nil { + t.Fatalf("Testcase, %v, failed with unexpected error: %v. ExpErr: %v", testCase.description, err, testCase.expErr) + } + } else { + if !strings.Contains(fmt.Sprintf("%v", err), testCase.expErr) { + t.Fatalf("Testcase, %v, failed with unexpected error: %v. ExpErr: %v", testCase.description, err, testCase.expErr) + } + } + + } +} diff --git a/plugin/pkg/admission/resourcequota/apis/resourcequota/BUILD b/plugin/pkg/admission/resourcequota/apis/resourcequota/BUILD index 7c43ea4a124..0929b396511 100644 --- a/plugin/pkg/admission/resourcequota/apis/resourcequota/BUILD +++ b/plugin/pkg/admission/resourcequota/apis/resourcequota/BUILD @@ -15,6 +15,7 @@ go_library( ], importpath = "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota", deps = [ + "//pkg/apis/core:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/plugin/pkg/admission/resourcequota/apis/resourcequota/types.go b/plugin/pkg/admission/resourcequota/apis/resourcequota/types.go index 88602d01582..7686e4dab5c 100644 --- a/plugin/pkg/admission/resourcequota/apis/resourcequota/types.go +++ b/plugin/pkg/admission/resourcequota/apis/resourcequota/types.go @@ -16,7 +16,10 @@ limitations under the License. package resourcequota -import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/core" +) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -54,4 +57,16 @@ type LimitedResource struct { // with any storage class, the list would include // ".storageclass.storage.k8s.io/requests.storage" MatchContains []string + + // For each intercepted request, the quota system will figure out if the input object + // satisfies a scope which is present in this listing, then + // quota system will ensure that there is a covering quota. In the + // absence of a covering quota, the quota system will deny the request. + // For example, if an administrator wants to globally enforce that + // a quota must exist to create a pod with "cluster-services" priorityclass + // the list would include + // "PriorityClassNameIn=cluster-services" + // +optional + // MatchScopes []string `json:"matchScopes,omitempty"` + MatchScopes []core.ScopedResourceSelectorRequirement `json:"matchScopes,omitempty"` } diff --git a/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/BUILD b/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/BUILD index 0ffe75d6c0b..1b4f8ae2d47 100644 --- a/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/BUILD +++ b/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/BUILD @@ -18,7 +18,9 @@ go_library( ], importpath = "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1", deps = [ + "//pkg/apis/core:go_default_library", "//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/types.go b/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/types.go index 4774582314d..9ea8fe5adb1 100644 --- a/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/types.go +++ b/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/types.go @@ -16,7 +16,10 @@ limitations under the License. package v1alpha1 -import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +import ( + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -54,4 +57,13 @@ type LimitedResource struct { // with any storage class, the list would include // ".storageclass.storage.k8s.io/requests.storage" MatchContains []string `json:"matchContains,omitempty"` + // For each intercepted request, the quota system will figure out if the input object + // satisfies a scope which is present in this listing, then + // quota system will ensure that there is a covering quota. In the + // absence of a covering quota, the quota system will deny the request. + // For example, if an administrator wants to globally enforce that + // a quota must exist to create a pod with "cluster-services" priorityclass + // the list would include "scopeName=PriorityClass, Operator=In, Value=cluster-services" + // +optional + MatchScopes []v1.ScopedResourceSelectorRequirement `json:"matchScopes,omitempty"` } diff --git a/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.conversion.go b/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.conversion.go index 9036411d5f9..02f00e8f913 100644 --- a/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.conversion.go +++ b/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.conversion.go @@ -23,8 +23,10 @@ package v1alpha1 import ( unsafe "unsafe" + v1 "k8s.io/api/core/v1" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" + core "k8s.io/kubernetes/pkg/apis/core" resourcequota "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota" ) @@ -67,6 +69,7 @@ func autoConvert_v1alpha1_LimitedResource_To_resourcequota_LimitedResource(in *L out.APIGroup = in.APIGroup out.Resource = in.Resource out.MatchContains = *(*[]string)(unsafe.Pointer(&in.MatchContains)) + out.MatchScopes = *(*[]core.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchScopes)) return nil } @@ -79,6 +82,7 @@ func autoConvert_resourcequota_LimitedResource_To_v1alpha1_LimitedResource(in *r out.APIGroup = in.APIGroup out.Resource = in.Resource out.MatchContains = *(*[]string)(unsafe.Pointer(&in.MatchContains)) + out.MatchScopes = *(*[]v1.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchScopes)) return nil } diff --git a/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.deepcopy.go b/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.deepcopy.go index b09aca57bc4..95a100b92e9 100644 --- a/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.deepcopy.go +++ b/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.deepcopy.go @@ -21,6 +21,7 @@ limitations under the License. package v1alpha1 import ( + v1 "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -64,6 +65,13 @@ func (in *LimitedResource) DeepCopyInto(out *LimitedResource) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.MatchScopes != nil { + in, out := &in.MatchScopes, &out.MatchScopes + *out = make([]v1.ScopedResourceSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/plugin/pkg/admission/resourcequota/apis/resourcequota/zz_generated.deepcopy.go b/plugin/pkg/admission/resourcequota/apis/resourcequota/zz_generated.deepcopy.go index 4cf223c33c3..c33c217ca7c 100644 --- a/plugin/pkg/admission/resourcequota/apis/resourcequota/zz_generated.deepcopy.go +++ b/plugin/pkg/admission/resourcequota/apis/resourcequota/zz_generated.deepcopy.go @@ -22,6 +22,7 @@ package resourcequota import ( runtime "k8s.io/apimachinery/pkg/runtime" + core "k8s.io/kubernetes/pkg/apis/core" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -64,6 +65,13 @@ func (in *LimitedResource) DeepCopyInto(out *LimitedResource) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.MatchScopes != nil { + in, out := &in.MatchScopes, &out.MatchScopes + *out = make([]core.ScopedResourceSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/plugin/pkg/admission/resourcequota/controller.go b/plugin/pkg/admission/resourcequota/controller.go index 0f254365880..063626d33eb 100644 --- a/plugin/pkg/admission/resourcequota/controller.go +++ b/plugin/pkg/admission/resourcequota/controller.go @@ -27,6 +27,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/sets" @@ -367,6 +368,21 @@ func limitedByDefault(usage api.ResourceList, limitedResources []resourcequotaap return result } +func getMatchedLimitedScopes(evaluator quota.Evaluator, inputObject runtime.Object, limitedResources []resourcequotaapi.LimitedResource) ([]api.ScopedResourceSelectorRequirement, error) { + scopes := []api.ScopedResourceSelectorRequirement{} + for _, limitedResource := range limitedResources { + matched, err := evaluator.MatchingScopes(inputObject, limitedResource.MatchScopes) + if err != nil { + glog.Errorf("Error while matching limited Scopes: %v", err) + return []api.ScopedResourceSelectorRequirement{}, err + } + for _, scope := range matched { + scopes = append(scopes, scope) + } + } + return scopes, nil +} + // checkRequest verifies that the request does not exceed any quota constraint. it returns a copy of quotas not yet persisted // that capture what the usage would be if the request succeeded. It return an error if there is insufficient quota to satisfy the request func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.Attributes) ([]api.ResourceQuota, error) { @@ -383,6 +399,12 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At // if we have limited resources enabled for this resource, always calculate usage inputObject := a.GetObject() + // Check if object matches AdmissionConfiguration matchScopes + limitedScopes, err := getMatchedLimitedScopes(evaluator, inputObject, e.config.LimitedResources) + if err != nil { + return quotas, nil + } + // determine the set of resource names that must exist in a covering quota limitedResourceNames := []api.ResourceName{} limitedResources := filterLimitedResourcesByGroupResource(e.config.LimitedResources, a.GetResource().GroupResource()) @@ -404,10 +426,21 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At // this is needed to know if we have satisfied any constraints where consumption // was limited by default. restrictedResourcesSet := sets.String{} + restrictedScopes := []api.ScopedResourceSelectorRequirement{} for i := range quotas { resourceQuota := quotas[i] + scopeSelectors := getScopeSelectorsFromQuota(resourceQuota) + localRestrictedScopes, err := evaluator.MatchingScopes(inputObject, scopeSelectors) + if err != nil { + return nil, fmt.Errorf("error matching scopes of quota %s, err: %v", resourceQuota.Name, err) + } + for _, scope := range localRestrictedScopes { + restrictedScopes = append(restrictedScopes, scope) + } + match, err := evaluator.Matches(&resourceQuota, inputObject) if err != nil { + glog.Errorf("Error occurred while matching resource quota, %v, against input object. Err: %v", resourceQuota, err) return quotas, err } if !match { @@ -435,6 +468,17 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At return quotas, admission.NewForbidden(a, fmt.Errorf("insufficient quota to consume: %v", strings.Join(hasNoCoveringQuota.List(), ","))) } + // verify that for every scope that had limited access enabled + // that there was a corresponding quota that covered it. + // if not, we reject the request. + scopesHasNoCoveringQuota, err := evaluator.UncoveredQuotaScopes(limitedScopes, restrictedScopes) + if err != nil { + return quotas, err + } + if len(scopesHasNoCoveringQuota) > 0 { + return quotas, fmt.Errorf("insufficient quota to match these scopes: %v", scopesHasNoCoveringQuota) + } + if len(interestingQuotaIndexes) == 0 { return quotas, nil } @@ -516,6 +560,21 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At return outQuotas, nil } +func getScopeSelectorsFromQuota(quota api.ResourceQuota) []api.ScopedResourceSelectorRequirement { + selectors := []api.ScopedResourceSelectorRequirement{} + for _, scope := range quota.Spec.Scopes { + selectors = append(selectors, api.ScopedResourceSelectorRequirement{ + ScopeName: scope, + Operator: api.ScopeSelectorOpExists}) + } + if quota.Spec.ScopeSelector != nil { + for _, scopeSelector := range quota.Spec.ScopeSelector.MatchExpressions { + selectors = append(selectors, scopeSelector) + } + } + return selectors +} + func (e *quotaEvaluator) Evaluate(a admission.Attributes) error { e.init.Do(func() { go e.run() diff --git a/plugin/pkg/admission/security/podsecuritypolicy/BUILD b/plugin/pkg/admission/security/podsecuritypolicy/BUILD index 71564851cec..448b32c3eca 100644 --- a/plugin/pkg/admission/security/podsecuritypolicy/BUILD +++ b/plugin/pkg/admission/security/podsecuritypolicy/BUILD @@ -39,7 +39,6 @@ go_test( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/core/helper:go_default_library", "//pkg/apis/policy:go_default_library", "//pkg/client/informers/informers_generated/internalversion:go_default_library", "//pkg/controller:go_default_library", diff --git a/plugin/pkg/admission/security/podsecuritypolicy/admission.go b/plugin/pkg/admission/security/podsecuritypolicy/admission.go index 3a31f33f968..1c1b571f82f 100644 --- a/plugin/pkg/admission/security/podsecuritypolicy/admission.go +++ b/plugin/pkg/admission/security/podsecuritypolicy/admission.go @@ -84,6 +84,7 @@ var _ admission.MutationInterface = &PodSecurityPolicyPlugin{} var _ admission.ValidationInterface = &PodSecurityPolicyPlugin{} var _ genericadmissioninit.WantsAuthorizer = &PodSecurityPolicyPlugin{} var _ kubeapiserveradmission.WantsInternalKubeInformerFactory = &PodSecurityPolicyPlugin{} +var auditKeyPrefix = strings.ToLower(PluginName) + "." + policy.GroupName + ".k8s.io" // newPlugin creates a new PSP admission plugin. func newPlugin(strategyFactory psp.StrategyFactory, failOnNoPolicies bool) *PodSecurityPolicyPlugin { @@ -136,6 +137,10 @@ func (c *PodSecurityPolicyPlugin) Admit(a admission.Attributes) error { pod.ObjectMeta.Annotations = map[string]string{} } pod.ObjectMeta.Annotations[psputil.ValidatedPSPAnnotation] = pspName + key := auditKeyPrefix + "/" + "admit-policy" + if err := a.AddAnnotation(key, pspName); err != nil { + glog.Warningf("failed to set admission audit annotation %s to %s: %v", key, pspName, err) + } return nil } @@ -154,11 +159,15 @@ func (c *PodSecurityPolicyPlugin) Validate(a admission.Attributes) error { pod := a.GetObject().(*api.Pod) // compute the context. Mutation is not allowed. ValidatedPSPAnnotation is used as a hint to gain same speed-up. - allowedPod, _, validationErrs, err := c.computeSecurityContext(a, pod, false, pod.ObjectMeta.Annotations[psputil.ValidatedPSPAnnotation]) + allowedPod, pspName, validationErrs, err := c.computeSecurityContext(a, pod, false, pod.ObjectMeta.Annotations[psputil.ValidatedPSPAnnotation]) if err != nil { return admission.NewForbidden(a, err) } if apiequality.Semantic.DeepEqual(pod, allowedPod) { + key := auditKeyPrefix + "/" + "validate-policy" + if err := a.AddAnnotation(key, pspName); err != nil { + glog.Warningf("failed to set admission audit annotation %s to %s: %v", key, pspName, err) + } return nil } diff --git a/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go b/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go index 6cdf1d3c935..92d4a36da5a 100644 --- a/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go +++ b/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go @@ -35,7 +35,6 @@ import ( "k8s.io/apiserver/pkg/authorization/authorizerfactory" "k8s.io/kubernetes/pkg/api/legacyscheme" kapi "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/helper" "k8s.io/kubernetes/pkg/apis/policy" informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" "k8s.io/kubernetes/pkg/controller" @@ -1608,37 +1607,40 @@ func TestAdmitSysctls(t *testing.T) { } return sysctls } - pod.Annotations[kapi.SysctlsPodAnnotationKey] = helper.PodAnnotationsFromSysctls(dummySysctls(safeSysctls)) - pod.Annotations[kapi.UnsafeSysctlsPodAnnotationKey] = helper.PodAnnotationsFromSysctls(dummySysctls(unsafeSysctls)) + pod.Spec.SecurityContext = &kapi.PodSecurityContext{ + Sysctls: dummySysctls(append(safeSysctls, unsafeSysctls...)), + } + return pod } - noSysctls := restrictivePSP() - noSysctls.Name = "no sysctls" + safeSysctls := restrictivePSP() + safeSysctls.Name = "no sysctls" - emptySysctls := restrictivePSP() - emptySysctls.Name = "empty sysctls" - emptySysctls.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "" + noSysctls := restrictivePSP() + noSysctls.Name = "empty sysctls" + noSysctls.Spec.ForbiddenSysctls = []string{"*"} mixedSysctls := restrictivePSP() mixedSysctls.Name = "wildcard sysctls" - mixedSysctls.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "a.*,b.*,c,d.e.f" + mixedSysctls.Spec.ForbiddenSysctls = []string{"net.*"} + mixedSysctls.Spec.AllowedUnsafeSysctls = []string{"a.*", "b.*"} - aSysctl := restrictivePSP() - aSysctl.Name = "a sysctl" - aSysctl.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "a" + aUnsafeSysctl := restrictivePSP() + aUnsafeSysctl.Name = "a sysctl" + aUnsafeSysctl.Spec.AllowedUnsafeSysctls = []string{"a"} - bSysctl := restrictivePSP() - bSysctl.Name = "b sysctl" - bSysctl.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "b" + bUnsafeSysctl := restrictivePSP() + bUnsafeSysctl.Name = "b sysctl" + bUnsafeSysctl.Spec.AllowedUnsafeSysctls = []string{"b"} - cSysctl := restrictivePSP() - cSysctl.Name = "c sysctl" - cSysctl.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "c" + cUnsafeSysctl := restrictivePSP() + cUnsafeSysctl.Name = "c sysctl" + cUnsafeSysctl.Spec.AllowedUnsafeSysctls = []string{"c"} catchallSysctls := restrictivePSP() catchallSysctls.Name = "catchall sysctl" - catchallSysctls.Annotations[policy.SysctlsPodSecurityPolicyAnnotationKey] = "*" + catchallSysctls.Spec.AllowedUnsafeSysctls = []string{"*"} tests := map[string]struct { pod *kapi.Pod @@ -1647,148 +1649,102 @@ func TestAdmitSysctls(t *testing.T) { shouldPassValidate bool expectedPSP string }{ - "pod without unsafe sysctls request allowed under noSysctls PSP": { + "pod without any sysctls request allowed under safeSysctls PSP": { + pod: goodPod(), + psps: []*policy.PodSecurityPolicy{safeSysctls}, + shouldPassAdmit: true, + shouldPassValidate: true, + expectedPSP: safeSysctls.Name, + }, + "pod without any sysctls request allowed under noSysctls PSP": { pod: goodPod(), psps: []*policy.PodSecurityPolicy{noSysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: noSysctls.Name, }, - "pod without any sysctls request allowed under emptySysctls PSP": { - pod: goodPod(), - psps: []*policy.PodSecurityPolicy{emptySysctls}, + "pod with safe sysctls request allowed under safeSysctls PSP": { + pod: podWithSysctls([]string{"kernel.shm_rmid_forced", "net.ipv4.tcp_syncookies"}, []string{}), + psps: []*policy.PodSecurityPolicy{safeSysctls}, shouldPassAdmit: true, shouldPassValidate: true, - expectedPSP: emptySysctls.Name, + expectedPSP: safeSysctls.Name, }, - "pod with safe sysctls request allowed under noSysctls PSP": { - pod: podWithSysctls([]string{"a", "b"}, []string{}), - psps: []*policy.PodSecurityPolicy{noSysctls}, - shouldPassAdmit: true, - shouldPassValidate: true, - expectedPSP: noSysctls.Name, - }, - "pod with unsafe sysctls request allowed under noSysctls PSP": { + "pod with unsafe sysctls request disallowed under noSysctls PSP": { pod: podWithSysctls([]string{}, []string{"a", "b"}), psps: []*policy.PodSecurityPolicy{noSysctls}, - shouldPassAdmit: true, - shouldPassValidate: true, + shouldPassAdmit: false, + shouldPassValidate: false, expectedPSP: noSysctls.Name, }, - "pod with safe sysctls request disallowed under emptySysctls PSP": { - pod: podWithSysctls([]string{"a", "b"}, []string{}), - psps: []*policy.PodSecurityPolicy{emptySysctls}, + "pod with unsafe sysctls a, b request disallowed under aUnsafeSysctl SCC": { + pod: podWithSysctls([]string{}, []string{"a", "b"}), + psps: []*policy.PodSecurityPolicy{aUnsafeSysctl}, shouldPassAdmit: false, shouldPassValidate: false, }, - "pod with unsafe sysctls a, b request disallowed under aSysctls SCC": { - pod: podWithSysctls([]string{}, []string{"a", "b"}), - psps: []*policy.PodSecurityPolicy{aSysctl}, - shouldPassAdmit: false, - shouldPassValidate: false, - }, - "pod with unsafe sysctls b request disallowed under aSysctls SCC": { + "pod with unsafe sysctls b request disallowed under aUnsafeSysctl SCC": { pod: podWithSysctls([]string{}, []string{"b"}), - psps: []*policy.PodSecurityPolicy{aSysctl}, + psps: []*policy.PodSecurityPolicy{aUnsafeSysctl}, shouldPassAdmit: false, shouldPassValidate: false, }, - "pod with unsafe sysctls a request allowed under aSysctls SCC": { + "pod with unsafe sysctls a request allowed under aUnsafeSysctl SCC": { pod: podWithSysctls([]string{}, []string{"a"}), - psps: []*policy.PodSecurityPolicy{aSysctl}, + psps: []*policy.PodSecurityPolicy{aUnsafeSysctl}, shouldPassAdmit: true, shouldPassValidate: true, - expectedPSP: aSysctl.Name, + expectedPSP: aUnsafeSysctl.Name, }, - "pod with safe sysctls a, b request disallowed under aSysctls SCC": { - pod: podWithSysctls([]string{"a", "b"}, []string{}), - psps: []*policy.PodSecurityPolicy{aSysctl}, - shouldPassAdmit: false, - shouldPassValidate: false, - }, - "pod with safe sysctls b request disallowed under aSysctls SCC": { - pod: podWithSysctls([]string{"b"}, []string{}), - psps: []*policy.PodSecurityPolicy{aSysctl}, - shouldPassAdmit: false, - shouldPassValidate: false, - }, - "pod with safe sysctls a request allowed under aSysctls SCC": { - pod: podWithSysctls([]string{"a"}, []string{}), - psps: []*policy.PodSecurityPolicy{aSysctl}, + "pod with safe net sysctl request allowed under aUnsafeSysctl SCC": { + pod: podWithSysctls([]string{"net.ipv4.ip_local_port_range"}, []string{}), + psps: []*policy.PodSecurityPolicy{aUnsafeSysctl}, shouldPassAdmit: true, shouldPassValidate: true, - expectedPSP: aSysctl.Name, + expectedPSP: aUnsafeSysctl.Name, }, - "pod with unsafe sysctls request disallowed under emptySysctls PSP": { - pod: podWithSysctls([]string{}, []string{"a", "b"}), - psps: []*policy.PodSecurityPolicy{emptySysctls}, + "pod with safe sysctls request disallowed under noSysctls PSP": { + pod: podWithSysctls([]string{"net.ipv4.ip_local_port_range"}, []string{}), + psps: []*policy.PodSecurityPolicy{noSysctls}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with matching sysctls request allowed under mixedSysctls PSP": { - pod: podWithSysctls([]string{"a.b", "b.c"}, []string{"c", "d.e.f"}), + pod: podWithSysctls([]string{"kernel.shm_rmid_forced"}, []string{"a.b", "b.a"}), psps: []*policy.PodSecurityPolicy{mixedSysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: mixedSysctls.Name, }, "pod with not-matching unsafe sysctls request disallowed under mixedSysctls PSP": { - pod: podWithSysctls([]string{"a.b", "b.c", "c", "d.e.f"}, []string{"e"}), + pod: podWithSysctls([]string{}, []string{"e"}), psps: []*policy.PodSecurityPolicy{mixedSysctls}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with not-matching safe sysctls request disallowed under mixedSysctls PSP": { - pod: podWithSysctls([]string{"a.b", "b.c", "c", "d.e.f", "e"}, []string{}), + pod: podWithSysctls([]string{"net.ipv4.ip_local_port_range"}, []string{}), psps: []*policy.PodSecurityPolicy{mixedSysctls}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with sysctls request allowed under catchallSysctls PSP": { - pod: podWithSysctls([]string{"e"}, []string{"f"}), + pod: podWithSysctls([]string{"net.ipv4.ip_local_port_range"}, []string{"f"}), psps: []*policy.PodSecurityPolicy{catchallSysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: catchallSysctls.Name, }, - "pod with sysctls request allowed under catchallSysctls PSP, not under mixedSysctls or emptySysctls PSP": { - pod: podWithSysctls([]string{"e"}, []string{"f"}), - psps: []*policy.PodSecurityPolicy{mixedSysctls, catchallSysctls, emptySysctls}, - shouldPassAdmit: true, - shouldPassValidate: true, - expectedPSP: catchallSysctls.Name, - }, - "pod with safe c sysctl request allowed under cSysctl PSP, not under aSysctl or bSysctl PSP": { - pod: podWithSysctls([]string{}, []string{"c"}), - psps: []*policy.PodSecurityPolicy{aSysctl, bSysctl, cSysctl}, - shouldPassAdmit: true, - shouldPassValidate: true, - expectedPSP: cSysctl.Name, - }, - "pod with unsafe c sysctl request allowed under cSysctl PSP, not under aSysctl or bSysctl PSP": { - pod: podWithSysctls([]string{"c"}, []string{}), - psps: []*policy.PodSecurityPolicy{aSysctl, bSysctl, cSysctl}, - shouldPassAdmit: true, - shouldPassValidate: true, - expectedPSP: cSysctl.Name, - }, } for k, v := range tests { - origSafeSysctls, origUnsafeSysctls, err := helper.SysctlsFromPodAnnotations(v.pod.Annotations) - if err != nil { - t.Fatalf("invalid sysctl annotation: %v", err) - } + origSysctl := v.pod.Spec.SecurityContext.Sysctls testPSPAdmit(k, v.psps, v.pod, v.shouldPassAdmit, v.shouldPassValidate, v.expectedPSP, t) if v.shouldPassAdmit { - safeSysctls, unsafeSysctls, _ := helper.SysctlsFromPodAnnotations(v.pod.Annotations) - if !reflect.DeepEqual(safeSysctls, origSafeSysctls) { - t.Errorf("%s: wrong safe sysctls: expected=%v, got=%v", k, origSafeSysctls, safeSysctls) - } - if !reflect.DeepEqual(unsafeSysctls, origUnsafeSysctls) { - t.Errorf("%s: wrong unsafe sysctls: expected=%v, got=%v", k, origSafeSysctls, safeSysctls) + if !reflect.DeepEqual(v.pod.Spec.SecurityContext.Sysctls, origSysctl) { + t.Errorf("%s: wrong sysctls: expected=%v, got=%v", k, origSysctl, v.pod.Spec.SecurityContext.Sysctls) } } } @@ -1798,11 +1754,24 @@ func testPSPAdmit(testCaseName string, psps []*policy.PodSecurityPolicy, pod *ka testPSPAdmitAdvanced(testCaseName, kadmission.Create, psps, nil, &user.DefaultInfo{}, pod, nil, shouldPassAdmit, shouldPassValidate, true, expectedPSP, t) } +// fakeAttributes decorate kadmission.Attributes. It's used to trace the added annotations. +type fakeAttributes struct { + kadmission.Attributes + annotations map[string]string +} + +func (f fakeAttributes) AddAnnotation(k, v string) error { + f.annotations[k] = v + return f.Attributes.AddAnnotation(k, v) +} + func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []*policy.PodSecurityPolicy, authz authorizer.Authorizer, userInfo user.Info, pod, oldPod *kapi.Pod, shouldPassAdmit, shouldPassValidate bool, canMutate bool, expectedPSP string, t *testing.T) { originalPod := pod.DeepCopy() plugin := NewTestAdmission(psps, authz) attrs := kadmission.NewAttributesRecord(pod, oldPod, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, "", kapi.Resource("pods").WithVersion("version"), "", op, userInfo) + annotations := make(map[string]string) + attrs = &fakeAttributes{attrs, annotations} err := plugin.Admit(attrs) if shouldPassAdmit && err != nil { @@ -1832,11 +1801,27 @@ func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []* } err = plugin.Validate(attrs) + psp := "" + if shouldPassAdmit && op == kadmission.Create { + psp = expectedPSP + } + validateAuditAnnotation(t, testCaseName, annotations, "podsecuritypolicy.policy.k8s.io/admit-policy", psp) if shouldPassValidate && err != nil { t.Errorf("%s: expected no errors on Validate but received %v", testCaseName, err) } else if !shouldPassValidate && err == nil { t.Errorf("%s: expected errors on Validate but received none", testCaseName) } + if shouldPassValidate { + validateAuditAnnotation(t, testCaseName, annotations, "podsecuritypolicy.policy.k8s.io/validate-policy", expectedPSP) + } else { + validateAuditAnnotation(t, testCaseName, annotations, "podsecuritypolicy.policy.k8s.io/validate-policy", "") + } +} + +func validateAuditAnnotation(t *testing.T, testCaseName string, annotations map[string]string, key, value string) { + if annotations[key] != value { + t.Errorf("%s: expected to have annotations[%s] set to %q, got %q", testCaseName, key, value, annotations[key]) + } } func TestAssignSecurityContext(t *testing.T) { diff --git a/plugin/pkg/admission/serviceaccount/admission.go b/plugin/pkg/admission/serviceaccount/admission.go index 6e245ecf8b0..7a831a295b6 100644 --- a/plugin/pkg/admission/serviceaccount/admission.go +++ b/plugin/pkg/admission/serviceaccount/admission.go @@ -208,6 +208,15 @@ func (s *serviceAccount) Validate(a admission.Attributes) (err error) { if hasSecrets { return admission.NewForbidden(a, fmt.Errorf("a mirror pod may not reference secrets")) } + for _, v := range pod.Spec.Volumes { + if proj := v.Projected; proj != nil { + for _, projSource := range proj.Sources { + if projSource.ServiceAccountToken != nil { + return admission.NewForbidden(a, fmt.Errorf("a mirror pod may not use ServiceAccountToken volume projections")) + } + } + } + } return nil } diff --git a/plugin/pkg/admission/serviceaccount/admission_test.go b/plugin/pkg/admission/serviceaccount/admission_test.go index d5167718647..18ed0ee9ee0 100644 --- a/plugin/pkg/admission/serviceaccount/admission_test.go +++ b/plugin/pkg/admission/serviceaccount/admission_test.go @@ -138,6 +138,31 @@ func TestRejectsMirrorPodWithSecretVolumes(t *testing.T) { } } +func TestRejectsMirrorPodWithServiceAccountTokenVolumeProjections(t *testing.T) { + pod := &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + kubelet.ConfigMirrorAnnotationKey: "true", + }, + }, + Spec: api.PodSpec{ + Volumes: []api.Volume{ + {VolumeSource: api.VolumeSource{ + Projected: &api.ProjectedVolumeSource{ + Sources: []api.VolumeProjection{{ServiceAccountToken: &api.ServiceAccountTokenProjection{}}}, + }, + }, + }, + }, + }, + } + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, nil) + err := NewServiceAccount().Admit(attrs) + if err == nil { + t.Errorf("Expected a mirror pod to be prevented from referencing a ServiceAccountToken volume projection") + } +} + func TestAssignsDefaultServiceAccountAndToleratesMissingAPIToken(t *testing.T) { ns := "myns" diff --git a/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go b/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go index c8cbc7ff4f4..f04939152e2 100644 --- a/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go +++ b/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go @@ -36,7 +36,7 @@ type mockVolumes struct { var _ aws.Volumes = &mockVolumes{} -func (v *mockVolumes) AttachDisk(diskName aws.KubernetesVolumeID, nodeName types.NodeName, readOnly bool) (string, error) { +func (v *mockVolumes) AttachDisk(diskName aws.KubernetesVolumeID, nodeName types.NodeName) (string, error) { return "", fmt.Errorf("not implemented") } diff --git a/plugin/pkg/admission/storage/persistentvolume/resize/admission.go b/plugin/pkg/admission/storage/persistentvolume/resize/admission.go index 6d6b500aa8c..389e39395d8 100644 --- a/plugin/pkg/admission/storage/persistentvolume/resize/admission.go +++ b/plugin/pkg/admission/storage/persistentvolume/resize/admission.go @@ -164,5 +164,9 @@ func (pvcr *persistentVolumeClaimResize) checkVolumePlugin(pv *api.PersistentVol if pv.Spec.AzureFile != nil { return true } + + if pv.Spec.AzureDisk != nil { + return true + } return false } diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go index 912ab05a1b3..815f3787c7e 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go @@ -119,7 +119,7 @@ func NodeRules() []rbacv1.PolicyRule { rbacv1helpers.NewRule("create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), // Needed for the node to report status of pods it is running. // Use the NodeRestriction admission plugin to limit a node to updating status of pods bound to itself. - rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), + rbacv1helpers.NewRule("update", "patch").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), // Needed for the node to create pod evictions. // Use the NodeRestriction admission plugin to limit a node to creating evictions for pods bound to itself. rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/eviction").RuleOrDie(), @@ -466,7 +466,7 @@ func ClusterRoles() []rbacv1.ClusterRole { // a role for the csi external provisioner ObjectMeta: metav1.ObjectMeta{Name: "system:csi-external-provisioner"}, Rules: []rbacv1.PolicyRule{ - rbacv1helpers.NewRule("create", "delete", "list", "watch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule("create", "delete", "get", "list", "watch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), rbacv1helpers.NewRule("list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(), 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 300b66485ca..0aee48909f5 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml @@ -688,6 +688,7 @@ items: verbs: - create - delete + - get - list - watch - apiGroups: @@ -1098,6 +1099,7 @@ items: resources: - pods/status verbs: + - patch - update - apiGroups: - "" diff --git a/staging/src/k8s.io/api/Godeps/Godeps.json b/staging/src/k8s.io/api/Godeps/Godeps.json index da0412bc1a1..284ccea51de 100644 --- a/staging/src/k8s.io/api/Godeps/Godeps.json +++ b/staging/src/k8s.io/api/Godeps/Godeps.json @@ -28,7 +28,7 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/gofuzz", @@ -36,7 +36,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "2ddf6d758266fcb080a4f9e054b9f292c85e6798" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/modern-go/concurrent", diff --git a/staging/src/k8s.io/api/SECURITY_CONTACTS b/staging/src/k8s.io/api/SECURITY_CONTACTS new file mode 100644 index 00000000000..0648a8ebff7 --- /dev/null +++ b/staging/src/k8s.io/api/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# 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/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/staging/src/k8s.io/api/core/v1/annotation_key_constants.go b/staging/src/k8s.io/api/core/v1/annotation_key_constants.go index 95fff364283..16a0cfced13 100644 --- a/staging/src/k8s.io/api/core/v1/annotation_key_constants.go +++ b/staging/src/k8s.io/api/core/v1/annotation_key_constants.go @@ -56,20 +56,6 @@ const ( // in the Annotations of a Node. PreferAvoidPodsAnnotationKey string = "scheduler.alpha.kubernetes.io/preferAvoidPods" - // SysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Only a limited set of whitelisted and isolated sysctls is supported by - // the kubelet. Pods with other sysctls will fail to launch. - SysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/sysctls" - - // UnsafeSysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Unsafe sysctls must be explicitly enabled for a kubelet. They are properly - // namespaced to a pod or a container, but their isolation is usually unclear or weak. Their use - // is at-your-own-risk. Pods that attempt to set an unsafe sysctl that is not enabled for a kubelet - // will fail to launch. - UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls" - // ObjectTTLAnnotations represents a suggestion for kubelet for how long it can cache // an object (e.g. secret, config map) before fetching it again from apiserver. // This annotation can be attached to node. diff --git a/staging/src/k8s.io/api/core/v1/generated.pb.go b/staging/src/k8s.io/api/core/v1/generated.pb.go index 570ea23fddb..48b5a3c5b5b 100644 --- a/staging/src/k8s.io/api/core/v1/generated.pb.go +++ b/staging/src/k8s.io/api/core/v1/generated.pb.go @@ -37,6 +37,7 @@ limitations under the License. Capabilities CephFSPersistentVolumeSource CephFSVolumeSource + CinderPersistentVolumeSource CinderVolumeSource ClientIPConfig ComponentCondition @@ -148,6 +149,7 @@ limitations under the License. PodLogOptions PodPortForwardOptions PodProxyOptions + PodReadinessGate PodSecurityContext PodSignature PodSpec @@ -180,6 +182,8 @@ limitations under the License. SELinuxOptions ScaleIOPersistentVolumeSource ScaleIOVolumeSource + ScopeSelector + ScopedResourceSelectorRequirement Secret SecretEnvSource SecretKeySelector @@ -192,6 +196,7 @@ limitations under the License. Service ServiceAccount ServiceAccountList + ServiceAccountTokenProjection ServiceList ServicePort ServiceProxyOptions @@ -204,6 +209,8 @@ limitations under the License. TCPSocketAction Taint Toleration + TopologySelectorLabelRequirement + TopologySelectorTerm Volume VolumeDevice VolumeMount @@ -299,754 +306,790 @@ func (m *CephFSVolumeSource) Reset() { *m = CephFSVolumeSourc func (*CephFSVolumeSource) ProtoMessage() {} func (*CephFSVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } +func (m *CinderPersistentVolumeSource) Reset() { *m = CinderPersistentVolumeSource{} } +func (*CinderPersistentVolumeSource) ProtoMessage() {} +func (*CinderPersistentVolumeSource) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{12} +} + func (m *CinderVolumeSource) Reset() { *m = CinderVolumeSource{} } func (*CinderVolumeSource) ProtoMessage() {} -func (*CinderVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } +func (*CinderVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } func (m *ClientIPConfig) Reset() { *m = ClientIPConfig{} } func (*ClientIPConfig) ProtoMessage() {} -func (*ClientIPConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } +func (*ClientIPConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } func (m *ComponentCondition) Reset() { *m = ComponentCondition{} } func (*ComponentCondition) ProtoMessage() {} -func (*ComponentCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } +func (*ComponentCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } func (m *ComponentStatus) Reset() { *m = ComponentStatus{} } func (*ComponentStatus) ProtoMessage() {} -func (*ComponentStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } +func (*ComponentStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } func (m *ComponentStatusList) Reset() { *m = ComponentStatusList{} } func (*ComponentStatusList) ProtoMessage() {} -func (*ComponentStatusList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } +func (*ComponentStatusList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } func (m *ConfigMap) Reset() { *m = ConfigMap{} } func (*ConfigMap) ProtoMessage() {} -func (*ConfigMap) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } +func (*ConfigMap) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } func (m *ConfigMapEnvSource) Reset() { *m = ConfigMapEnvSource{} } func (*ConfigMapEnvSource) ProtoMessage() {} -func (*ConfigMapEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } +func (*ConfigMapEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } func (m *ConfigMapKeySelector) Reset() { *m = ConfigMapKeySelector{} } func (*ConfigMapKeySelector) ProtoMessage() {} -func (*ConfigMapKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } +func (*ConfigMapKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } func (m *ConfigMapList) Reset() { *m = ConfigMapList{} } func (*ConfigMapList) ProtoMessage() {} -func (*ConfigMapList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } +func (*ConfigMapList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} } func (m *ConfigMapNodeConfigSource) Reset() { *m = ConfigMapNodeConfigSource{} } func (*ConfigMapNodeConfigSource) ProtoMessage() {} func (*ConfigMapNodeConfigSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{21} + return fileDescriptorGenerated, []int{22} } func (m *ConfigMapProjection) Reset() { *m = ConfigMapProjection{} } func (*ConfigMapProjection) ProtoMessage() {} -func (*ConfigMapProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{22} } +func (*ConfigMapProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } func (m *ConfigMapVolumeSource) Reset() { *m = ConfigMapVolumeSource{} } func (*ConfigMapVolumeSource) ProtoMessage() {} -func (*ConfigMapVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } +func (*ConfigMapVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } func (m *Container) Reset() { *m = Container{} } func (*Container) ProtoMessage() {} -func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } +func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } func (m *ContainerImage) Reset() { *m = ContainerImage{} } func (*ContainerImage) ProtoMessage() {} -func (*ContainerImage) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } +func (*ContainerImage) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } func (m *ContainerPort) Reset() { *m = ContainerPort{} } func (*ContainerPort) ProtoMessage() {} -func (*ContainerPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } +func (*ContainerPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } func (m *ContainerState) Reset() { *m = ContainerState{} } func (*ContainerState) ProtoMessage() {} -func (*ContainerState) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } +func (*ContainerState) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{28} } func (m *ContainerStateRunning) Reset() { *m = ContainerStateRunning{} } func (*ContainerStateRunning) ProtoMessage() {} -func (*ContainerStateRunning) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{28} } +func (*ContainerStateRunning) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } func (m *ContainerStateTerminated) Reset() { *m = ContainerStateTerminated{} } func (*ContainerStateTerminated) ProtoMessage() {} func (*ContainerStateTerminated) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{29} + return fileDescriptorGenerated, []int{30} } func (m *ContainerStateWaiting) Reset() { *m = ContainerStateWaiting{} } func (*ContainerStateWaiting) ProtoMessage() {} -func (*ContainerStateWaiting) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{30} } +func (*ContainerStateWaiting) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{31} } func (m *ContainerStatus) Reset() { *m = ContainerStatus{} } func (*ContainerStatus) ProtoMessage() {} -func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{31} } +func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } func (m *DaemonEndpoint) Reset() { *m = DaemonEndpoint{} } func (*DaemonEndpoint) ProtoMessage() {} -func (*DaemonEndpoint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } +func (*DaemonEndpoint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } func (m *DownwardAPIProjection) Reset() { *m = DownwardAPIProjection{} } func (*DownwardAPIProjection) ProtoMessage() {} -func (*DownwardAPIProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } +func (*DownwardAPIProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{34} } func (m *DownwardAPIVolumeFile) Reset() { *m = DownwardAPIVolumeFile{} } func (*DownwardAPIVolumeFile) ProtoMessage() {} -func (*DownwardAPIVolumeFile) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{34} } +func (*DownwardAPIVolumeFile) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{35} } func (m *DownwardAPIVolumeSource) Reset() { *m = DownwardAPIVolumeSource{} } func (*DownwardAPIVolumeSource) ProtoMessage() {} func (*DownwardAPIVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{35} + return fileDescriptorGenerated, []int{36} } func (m *EmptyDirVolumeSource) Reset() { *m = EmptyDirVolumeSource{} } func (*EmptyDirVolumeSource) ProtoMessage() {} -func (*EmptyDirVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{36} } +func (*EmptyDirVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{37} } func (m *EndpointAddress) Reset() { *m = EndpointAddress{} } func (*EndpointAddress) ProtoMessage() {} -func (*EndpointAddress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{37} } +func (*EndpointAddress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{38} } func (m *EndpointPort) Reset() { *m = EndpointPort{} } func (*EndpointPort) ProtoMessage() {} -func (*EndpointPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{38} } +func (*EndpointPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{39} } func (m *EndpointSubset) Reset() { *m = EndpointSubset{} } func (*EndpointSubset) ProtoMessage() {} -func (*EndpointSubset) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{39} } +func (*EndpointSubset) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{40} } func (m *Endpoints) Reset() { *m = Endpoints{} } func (*Endpoints) ProtoMessage() {} -func (*Endpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{40} } +func (*Endpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{41} } func (m *EndpointsList) Reset() { *m = EndpointsList{} } func (*EndpointsList) ProtoMessage() {} -func (*EndpointsList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{41} } +func (*EndpointsList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{42} } func (m *EnvFromSource) Reset() { *m = EnvFromSource{} } func (*EnvFromSource) ProtoMessage() {} -func (*EnvFromSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{42} } +func (*EnvFromSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{43} } func (m *EnvVar) Reset() { *m = EnvVar{} } func (*EnvVar) ProtoMessage() {} -func (*EnvVar) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{43} } +func (*EnvVar) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{44} } func (m *EnvVarSource) Reset() { *m = EnvVarSource{} } func (*EnvVarSource) ProtoMessage() {} -func (*EnvVarSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{44} } +func (*EnvVarSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{45} } func (m *Event) Reset() { *m = Event{} } func (*Event) ProtoMessage() {} -func (*Event) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{45} } +func (*Event) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{46} } func (m *EventList) Reset() { *m = EventList{} } func (*EventList) ProtoMessage() {} -func (*EventList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{46} } +func (*EventList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{47} } func (m *EventSeries) Reset() { *m = EventSeries{} } func (*EventSeries) ProtoMessage() {} -func (*EventSeries) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{47} } +func (*EventSeries) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{48} } func (m *EventSource) Reset() { *m = EventSource{} } func (*EventSource) ProtoMessage() {} -func (*EventSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{48} } +func (*EventSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{49} } func (m *ExecAction) Reset() { *m = ExecAction{} } func (*ExecAction) ProtoMessage() {} -func (*ExecAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{49} } +func (*ExecAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{50} } func (m *FCVolumeSource) Reset() { *m = FCVolumeSource{} } func (*FCVolumeSource) ProtoMessage() {} -func (*FCVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{50} } +func (*FCVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{51} } func (m *FlexPersistentVolumeSource) Reset() { *m = FlexPersistentVolumeSource{} } func (*FlexPersistentVolumeSource) ProtoMessage() {} func (*FlexPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{51} + return fileDescriptorGenerated, []int{52} } func (m *FlexVolumeSource) Reset() { *m = FlexVolumeSource{} } func (*FlexVolumeSource) ProtoMessage() {} -func (*FlexVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{52} } +func (*FlexVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{53} } func (m *FlockerVolumeSource) Reset() { *m = FlockerVolumeSource{} } func (*FlockerVolumeSource) ProtoMessage() {} -func (*FlockerVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{53} } +func (*FlockerVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{54} } func (m *GCEPersistentDiskVolumeSource) Reset() { *m = GCEPersistentDiskVolumeSource{} } func (*GCEPersistentDiskVolumeSource) ProtoMessage() {} func (*GCEPersistentDiskVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{54} + return fileDescriptorGenerated, []int{55} } func (m *GitRepoVolumeSource) Reset() { *m = GitRepoVolumeSource{} } func (*GitRepoVolumeSource) ProtoMessage() {} -func (*GitRepoVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{55} } +func (*GitRepoVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{56} } func (m *GlusterfsVolumeSource) Reset() { *m = GlusterfsVolumeSource{} } func (*GlusterfsVolumeSource) ProtoMessage() {} -func (*GlusterfsVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{56} } +func (*GlusterfsVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{57} } func (m *HTTPGetAction) Reset() { *m = HTTPGetAction{} } func (*HTTPGetAction) ProtoMessage() {} -func (*HTTPGetAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{57} } +func (*HTTPGetAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{58} } func (m *HTTPHeader) Reset() { *m = HTTPHeader{} } func (*HTTPHeader) ProtoMessage() {} -func (*HTTPHeader) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{58} } +func (*HTTPHeader) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{59} } func (m *Handler) Reset() { *m = Handler{} } func (*Handler) ProtoMessage() {} -func (*Handler) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{59} } +func (*Handler) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{60} } func (m *HostAlias) Reset() { *m = HostAlias{} } func (*HostAlias) ProtoMessage() {} -func (*HostAlias) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{60} } +func (*HostAlias) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{61} } func (m *HostPathVolumeSource) Reset() { *m = HostPathVolumeSource{} } func (*HostPathVolumeSource) ProtoMessage() {} -func (*HostPathVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{61} } +func (*HostPathVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{62} } func (m *ISCSIPersistentVolumeSource) Reset() { *m = ISCSIPersistentVolumeSource{} } func (*ISCSIPersistentVolumeSource) ProtoMessage() {} func (*ISCSIPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{62} + return fileDescriptorGenerated, []int{63} } func (m *ISCSIVolumeSource) Reset() { *m = ISCSIVolumeSource{} } func (*ISCSIVolumeSource) ProtoMessage() {} -func (*ISCSIVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{63} } +func (*ISCSIVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{64} } func (m *KeyToPath) Reset() { *m = KeyToPath{} } func (*KeyToPath) ProtoMessage() {} -func (*KeyToPath) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{64} } +func (*KeyToPath) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{65} } func (m *Lifecycle) Reset() { *m = Lifecycle{} } func (*Lifecycle) ProtoMessage() {} -func (*Lifecycle) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{65} } +func (*Lifecycle) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{66} } func (m *LimitRange) Reset() { *m = LimitRange{} } func (*LimitRange) ProtoMessage() {} -func (*LimitRange) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{66} } +func (*LimitRange) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{67} } func (m *LimitRangeItem) Reset() { *m = LimitRangeItem{} } func (*LimitRangeItem) ProtoMessage() {} -func (*LimitRangeItem) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{67} } +func (*LimitRangeItem) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{68} } func (m *LimitRangeList) Reset() { *m = LimitRangeList{} } func (*LimitRangeList) ProtoMessage() {} -func (*LimitRangeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{68} } +func (*LimitRangeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{69} } func (m *LimitRangeSpec) Reset() { *m = LimitRangeSpec{} } func (*LimitRangeSpec) ProtoMessage() {} -func (*LimitRangeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{69} } +func (*LimitRangeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{70} } func (m *List) Reset() { *m = List{} } func (*List) ProtoMessage() {} -func (*List) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{70} } +func (*List) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{71} } func (m *LoadBalancerIngress) Reset() { *m = LoadBalancerIngress{} } func (*LoadBalancerIngress) ProtoMessage() {} -func (*LoadBalancerIngress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{71} } +func (*LoadBalancerIngress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{72} } func (m *LoadBalancerStatus) Reset() { *m = LoadBalancerStatus{} } func (*LoadBalancerStatus) ProtoMessage() {} -func (*LoadBalancerStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{72} } +func (*LoadBalancerStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{73} } func (m *LocalObjectReference) Reset() { *m = LocalObjectReference{} } func (*LocalObjectReference) ProtoMessage() {} -func (*LocalObjectReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{73} } +func (*LocalObjectReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{74} } func (m *LocalVolumeSource) Reset() { *m = LocalVolumeSource{} } func (*LocalVolumeSource) ProtoMessage() {} -func (*LocalVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{74} } +func (*LocalVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{75} } func (m *NFSVolumeSource) Reset() { *m = NFSVolumeSource{} } func (*NFSVolumeSource) ProtoMessage() {} -func (*NFSVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{75} } +func (*NFSVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{76} } func (m *Namespace) Reset() { *m = Namespace{} } func (*Namespace) ProtoMessage() {} -func (*Namespace) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{76} } +func (*Namespace) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{77} } func (m *NamespaceList) Reset() { *m = NamespaceList{} } func (*NamespaceList) ProtoMessage() {} -func (*NamespaceList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{77} } +func (*NamespaceList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{78} } func (m *NamespaceSpec) Reset() { *m = NamespaceSpec{} } func (*NamespaceSpec) ProtoMessage() {} -func (*NamespaceSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{78} } +func (*NamespaceSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{79} } func (m *NamespaceStatus) Reset() { *m = NamespaceStatus{} } func (*NamespaceStatus) ProtoMessage() {} -func (*NamespaceStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{79} } +func (*NamespaceStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{80} } func (m *Node) Reset() { *m = Node{} } func (*Node) ProtoMessage() {} -func (*Node) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{80} } +func (*Node) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{81} } func (m *NodeAddress) Reset() { *m = NodeAddress{} } func (*NodeAddress) ProtoMessage() {} -func (*NodeAddress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{81} } +func (*NodeAddress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{82} } func (m *NodeAffinity) Reset() { *m = NodeAffinity{} } func (*NodeAffinity) ProtoMessage() {} -func (*NodeAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{82} } +func (*NodeAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{83} } func (m *NodeCondition) Reset() { *m = NodeCondition{} } func (*NodeCondition) ProtoMessage() {} -func (*NodeCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{83} } +func (*NodeCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{84} } func (m *NodeConfigSource) Reset() { *m = NodeConfigSource{} } func (*NodeConfigSource) ProtoMessage() {} -func (*NodeConfigSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{84} } +func (*NodeConfigSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{85} } func (m *NodeConfigStatus) Reset() { *m = NodeConfigStatus{} } func (*NodeConfigStatus) ProtoMessage() {} -func (*NodeConfigStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{85} } +func (*NodeConfigStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{86} } func (m *NodeDaemonEndpoints) Reset() { *m = NodeDaemonEndpoints{} } func (*NodeDaemonEndpoints) ProtoMessage() {} -func (*NodeDaemonEndpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{86} } +func (*NodeDaemonEndpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{87} } func (m *NodeList) Reset() { *m = NodeList{} } func (*NodeList) ProtoMessage() {} -func (*NodeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{87} } +func (*NodeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{88} } func (m *NodeProxyOptions) Reset() { *m = NodeProxyOptions{} } func (*NodeProxyOptions) ProtoMessage() {} -func (*NodeProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{88} } +func (*NodeProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{89} } func (m *NodeResources) Reset() { *m = NodeResources{} } func (*NodeResources) ProtoMessage() {} -func (*NodeResources) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{89} } +func (*NodeResources) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{90} } func (m *NodeSelector) Reset() { *m = NodeSelector{} } func (*NodeSelector) ProtoMessage() {} -func (*NodeSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{90} } +func (*NodeSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{91} } func (m *NodeSelectorRequirement) Reset() { *m = NodeSelectorRequirement{} } func (*NodeSelectorRequirement) ProtoMessage() {} func (*NodeSelectorRequirement) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{91} + return fileDescriptorGenerated, []int{92} } func (m *NodeSelectorTerm) Reset() { *m = NodeSelectorTerm{} } func (*NodeSelectorTerm) ProtoMessage() {} -func (*NodeSelectorTerm) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{92} } +func (*NodeSelectorTerm) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{93} } func (m *NodeSpec) Reset() { *m = NodeSpec{} } func (*NodeSpec) ProtoMessage() {} -func (*NodeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{93} } +func (*NodeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{94} } func (m *NodeStatus) Reset() { *m = NodeStatus{} } func (*NodeStatus) ProtoMessage() {} -func (*NodeStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{94} } +func (*NodeStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{95} } func (m *NodeSystemInfo) Reset() { *m = NodeSystemInfo{} } func (*NodeSystemInfo) ProtoMessage() {} -func (*NodeSystemInfo) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{95} } +func (*NodeSystemInfo) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{96} } func (m *ObjectFieldSelector) Reset() { *m = ObjectFieldSelector{} } func (*ObjectFieldSelector) ProtoMessage() {} -func (*ObjectFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{96} } +func (*ObjectFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{97} } func (m *ObjectReference) Reset() { *m = ObjectReference{} } func (*ObjectReference) ProtoMessage() {} -func (*ObjectReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{97} } +func (*ObjectReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{98} } func (m *PersistentVolume) Reset() { *m = PersistentVolume{} } func (*PersistentVolume) ProtoMessage() {} -func (*PersistentVolume) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{98} } +func (*PersistentVolume) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{99} } func (m *PersistentVolumeClaim) Reset() { *m = PersistentVolumeClaim{} } func (*PersistentVolumeClaim) ProtoMessage() {} -func (*PersistentVolumeClaim) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{99} } +func (*PersistentVolumeClaim) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{100} } func (m *PersistentVolumeClaimCondition) Reset() { *m = PersistentVolumeClaimCondition{} } func (*PersistentVolumeClaimCondition) ProtoMessage() {} func (*PersistentVolumeClaimCondition) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{100} + return fileDescriptorGenerated, []int{101} } func (m *PersistentVolumeClaimList) Reset() { *m = PersistentVolumeClaimList{} } func (*PersistentVolumeClaimList) ProtoMessage() {} func (*PersistentVolumeClaimList) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{101} + return fileDescriptorGenerated, []int{102} } func (m *PersistentVolumeClaimSpec) Reset() { *m = PersistentVolumeClaimSpec{} } func (*PersistentVolumeClaimSpec) ProtoMessage() {} func (*PersistentVolumeClaimSpec) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{102} + return fileDescriptorGenerated, []int{103} } func (m *PersistentVolumeClaimStatus) Reset() { *m = PersistentVolumeClaimStatus{} } func (*PersistentVolumeClaimStatus) ProtoMessage() {} func (*PersistentVolumeClaimStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{103} + return fileDescriptorGenerated, []int{104} } func (m *PersistentVolumeClaimVolumeSource) Reset() { *m = PersistentVolumeClaimVolumeSource{} } func (*PersistentVolumeClaimVolumeSource) ProtoMessage() {} func (*PersistentVolumeClaimVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{104} + return fileDescriptorGenerated, []int{105} } func (m *PersistentVolumeList) Reset() { *m = PersistentVolumeList{} } func (*PersistentVolumeList) ProtoMessage() {} -func (*PersistentVolumeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{105} } +func (*PersistentVolumeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{106} } func (m *PersistentVolumeSource) Reset() { *m = PersistentVolumeSource{} } func (*PersistentVolumeSource) ProtoMessage() {} func (*PersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{106} + return fileDescriptorGenerated, []int{107} } func (m *PersistentVolumeSpec) Reset() { *m = PersistentVolumeSpec{} } func (*PersistentVolumeSpec) ProtoMessage() {} -func (*PersistentVolumeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{107} } +func (*PersistentVolumeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{108} } func (m *PersistentVolumeStatus) Reset() { *m = PersistentVolumeStatus{} } func (*PersistentVolumeStatus) ProtoMessage() {} func (*PersistentVolumeStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{108} + return fileDescriptorGenerated, []int{109} } func (m *PhotonPersistentDiskVolumeSource) Reset() { *m = PhotonPersistentDiskVolumeSource{} } func (*PhotonPersistentDiskVolumeSource) ProtoMessage() {} func (*PhotonPersistentDiskVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{109} + return fileDescriptorGenerated, []int{110} } func (m *Pod) Reset() { *m = Pod{} } func (*Pod) ProtoMessage() {} -func (*Pod) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{110} } +func (*Pod) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{111} } func (m *PodAffinity) Reset() { *m = PodAffinity{} } func (*PodAffinity) ProtoMessage() {} -func (*PodAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{111} } +func (*PodAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{112} } func (m *PodAffinityTerm) Reset() { *m = PodAffinityTerm{} } func (*PodAffinityTerm) ProtoMessage() {} -func (*PodAffinityTerm) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{112} } +func (*PodAffinityTerm) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{113} } func (m *PodAntiAffinity) Reset() { *m = PodAntiAffinity{} } func (*PodAntiAffinity) ProtoMessage() {} -func (*PodAntiAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{113} } +func (*PodAntiAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{114} } func (m *PodAttachOptions) Reset() { *m = PodAttachOptions{} } func (*PodAttachOptions) ProtoMessage() {} -func (*PodAttachOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{114} } +func (*PodAttachOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{115} } func (m *PodCondition) Reset() { *m = PodCondition{} } func (*PodCondition) ProtoMessage() {} -func (*PodCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{115} } +func (*PodCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{116} } func (m *PodDNSConfig) Reset() { *m = PodDNSConfig{} } func (*PodDNSConfig) ProtoMessage() {} -func (*PodDNSConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{116} } +func (*PodDNSConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{117} } func (m *PodDNSConfigOption) Reset() { *m = PodDNSConfigOption{} } func (*PodDNSConfigOption) ProtoMessage() {} -func (*PodDNSConfigOption) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{117} } +func (*PodDNSConfigOption) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{118} } func (m *PodExecOptions) Reset() { *m = PodExecOptions{} } func (*PodExecOptions) ProtoMessage() {} -func (*PodExecOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{118} } +func (*PodExecOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{119} } func (m *PodList) Reset() { *m = PodList{} } func (*PodList) ProtoMessage() {} -func (*PodList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{119} } +func (*PodList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{120} } func (m *PodLogOptions) Reset() { *m = PodLogOptions{} } func (*PodLogOptions) ProtoMessage() {} -func (*PodLogOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{120} } +func (*PodLogOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{121} } func (m *PodPortForwardOptions) Reset() { *m = PodPortForwardOptions{} } func (*PodPortForwardOptions) ProtoMessage() {} -func (*PodPortForwardOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{121} } +func (*PodPortForwardOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{122} } func (m *PodProxyOptions) Reset() { *m = PodProxyOptions{} } func (*PodProxyOptions) ProtoMessage() {} -func (*PodProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{122} } +func (*PodProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{123} } + +func (m *PodReadinessGate) Reset() { *m = PodReadinessGate{} } +func (*PodReadinessGate) ProtoMessage() {} +func (*PodReadinessGate) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{124} } func (m *PodSecurityContext) Reset() { *m = PodSecurityContext{} } func (*PodSecurityContext) ProtoMessage() {} -func (*PodSecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{123} } +func (*PodSecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{125} } func (m *PodSignature) Reset() { *m = PodSignature{} } func (*PodSignature) ProtoMessage() {} -func (*PodSignature) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{124} } +func (*PodSignature) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{126} } func (m *PodSpec) Reset() { *m = PodSpec{} } func (*PodSpec) ProtoMessage() {} -func (*PodSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{125} } +func (*PodSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{127} } func (m *PodStatus) Reset() { *m = PodStatus{} } func (*PodStatus) ProtoMessage() {} -func (*PodStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{126} } +func (*PodStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{128} } func (m *PodStatusResult) Reset() { *m = PodStatusResult{} } func (*PodStatusResult) ProtoMessage() {} -func (*PodStatusResult) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{127} } +func (*PodStatusResult) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{129} } func (m *PodTemplate) Reset() { *m = PodTemplate{} } func (*PodTemplate) ProtoMessage() {} -func (*PodTemplate) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{128} } +func (*PodTemplate) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{130} } func (m *PodTemplateList) Reset() { *m = PodTemplateList{} } func (*PodTemplateList) ProtoMessage() {} -func (*PodTemplateList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{129} } +func (*PodTemplateList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{131} } func (m *PodTemplateSpec) Reset() { *m = PodTemplateSpec{} } func (*PodTemplateSpec) ProtoMessage() {} -func (*PodTemplateSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{130} } +func (*PodTemplateSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{132} } func (m *PortworxVolumeSource) Reset() { *m = PortworxVolumeSource{} } func (*PortworxVolumeSource) ProtoMessage() {} -func (*PortworxVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{131} } +func (*PortworxVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{133} } func (m *Preconditions) Reset() { *m = Preconditions{} } func (*Preconditions) ProtoMessage() {} -func (*Preconditions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{132} } +func (*Preconditions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{134} } func (m *PreferAvoidPodsEntry) Reset() { *m = PreferAvoidPodsEntry{} } func (*PreferAvoidPodsEntry) ProtoMessage() {} -func (*PreferAvoidPodsEntry) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{133} } +func (*PreferAvoidPodsEntry) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{135} } func (m *PreferredSchedulingTerm) Reset() { *m = PreferredSchedulingTerm{} } func (*PreferredSchedulingTerm) ProtoMessage() {} func (*PreferredSchedulingTerm) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{134} + return fileDescriptorGenerated, []int{136} } func (m *Probe) Reset() { *m = Probe{} } func (*Probe) ProtoMessage() {} -func (*Probe) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{135} } +func (*Probe) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{137} } func (m *ProjectedVolumeSource) Reset() { *m = ProjectedVolumeSource{} } func (*ProjectedVolumeSource) ProtoMessage() {} -func (*ProjectedVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{136} } +func (*ProjectedVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{138} } func (m *QuobyteVolumeSource) Reset() { *m = QuobyteVolumeSource{} } func (*QuobyteVolumeSource) ProtoMessage() {} -func (*QuobyteVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{137} } +func (*QuobyteVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{139} } func (m *RBDPersistentVolumeSource) Reset() { *m = RBDPersistentVolumeSource{} } func (*RBDPersistentVolumeSource) ProtoMessage() {} func (*RBDPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{138} + return fileDescriptorGenerated, []int{140} } func (m *RBDVolumeSource) Reset() { *m = RBDVolumeSource{} } func (*RBDVolumeSource) ProtoMessage() {} -func (*RBDVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{139} } +func (*RBDVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{141} } func (m *RangeAllocation) Reset() { *m = RangeAllocation{} } func (*RangeAllocation) ProtoMessage() {} -func (*RangeAllocation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{140} } +func (*RangeAllocation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{142} } func (m *ReplicationController) Reset() { *m = ReplicationController{} } func (*ReplicationController) ProtoMessage() {} -func (*ReplicationController) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{141} } +func (*ReplicationController) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{143} } func (m *ReplicationControllerCondition) Reset() { *m = ReplicationControllerCondition{} } func (*ReplicationControllerCondition) ProtoMessage() {} func (*ReplicationControllerCondition) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{142} + return fileDescriptorGenerated, []int{144} } func (m *ReplicationControllerList) Reset() { *m = ReplicationControllerList{} } func (*ReplicationControllerList) ProtoMessage() {} func (*ReplicationControllerList) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{143} + return fileDescriptorGenerated, []int{145} } func (m *ReplicationControllerSpec) Reset() { *m = ReplicationControllerSpec{} } func (*ReplicationControllerSpec) ProtoMessage() {} func (*ReplicationControllerSpec) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{144} + return fileDescriptorGenerated, []int{146} } func (m *ReplicationControllerStatus) Reset() { *m = ReplicationControllerStatus{} } func (*ReplicationControllerStatus) ProtoMessage() {} func (*ReplicationControllerStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{145} + return fileDescriptorGenerated, []int{147} } func (m *ResourceFieldSelector) Reset() { *m = ResourceFieldSelector{} } func (*ResourceFieldSelector) ProtoMessage() {} -func (*ResourceFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{146} } +func (*ResourceFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{148} } func (m *ResourceQuota) Reset() { *m = ResourceQuota{} } func (*ResourceQuota) ProtoMessage() {} -func (*ResourceQuota) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{147} } +func (*ResourceQuota) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{149} } func (m *ResourceQuotaList) Reset() { *m = ResourceQuotaList{} } func (*ResourceQuotaList) ProtoMessage() {} -func (*ResourceQuotaList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{148} } +func (*ResourceQuotaList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{150} } func (m *ResourceQuotaSpec) Reset() { *m = ResourceQuotaSpec{} } func (*ResourceQuotaSpec) ProtoMessage() {} -func (*ResourceQuotaSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{149} } +func (*ResourceQuotaSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{151} } func (m *ResourceQuotaStatus) Reset() { *m = ResourceQuotaStatus{} } func (*ResourceQuotaStatus) ProtoMessage() {} -func (*ResourceQuotaStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{150} } +func (*ResourceQuotaStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{152} } func (m *ResourceRequirements) Reset() { *m = ResourceRequirements{} } func (*ResourceRequirements) ProtoMessage() {} -func (*ResourceRequirements) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{151} } +func (*ResourceRequirements) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{153} } func (m *SELinuxOptions) Reset() { *m = SELinuxOptions{} } func (*SELinuxOptions) ProtoMessage() {} -func (*SELinuxOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{152} } +func (*SELinuxOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{154} } func (m *ScaleIOPersistentVolumeSource) Reset() { *m = ScaleIOPersistentVolumeSource{} } func (*ScaleIOPersistentVolumeSource) ProtoMessage() {} func (*ScaleIOPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{153} + return fileDescriptorGenerated, []int{155} } func (m *ScaleIOVolumeSource) Reset() { *m = ScaleIOVolumeSource{} } func (*ScaleIOVolumeSource) ProtoMessage() {} -func (*ScaleIOVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{154} } +func (*ScaleIOVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{156} } + +func (m *ScopeSelector) Reset() { *m = ScopeSelector{} } +func (*ScopeSelector) ProtoMessage() {} +func (*ScopeSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{157} } + +func (m *ScopedResourceSelectorRequirement) Reset() { *m = ScopedResourceSelectorRequirement{} } +func (*ScopedResourceSelectorRequirement) ProtoMessage() {} +func (*ScopedResourceSelectorRequirement) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{158} +} func (m *Secret) Reset() { *m = Secret{} } func (*Secret) ProtoMessage() {} -func (*Secret) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{155} } +func (*Secret) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{159} } func (m *SecretEnvSource) Reset() { *m = SecretEnvSource{} } func (*SecretEnvSource) ProtoMessage() {} -func (*SecretEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{156} } +func (*SecretEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{160} } func (m *SecretKeySelector) Reset() { *m = SecretKeySelector{} } func (*SecretKeySelector) ProtoMessage() {} -func (*SecretKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{157} } +func (*SecretKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{161} } func (m *SecretList) Reset() { *m = SecretList{} } func (*SecretList) ProtoMessage() {} -func (*SecretList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{158} } +func (*SecretList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{162} } func (m *SecretProjection) Reset() { *m = SecretProjection{} } func (*SecretProjection) ProtoMessage() {} -func (*SecretProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{159} } +func (*SecretProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{163} } func (m *SecretReference) Reset() { *m = SecretReference{} } func (*SecretReference) ProtoMessage() {} -func (*SecretReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{160} } +func (*SecretReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{164} } func (m *SecretVolumeSource) Reset() { *m = SecretVolumeSource{} } func (*SecretVolumeSource) ProtoMessage() {} -func (*SecretVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{161} } +func (*SecretVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{165} } func (m *SecurityContext) Reset() { *m = SecurityContext{} } func (*SecurityContext) ProtoMessage() {} -func (*SecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{162} } +func (*SecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{166} } func (m *SerializedReference) Reset() { *m = SerializedReference{} } func (*SerializedReference) ProtoMessage() {} -func (*SerializedReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{163} } +func (*SerializedReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{167} } func (m *Service) Reset() { *m = Service{} } func (*Service) ProtoMessage() {} -func (*Service) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{164} } +func (*Service) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{168} } func (m *ServiceAccount) Reset() { *m = ServiceAccount{} } func (*ServiceAccount) ProtoMessage() {} -func (*ServiceAccount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{165} } +func (*ServiceAccount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{169} } func (m *ServiceAccountList) Reset() { *m = ServiceAccountList{} } func (*ServiceAccountList) ProtoMessage() {} -func (*ServiceAccountList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{166} } +func (*ServiceAccountList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{170} } + +func (m *ServiceAccountTokenProjection) Reset() { *m = ServiceAccountTokenProjection{} } +func (*ServiceAccountTokenProjection) ProtoMessage() {} +func (*ServiceAccountTokenProjection) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{171} +} func (m *ServiceList) Reset() { *m = ServiceList{} } func (*ServiceList) ProtoMessage() {} -func (*ServiceList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{167} } +func (*ServiceList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{172} } func (m *ServicePort) Reset() { *m = ServicePort{} } func (*ServicePort) ProtoMessage() {} -func (*ServicePort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{168} } +func (*ServicePort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{173} } func (m *ServiceProxyOptions) Reset() { *m = ServiceProxyOptions{} } func (*ServiceProxyOptions) ProtoMessage() {} -func (*ServiceProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{169} } +func (*ServiceProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{174} } func (m *ServiceSpec) Reset() { *m = ServiceSpec{} } func (*ServiceSpec) ProtoMessage() {} -func (*ServiceSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{170} } +func (*ServiceSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{175} } func (m *ServiceStatus) Reset() { *m = ServiceStatus{} } func (*ServiceStatus) ProtoMessage() {} -func (*ServiceStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{171} } +func (*ServiceStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{176} } func (m *SessionAffinityConfig) Reset() { *m = SessionAffinityConfig{} } func (*SessionAffinityConfig) ProtoMessage() {} -func (*SessionAffinityConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{172} } +func (*SessionAffinityConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{177} } func (m *StorageOSPersistentVolumeSource) Reset() { *m = StorageOSPersistentVolumeSource{} } func (*StorageOSPersistentVolumeSource) ProtoMessage() {} func (*StorageOSPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{173} + return fileDescriptorGenerated, []int{178} } func (m *StorageOSVolumeSource) Reset() { *m = StorageOSVolumeSource{} } func (*StorageOSVolumeSource) ProtoMessage() {} -func (*StorageOSVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{174} } +func (*StorageOSVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{179} } func (m *Sysctl) Reset() { *m = Sysctl{} } func (*Sysctl) ProtoMessage() {} -func (*Sysctl) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{175} } +func (*Sysctl) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{180} } func (m *TCPSocketAction) Reset() { *m = TCPSocketAction{} } func (*TCPSocketAction) ProtoMessage() {} -func (*TCPSocketAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{176} } +func (*TCPSocketAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{181} } func (m *Taint) Reset() { *m = Taint{} } func (*Taint) ProtoMessage() {} -func (*Taint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{177} } +func (*Taint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{182} } func (m *Toleration) Reset() { *m = Toleration{} } func (*Toleration) ProtoMessage() {} -func (*Toleration) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{178} } +func (*Toleration) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{183} } + +func (m *TopologySelectorLabelRequirement) Reset() { *m = TopologySelectorLabelRequirement{} } +func (*TopologySelectorLabelRequirement) ProtoMessage() {} +func (*TopologySelectorLabelRequirement) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{184} +} + +func (m *TopologySelectorTerm) Reset() { *m = TopologySelectorTerm{} } +func (*TopologySelectorTerm) ProtoMessage() {} +func (*TopologySelectorTerm) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{185} } func (m *Volume) Reset() { *m = Volume{} } func (*Volume) ProtoMessage() {} -func (*Volume) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{179} } +func (*Volume) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{186} } func (m *VolumeDevice) Reset() { *m = VolumeDevice{} } func (*VolumeDevice) ProtoMessage() {} -func (*VolumeDevice) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{180} } +func (*VolumeDevice) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{187} } func (m *VolumeMount) Reset() { *m = VolumeMount{} } func (*VolumeMount) ProtoMessage() {} -func (*VolumeMount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{181} } +func (*VolumeMount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{188} } func (m *VolumeNodeAffinity) Reset() { *m = VolumeNodeAffinity{} } func (*VolumeNodeAffinity) ProtoMessage() {} -func (*VolumeNodeAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{182} } +func (*VolumeNodeAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{189} } func (m *VolumeProjection) Reset() { *m = VolumeProjection{} } func (*VolumeProjection) ProtoMessage() {} -func (*VolumeProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{183} } +func (*VolumeProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{190} } func (m *VolumeSource) Reset() { *m = VolumeSource{} } func (*VolumeSource) ProtoMessage() {} -func (*VolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{184} } +func (*VolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{191} } func (m *VsphereVirtualDiskVolumeSource) Reset() { *m = VsphereVirtualDiskVolumeSource{} } func (*VsphereVirtualDiskVolumeSource) ProtoMessage() {} func (*VsphereVirtualDiskVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{185} + return fileDescriptorGenerated, []int{192} } func (m *WeightedPodAffinityTerm) Reset() { *m = WeightedPodAffinityTerm{} } func (*WeightedPodAffinityTerm) ProtoMessage() {} func (*WeightedPodAffinityTerm) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{186} + return fileDescriptorGenerated, []int{193} } func init() { @@ -1062,6 +1105,7 @@ func init() { proto.RegisterType((*Capabilities)(nil), "k8s.io.api.core.v1.Capabilities") proto.RegisterType((*CephFSPersistentVolumeSource)(nil), "k8s.io.api.core.v1.CephFSPersistentVolumeSource") proto.RegisterType((*CephFSVolumeSource)(nil), "k8s.io.api.core.v1.CephFSVolumeSource") + proto.RegisterType((*CinderPersistentVolumeSource)(nil), "k8s.io.api.core.v1.CinderPersistentVolumeSource") proto.RegisterType((*CinderVolumeSource)(nil), "k8s.io.api.core.v1.CinderVolumeSource") proto.RegisterType((*ClientIPConfig)(nil), "k8s.io.api.core.v1.ClientIPConfig") proto.RegisterType((*ComponentCondition)(nil), "k8s.io.api.core.v1.ComponentCondition") @@ -1173,6 +1217,7 @@ func init() { proto.RegisterType((*PodLogOptions)(nil), "k8s.io.api.core.v1.PodLogOptions") proto.RegisterType((*PodPortForwardOptions)(nil), "k8s.io.api.core.v1.PodPortForwardOptions") proto.RegisterType((*PodProxyOptions)(nil), "k8s.io.api.core.v1.PodProxyOptions") + proto.RegisterType((*PodReadinessGate)(nil), "k8s.io.api.core.v1.PodReadinessGate") proto.RegisterType((*PodSecurityContext)(nil), "k8s.io.api.core.v1.PodSecurityContext") proto.RegisterType((*PodSignature)(nil), "k8s.io.api.core.v1.PodSignature") proto.RegisterType((*PodSpec)(nil), "k8s.io.api.core.v1.PodSpec") @@ -1205,6 +1250,8 @@ func init() { proto.RegisterType((*SELinuxOptions)(nil), "k8s.io.api.core.v1.SELinuxOptions") proto.RegisterType((*ScaleIOPersistentVolumeSource)(nil), "k8s.io.api.core.v1.ScaleIOPersistentVolumeSource") proto.RegisterType((*ScaleIOVolumeSource)(nil), "k8s.io.api.core.v1.ScaleIOVolumeSource") + proto.RegisterType((*ScopeSelector)(nil), "k8s.io.api.core.v1.ScopeSelector") + proto.RegisterType((*ScopedResourceSelectorRequirement)(nil), "k8s.io.api.core.v1.ScopedResourceSelectorRequirement") proto.RegisterType((*Secret)(nil), "k8s.io.api.core.v1.Secret") proto.RegisterType((*SecretEnvSource)(nil), "k8s.io.api.core.v1.SecretEnvSource") proto.RegisterType((*SecretKeySelector)(nil), "k8s.io.api.core.v1.SecretKeySelector") @@ -1217,6 +1264,7 @@ func init() { proto.RegisterType((*Service)(nil), "k8s.io.api.core.v1.Service") proto.RegisterType((*ServiceAccount)(nil), "k8s.io.api.core.v1.ServiceAccount") proto.RegisterType((*ServiceAccountList)(nil), "k8s.io.api.core.v1.ServiceAccountList") + proto.RegisterType((*ServiceAccountTokenProjection)(nil), "k8s.io.api.core.v1.ServiceAccountTokenProjection") proto.RegisterType((*ServiceList)(nil), "k8s.io.api.core.v1.ServiceList") proto.RegisterType((*ServicePort)(nil), "k8s.io.api.core.v1.ServicePort") proto.RegisterType((*ServiceProxyOptions)(nil), "k8s.io.api.core.v1.ServiceProxyOptions") @@ -1229,6 +1277,8 @@ func init() { proto.RegisterType((*TCPSocketAction)(nil), "k8s.io.api.core.v1.TCPSocketAction") proto.RegisterType((*Taint)(nil), "k8s.io.api.core.v1.Taint") proto.RegisterType((*Toleration)(nil), "k8s.io.api.core.v1.Toleration") + proto.RegisterType((*TopologySelectorLabelRequirement)(nil), "k8s.io.api.core.v1.TopologySelectorLabelRequirement") + proto.RegisterType((*TopologySelectorTerm)(nil), "k8s.io.api.core.v1.TopologySelectorTerm") proto.RegisterType((*Volume)(nil), "k8s.io.api.core.v1.Volume") proto.RegisterType((*VolumeDevice)(nil), "k8s.io.api.core.v1.VolumeDevice") proto.RegisterType((*VolumeMount)(nil), "k8s.io.api.core.v1.VolumeMount") @@ -1805,6 +1855,50 @@ func (m *CephFSVolumeSource) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *CinderPersistentVolumeSource) 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 *CinderPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.VolumeID))) + i += copy(dAtA[i:], m.VolumeID) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.FSType))) + i += copy(dAtA[i:], m.FSType) + dAtA[i] = 0x18 + i++ + if m.ReadOnly { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + if m.SecretRef != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) + n11, err := m.SecretRef.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n11 + } + return i, nil +} + func (m *CinderVolumeSource) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1836,6 +1930,16 @@ func (m *CinderVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0 } i++ + if m.SecretRef != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) + n12, err := m.SecretRef.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n12 + } return i, nil } @@ -1914,11 +2018,11 @@ func (m *ComponentStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n11, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n13, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n11 + i += n13 if len(m.Conditions) > 0 { for _, msg := range m.Conditions { dAtA[i] = 0x12 @@ -1952,11 +2056,11 @@ func (m *ComponentStatusList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n12, err := m.ListMeta.MarshalTo(dAtA[i:]) + n14, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n12 + i += n14 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -1990,11 +2094,11 @@ func (m *ConfigMap) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n13, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n15, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n13 + i += n15 if len(m.Data) > 0 { keysForData := make([]string, 0, len(m.Data)) for k := range m.Data { @@ -2066,11 +2170,11 @@ func (m *ConfigMapEnvSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n14, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n16, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n14 + i += n16 if m.Optional != nil { dAtA[i] = 0x10 i++ @@ -2102,11 +2206,11 @@ func (m *ConfigMapKeySelector) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n15, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n17, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n15 + i += n17 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key))) @@ -2142,11 +2246,11 @@ func (m *ConfigMapList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n16, err := m.ListMeta.MarshalTo(dAtA[i:]) + n18, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n16 + i += n18 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -2218,11 +2322,11 @@ func (m *ConfigMapProjection) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n17, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n19, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n17 + i += n19 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -2266,11 +2370,11 @@ func (m *ConfigMapVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n18, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n20, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n18 + i += n20 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -2385,11 +2489,11 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x42 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Resources.Size())) - n19, err := m.Resources.MarshalTo(dAtA[i:]) + n21, err := m.Resources.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n19 + i += n21 if len(m.VolumeMounts) > 0 { for _, msg := range m.VolumeMounts { dAtA[i] = 0x4a @@ -2406,31 +2510,31 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LivenessProbe.Size())) - n20, err := m.LivenessProbe.MarshalTo(dAtA[i:]) + n22, err := m.LivenessProbe.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n20 + i += n22 } if m.ReadinessProbe != nil { dAtA[i] = 0x5a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ReadinessProbe.Size())) - n21, err := m.ReadinessProbe.MarshalTo(dAtA[i:]) + n23, err := m.ReadinessProbe.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n21 + i += n23 } if m.Lifecycle != nil { dAtA[i] = 0x62 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Lifecycle.Size())) - n22, err := m.Lifecycle.MarshalTo(dAtA[i:]) + n24, err := m.Lifecycle.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n22 + i += n24 } dAtA[i] = 0x6a i++ @@ -2444,11 +2548,11 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x7a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecurityContext.Size())) - n23, err := m.SecurityContext.MarshalTo(dAtA[i:]) + n25, err := m.SecurityContext.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n23 + i += n25 } dAtA[i] = 0x80 i++ @@ -2608,31 +2712,31 @@ func (m *ContainerState) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Waiting.Size())) - n24, err := m.Waiting.MarshalTo(dAtA[i:]) + n26, err := m.Waiting.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n24 + i += n26 } if m.Running != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Running.Size())) - n25, err := m.Running.MarshalTo(dAtA[i:]) + n27, err := m.Running.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n25 + i += n27 } if m.Terminated != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Terminated.Size())) - n26, err := m.Terminated.MarshalTo(dAtA[i:]) + n28, err := m.Terminated.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n26 + i += n28 } return i, nil } @@ -2655,11 +2759,11 @@ func (m *ContainerStateRunning) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StartedAt.Size())) - n27, err := m.StartedAt.MarshalTo(dAtA[i:]) + n29, err := m.StartedAt.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n27 + i += n29 return i, nil } @@ -2695,19 +2799,19 @@ func (m *ContainerStateTerminated) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StartedAt.Size())) - n28, err := m.StartedAt.MarshalTo(dAtA[i:]) + n30, err := m.StartedAt.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n28 + i += n30 dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FinishedAt.Size())) - n29, err := m.FinishedAt.MarshalTo(dAtA[i:]) + n31, err := m.FinishedAt.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n29 + i += n31 dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.ContainerID))) @@ -2763,19 +2867,19 @@ func (m *ContainerStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.State.Size())) - n30, err := m.State.MarshalTo(dAtA[i:]) + n32, err := m.State.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n30 + i += n32 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTerminationState.Size())) - n31, err := m.LastTerminationState.MarshalTo(dAtA[i:]) + n33, err := m.LastTerminationState.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n31 + i += n33 dAtA[i] = 0x20 i++ if m.Ready { @@ -2876,21 +2980,21 @@ func (m *DownwardAPIVolumeFile) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FieldRef.Size())) - n32, err := m.FieldRef.MarshalTo(dAtA[i:]) + n34, err := m.FieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n32 + i += n34 } if m.ResourceFieldRef != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ResourceFieldRef.Size())) - n33, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) + n35, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n33 + i += n35 } if m.Mode != nil { dAtA[i] = 0x20 @@ -2958,11 +3062,11 @@ func (m *EmptyDirVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SizeLimit.Size())) - n34, err := m.SizeLimit.MarshalTo(dAtA[i:]) + n36, err := m.SizeLimit.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n34 + i += n36 } return i, nil } @@ -2990,11 +3094,11 @@ func (m *EndpointAddress) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TargetRef.Size())) - n35, err := m.TargetRef.MarshalTo(dAtA[i:]) + n37, err := m.TargetRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n35 + i += n37 } dAtA[i] = 0x1a i++ @@ -3110,11 +3214,11 @@ func (m *Endpoints) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n36, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n38, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n36 + i += n38 if len(m.Subsets) > 0 { for _, msg := range m.Subsets { dAtA[i] = 0x12 @@ -3148,11 +3252,11 @@ func (m *EndpointsList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n37, err := m.ListMeta.MarshalTo(dAtA[i:]) + n39, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n37 + i += n39 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -3191,21 +3295,21 @@ func (m *EnvFromSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMapRef.Size())) - n38, err := m.ConfigMapRef.MarshalTo(dAtA[i:]) + n40, err := m.ConfigMapRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n38 + i += n40 } if m.SecretRef != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n39, err := m.SecretRef.MarshalTo(dAtA[i:]) + n41, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n39 + i += n41 } return i, nil } @@ -3237,11 +3341,11 @@ func (m *EnvVar) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ValueFrom.Size())) - n40, err := m.ValueFrom.MarshalTo(dAtA[i:]) + n42, err := m.ValueFrom.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n40 + i += n42 } return i, nil } @@ -3265,42 +3369,42 @@ func (m *EnvVarSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FieldRef.Size())) - n41, err := m.FieldRef.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n41 - } - if m.ResourceFieldRef != nil { - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.ResourceFieldRef.Size())) - n42, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n42 - } - if m.ConfigMapKeyRef != nil { - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMapKeyRef.Size())) - n43, err := m.ConfigMapKeyRef.MarshalTo(dAtA[i:]) + n43, err := m.FieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n43 } - if m.SecretKeyRef != nil { - dAtA[i] = 0x22 + if m.ResourceFieldRef != nil { + dAtA[i] = 0x12 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.SecretKeyRef.Size())) - n44, err := m.SecretKeyRef.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.ResourceFieldRef.Size())) + n44, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n44 } + if m.ConfigMapKeyRef != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMapKeyRef.Size())) + n45, err := m.ConfigMapKeyRef.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n45 + } + if m.SecretKeyRef != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.SecretKeyRef.Size())) + n46, err := m.SecretKeyRef.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n46 + } return i, nil } @@ -3322,19 +3426,19 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n45, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n47, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n45 + i += n47 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.InvolvedObject.Size())) - n46, err := m.InvolvedObject.MarshalTo(dAtA[i:]) + n48, err := m.InvolvedObject.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n46 + i += n48 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -3346,27 +3450,27 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Source.Size())) - n47, err := m.Source.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n47 - dAtA[i] = 0x32 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.FirstTimestamp.Size())) - n48, err := m.FirstTimestamp.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n48 - dAtA[i] = 0x3a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.LastTimestamp.Size())) - n49, err := m.LastTimestamp.MarshalTo(dAtA[i:]) + n49, err := m.Source.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n49 + dAtA[i] = 0x32 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.FirstTimestamp.Size())) + n50, err := m.FirstTimestamp.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n50 + dAtA[i] = 0x3a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.LastTimestamp.Size())) + n51, err := m.LastTimestamp.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n51 dAtA[i] = 0x40 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Count)) @@ -3377,20 +3481,20 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.EventTime.Size())) - n50, err := m.EventTime.MarshalTo(dAtA[i:]) + n52, err := m.EventTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n50 + i += n52 if m.Series != nil { dAtA[i] = 0x5a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Series.Size())) - n51, err := m.Series.MarshalTo(dAtA[i:]) + n53, err := m.Series.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n51 + i += n53 } dAtA[i] = 0x62 i++ @@ -3400,11 +3504,11 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x6a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Related.Size())) - n52, err := m.Related.MarshalTo(dAtA[i:]) + n54, err := m.Related.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n52 + i += n54 } dAtA[i] = 0x72 i++ @@ -3435,11 +3539,11 @@ func (m *EventList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n53, err := m.ListMeta.MarshalTo(dAtA[i:]) + n55, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n53 + i += n55 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -3476,11 +3580,11 @@ func (m *EventSeries) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastObservedTime.Size())) - n54, err := m.LastObservedTime.MarshalTo(dAtA[i:]) + n56, err := m.LastObservedTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n54 + i += n56 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.State))) @@ -3639,11 +3743,11 @@ func (m *FlexPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n55, err := m.SecretRef.MarshalTo(dAtA[i:]) + n57, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n55 + i += n57 } dAtA[i] = 0x20 i++ @@ -3705,11 +3809,11 @@ func (m *FlexVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n56, err := m.SecretRef.MarshalTo(dAtA[i:]) + n58, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n56 + i += n58 } dAtA[i] = 0x20 i++ @@ -3893,11 +3997,11 @@ func (m *HTTPGetAction) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Port.Size())) - n57, err := m.Port.MarshalTo(dAtA[i:]) + n59, err := m.Port.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n57 + i += n59 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Host))) @@ -3966,31 +4070,31 @@ func (m *Handler) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Exec.Size())) - n58, err := m.Exec.MarshalTo(dAtA[i:]) + n60, err := m.Exec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n58 + i += n60 } if m.HTTPGet != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.HTTPGet.Size())) - n59, err := m.HTTPGet.MarshalTo(dAtA[i:]) + n61, err := m.HTTPGet.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n59 + i += n61 } if m.TCPSocket != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TCPSocket.Size())) - n60, err := m.TCPSocket.MarshalTo(dAtA[i:]) + n62, err := m.TCPSocket.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n60 + i += n62 } return i, nil } @@ -4129,11 +4233,11 @@ func (m *ISCSIPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n61, err := m.SecretRef.MarshalTo(dAtA[i:]) + n63, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n61 + i += n63 } dAtA[i] = 0x58 i++ @@ -4221,11 +4325,11 @@ func (m *ISCSIVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n62, err := m.SecretRef.MarshalTo(dAtA[i:]) + n64, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n62 + i += n64 } dAtA[i] = 0x58 i++ @@ -4294,21 +4398,21 @@ func (m *Lifecycle) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PostStart.Size())) - n63, err := m.PostStart.MarshalTo(dAtA[i:]) + n65, err := m.PostStart.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n63 + i += n65 } if m.PreStop != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PreStop.Size())) - n64, err := m.PreStop.MarshalTo(dAtA[i:]) + n66, err := m.PreStop.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n64 + i += n66 } return i, nil } @@ -4331,19 +4435,19 @@ func (m *LimitRange) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n65, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n67, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n65 + i += n67 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n66, err := m.Spec.MarshalTo(dAtA[i:]) + n68, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n66 + i += n68 return i, nil } @@ -4390,11 +4494,11 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n67, err := (&v).MarshalTo(dAtA[i:]) + n69, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n67 + i += n69 } } if len(m.Min) > 0 { @@ -4421,11 +4525,11 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n68, err := (&v).MarshalTo(dAtA[i:]) + n70, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n68 + i += n70 } } if len(m.Default) > 0 { @@ -4452,11 +4556,11 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n69, err := (&v).MarshalTo(dAtA[i:]) + n71, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n69 + i += n71 } } if len(m.DefaultRequest) > 0 { @@ -4483,11 +4587,11 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n70, err := (&v).MarshalTo(dAtA[i:]) + n72, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n70 + i += n72 } } if len(m.MaxLimitRequestRatio) > 0 { @@ -4514,11 +4618,11 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n71, err := (&v).MarshalTo(dAtA[i:]) + n73, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n71 + i += n73 } } return i, nil @@ -4542,11 +4646,11 @@ func (m *LimitRangeList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n72, err := m.ListMeta.MarshalTo(dAtA[i:]) + n74, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n72 + i += n74 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -4610,11 +4714,11 @@ func (m *List) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n73, err := m.ListMeta.MarshalTo(dAtA[i:]) + n75, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n73 + i += n75 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -4782,27 +4886,27 @@ func (m *Namespace) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n74, err := m.ObjectMeta.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n74 - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n75, err := m.Spec.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n75 - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n76, err := m.Status.MarshalTo(dAtA[i:]) + n76, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n76 + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) + n77, err := m.Spec.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n77 + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) + n78, err := m.Status.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n78 return i, nil } @@ -4824,11 +4928,11 @@ func (m *NamespaceList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n77, err := m.ListMeta.MarshalTo(dAtA[i:]) + n79, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n77 + i += n79 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -4917,27 +5021,27 @@ func (m *Node) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n78, err := m.ObjectMeta.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n78 - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n79, err := m.Spec.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n79 - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n80, err := m.Status.MarshalTo(dAtA[i:]) + n80, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n80 + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) + n81, err := m.Spec.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n81 + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) + n82, err := m.Status.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n82 return i, nil } @@ -4986,11 +5090,11 @@ func (m *NodeAffinity) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.RequiredDuringSchedulingIgnoredDuringExecution.Size())) - n81, err := m.RequiredDuringSchedulingIgnoredDuringExecution.MarshalTo(dAtA[i:]) + n83, err := m.RequiredDuringSchedulingIgnoredDuringExecution.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n81 + i += n83 } if len(m.PreferredDuringSchedulingIgnoredDuringExecution) > 0 { for _, msg := range m.PreferredDuringSchedulingIgnoredDuringExecution { @@ -5033,19 +5137,19 @@ func (m *NodeCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastHeartbeatTime.Size())) - n82, err := m.LastHeartbeatTime.MarshalTo(dAtA[i:]) + n84, err := m.LastHeartbeatTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n82 + i += n84 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n83, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n85, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n83 + i += n85 dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -5076,11 +5180,11 @@ func (m *NodeConfigSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMap.Size())) - n84, err := m.ConfigMap.MarshalTo(dAtA[i:]) + n86, err := m.ConfigMap.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n84 + i += n86 } return i, nil } @@ -5104,31 +5208,31 @@ func (m *NodeConfigStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Assigned.Size())) - n85, err := m.Assigned.MarshalTo(dAtA[i:]) + n87, err := m.Assigned.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n85 + i += n87 } if m.Active != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Active.Size())) - n86, err := m.Active.MarshalTo(dAtA[i:]) + n88, err := m.Active.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n86 + i += n88 } if m.LastKnownGood != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastKnownGood.Size())) - n87, err := m.LastKnownGood.MarshalTo(dAtA[i:]) + n89, err := m.LastKnownGood.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n87 + i += n89 } dAtA[i] = 0x22 i++ @@ -5155,11 +5259,11 @@ func (m *NodeDaemonEndpoints) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.KubeletEndpoint.Size())) - n88, err := m.KubeletEndpoint.MarshalTo(dAtA[i:]) + n90, err := m.KubeletEndpoint.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n88 + i += n90 return i, nil } @@ -5181,11 +5285,11 @@ func (m *NodeList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n89, err := m.ListMeta.MarshalTo(dAtA[i:]) + n91, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n89 + i += n91 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -5262,11 +5366,11 @@ func (m *NodeResources) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n90, err := (&v).MarshalTo(dAtA[i:]) + n92, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n90 + i += n92 } } return i, nil @@ -5436,11 +5540,11 @@ func (m *NodeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigSource.Size())) - n91, err := m.ConfigSource.MarshalTo(dAtA[i:]) + n93, err := m.ConfigSource.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n91 + i += n93 } return i, nil } @@ -5484,11 +5588,11 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n92, err := (&v).MarshalTo(dAtA[i:]) + n94, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n92 + i += n94 } } if len(m.Allocatable) > 0 { @@ -5515,11 +5619,11 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n93, err := (&v).MarshalTo(dAtA[i:]) + n95, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n93 + i += n95 } } dAtA[i] = 0x1a @@ -5553,19 +5657,19 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DaemonEndpoints.Size())) - n94, err := m.DaemonEndpoints.MarshalTo(dAtA[i:]) + n96, err := m.DaemonEndpoints.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n94 + i += n96 dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NodeInfo.Size())) - n95, err := m.NodeInfo.MarshalTo(dAtA[i:]) + n97, err := m.NodeInfo.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n95 + i += n97 if len(m.Images) > 0 { for _, msg := range m.Images { dAtA[i] = 0x42 @@ -5609,11 +5713,11 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x5a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Config.Size())) - n96, err := m.Config.MarshalTo(dAtA[i:]) + n98, err := m.Config.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n96 + i += n98 } return i, nil } @@ -5766,27 +5870,27 @@ func (m *PersistentVolume) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n97, err := m.ObjectMeta.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n97 - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n98, err := m.Spec.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n98 - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n99, err := m.Status.MarshalTo(dAtA[i:]) + n99, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n99 + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) + n100, err := m.Spec.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n100 + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) + n101, err := m.Status.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n101 return i, nil } @@ -5808,27 +5912,27 @@ func (m *PersistentVolumeClaim) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n100, err := m.ObjectMeta.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n100 - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n101, err := m.Spec.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n101 - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n102, err := m.Status.MarshalTo(dAtA[i:]) + n102, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n102 + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) + n103, err := m.Spec.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n103 + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) + n104, err := m.Status.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n104 return i, nil } @@ -5858,19 +5962,19 @@ func (m *PersistentVolumeClaimCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastProbeTime.Size())) - n103, err := m.LastProbeTime.MarshalTo(dAtA[i:]) + n105, err := m.LastProbeTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n103 + i += n105 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n104, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n106, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n104 + i += n106 dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -5900,11 +6004,11 @@ func (m *PersistentVolumeClaimList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n105, err := m.ListMeta.MarshalTo(dAtA[i:]) + n107, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n105 + i += n107 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -5953,11 +6057,11 @@ func (m *PersistentVolumeClaimSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Resources.Size())) - n106, err := m.Resources.MarshalTo(dAtA[i:]) + n108, err := m.Resources.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n106 + i += n108 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.VolumeName))) @@ -5966,11 +6070,11 @@ func (m *PersistentVolumeClaimSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Selector.Size())) - n107, err := m.Selector.MarshalTo(dAtA[i:]) + n109, err := m.Selector.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n107 + i += n109 } if m.StorageClassName != nil { dAtA[i] = 0x2a @@ -6045,11 +6149,11 @@ func (m *PersistentVolumeClaimStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n108, err := (&v).MarshalTo(dAtA[i:]) + n110, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n108 + i += n110 } } if len(m.Conditions) > 0 { @@ -6115,11 +6219,11 @@ func (m *PersistentVolumeList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n109, err := m.ListMeta.MarshalTo(dAtA[i:]) + n111, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n109 + i += n111 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -6154,163 +6258,163 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.GCEPersistentDisk.Size())) - n110, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n110 - } - if m.AWSElasticBlockStore != nil { - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.AWSElasticBlockStore.Size())) - n111, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n111 - } - if m.HostPath != nil { - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.HostPath.Size())) - n112, err := m.HostPath.MarshalTo(dAtA[i:]) + n112, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n112 } - if m.Glusterfs != nil { - dAtA[i] = 0x22 + if m.AWSElasticBlockStore != nil { + dAtA[i] = 0x12 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Glusterfs.Size())) - n113, err := m.Glusterfs.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.AWSElasticBlockStore.Size())) + n113, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n113 } - if m.NFS != nil { - dAtA[i] = 0x2a + if m.HostPath != nil { + dAtA[i] = 0x1a i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.NFS.Size())) - n114, err := m.NFS.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.HostPath.Size())) + n114, err := m.HostPath.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n114 } - if m.RBD != nil { - dAtA[i] = 0x32 + if m.Glusterfs != nil { + dAtA[i] = 0x22 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.RBD.Size())) - n115, err := m.RBD.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.Glusterfs.Size())) + n115, err := m.Glusterfs.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n115 } - if m.ISCSI != nil { - dAtA[i] = 0x3a + if m.NFS != nil { + dAtA[i] = 0x2a i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.ISCSI.Size())) - n116, err := m.ISCSI.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.NFS.Size())) + n116, err := m.NFS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n116 } - if m.Cinder != nil { - dAtA[i] = 0x42 + if m.RBD != nil { + dAtA[i] = 0x32 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Cinder.Size())) - n117, err := m.Cinder.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.RBD.Size())) + n117, err := m.RBD.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n117 } - if m.CephFS != nil { - dAtA[i] = 0x4a + if m.ISCSI != nil { + dAtA[i] = 0x3a i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.CephFS.Size())) - n118, err := m.CephFS.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.ISCSI.Size())) + n118, err := m.ISCSI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n118 } - if m.FC != nil { - dAtA[i] = 0x52 + if m.Cinder != nil { + dAtA[i] = 0x42 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.FC.Size())) - n119, err := m.FC.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.Cinder.Size())) + n119, err := m.Cinder.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n119 } - if m.Flocker != nil { - dAtA[i] = 0x5a + if m.CephFS != nil { + dAtA[i] = 0x4a i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Flocker.Size())) - n120, err := m.Flocker.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.CephFS.Size())) + n120, err := m.CephFS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n120 } - if m.FlexVolume != nil { - dAtA[i] = 0x62 + if m.FC != nil { + dAtA[i] = 0x52 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.FlexVolume.Size())) - n121, err := m.FlexVolume.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.FC.Size())) + n121, err := m.FC.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n121 } - if m.AzureFile != nil { - dAtA[i] = 0x6a + if m.Flocker != nil { + dAtA[i] = 0x5a i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.AzureFile.Size())) - n122, err := m.AzureFile.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.Flocker.Size())) + n122, err := m.Flocker.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n122 } - if m.VsphereVolume != nil { - dAtA[i] = 0x72 + if m.FlexVolume != nil { + dAtA[i] = 0x62 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.VsphereVolume.Size())) - n123, err := m.VsphereVolume.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.FlexVolume.Size())) + n123, err := m.FlexVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n123 } - if m.Quobyte != nil { - dAtA[i] = 0x7a + if m.AzureFile != nil { + dAtA[i] = 0x6a i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Quobyte.Size())) - n124, err := m.Quobyte.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.AzureFile.Size())) + n124, err := m.AzureFile.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n124 } + if m.VsphereVolume != nil { + dAtA[i] = 0x72 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.VsphereVolume.Size())) + n125, err := m.VsphereVolume.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n125 + } + if m.Quobyte != nil { + dAtA[i] = 0x7a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Quobyte.Size())) + n126, err := m.Quobyte.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n126 + } if m.AzureDisk != nil { dAtA[i] = 0x82 i++ dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AzureDisk.Size())) - n125, err := m.AzureDisk.MarshalTo(dAtA[i:]) + n127, err := m.AzureDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n125 + i += n127 } if m.PhotonPersistentDisk != nil { dAtA[i] = 0x8a @@ -6318,11 +6422,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PhotonPersistentDisk.Size())) - n126, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) + n128, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n126 + i += n128 } if m.PortworxVolume != nil { dAtA[i] = 0x92 @@ -6330,11 +6434,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PortworxVolume.Size())) - n127, err := m.PortworxVolume.MarshalTo(dAtA[i:]) + n129, err := m.PortworxVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n127 + i += n129 } if m.ScaleIO != nil { dAtA[i] = 0x9a @@ -6342,11 +6446,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ScaleIO.Size())) - n128, err := m.ScaleIO.MarshalTo(dAtA[i:]) + n130, err := m.ScaleIO.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n128 + i += n130 } if m.Local != nil { dAtA[i] = 0xa2 @@ -6354,11 +6458,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Local.Size())) - n129, err := m.Local.MarshalTo(dAtA[i:]) + n131, err := m.Local.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n129 + i += n131 } if m.StorageOS != nil { dAtA[i] = 0xaa @@ -6366,11 +6470,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StorageOS.Size())) - n130, err := m.StorageOS.MarshalTo(dAtA[i:]) + n132, err := m.StorageOS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n130 + i += n132 } if m.CSI != nil { dAtA[i] = 0xb2 @@ -6378,11 +6482,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.CSI.Size())) - n131, err := m.CSI.MarshalTo(dAtA[i:]) + n133, err := m.CSI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n131 + i += n133 } return i, nil } @@ -6426,21 +6530,21 @@ func (m *PersistentVolumeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n132, err := (&v).MarshalTo(dAtA[i:]) + n134, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n132 + i += n134 } } dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PersistentVolumeSource.Size())) - n133, err := m.PersistentVolumeSource.MarshalTo(dAtA[i:]) + n135, err := m.PersistentVolumeSource.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n133 + i += n135 if len(m.AccessModes) > 0 { for _, s := range m.AccessModes { dAtA[i] = 0x1a @@ -6460,11 +6564,11 @@ func (m *PersistentVolumeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ClaimRef.Size())) - n134, err := m.ClaimRef.MarshalTo(dAtA[i:]) + n136, err := m.ClaimRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n134 + i += n136 } dAtA[i] = 0x2a i++ @@ -6499,11 +6603,11 @@ func (m *PersistentVolumeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x4a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NodeAffinity.Size())) - n135, err := m.NodeAffinity.MarshalTo(dAtA[i:]) + n137, err := m.NodeAffinity.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n135 + i += n137 } return i, nil } @@ -6582,27 +6686,27 @@ func (m *Pod) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n136, err := m.ObjectMeta.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n136 - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n137, err := m.Spec.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n137 - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n138, err := m.Status.MarshalTo(dAtA[i:]) + n138, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n138 + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) + n139, err := m.Spec.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n139 + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) + n140, err := m.Status.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n140 return i, nil } @@ -6667,11 +6771,11 @@ func (m *PodAffinityTerm) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LabelSelector.Size())) - n139, err := m.LabelSelector.MarshalTo(dAtA[i:]) + n141, err := m.LabelSelector.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n139 + i += n141 } if len(m.Namespaces) > 0 { for _, s := range m.Namespaces { @@ -6817,19 +6921,19 @@ func (m *PodCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastProbeTime.Size())) - n140, err := m.LastProbeTime.MarshalTo(dAtA[i:]) + n142, err := m.LastProbeTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n140 + i += n142 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n141, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n143, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n141 + i += n143 dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -7016,11 +7120,11 @@ func (m *PodList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n142, err := m.ListMeta.MarshalTo(dAtA[i:]) + n144, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n142 + i += n144 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -7080,11 +7184,11 @@ func (m *PodLogOptions) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SinceTime.Size())) - n143, err := m.SinceTime.MarshalTo(dAtA[i:]) + n145, err := m.SinceTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n143 + i += n145 } dAtA[i] = 0x30 i++ @@ -7154,6 +7258,28 @@ func (m *PodProxyOptions) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *PodReadinessGate) 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 *PodReadinessGate) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ConditionType))) + i += copy(dAtA[i:], m.ConditionType) + return i, nil +} + func (m *PodSecurityContext) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -7173,11 +7299,11 @@ func (m *PodSecurityContext) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SELinuxOptions.Size())) - n144, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) + n146, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n144 + i += n146 } if m.RunAsUser != nil { dAtA[i] = 0x10 @@ -7211,6 +7337,18 @@ func (m *PodSecurityContext) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintGenerated(dAtA, i, uint64(*m.RunAsGroup)) } + if len(m.Sysctls) > 0 { + for _, msg := range m.Sysctls { + dAtA[i] = 0x3a + 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 } @@ -7233,11 +7371,11 @@ func (m *PodSignature) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PodController.Size())) - n145, err := m.PodController.MarshalTo(dAtA[i:]) + n147, err := m.PodController.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n145 + i += n147 } return i, nil } @@ -7361,11 +7499,11 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x72 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecurityContext.Size())) - n146, err := m.SecurityContext.MarshalTo(dAtA[i:]) + n148, err := m.SecurityContext.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n146 + i += n148 } if len(m.ImagePullSecrets) > 0 { for _, msg := range m.ImagePullSecrets { @@ -7397,11 +7535,11 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Affinity.Size())) - n147, err := m.Affinity.MarshalTo(dAtA[i:]) + n149, err := m.Affinity.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n147 + i += n149 } dAtA[i] = 0x9a i++ @@ -7482,11 +7620,11 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DNSConfig.Size())) - n148, err := m.DNSConfig.MarshalTo(dAtA[i:]) + n150, err := m.DNSConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n148 + i += n150 } if m.ShareProcessNamespace != nil { dAtA[i] = 0xd8 @@ -7500,6 +7638,20 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { } i++ } + if len(m.ReadinessGates) > 0 { + for _, msg := range m.ReadinessGates { + dAtA[i] = 0xe2 + i++ + dAtA[i] = 0x1 + 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 } @@ -7554,11 +7706,11 @@ func (m *PodStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StartTime.Size())) - n149, err := m.StartTime.MarshalTo(dAtA[i:]) + n151, err := m.StartTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n149 + i += n151 } if len(m.ContainerStatuses) > 0 { for _, msg := range m.ContainerStatuses { @@ -7613,19 +7765,19 @@ func (m *PodStatusResult) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n150, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n152, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n150 + i += n152 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n151, err := m.Status.MarshalTo(dAtA[i:]) + n153, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n151 + i += n153 return i, nil } @@ -7647,19 +7799,19 @@ func (m *PodTemplate) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n152, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n154, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n152 + i += n154 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Template.Size())) - n153, err := m.Template.MarshalTo(dAtA[i:]) + n155, err := m.Template.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n153 + i += n155 return i, nil } @@ -7681,11 +7833,11 @@ func (m *PodTemplateList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n154, err := m.ListMeta.MarshalTo(dAtA[i:]) + n156, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n154 + i += n156 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -7719,19 +7871,19 @@ func (m *PodTemplateSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n155, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n157, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n155 + i += n157 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n156, err := m.Spec.MarshalTo(dAtA[i:]) + n158, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n156 + i += n158 return i, nil } @@ -7811,19 +7963,19 @@ func (m *PreferAvoidPodsEntry) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PodSignature.Size())) - n157, err := m.PodSignature.MarshalTo(dAtA[i:]) + n159, err := m.PodSignature.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n157 + i += n159 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.EvictionTime.Size())) - n158, err := m.EvictionTime.MarshalTo(dAtA[i:]) + n160, err := m.EvictionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n158 + i += n160 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -7856,11 +8008,11 @@ func (m *PreferredSchedulingTerm) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Preference.Size())) - n159, err := m.Preference.MarshalTo(dAtA[i:]) + n161, err := m.Preference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n159 + i += n161 return i, nil } @@ -7882,11 +8034,11 @@ func (m *Probe) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Handler.Size())) - n160, err := m.Handler.MarshalTo(dAtA[i:]) + n162, err := m.Handler.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n160 + i += n162 dAtA[i] = 0x10 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.InitialDelaySeconds)) @@ -8036,11 +8188,11 @@ func (m *RBDPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n161, err := m.SecretRef.MarshalTo(dAtA[i:]) + n163, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n161 + i += n163 } dAtA[i] = 0x40 i++ @@ -8107,11 +8259,11 @@ func (m *RBDVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n162, err := m.SecretRef.MarshalTo(dAtA[i:]) + n164, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n162 + i += n164 } dAtA[i] = 0x40 i++ @@ -8142,11 +8294,11 @@ func (m *RangeAllocation) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n163, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n165, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n163 + i += n165 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Range))) @@ -8178,27 +8330,27 @@ func (m *ReplicationController) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n164, err := m.ObjectMeta.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n164 - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n165, err := m.Spec.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n165 - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n166, err := m.Status.MarshalTo(dAtA[i:]) + n166, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n166 + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) + n167, err := m.Spec.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n167 + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) + n168, err := m.Status.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n168 return i, nil } @@ -8228,11 +8380,11 @@ func (m *ReplicationControllerCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n167, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n169, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n167 + i += n169 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -8262,11 +8414,11 @@ func (m *ReplicationControllerList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n168, err := m.ListMeta.MarshalTo(dAtA[i:]) + n170, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n168 + i += n170 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -8328,11 +8480,11 @@ func (m *ReplicationControllerSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Template.Size())) - n169, err := m.Template.MarshalTo(dAtA[i:]) + n171, err := m.Template.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n169 + i += n171 } dAtA[i] = 0x20 i++ @@ -8411,11 +8563,11 @@ func (m *ResourceFieldSelector) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Divisor.Size())) - n170, err := m.Divisor.MarshalTo(dAtA[i:]) + n172, err := m.Divisor.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n170 + i += n172 return i, nil } @@ -8437,27 +8589,27 @@ func (m *ResourceQuota) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n171, err := m.ObjectMeta.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n171 - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n172, err := m.Spec.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n172 - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n173, err := m.Status.MarshalTo(dAtA[i:]) + n173, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n173 + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) + n174, err := m.Spec.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n174 + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) + n175, err := m.Status.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n175 return i, nil } @@ -8479,11 +8631,11 @@ func (m *ResourceQuotaList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n174, err := m.ListMeta.MarshalTo(dAtA[i:]) + n176, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n174 + i += n176 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -8538,11 +8690,11 @@ func (m *ResourceQuotaSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n175, err := (&v).MarshalTo(dAtA[i:]) + n177, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n175 + i += n177 } } if len(m.Scopes) > 0 { @@ -8560,6 +8712,16 @@ func (m *ResourceQuotaSpec) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], s) } } + if m.ScopeSelector != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ScopeSelector.Size())) + n178, err := m.ScopeSelector.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n178 + } return i, nil } @@ -8602,11 +8764,11 @@ func (m *ResourceQuotaStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n176, err := (&v).MarshalTo(dAtA[i:]) + n179, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n176 + i += n179 } } if len(m.Used) > 0 { @@ -8633,11 +8795,11 @@ func (m *ResourceQuotaStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n177, err := (&v).MarshalTo(dAtA[i:]) + n180, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n177 + i += n180 } } return i, nil @@ -8682,11 +8844,11 @@ func (m *ResourceRequirements) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n178, err := (&v).MarshalTo(dAtA[i:]) + n181, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n178 + i += n181 } } if len(m.Requests) > 0 { @@ -8713,11 +8875,11 @@ func (m *ResourceRequirements) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n179, err := (&v).MarshalTo(dAtA[i:]) + n182, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n179 + i += n182 } } return i, nil @@ -8784,11 +8946,11 @@ func (m *ScaleIOPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n180, err := m.SecretRef.MarshalTo(dAtA[i:]) + n183, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n180 + i += n183 } dAtA[i] = 0x20 i++ @@ -8856,11 +9018,11 @@ func (m *ScaleIOVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n181, err := m.SecretRef.MarshalTo(dAtA[i:]) + n184, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n181 + i += n184 } dAtA[i] = 0x20 i++ @@ -8901,6 +9063,77 @@ func (m *ScaleIOVolumeSource) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ScopeSelector) 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 *ScopeSelector) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.MatchExpressions) > 0 { + for _, msg := range m.MatchExpressions { + dAtA[i] = 0xa + 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 *ScopedResourceSelectorRequirement) 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 *ScopedResourceSelectorRequirement) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ScopeName))) + i += copy(dAtA[i:], m.ScopeName) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Operator))) + i += copy(dAtA[i:], m.Operator) + if len(m.Values) > 0 { + for _, s := range m.Values { + dAtA[i] = 0x1a + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + return i, nil +} + func (m *Secret) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -8919,11 +9152,11 @@ func (m *Secret) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n182, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n185, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n182 + i += n185 if len(m.Data) > 0 { keysForData := make([]string, 0, len(m.Data)) for k := range m.Data { @@ -8999,11 +9232,11 @@ func (m *SecretEnvSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n183, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n186, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n183 + i += n186 if m.Optional != nil { dAtA[i] = 0x10 i++ @@ -9035,11 +9268,11 @@ func (m *SecretKeySelector) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n184, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n187, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n184 + i += n187 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key))) @@ -9075,11 +9308,11 @@ func (m *SecretList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n185, err := m.ListMeta.MarshalTo(dAtA[i:]) + n188, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n185 + i += n188 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9113,11 +9346,11 @@ func (m *SecretProjection) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n186, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n189, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n186 + i += n189 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9237,11 +9470,11 @@ func (m *SecurityContext) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Capabilities.Size())) - n187, err := m.Capabilities.MarshalTo(dAtA[i:]) + n190, err := m.Capabilities.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n187 + i += n190 } if m.Privileged != nil { dAtA[i] = 0x10 @@ -9257,11 +9490,11 @@ func (m *SecurityContext) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SELinuxOptions.Size())) - n188, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) + n191, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n188 + i += n191 } if m.RunAsUser != nil { dAtA[i] = 0x20 @@ -9324,11 +9557,11 @@ func (m *SerializedReference) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Reference.Size())) - n189, err := m.Reference.MarshalTo(dAtA[i:]) + n192, err := m.Reference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n189 + i += n192 return i, nil } @@ -9350,27 +9583,27 @@ func (m *Service) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n190, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n193, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n190 + i += n193 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n191, err := m.Spec.MarshalTo(dAtA[i:]) + n194, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n191 + i += n194 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n192, err := m.Status.MarshalTo(dAtA[i:]) + n195, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n192 + i += n195 return i, nil } @@ -9392,11 +9625,11 @@ func (m *ServiceAccount) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n193, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n196, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n193 + i += n196 if len(m.Secrets) > 0 { for _, msg := range m.Secrets { dAtA[i] = 0x12 @@ -9452,11 +9685,11 @@ func (m *ServiceAccountList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n194, err := m.ListMeta.MarshalTo(dAtA[i:]) + n197, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n194 + i += n197 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9472,6 +9705,37 @@ func (m *ServiceAccountList) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ServiceAccountTokenProjection) 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 *ServiceAccountTokenProjection) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Audience))) + i += copy(dAtA[i:], m.Audience) + if m.ExpirationSeconds != nil { + dAtA[i] = 0x10 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(*m.ExpirationSeconds)) + } + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Path))) + i += copy(dAtA[i:], m.Path) + return i, nil +} + func (m *ServiceList) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -9490,11 +9754,11 @@ func (m *ServiceList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n195, err := m.ListMeta.MarshalTo(dAtA[i:]) + n198, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n195 + i += n198 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9539,11 +9803,11 @@ func (m *ServicePort) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TargetPort.Size())) - n196, err := m.TargetPort.MarshalTo(dAtA[i:]) + n199, err := m.TargetPort.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n196 + i += n199 dAtA[i] = 0x28 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NodePort)) @@ -9690,11 +9954,11 @@ func (m *ServiceSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x72 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SessionAffinityConfig.Size())) - n197, err := m.SessionAffinityConfig.MarshalTo(dAtA[i:]) + n200, err := m.SessionAffinityConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n197 + i += n200 } return i, nil } @@ -9717,11 +9981,11 @@ func (m *ServiceStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LoadBalancer.Size())) - n198, err := m.LoadBalancer.MarshalTo(dAtA[i:]) + n201, err := m.LoadBalancer.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n198 + i += n201 return i, nil } @@ -9744,11 +10008,11 @@ func (m *SessionAffinityConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ClientIP.Size())) - n199, err := m.ClientIP.MarshalTo(dAtA[i:]) + n202, err := m.ClientIP.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n199 + i += n202 } return i, nil } @@ -9792,11 +10056,11 @@ func (m *StorageOSPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n200, err := m.SecretRef.MarshalTo(dAtA[i:]) + n203, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n200 + i += n203 } return i, nil } @@ -9840,11 +10104,11 @@ func (m *StorageOSVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n201, err := m.SecretRef.MarshalTo(dAtA[i:]) + n204, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n201 + i += n204 } return i, nil } @@ -9893,11 +10157,11 @@ func (m *TCPSocketAction) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Port.Size())) - n202, err := m.Port.MarshalTo(dAtA[i:]) + n205, err := m.Port.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n202 + i += n205 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Host))) @@ -9936,11 +10200,11 @@ func (m *Taint) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TimeAdded.Size())) - n203, err := m.TimeAdded.MarshalTo(dAtA[i:]) + n206, err := m.TimeAdded.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n203 + i += n206 } return i, nil } @@ -9984,6 +10248,73 @@ func (m *Toleration) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *TopologySelectorLabelRequirement) 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 *TopologySelectorLabelRequirement) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key))) + i += copy(dAtA[i:], m.Key) + if len(m.Values) > 0 { + for _, s := range m.Values { + dAtA[i] = 0x12 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + return i, nil +} + +func (m *TopologySelectorTerm) 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 *TopologySelectorTerm) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.MatchLabelExpressions) > 0 { + for _, msg := range m.MatchLabelExpressions { + dAtA[i] = 0xa + 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 *Volume) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -10006,11 +10337,11 @@ func (m *Volume) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.VolumeSource.Size())) - n204, err := m.VolumeSource.MarshalTo(dAtA[i:]) + n207, err := m.VolumeSource.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n204 + i += n207 return i, nil } @@ -10103,11 +10434,11 @@ func (m *VolumeNodeAffinity) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Required.Size())) - n205, err := m.Required.MarshalTo(dAtA[i:]) + n208, err := m.Required.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n205 + i += n208 } return i, nil } @@ -10131,31 +10462,41 @@ func (m *VolumeProjection) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Secret.Size())) - n206, err := m.Secret.MarshalTo(dAtA[i:]) + n209, err := m.Secret.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n206 + i += n209 } if m.DownwardAPI != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DownwardAPI.Size())) - n207, err := m.DownwardAPI.MarshalTo(dAtA[i:]) + n210, err := m.DownwardAPI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n207 + i += n210 } if m.ConfigMap != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMap.Size())) - n208, err := m.ConfigMap.MarshalTo(dAtA[i:]) + n211, err := m.ConfigMap.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n208 + i += n211 + } + if m.ServiceAccountToken != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ServiceAccountToken.Size())) + n212, err := m.ServiceAccountToken.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n212 } return i, nil } @@ -10179,163 +10520,163 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.HostPath.Size())) - n209, err := m.HostPath.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n209 - } - if m.EmptyDir != nil { - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.EmptyDir.Size())) - n210, err := m.EmptyDir.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n210 - } - if m.GCEPersistentDisk != nil { - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.GCEPersistentDisk.Size())) - n211, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n211 - } - if m.AWSElasticBlockStore != nil { - dAtA[i] = 0x22 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.AWSElasticBlockStore.Size())) - n212, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n212 - } - if m.GitRepo != nil { - dAtA[i] = 0x2a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.GitRepo.Size())) - n213, err := m.GitRepo.MarshalTo(dAtA[i:]) + n213, err := m.HostPath.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n213 } - if m.Secret != nil { - dAtA[i] = 0x32 + if m.EmptyDir != nil { + dAtA[i] = 0x12 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Secret.Size())) - n214, err := m.Secret.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.EmptyDir.Size())) + n214, err := m.EmptyDir.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n214 } - if m.NFS != nil { - dAtA[i] = 0x3a + if m.GCEPersistentDisk != nil { + dAtA[i] = 0x1a i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.NFS.Size())) - n215, err := m.NFS.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.GCEPersistentDisk.Size())) + n215, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n215 } - if m.ISCSI != nil { - dAtA[i] = 0x42 + if m.AWSElasticBlockStore != nil { + dAtA[i] = 0x22 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.ISCSI.Size())) - n216, err := m.ISCSI.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.AWSElasticBlockStore.Size())) + n216, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n216 } - if m.Glusterfs != nil { - dAtA[i] = 0x4a + if m.GitRepo != nil { + dAtA[i] = 0x2a i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Glusterfs.Size())) - n217, err := m.Glusterfs.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.GitRepo.Size())) + n217, err := m.GitRepo.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n217 } - if m.PersistentVolumeClaim != nil { - dAtA[i] = 0x52 + if m.Secret != nil { + dAtA[i] = 0x32 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.PersistentVolumeClaim.Size())) - n218, err := m.PersistentVolumeClaim.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.Secret.Size())) + n218, err := m.Secret.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n218 } - if m.RBD != nil { - dAtA[i] = 0x5a + if m.NFS != nil { + dAtA[i] = 0x3a i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.RBD.Size())) - n219, err := m.RBD.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.NFS.Size())) + n219, err := m.NFS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n219 } - if m.FlexVolume != nil { - dAtA[i] = 0x62 + if m.ISCSI != nil { + dAtA[i] = 0x42 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.FlexVolume.Size())) - n220, err := m.FlexVolume.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.ISCSI.Size())) + n220, err := m.ISCSI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n220 } - if m.Cinder != nil { - dAtA[i] = 0x6a + if m.Glusterfs != nil { + dAtA[i] = 0x4a i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Cinder.Size())) - n221, err := m.Cinder.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.Glusterfs.Size())) + n221, err := m.Glusterfs.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n221 } - if m.CephFS != nil { - dAtA[i] = 0x72 + if m.PersistentVolumeClaim != nil { + dAtA[i] = 0x52 i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.CephFS.Size())) - n222, err := m.CephFS.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.PersistentVolumeClaim.Size())) + n222, err := m.PersistentVolumeClaim.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n222 } - if m.Flocker != nil { - dAtA[i] = 0x7a + if m.RBD != nil { + dAtA[i] = 0x5a i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Flocker.Size())) - n223, err := m.Flocker.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.RBD.Size())) + n223, err := m.RBD.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n223 } + if m.FlexVolume != nil { + dAtA[i] = 0x62 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.FlexVolume.Size())) + n224, err := m.FlexVolume.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n224 + } + if m.Cinder != nil { + dAtA[i] = 0x6a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Cinder.Size())) + n225, err := m.Cinder.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n225 + } + if m.CephFS != nil { + dAtA[i] = 0x72 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.CephFS.Size())) + n226, err := m.CephFS.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n226 + } + if m.Flocker != nil { + dAtA[i] = 0x7a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Flocker.Size())) + n227, err := m.Flocker.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n227 + } if m.DownwardAPI != nil { dAtA[i] = 0x82 i++ dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DownwardAPI.Size())) - n224, err := m.DownwardAPI.MarshalTo(dAtA[i:]) + n228, err := m.DownwardAPI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n224 + i += n228 } if m.FC != nil { dAtA[i] = 0x8a @@ -10343,11 +10684,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FC.Size())) - n225, err := m.FC.MarshalTo(dAtA[i:]) + n229, err := m.FC.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n225 + i += n229 } if m.AzureFile != nil { dAtA[i] = 0x92 @@ -10355,11 +10696,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AzureFile.Size())) - n226, err := m.AzureFile.MarshalTo(dAtA[i:]) + n230, err := m.AzureFile.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n226 + i += n230 } if m.ConfigMap != nil { dAtA[i] = 0x9a @@ -10367,11 +10708,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMap.Size())) - n227, err := m.ConfigMap.MarshalTo(dAtA[i:]) + n231, err := m.ConfigMap.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n227 + i += n231 } if m.VsphereVolume != nil { dAtA[i] = 0xa2 @@ -10379,11 +10720,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.VsphereVolume.Size())) - n228, err := m.VsphereVolume.MarshalTo(dAtA[i:]) + n232, err := m.VsphereVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n228 + i += n232 } if m.Quobyte != nil { dAtA[i] = 0xaa @@ -10391,11 +10732,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Quobyte.Size())) - n229, err := m.Quobyte.MarshalTo(dAtA[i:]) + n233, err := m.Quobyte.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n229 + i += n233 } if m.AzureDisk != nil { dAtA[i] = 0xb2 @@ -10403,11 +10744,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AzureDisk.Size())) - n230, err := m.AzureDisk.MarshalTo(dAtA[i:]) + n234, err := m.AzureDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n230 + i += n234 } if m.PhotonPersistentDisk != nil { dAtA[i] = 0xba @@ -10415,11 +10756,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PhotonPersistentDisk.Size())) - n231, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) + n235, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n231 + i += n235 } if m.PortworxVolume != nil { dAtA[i] = 0xc2 @@ -10427,11 +10768,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PortworxVolume.Size())) - n232, err := m.PortworxVolume.MarshalTo(dAtA[i:]) + n236, err := m.PortworxVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n232 + i += n236 } if m.ScaleIO != nil { dAtA[i] = 0xca @@ -10439,11 +10780,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ScaleIO.Size())) - n233, err := m.ScaleIO.MarshalTo(dAtA[i:]) + n237, err := m.ScaleIO.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n233 + i += n237 } if m.Projected != nil { dAtA[i] = 0xd2 @@ -10451,11 +10792,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Projected.Size())) - n234, err := m.Projected.MarshalTo(dAtA[i:]) + n238, err := m.Projected.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n234 + i += n238 } if m.StorageOS != nil { dAtA[i] = 0xda @@ -10463,11 +10804,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StorageOS.Size())) - n235, err := m.StorageOS.MarshalTo(dAtA[i:]) + n239, err := m.StorageOS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n235 + i += n239 } return i, nil } @@ -10527,11 +10868,11 @@ func (m *WeightedPodAffinityTerm) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PodAffinityTerm.Size())) - n236, err := m.PodAffinityTerm.MarshalTo(dAtA[i:]) + n240, err := m.PodAffinityTerm.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n236 + i += n240 return i, nil } @@ -10772,6 +11113,21 @@ func (m *CephFSVolumeSource) Size() (n int) { return n } +func (m *CinderPersistentVolumeSource) Size() (n int) { + var l int + _ = l + l = len(m.VolumeID) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.FSType) + n += 1 + l + sovGenerated(uint64(l)) + n += 2 + if m.SecretRef != nil { + l = m.SecretRef.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *CinderVolumeSource) Size() (n int) { var l int _ = l @@ -10780,6 +11136,10 @@ func (m *CinderVolumeSource) Size() (n int) { l = len(m.FSType) n += 1 + l + sovGenerated(uint64(l)) n += 2 + if m.SecretRef != nil { + l = m.SecretRef.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -12721,6 +13081,14 @@ func (m *PodProxyOptions) Size() (n int) { return n } +func (m *PodReadinessGate) Size() (n int) { + var l int + _ = l + l = len(m.ConditionType) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *PodSecurityContext) Size() (n int) { var l int _ = l @@ -12745,6 +13113,12 @@ func (m *PodSecurityContext) Size() (n int) { if m.RunAsGroup != nil { n += 1 + sovGenerated(uint64(*m.RunAsGroup)) } + if len(m.Sysctls) > 0 { + for _, e := range m.Sysctls { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -12853,6 +13227,12 @@ func (m *PodSpec) Size() (n int) { if m.ShareProcessNamespace != nil { n += 3 } + if len(m.ReadinessGates) > 0 { + for _, e := range m.ReadinessGates { + l = e.Size() + n += 2 + l + sovGenerated(uint64(l)) + } + } return n } @@ -13234,6 +13614,10 @@ func (m *ResourceQuotaSpec) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + if m.ScopeSelector != nil { + l = m.ScopeSelector.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -13351,6 +13735,34 @@ func (m *ScaleIOVolumeSource) Size() (n int) { return n } +func (m *ScopeSelector) Size() (n int) { + var l int + _ = l + if len(m.MatchExpressions) > 0 { + for _, e := range m.MatchExpressions { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *ScopedResourceSelectorRequirement) Size() (n int) { + var l int + _ = l + l = len(m.ScopeName) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Operator) + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Values) > 0 { + for _, s := range m.Values { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + func (m *Secret) Size() (n int) { var l int _ = l @@ -13555,6 +13967,19 @@ func (m *ServiceAccountList) Size() (n int) { return n } +func (m *ServiceAccountTokenProjection) Size() (n int) { + var l int + _ = l + l = len(m.Audience) + n += 1 + l + sovGenerated(uint64(l)) + if m.ExpirationSeconds != nil { + n += 1 + sovGenerated(uint64(*m.ExpirationSeconds)) + } + l = len(m.Path) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *ServiceList) Size() (n int) { var l int _ = l @@ -13746,6 +14171,32 @@ func (m *Toleration) Size() (n int) { return n } +func (m *TopologySelectorLabelRequirement) Size() (n int) { + var l int + _ = l + l = len(m.Key) + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Values) > 0 { + for _, s := range m.Values { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *TopologySelectorTerm) Size() (n int) { + var l int + _ = l + if len(m.MatchLabelExpressions) > 0 { + for _, e := range m.MatchLabelExpressions { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + func (m *Volume) Size() (n int) { var l int _ = l @@ -13808,6 +14259,10 @@ func (m *VolumeProjection) Size() (n int) { l = m.ConfigMap.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.ServiceAccountToken != nil { + l = m.ServiceAccountToken.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -14126,6 +14581,19 @@ func (this *CephFSVolumeSource) String() string { }, "") return s } +func (this *CinderPersistentVolumeSource) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CinderPersistentVolumeSource{`, + `VolumeID:` + fmt.Sprintf("%v", this.VolumeID) + `,`, + `FSType:` + fmt.Sprintf("%v", this.FSType) + `,`, + `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, + `SecretRef:` + strings.Replace(fmt.Sprintf("%v", this.SecretRef), "SecretReference", "SecretReference", 1) + `,`, + `}`, + }, "") + return s +} func (this *CinderVolumeSource) String() string { if this == nil { return "nil" @@ -14134,6 +14602,7 @@ func (this *CinderVolumeSource) String() string { `VolumeID:` + fmt.Sprintf("%v", this.VolumeID) + `,`, `FSType:` + fmt.Sprintf("%v", this.FSType) + `,`, `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, + `SecretRef:` + strings.Replace(fmt.Sprintf("%v", this.SecretRef), "LocalObjectReference", "LocalObjectReference", 1) + `,`, `}`, }, "") return s @@ -15443,7 +15912,7 @@ func (this *PersistentVolumeSource) String() string { `NFS:` + strings.Replace(fmt.Sprintf("%v", this.NFS), "NFSVolumeSource", "NFSVolumeSource", 1) + `,`, `RBD:` + strings.Replace(fmt.Sprintf("%v", this.RBD), "RBDPersistentVolumeSource", "RBDPersistentVolumeSource", 1) + `,`, `ISCSI:` + strings.Replace(fmt.Sprintf("%v", this.ISCSI), "ISCSIPersistentVolumeSource", "ISCSIPersistentVolumeSource", 1) + `,`, - `Cinder:` + strings.Replace(fmt.Sprintf("%v", this.Cinder), "CinderVolumeSource", "CinderVolumeSource", 1) + `,`, + `Cinder:` + strings.Replace(fmt.Sprintf("%v", this.Cinder), "CinderPersistentVolumeSource", "CinderPersistentVolumeSource", 1) + `,`, `CephFS:` + strings.Replace(fmt.Sprintf("%v", this.CephFS), "CephFSPersistentVolumeSource", "CephFSPersistentVolumeSource", 1) + `,`, `FC:` + strings.Replace(fmt.Sprintf("%v", this.FC), "FCVolumeSource", "FCVolumeSource", 1) + `,`, `Flocker:` + strings.Replace(fmt.Sprintf("%v", this.Flocker), "FlockerVolumeSource", "FlockerVolumeSource", 1) + `,`, @@ -15674,6 +16143,16 @@ func (this *PodProxyOptions) String() string { }, "") return s } +func (this *PodReadinessGate) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodReadinessGate{`, + `ConditionType:` + fmt.Sprintf("%v", this.ConditionType) + `,`, + `}`, + }, "") + return s +} func (this *PodSecurityContext) String() string { if this == nil { return "nil" @@ -15685,6 +16164,7 @@ func (this *PodSecurityContext) String() string { `SupplementalGroups:` + fmt.Sprintf("%v", this.SupplementalGroups) + `,`, `FSGroup:` + valueToStringGenerated(this.FSGroup) + `,`, `RunAsGroup:` + valueToStringGenerated(this.RunAsGroup) + `,`, + `Sysctls:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Sysctls), "Sysctl", "Sysctl", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -15741,6 +16221,7 @@ func (this *PodSpec) String() string { `Priority:` + valueToStringGenerated(this.Priority) + `,`, `DNSConfig:` + strings.Replace(fmt.Sprintf("%v", this.DNSConfig), "PodDNSConfig", "PodDNSConfig", 1) + `,`, `ShareProcessNamespace:` + valueToStringGenerated(this.ShareProcessNamespace) + `,`, + `ReadinessGates:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ReadinessGates), "PodReadinessGate", "PodReadinessGate", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -16068,6 +16549,7 @@ func (this *ResourceQuotaSpec) String() string { s := strings.Join([]string{`&ResourceQuotaSpec{`, `Hard:` + mapStringForHard + `,`, `Scopes:` + fmt.Sprintf("%v", this.Scopes) + `,`, + `ScopeSelector:` + strings.Replace(fmt.Sprintf("%v", this.ScopeSelector), "ScopeSelector", "ScopeSelector", 1) + `,`, `}`, }, "") return s @@ -16185,6 +16667,28 @@ func (this *ScaleIOVolumeSource) String() string { }, "") return s } +func (this *ScopeSelector) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ScopeSelector{`, + `MatchExpressions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.MatchExpressions), "ScopedResourceSelectorRequirement", "ScopedResourceSelectorRequirement", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *ScopedResourceSelectorRequirement) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ScopedResourceSelectorRequirement{`, + `ScopeName:` + fmt.Sprintf("%v", this.ScopeName) + `,`, + `Operator:` + fmt.Sprintf("%v", this.Operator) + `,`, + `Values:` + fmt.Sprintf("%v", this.Values) + `,`, + `}`, + }, "") + return s +} func (this *Secret) String() string { if this == nil { return "nil" @@ -16351,6 +16855,18 @@ func (this *ServiceAccountList) String() string { }, "") return s } +func (this *ServiceAccountTokenProjection) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ServiceAccountTokenProjection{`, + `Audience:` + fmt.Sprintf("%v", this.Audience) + `,`, + `ExpirationSeconds:` + valueToStringGenerated(this.ExpirationSeconds) + `,`, + `Path:` + fmt.Sprintf("%v", this.Path) + `,`, + `}`, + }, "") + return s +} func (this *ServiceList) String() string { if this == nil { return "nil" @@ -16515,6 +17031,27 @@ func (this *Toleration) String() string { }, "") return s } +func (this *TopologySelectorLabelRequirement) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&TopologySelectorLabelRequirement{`, + `Key:` + fmt.Sprintf("%v", this.Key) + `,`, + `Values:` + fmt.Sprintf("%v", this.Values) + `,`, + `}`, + }, "") + return s +} +func (this *TopologySelectorTerm) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&TopologySelectorTerm{`, + `MatchLabelExpressions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.MatchLabelExpressions), "TopologySelectorLabelRequirement", "TopologySelectorLabelRequirement", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} func (this *Volume) String() string { if this == nil { return "nil" @@ -16569,6 +17106,7 @@ func (this *VolumeProjection) String() string { `Secret:` + strings.Replace(fmt.Sprintf("%v", this.Secret), "SecretProjection", "SecretProjection", 1) + `,`, `DownwardAPI:` + strings.Replace(fmt.Sprintf("%v", this.DownwardAPI), "DownwardAPIProjection", "DownwardAPIProjection", 1) + `,`, `ConfigMap:` + strings.Replace(fmt.Sprintf("%v", this.ConfigMap), "ConfigMapProjection", "ConfigMapProjection", 1) + `,`, + `ServiceAccountToken:` + strings.Replace(fmt.Sprintf("%v", this.ServiceAccountToken), "ServiceAccountTokenProjection", "ServiceAccountTokenProjection", 1) + `,`, `}`, }, "") return s @@ -18659,6 +19197,167 @@ func (m *CephFSVolumeSource) Unmarshal(dAtA []byte) error { } return nil } +func (m *CinderPersistentVolumeSource) 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: CinderPersistentVolumeSource: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CinderPersistentVolumeSource: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VolumeID", 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 + } + m.VolumeID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FSType", 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 + } + m.FSType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ReadOnly = bool(v != 0) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecretRef", 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.SecretRef == nil { + m.SecretRef = &SecretReference{} + } + if err := m.SecretRef.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 *CinderVolumeSource) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -18766,6 +19465,39 @@ func (m *CinderVolumeSource) Unmarshal(dAtA []byte) error { } } m.ReadOnly = bool(v != 0) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecretRef", 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.SecretRef == nil { + m.SecretRef = &LocalObjectReference{} + } + if err := m.SecretRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -34258,7 +34990,7 @@ func (m *PersistentVolumeSource) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.Cinder == nil { - m.Cinder = &CinderVolumeSource{} + m.Cinder = &CinderPersistentVolumeSource{} } if err := m.Cinder.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -37265,6 +37997,85 @@ func (m *PodProxyOptions) Unmarshal(dAtA []byte) error { } return nil } +func (m *PodReadinessGate) 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: PodReadinessGate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodReadinessGate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConditionType", 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 + } + m.ConditionType = PodConditionType(dAtA[iNdEx:postIndex]) + 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 *PodSecurityContext) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -37470,6 +38281,37 @@ func (m *PodSecurityContext) Unmarshal(dAtA []byte) error { } } m.RunAsGroup = &v + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sysctls", 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.Sysctls = append(m.Sysctls, Sysctl{}) + if err := m.Sysctls[len(m.Sysctls)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -38427,6 +39269,37 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { } b := bool(v != 0) m.ShareProcessNamespace = &b + case 28: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadinessGates", 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.ReadinessGates = append(m.ReadinessGates, PodReadinessGate{}) + if err := m.ReadinessGates[len(m.ReadinessGates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -42328,6 +43201,39 @@ func (m *ResourceQuotaSpec) Unmarshal(dAtA []byte) error { } m.Scopes = append(m.Scopes, ResourceQuotaScope(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ScopeSelector", 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.ScopeSelector == nil { + m.ScopeSelector = &ScopeSelector{} + } + if err := m.ScopeSelector.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -43751,6 +44657,224 @@ func (m *ScaleIOVolumeSource) Unmarshal(dAtA []byte) error { } return nil } +func (m *ScopeSelector) 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: ScopeSelector: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ScopeSelector: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MatchExpressions", 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.MatchExpressions = append(m.MatchExpressions, ScopedResourceSelectorRequirement{}) + if err := m.MatchExpressions[len(m.MatchExpressions)-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 *ScopedResourceSelectorRequirement) 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: ScopedResourceSelectorRequirement: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ScopedResourceSelectorRequirement: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ScopeName", 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 + } + m.ScopeName = ResourceQuotaScope(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Operator", 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 + } + m.Operator = ScopeSelectorOperator(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Values", 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 + } + m.Values = append(m.Values, string(dAtA[iNdEx:postIndex])) + 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 *Secret) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -45560,6 +46684,134 @@ func (m *ServiceAccountList) Unmarshal(dAtA []byte) error { } return nil } +func (m *ServiceAccountTokenProjection) 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: ServiceAccountTokenProjection: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ServiceAccountTokenProjection: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Audience", 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 + } + m.Audience = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ExpirationSeconds", wireType) + } + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ExpirationSeconds = &v + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Path", 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 + } + m.Path = string(dAtA[iNdEx:postIndex]) + 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 *ServiceList) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -47543,6 +48795,195 @@ func (m *Toleration) Unmarshal(dAtA []byte) error { } return nil } +func (m *TopologySelectorLabelRequirement) 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: TopologySelectorLabelRequirement: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TopologySelectorLabelRequirement: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", 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 + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Values", 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 + } + m.Values = append(m.Values, string(dAtA[iNdEx:postIndex])) + 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 *TopologySelectorTerm) 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: TopologySelectorTerm: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TopologySelectorTerm: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MatchLabelExpressions", 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.MatchLabelExpressions = append(m.MatchLabelExpressions, TopologySelectorLabelRequirement{}) + if err := m.MatchLabelExpressions[len(m.MatchLabelExpressions)-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 *Volume) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -48158,6 +49599,39 @@ func (m *VolumeProjection) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ServiceAccountToken", 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.ServiceAccountToken == nil { + m.ServiceAccountToken = &ServiceAccountTokenProjection{} + } + if err := m.ServiceAccountToken.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -49495,778 +50969,799 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 12356 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x5d, 0x6c, 0x24, 0x57, - 0x76, 0x18, 0xbc, 0xd5, 0xdd, 0xfc, 0xe9, 0xc3, 0xff, 0x3b, 0x33, 0x12, 0x87, 0x92, 0xa6, 0x47, - 0xa5, 0xdd, 0xd1, 0x68, 0x25, 0x91, 0xd6, 0x48, 0x5a, 0xc9, 0xab, 0x5d, 0xd9, 0x24, 0x9b, 0x9c, - 0x69, 0xcd, 0x90, 0xd3, 0xba, 0xcd, 0x99, 0xd9, 0x5d, 0x6b, 0xd7, 0x5b, 0xec, 0xbe, 0x24, 0x4b, - 0x2c, 0x56, 0xb5, 0xaa, 0xaa, 0x39, 0x43, 0xc1, 0x06, 0xbe, 0x4f, 0x4e, 0x9c, 0x38, 0xf6, 0xc3, - 0x22, 0x36, 0x12, 0xc7, 0x36, 0x1c, 0x20, 0x71, 0x60, 0x6f, 0x9c, 0x04, 0x71, 0xec, 0xd8, 0xce, - 0xae, 0x93, 0x38, 0x4e, 0x1e, 0x9c, 0x97, 0x8d, 0x93, 0x97, 0x35, 0x60, 0x84, 0xb1, 0x69, 0x23, - 0x81, 0x1f, 0x12, 0x04, 0x31, 0x10, 0xc0, 0x8c, 0x11, 0x07, 0xf7, 0xb7, 0xee, 0xad, 0xae, 0xea, - 0x6e, 0x8e, 0x38, 0x94, 0x6c, 0xec, 0x5b, 0xf7, 0x3d, 0xe7, 0x9e, 0x7b, 0xeb, 0xfe, 0x9e, 0x73, - 0xee, 0xf9, 0x81, 0x37, 0x76, 0x5f, 0x8f, 0xe6, 0xdd, 0x60, 0x61, 0xb7, 0xb3, 0x49, 0x42, 0x9f, - 0xc4, 0x24, 0x5a, 0xd8, 0x27, 0x7e, 0x2b, 0x08, 0x17, 0x04, 0xc0, 0x69, 0xbb, 0x0b, 0xcd, 0x20, - 0x24, 0x0b, 0xfb, 0x2f, 0x2d, 0x6c, 0x13, 0x9f, 0x84, 0x4e, 0x4c, 0x5a, 0xf3, 0xed, 0x30, 0x88, - 0x03, 0x84, 0x38, 0xce, 0xbc, 0xd3, 0x76, 0xe7, 0x29, 0xce, 0xfc, 0xfe, 0x4b, 0x73, 0x2f, 0x6e, - 0xbb, 0xf1, 0x4e, 0x67, 0x73, 0xbe, 0x19, 0xec, 0x2d, 0x6c, 0x07, 0xdb, 0xc1, 0x02, 0x43, 0xdd, - 0xec, 0x6c, 0xb1, 0x7f, 0xec, 0x0f, 0xfb, 0xc5, 0x49, 0xcc, 0xad, 0x25, 0xcd, 0x90, 0x07, 0x31, - 0xf1, 0x23, 0x37, 0xf0, 0xa3, 0x17, 0x9d, 0xb6, 0x1b, 0x91, 0x70, 0x9f, 0x84, 0x0b, 0xed, 0xdd, - 0x6d, 0x0a, 0x8b, 0x4c, 0x84, 0x85, 0xfd, 0x97, 0x36, 0x49, 0xec, 0x74, 0xf5, 0x68, 0xee, 0x95, - 0x84, 0xdc, 0x9e, 0xd3, 0xdc, 0x71, 0x7d, 0x12, 0x1e, 0x48, 0x1a, 0x0b, 0x21, 0x89, 0x82, 0x4e, - 0xd8, 0x24, 0x27, 0xaa, 0x15, 0x2d, 0xec, 0x91, 0xd8, 0xc9, 0xf8, 0xfa, 0xb9, 0x85, 0xbc, 0x5a, - 0x61, 0xc7, 0x8f, 0xdd, 0xbd, 0xee, 0x66, 0x3e, 0xd3, 0xaf, 0x42, 0xd4, 0xdc, 0x21, 0x7b, 0x4e, - 0x57, 0xbd, 0x97, 0xf3, 0xea, 0x75, 0x62, 0xd7, 0x5b, 0x70, 0xfd, 0x38, 0x8a, 0xc3, 0x74, 0x25, - 0xfb, 0xdb, 0x16, 0x5c, 0x5e, 0xbc, 0xd7, 0x58, 0xf1, 0x9c, 0x28, 0x76, 0x9b, 0x4b, 0x5e, 0xd0, - 0xdc, 0x6d, 0xc4, 0x41, 0x48, 0xee, 0x06, 0x5e, 0x67, 0x8f, 0x34, 0xd8, 0x40, 0xa0, 0x17, 0x60, - 0x74, 0x9f, 0xfd, 0xaf, 0x55, 0x67, 0xad, 0xcb, 0xd6, 0xd5, 0xf2, 0xd2, 0xf4, 0x6f, 0x1f, 0x56, - 0x3e, 0x71, 0x74, 0x58, 0x19, 0xbd, 0x2b, 0xca, 0xb1, 0xc2, 0x40, 0x57, 0x60, 0x78, 0x2b, 0xda, - 0x38, 0x68, 0x93, 0xd9, 0x02, 0xc3, 0x9d, 0x14, 0xb8, 0xc3, 0xab, 0x0d, 0x5a, 0x8a, 0x05, 0x14, - 0x2d, 0x40, 0xb9, 0xed, 0x84, 0xb1, 0x1b, 0xbb, 0x81, 0x3f, 0x5b, 0xbc, 0x6c, 0x5d, 0x1d, 0x5a, - 0x9a, 0x11, 0xa8, 0xe5, 0xba, 0x04, 0xe0, 0x04, 0x87, 0x76, 0x23, 0x24, 0x4e, 0xeb, 0xb6, 0xef, - 0x1d, 0xcc, 0x96, 0x2e, 0x5b, 0x57, 0x47, 0x93, 0x6e, 0x60, 0x51, 0x8e, 0x15, 0x86, 0xfd, 0x53, - 0x05, 0x18, 0x5d, 0xdc, 0xda, 0x72, 0x7d, 0x37, 0x3e, 0x40, 0x77, 0x61, 0xdc, 0x0f, 0x5a, 0x44, - 0xfe, 0x67, 0x5f, 0x31, 0x76, 0xed, 0xf2, 0x7c, 0xf7, 0xca, 0x9c, 0x5f, 0xd7, 0xf0, 0x96, 0xa6, - 0x8f, 0x0e, 0x2b, 0xe3, 0x7a, 0x09, 0x36, 0xe8, 0x20, 0x0c, 0x63, 0xed, 0xa0, 0xa5, 0xc8, 0x16, - 0x18, 0xd9, 0x4a, 0x16, 0xd9, 0x7a, 0x82, 0xb6, 0x34, 0x75, 0x74, 0x58, 0x19, 0xd3, 0x0a, 0xb0, - 0x4e, 0x04, 0x6d, 0xc2, 0x14, 0xfd, 0xeb, 0xc7, 0xae, 0xa2, 0x5b, 0x64, 0x74, 0x9f, 0xc9, 0xa3, - 0xab, 0xa1, 0x2e, 0x9d, 0x3b, 0x3a, 0xac, 0x4c, 0xa5, 0x0a, 0x71, 0x9a, 0xa0, 0xfd, 0x3e, 0x4c, - 0x2e, 0xc6, 0xb1, 0xd3, 0xdc, 0x21, 0x2d, 0x3e, 0x83, 0xe8, 0x15, 0x28, 0xf9, 0xce, 0x1e, 0x11, - 0xf3, 0x7b, 0x59, 0x0c, 0x6c, 0x69, 0xdd, 0xd9, 0x23, 0xc7, 0x87, 0x95, 0xe9, 0x3b, 0xbe, 0xfb, - 0x5e, 0x47, 0xac, 0x0a, 0x5a, 0x86, 0x19, 0x36, 0xba, 0x06, 0xd0, 0x22, 0xfb, 0x6e, 0x93, 0xd4, - 0x9d, 0x78, 0x47, 0xcc, 0x37, 0x12, 0x75, 0xa1, 0xaa, 0x20, 0x58, 0xc3, 0xb2, 0x1f, 0x40, 0x79, - 0x71, 0x3f, 0x70, 0x5b, 0xf5, 0xa0, 0x15, 0xa1, 0x5d, 0x98, 0x6a, 0x87, 0x64, 0x8b, 0x84, 0xaa, - 0x68, 0xd6, 0xba, 0x5c, 0xbc, 0x3a, 0x76, 0xed, 0x6a, 0xe6, 0xc7, 0x9a, 0xa8, 0x2b, 0x7e, 0x1c, - 0x1e, 0x2c, 0x3d, 0x2e, 0xda, 0x9b, 0x4a, 0x41, 0x71, 0x9a, 0xb2, 0xfd, 0xef, 0x0a, 0x70, 0x61, - 0xf1, 0xfd, 0x4e, 0x48, 0xaa, 0x6e, 0xb4, 0x9b, 0x5e, 0xe1, 0x2d, 0x37, 0xda, 0x5d, 0x4f, 0x46, - 0x40, 0x2d, 0xad, 0xaa, 0x28, 0xc7, 0x0a, 0x03, 0xbd, 0x08, 0x23, 0xf4, 0xf7, 0x1d, 0x5c, 0x13, - 0x9f, 0x7c, 0x4e, 0x20, 0x8f, 0x55, 0x9d, 0xd8, 0xa9, 0x72, 0x10, 0x96, 0x38, 0x68, 0x0d, 0xc6, - 0x9a, 0x6c, 0x43, 0x6e, 0xaf, 0x05, 0x2d, 0xc2, 0x26, 0xb3, 0xbc, 0xf4, 0x3c, 0x45, 0x5f, 0x4e, - 0x8a, 0x8f, 0x0f, 0x2b, 0xb3, 0xbc, 0x6f, 0x82, 0x84, 0x06, 0xc3, 0x7a, 0x7d, 0x64, 0xab, 0xfd, - 0x55, 0x62, 0x94, 0x20, 0x63, 0x6f, 0x5d, 0xd5, 0xb6, 0xca, 0x10, 0xdb, 0x2a, 0xe3, 0xd9, 0xdb, - 0x04, 0xbd, 0x04, 0xa5, 0x5d, 0xd7, 0x6f, 0xcd, 0x0e, 0x33, 0x5a, 0x4f, 0xd1, 0x39, 0xbf, 0xe9, - 0xfa, 0xad, 0xe3, 0xc3, 0xca, 0x8c, 0xd1, 0x1d, 0x5a, 0x88, 0x19, 0xaa, 0xfd, 0x27, 0x16, 0x54, - 0x18, 0x6c, 0xd5, 0xf5, 0x48, 0x9d, 0x84, 0x91, 0x1b, 0xc5, 0xc4, 0x8f, 0x8d, 0x01, 0xbd, 0x06, - 0x10, 0x91, 0x66, 0x48, 0x62, 0x6d, 0x48, 0xd5, 0xc2, 0x68, 0x28, 0x08, 0xd6, 0xb0, 0xe8, 0x81, - 0x10, 0xed, 0x38, 0x21, 0x5b, 0x5f, 0x62, 0x60, 0xd5, 0x81, 0xd0, 0x90, 0x00, 0x9c, 0xe0, 0x18, - 0x07, 0x42, 0xb1, 0xdf, 0x81, 0x80, 0x3e, 0x0f, 0x53, 0x49, 0x63, 0x51, 0xdb, 0x69, 0xca, 0x01, - 0x64, 0x5b, 0xa6, 0x61, 0x82, 0x70, 0x1a, 0xd7, 0xfe, 0x87, 0x96, 0x58, 0x3c, 0xf4, 0xab, 0x3f, - 0xe6, 0xdf, 0x6a, 0xff, 0xba, 0x05, 0x23, 0x4b, 0xae, 0xdf, 0x72, 0xfd, 0x6d, 0xf4, 0x55, 0x18, - 0xa5, 0x77, 0x53, 0xcb, 0x89, 0x1d, 0x71, 0xee, 0x7d, 0x97, 0xb6, 0xb7, 0xd4, 0x55, 0x31, 0xdf, - 0xde, 0xdd, 0xa6, 0x05, 0xd1, 0x3c, 0xc5, 0xa6, 0xbb, 0xed, 0xf6, 0xe6, 0xbb, 0xa4, 0x19, 0xaf, - 0x91, 0xd8, 0x49, 0x3e, 0x27, 0x29, 0xc3, 0x8a, 0x2a, 0xba, 0x09, 0xc3, 0xb1, 0x13, 0x6e, 0x93, - 0x58, 0x1c, 0x80, 0x99, 0x07, 0x15, 0xaf, 0x89, 0xe9, 0x8e, 0x24, 0x7e, 0x93, 0x24, 0xd7, 0xc2, - 0x06, 0xab, 0x8a, 0x05, 0x09, 0xfb, 0x6f, 0x0c, 0xc3, 0xc5, 0xe5, 0x46, 0x2d, 0x67, 0x5d, 0x5d, - 0x81, 0xe1, 0x56, 0xe8, 0xee, 0x93, 0x50, 0x8c, 0xb3, 0xa2, 0x52, 0x65, 0xa5, 0x58, 0x40, 0xd1, - 0xeb, 0x30, 0xce, 0x2f, 0xa4, 0x1b, 0x8e, 0xdf, 0xf2, 0xe4, 0x10, 0x9f, 0x17, 0xd8, 0xe3, 0x77, - 0x35, 0x18, 0x36, 0x30, 0x4f, 0xb8, 0xa8, 0xae, 0xa4, 0x36, 0x63, 0xde, 0x65, 0xf7, 0x23, 0x16, - 0x4c, 0xf3, 0x66, 0x16, 0xe3, 0x38, 0x74, 0x37, 0x3b, 0x31, 0x89, 0x66, 0x87, 0xd8, 0x49, 0xb7, - 0x9c, 0x35, 0x5a, 0xb9, 0x23, 0x30, 0x7f, 0x37, 0x45, 0x85, 0x1f, 0x82, 0xb3, 0xa2, 0xdd, 0xe9, - 0x34, 0x18, 0x77, 0x35, 0x8b, 0x7e, 0xc8, 0x82, 0xb9, 0x66, 0xe0, 0xc7, 0x61, 0xe0, 0x79, 0x24, - 0xac, 0x77, 0x36, 0x3d, 0x37, 0xda, 0xe1, 0xeb, 0x14, 0x93, 0x2d, 0x76, 0x12, 0xe4, 0xcc, 0xa1, - 0x42, 0x12, 0x73, 0x78, 0xe9, 0xe8, 0xb0, 0x32, 0xb7, 0x9c, 0x4b, 0x0a, 0xf7, 0x68, 0x06, 0xed, - 0x02, 0xa2, 0x57, 0x69, 0x23, 0x76, 0xb6, 0x49, 0xd2, 0xf8, 0xc8, 0xe0, 0x8d, 0x3f, 0x76, 0x74, - 0x58, 0x41, 0xeb, 0x5d, 0x24, 0x70, 0x06, 0x59, 0xf4, 0x1e, 0x9c, 0xa7, 0xa5, 0x5d, 0xdf, 0x3a, - 0x3a, 0x78, 0x73, 0xb3, 0x47, 0x87, 0x95, 0xf3, 0xeb, 0x19, 0x44, 0x70, 0x26, 0xe9, 0xb9, 0x65, - 0xb8, 0x90, 0x39, 0x55, 0x68, 0x1a, 0x8a, 0xbb, 0x84, 0xb3, 0x20, 0x65, 0x4c, 0x7f, 0xa2, 0xf3, - 0x30, 0xb4, 0xef, 0x78, 0x1d, 0xb1, 0x4a, 0x31, 0xff, 0xf3, 0xd9, 0xc2, 0xeb, 0x96, 0xdd, 0x84, - 0xf1, 0x65, 0xa7, 0xed, 0x6c, 0xba, 0x9e, 0x1b, 0xbb, 0x24, 0x42, 0xcf, 0x42, 0xd1, 0x69, 0xb5, - 0xd8, 0x15, 0x59, 0x5e, 0xba, 0x70, 0x74, 0x58, 0x29, 0x2e, 0xb6, 0xe8, 0x59, 0x0d, 0x0a, 0xeb, - 0x00, 0x53, 0x0c, 0xf4, 0x69, 0x28, 0xb5, 0xc2, 0xa0, 0x3d, 0x5b, 0x60, 0x98, 0x74, 0xa8, 0x4a, - 0xd5, 0x30, 0x68, 0xa7, 0x50, 0x19, 0x8e, 0xfd, 0x9b, 0x05, 0x78, 0x72, 0x99, 0xb4, 0x77, 0x56, - 0x1b, 0x39, 0x9b, 0xee, 0x2a, 0x8c, 0xee, 0x05, 0xbe, 0x1b, 0x07, 0x61, 0x24, 0x9a, 0x66, 0xb7, - 0xc9, 0x9a, 0x28, 0xc3, 0x0a, 0x8a, 0x2e, 0x43, 0xa9, 0x9d, 0x70, 0x02, 0xe3, 0x92, 0x8b, 0x60, - 0x3c, 0x00, 0x83, 0x50, 0x8c, 0x4e, 0x44, 0x42, 0x71, 0x0b, 0x2a, 0x8c, 0x3b, 0x11, 0x09, 0x31, - 0x83, 0x24, 0xc7, 0x29, 0x3d, 0x68, 0xc5, 0xb6, 0x4a, 0x1d, 0xa7, 0x14, 0x82, 0x35, 0x2c, 0x54, - 0x87, 0x72, 0xa4, 0x26, 0x75, 0x68, 0xf0, 0x49, 0x9d, 0x60, 0xe7, 0xad, 0x9a, 0xc9, 0x84, 0x88, - 0x71, 0x0c, 0x0c, 0xf7, 0x3d, 0x6f, 0xbf, 0x59, 0x00, 0xc4, 0x87, 0xf0, 0x2f, 0xd8, 0xc0, 0xdd, - 0xe9, 0x1e, 0xb8, 0x4c, 0xce, 0xeb, 0x56, 0xd0, 0x74, 0xbc, 0xf4, 0x11, 0x7e, 0x5a, 0xa3, 0xf7, - 0x93, 0x16, 0xa0, 0x65, 0xd7, 0x6f, 0x91, 0xf0, 0x0c, 0xc4, 0x8e, 0x93, 0x5d, 0xa4, 0xb7, 0x60, - 0x72, 0xd9, 0x73, 0x89, 0x1f, 0xd7, 0xea, 0xcb, 0x81, 0xbf, 0xe5, 0x6e, 0xa3, 0xcf, 0xc2, 0x24, - 0x95, 0xc2, 0x82, 0x4e, 0xdc, 0x20, 0xcd, 0xc0, 0x67, 0x0c, 0x2b, 0x95, 0x5d, 0xd0, 0xd1, 0x61, - 0x65, 0x72, 0xc3, 0x80, 0xe0, 0x14, 0xa6, 0xfd, 0x7b, 0xf4, 0x43, 0x83, 0xbd, 0x76, 0xe0, 0x13, - 0x3f, 0x5e, 0x0e, 0xfc, 0x16, 0x17, 0x6c, 0x3e, 0x0b, 0xa5, 0x98, 0x76, 0x9c, 0x7f, 0xe4, 0x15, - 0x39, 0xb5, 0xb4, 0xbb, 0xc7, 0x87, 0x95, 0xc7, 0xba, 0x6b, 0xb0, 0x0f, 0x62, 0x75, 0xd0, 0x77, - 0xc3, 0x70, 0x14, 0x3b, 0x71, 0x27, 0x12, 0x9f, 0xfd, 0xb4, 0xfc, 0xec, 0x06, 0x2b, 0x3d, 0x3e, - 0xac, 0x4c, 0xa9, 0x6a, 0xbc, 0x08, 0x8b, 0x0a, 0xe8, 0x39, 0x18, 0xd9, 0x23, 0x51, 0xe4, 0x6c, - 0x4b, 0x9e, 0x74, 0x4a, 0xd4, 0x1d, 0x59, 0xe3, 0xc5, 0x58, 0xc2, 0xd1, 0x33, 0x30, 0x44, 0xc2, - 0x30, 0x08, 0xc5, 0xaa, 0x9a, 0x10, 0x88, 0x43, 0x2b, 0xb4, 0x10, 0x73, 0x98, 0xfd, 0x1f, 0x2c, - 0x98, 0x52, 0x7d, 0xe5, 0x6d, 0x9d, 0x01, 0xf3, 0xf1, 0x25, 0x80, 0xa6, 0xfc, 0xc0, 0x88, 0x9d, - 0x77, 0x63, 0xd7, 0xae, 0x64, 0x5e, 0xa9, 0x5d, 0xc3, 0x98, 0x50, 0x56, 0x45, 0x11, 0xd6, 0xa8, - 0xd9, 0xff, 0xd2, 0x82, 0x73, 0xa9, 0x2f, 0xba, 0xe5, 0x46, 0x31, 0x7a, 0xa7, 0xeb, 0xab, 0xe6, - 0x07, 0xfb, 0x2a, 0x5a, 0x9b, 0x7d, 0x93, 0x5a, 0x73, 0xb2, 0x44, 0xfb, 0xa2, 0x1b, 0x30, 0xe4, - 0xc6, 0x64, 0x4f, 0x7e, 0xcc, 0x33, 0x3d, 0x3f, 0x86, 0xf7, 0x2a, 0x99, 0x91, 0x1a, 0xad, 0x89, - 0x39, 0x01, 0xfb, 0xc7, 0x8b, 0x50, 0xe6, 0xcb, 0x76, 0xcd, 0x69, 0x9f, 0xc1, 0x5c, 0xd4, 0xa0, - 0xc4, 0xa8, 0xf3, 0x8e, 0x3f, 0x9b, 0xdd, 0x71, 0xd1, 0x9d, 0x79, 0x2a, 0x59, 0x70, 0xe6, 0x45, - 0x1d, 0x66, 0xb4, 0x08, 0x33, 0x12, 0xc8, 0x01, 0xd8, 0x74, 0x7d, 0x27, 0x3c, 0xa0, 0x65, 0xb3, - 0x45, 0x46, 0xf0, 0xc5, 0xde, 0x04, 0x97, 0x14, 0x3e, 0x27, 0xab, 0xfa, 0x9a, 0x00, 0xb0, 0x46, - 0x74, 0xee, 0x35, 0x28, 0x2b, 0xe4, 0x93, 0xdc, 0xca, 0x73, 0x9f, 0x87, 0xa9, 0x54, 0x5b, 0xfd, - 0xaa, 0x8f, 0xeb, 0x97, 0xfa, 0x37, 0xd8, 0x29, 0x20, 0x7a, 0xbd, 0xe2, 0xef, 0x8b, 0xe3, 0xee, - 0x7d, 0x38, 0xef, 0x65, 0x9c, 0xb2, 0x62, 0xaa, 0x06, 0x3f, 0x95, 0x9f, 0x14, 0x9f, 0x7d, 0x3e, - 0x0b, 0x8a, 0x33, 0xdb, 0xa0, 0x17, 0x55, 0xd0, 0xa6, 0x6b, 0xde, 0xf1, 0x58, 0x7f, 0x85, 0xbc, - 0x78, 0x5b, 0x94, 0x61, 0x05, 0xa5, 0x47, 0xd8, 0x79, 0xd5, 0xf9, 0x9b, 0xe4, 0xa0, 0x41, 0x3c, - 0xd2, 0x8c, 0x83, 0xf0, 0x23, 0xed, 0xfe, 0x53, 0x7c, 0xf4, 0xf9, 0x09, 0x38, 0x26, 0x08, 0x14, - 0x6f, 0x92, 0x03, 0x3e, 0x15, 0xfa, 0xd7, 0x15, 0x7b, 0x7e, 0xdd, 0x2f, 0x59, 0x30, 0xa1, 0xbe, - 0xee, 0x0c, 0xb6, 0xfa, 0x92, 0xb9, 0xd5, 0x9f, 0xea, 0xb9, 0xc0, 0x73, 0x36, 0xf9, 0x37, 0x0b, - 0x70, 0x51, 0xe1, 0x50, 0x06, 0x95, 0xff, 0x11, 0xab, 0x6a, 0x01, 0xca, 0xbe, 0x92, 0x77, 0x2d, - 0x53, 0xd0, 0x4c, 0xa4, 0xdd, 0x04, 0x87, 0xf2, 0x19, 0x7e, 0x22, 0x94, 0x8e, 0xeb, 0x8a, 0x20, - 0xa1, 0xf4, 0x59, 0x82, 0x62, 0xc7, 0x6d, 0x89, 0x3b, 0xe3, 0xbb, 0xe4, 0x68, 0xdf, 0xa9, 0x55, - 0x8f, 0x0f, 0x2b, 0x4f, 0xe7, 0x29, 0x21, 0xe9, 0x65, 0x15, 0xcd, 0xdf, 0xa9, 0x55, 0x31, 0xad, - 0x8c, 0x16, 0x61, 0x4a, 0xea, 0x59, 0xef, 0x52, 0xa6, 0x33, 0xf0, 0xc5, 0xd5, 0xa2, 0xb4, 0x39, - 0xd8, 0x04, 0xe3, 0x34, 0x3e, 0xaa, 0xc2, 0xf4, 0x6e, 0x67, 0x93, 0x78, 0x24, 0xe6, 0x1f, 0x7c, - 0x93, 0x70, 0x5d, 0x47, 0x39, 0x11, 0x86, 0x6e, 0xa6, 0xe0, 0xb8, 0xab, 0x86, 0xfd, 0xe7, 0xec, - 0x88, 0x17, 0xa3, 0x57, 0x0f, 0x03, 0xba, 0xb0, 0x28, 0xf5, 0x8f, 0x72, 0x39, 0x0f, 0xb2, 0x2a, - 0x6e, 0x92, 0x83, 0x8d, 0x80, 0xb2, 0x87, 0xd9, 0xab, 0xc2, 0x58, 0xf3, 0xa5, 0x9e, 0x6b, 0xfe, - 0x57, 0x0a, 0x70, 0x41, 0x8d, 0x80, 0xc1, 0x80, 0xfd, 0x45, 0x1f, 0x83, 0x97, 0x60, 0xac, 0x45, - 0xb6, 0x9c, 0x8e, 0x17, 0x2b, 0xc5, 0xdb, 0x10, 0x57, 0xbe, 0x56, 0x93, 0x62, 0xac, 0xe3, 0x9c, - 0x60, 0xd8, 0x7e, 0x6e, 0x8c, 0xdd, 0xad, 0xb1, 0x43, 0xd7, 0xb8, 0xda, 0x35, 0x56, 0xee, 0xae, - 0x79, 0x06, 0x86, 0xdc, 0x3d, 0xca, 0x6b, 0x15, 0x4c, 0x16, 0xaa, 0x46, 0x0b, 0x31, 0x87, 0xa1, - 0x4f, 0xc1, 0x48, 0x33, 0xd8, 0xdb, 0x73, 0xfc, 0x16, 0xbb, 0xf2, 0xca, 0x4b, 0x63, 0x94, 0x1d, - 0x5b, 0xe6, 0x45, 0x58, 0xc2, 0xd0, 0x93, 0x50, 0x72, 0xc2, 0xed, 0x68, 0xb6, 0xc4, 0x70, 0x46, - 0x69, 0x4b, 0x8b, 0xe1, 0x76, 0x84, 0x59, 0x29, 0x95, 0x03, 0xee, 0x07, 0xe1, 0xae, 0xeb, 0x6f, - 0x57, 0xdd, 0x50, 0x6c, 0x09, 0x75, 0x17, 0xde, 0x53, 0x10, 0xac, 0x61, 0xa1, 0x55, 0x18, 0x6a, - 0x07, 0x61, 0x1c, 0xcd, 0x0e, 0xb3, 0xe1, 0x7e, 0x3a, 0xe7, 0x20, 0xe2, 0x5f, 0x5b, 0x0f, 0xc2, - 0x38, 0xf9, 0x00, 0xfa, 0x2f, 0xc2, 0xbc, 0x3a, 0xfa, 0x6e, 0x28, 0x12, 0x7f, 0x7f, 0x76, 0x84, - 0x51, 0x99, 0xcb, 0xa2, 0xb2, 0xe2, 0xef, 0xdf, 0x75, 0xc2, 0xe4, 0x94, 0x5e, 0xf1, 0xf7, 0x31, - 0xad, 0x83, 0xbe, 0x08, 0x65, 0xb9, 0xc5, 0x23, 0x21, 0x98, 0x67, 0x2e, 0x31, 0x79, 0x30, 0x60, - 0xf2, 0x5e, 0xc7, 0x0d, 0xc9, 0x1e, 0xf1, 0xe3, 0x28, 0x39, 0xd3, 0x24, 0x34, 0xc2, 0x09, 0x35, - 0xf4, 0x45, 0xa9, 0x0d, 0x5a, 0x0b, 0x3a, 0x7e, 0x1c, 0xcd, 0x96, 0x59, 0xf7, 0x32, 0xf5, 0xf4, - 0x77, 0x13, 0xbc, 0xb4, 0xba, 0x88, 0x57, 0xc6, 0x06, 0x29, 0x84, 0x61, 0xc2, 0x73, 0xf7, 0x89, - 0x4f, 0xa2, 0xa8, 0x1e, 0x06, 0x9b, 0x64, 0x16, 0x58, 0xcf, 0x2f, 0x66, 0xab, 0xaf, 0x83, 0x4d, - 0xb2, 0x34, 0x73, 0x74, 0x58, 0x99, 0xb8, 0xa5, 0xd7, 0xc1, 0x26, 0x09, 0x74, 0x07, 0x26, 0xa9, - 0x00, 0xe2, 0x26, 0x44, 0xc7, 0xfa, 0x11, 0x65, 0xd2, 0x07, 0x36, 0x2a, 0xe1, 0x14, 0x11, 0xf4, - 0x16, 0x94, 0x3d, 0x77, 0x8b, 0x34, 0x0f, 0x9a, 0x1e, 0x99, 0x1d, 0x67, 0x14, 0x33, 0xb7, 0xd5, - 0x2d, 0x89, 0xc4, 0x05, 0x3c, 0xf5, 0x17, 0x27, 0xd5, 0xd1, 0x5d, 0x78, 0x2c, 0x26, 0xe1, 0x9e, - 0xeb, 0x3b, 0x74, 0x3b, 0x08, 0x79, 0x81, 0x3d, 0x02, 0x4c, 0xb0, 0xf5, 0x76, 0x49, 0x0c, 0xdd, - 0x63, 0x1b, 0x99, 0x58, 0x38, 0xa7, 0x36, 0xba, 0x0d, 0x53, 0x6c, 0x27, 0xd4, 0x3b, 0x9e, 0x57, - 0x0f, 0x3c, 0xb7, 0x79, 0x30, 0x3b, 0xc9, 0x08, 0x7e, 0x4a, 0xde, 0x0b, 0x35, 0x13, 0x7c, 0x7c, - 0x58, 0x81, 0xe4, 0x1f, 0x4e, 0xd7, 0x46, 0x9b, 0x4c, 0xeb, 0xdb, 0x09, 0xdd, 0xf8, 0x80, 0xae, - 0x5f, 0xf2, 0x20, 0x9e, 0x9d, 0xea, 0xa9, 0x1f, 0xd0, 0x51, 0x95, 0x6a, 0x58, 0x2f, 0xc4, 0x69, - 0x82, 0x74, 0x6b, 0x47, 0x71, 0xcb, 0xf5, 0x67, 0xa7, 0xd9, 0x89, 0xa1, 0x76, 0x46, 0x83, 0x16, - 0x62, 0x0e, 0x63, 0x1a, 0x5f, 0xfa, 0xe3, 0x36, 0x3d, 0x41, 0x67, 0x18, 0x62, 0xa2, 0xf1, 0x95, - 0x00, 0x9c, 0xe0, 0x50, 0xa6, 0x26, 0x8e, 0x0f, 0x66, 0x11, 0x43, 0x55, 0xdb, 0x65, 0x63, 0xe3, - 0x8b, 0x98, 0x96, 0xa3, 0x5b, 0x30, 0x42, 0xfc, 0xfd, 0xd5, 0x30, 0xd8, 0x9b, 0x3d, 0x97, 0xbf, - 0x67, 0x57, 0x38, 0x0a, 0x3f, 0xd0, 0x13, 0x01, 0x4f, 0x14, 0x63, 0x49, 0x02, 0x3d, 0x80, 0xd9, - 0x8c, 0x19, 0xe1, 0x13, 0x70, 0x9e, 0x4d, 0xc0, 0xe7, 0x44, 0xdd, 0xd9, 0x8d, 0x1c, 0xbc, 0xe3, - 0x1e, 0x30, 0x9c, 0x4b, 0x1d, 0x7d, 0x19, 0x26, 0xf8, 0x86, 0xe2, 0xcf, 0x45, 0xd1, 0xec, 0x05, - 0xf6, 0x35, 0x97, 0xf3, 0x37, 0x27, 0x47, 0x5c, 0xba, 0x20, 0x3a, 0x34, 0xa1, 0x97, 0x46, 0xd8, - 0xa4, 0x66, 0x6f, 0xc2, 0xa4, 0x3a, 0xb7, 0xd8, 0xd2, 0x41, 0x15, 0x18, 0x62, 0xdc, 0x8e, 0xd0, - 0xc8, 0x94, 0xe9, 0x4c, 0x31, 0x4e, 0x08, 0xf3, 0x72, 0x36, 0x53, 0xee, 0xfb, 0x64, 0xe9, 0x20, - 0x26, 0x5c, 0xaa, 0x2e, 0x6a, 0x33, 0x25, 0x01, 0x38, 0xc1, 0xb1, 0xff, 0x2f, 0xe7, 0x1a, 0x93, - 0xc3, 0x71, 0x80, 0xeb, 0xe0, 0x05, 0x18, 0xdd, 0x09, 0xa2, 0x98, 0x62, 0xb3, 0x36, 0x86, 0x12, - 0x3e, 0xf1, 0x86, 0x28, 0xc7, 0x0a, 0x03, 0xbd, 0x01, 0x13, 0x4d, 0xbd, 0x01, 0x71, 0x97, 0xa9, - 0x21, 0x30, 0x5a, 0xc7, 0x26, 0x2e, 0x7a, 0x1d, 0x46, 0xd9, 0x63, 0x6f, 0x33, 0xf0, 0x04, 0x93, - 0x25, 0x2f, 0xe4, 0xd1, 0xba, 0x28, 0x3f, 0xd6, 0x7e, 0x63, 0x85, 0x8d, 0xae, 0xc0, 0x30, 0xed, - 0x42, 0xad, 0x2e, 0x6e, 0x11, 0xa5, 0x53, 0xb9, 0xc1, 0x4a, 0xb1, 0x80, 0xda, 0x7f, 0xb3, 0xa0, - 0x8d, 0x32, 0x95, 0x48, 0x09, 0xaa, 0xc3, 0xc8, 0x7d, 0xc7, 0x8d, 0x5d, 0x7f, 0x5b, 0xb0, 0x0b, - 0xcf, 0xf5, 0xbc, 0x52, 0x58, 0xa5, 0x7b, 0xbc, 0x02, 0xbf, 0xf4, 0xc4, 0x1f, 0x2c, 0xc9, 0x50, - 0x8a, 0x61, 0xc7, 0xf7, 0x29, 0xc5, 0xc2, 0xa0, 0x14, 0x31, 0xaf, 0xc0, 0x29, 0x8a, 0x3f, 0x58, - 0x92, 0x41, 0xef, 0x00, 0xc8, 0x65, 0x49, 0x5a, 0xe2, 0x91, 0xf5, 0x85, 0xfe, 0x44, 0x37, 0x54, - 0x9d, 0xa5, 0x49, 0x7a, 0xa5, 0x26, 0xff, 0xb1, 0x46, 0xcf, 0x8e, 0x19, 0x5b, 0xd5, 0xdd, 0x19, - 0xf4, 0x7d, 0xf4, 0x24, 0x70, 0xc2, 0x98, 0xb4, 0x16, 0x63, 0x31, 0x38, 0x9f, 0x1e, 0x4c, 0xa6, - 0xd8, 0x70, 0xf7, 0x88, 0x7e, 0x6a, 0x08, 0x22, 0x38, 0xa1, 0x67, 0xff, 0x5a, 0x11, 0x66, 0xf3, - 0xba, 0x4b, 0x17, 0x1d, 0x79, 0xe0, 0xc6, 0xcb, 0x94, 0x1b, 0xb2, 0xcc, 0x45, 0xb7, 0x22, 0xca, - 0xb1, 0xc2, 0xa0, 0xb3, 0x1f, 0xb9, 0xdb, 0x52, 0x24, 0x1c, 0x4a, 0x66, 0xbf, 0xc1, 0x4a, 0xb1, - 0x80, 0x52, 0xbc, 0x90, 0x38, 0x91, 0x78, 0xc5, 0xd7, 0x56, 0x09, 0x66, 0xa5, 0x58, 0x40, 0x75, - 0x7d, 0x53, 0xa9, 0x8f, 0xbe, 0xc9, 0x18, 0xa2, 0xa1, 0xd3, 0x1d, 0x22, 0xf4, 0x15, 0x80, 0x2d, - 0xd7, 0x77, 0xa3, 0x1d, 0x46, 0x7d, 0xf8, 0xc4, 0xd4, 0x15, 0x2f, 0xb5, 0xaa, 0xa8, 0x60, 0x8d, - 0x22, 0x7a, 0x15, 0xc6, 0xd4, 0x06, 0xac, 0x55, 0xd9, 0x93, 0x86, 0xf6, 0x44, 0x9c, 0x9c, 0x46, - 0x55, 0xac, 0xe3, 0xd9, 0xef, 0xa6, 0xd7, 0x8b, 0xd8, 0x01, 0xda, 0xf8, 0x5a, 0x83, 0x8e, 0x6f, - 0xa1, 0xf7, 0xf8, 0xda, 0xbf, 0x55, 0x84, 0x29, 0xa3, 0xb1, 0x4e, 0x34, 0xc0, 0x99, 0x75, 0x9d, - 0xde, 0x73, 0x4e, 0x4c, 0xc4, 0xfe, 0xb3, 0xfb, 0x6f, 0x15, 0xfd, 0x2e, 0xa4, 0x3b, 0x80, 0xd7, - 0x47, 0x5f, 0x81, 0xb2, 0xe7, 0x44, 0x4c, 0x77, 0x45, 0xc4, 0xbe, 0x1b, 0x84, 0x58, 0x22, 0x47, - 0x38, 0x51, 0xac, 0x5d, 0x35, 0x9c, 0x76, 0x42, 0x92, 0x5e, 0xc8, 0x94, 0xf7, 0x91, 0x66, 0x22, - 0xaa, 0x13, 0x94, 0x41, 0x3a, 0xc0, 0x1c, 0x86, 0x5e, 0x87, 0xf1, 0x90, 0xb0, 0x55, 0xb1, 0x4c, - 0x59, 0x39, 0xb6, 0xcc, 0x86, 0x12, 0x9e, 0x0f, 0x6b, 0x30, 0x6c, 0x60, 0x26, 0xac, 0xfc, 0x70, - 0x0f, 0x56, 0xfe, 0x39, 0x18, 0x61, 0x3f, 0xd4, 0x0a, 0x50, 0xb3, 0x51, 0xe3, 0xc5, 0x58, 0xc2, - 0xd3, 0x0b, 0x66, 0x74, 0xc0, 0x05, 0xf3, 0x69, 0x98, 0xac, 0x3a, 0x64, 0x2f, 0xf0, 0x57, 0xfc, - 0x56, 0x3b, 0x70, 0xfd, 0x18, 0xcd, 0x42, 0x89, 0xdd, 0x0e, 0x7c, 0x6f, 0x97, 0x28, 0x05, 0x5c, - 0xa2, 0x8c, 0xb9, 0xbd, 0x0d, 0x17, 0xaa, 0xc1, 0x7d, 0xff, 0xbe, 0x13, 0xb6, 0x16, 0xeb, 0x35, - 0x4d, 0xce, 0x5d, 0x97, 0x72, 0x16, 0x37, 0xbb, 0xc8, 0x3c, 0x53, 0xb5, 0x9a, 0xfc, 0xae, 0x5d, - 0x75, 0x3d, 0x92, 0xa3, 0x8d, 0xf8, 0xdb, 0x05, 0xa3, 0xa5, 0x04, 0x5f, 0x3d, 0x71, 0x58, 0xb9, - 0x4f, 0x1c, 0x6f, 0xc3, 0xe8, 0x96, 0x4b, 0xbc, 0x16, 0x26, 0x5b, 0x62, 0x89, 0x3d, 0x9b, 0xff, - 0x92, 0xbc, 0x4a, 0x31, 0xa5, 0xf6, 0x89, 0x4b, 0x69, 0xab, 0xa2, 0x32, 0x56, 0x64, 0xd0, 0x2e, - 0x4c, 0x4b, 0x31, 0x40, 0x42, 0xc5, 0x82, 0x7b, 0xae, 0x97, 0x6c, 0x61, 0x12, 0x3f, 0x7f, 0x74, - 0x58, 0x99, 0xc6, 0x29, 0x32, 0xb8, 0x8b, 0x30, 0x15, 0xcb, 0xf6, 0xe8, 0xd1, 0x5a, 0x62, 0xc3, - 0xcf, 0xc4, 0x32, 0x26, 0x61, 0xb2, 0x52, 0xfb, 0x67, 0x2c, 0x78, 0xbc, 0x6b, 0x64, 0x84, 0xa4, - 0x7d, 0xca, 0xb3, 0x90, 0x96, 0x7c, 0x0b, 0xfd, 0x25, 0x5f, 0xfb, 0x1f, 0x59, 0x70, 0x7e, 0x65, - 0xaf, 0x1d, 0x1f, 0x54, 0x5d, 0xf3, 0x19, 0xe6, 0x35, 0x18, 0xde, 0x23, 0x2d, 0xb7, 0xb3, 0x27, - 0x66, 0xae, 0x22, 0x8f, 0x9f, 0x35, 0x56, 0x7a, 0x7c, 0x58, 0x99, 0x68, 0xc4, 0x41, 0xe8, 0x6c, - 0x13, 0x5e, 0x80, 0x05, 0x3a, 0x3b, 0xc4, 0xdd, 0xf7, 0xc9, 0x2d, 0x77, 0xcf, 0x95, 0x96, 0x01, - 0x3d, 0x75, 0x67, 0xf3, 0x72, 0x40, 0xe7, 0xdf, 0xee, 0x38, 0x7e, 0xec, 0xc6, 0x07, 0xe2, 0x85, - 0x49, 0x12, 0xc1, 0x09, 0x3d, 0xfb, 0xdb, 0x16, 0x4c, 0xc9, 0x75, 0xbf, 0xd8, 0x6a, 0x85, 0x24, - 0x8a, 0xd0, 0x1c, 0x14, 0xdc, 0xb6, 0xe8, 0x25, 0x88, 0x5e, 0x16, 0x6a, 0x75, 0x5c, 0x70, 0xdb, - 0xa8, 0x0e, 0x65, 0x6e, 0x60, 0x90, 0x2c, 0xae, 0x81, 0xcc, 0x14, 0x58, 0x0f, 0x36, 0x64, 0x4d, - 0x9c, 0x10, 0x91, 0x1c, 0x1c, 0x3b, 0x33, 0x8b, 0xe6, 0xf3, 0xd4, 0x0d, 0x51, 0x8e, 0x15, 0x06, - 0xba, 0x0a, 0xa3, 0x7e, 0xd0, 0xe2, 0xf6, 0x1e, 0xfc, 0xf6, 0x63, 0x4b, 0x76, 0x5d, 0x94, 0x61, - 0x05, 0xb5, 0x7f, 0xcc, 0x82, 0x71, 0xf9, 0x65, 0x03, 0x32, 0x93, 0x74, 0x6b, 0x25, 0x8c, 0x64, - 0xb2, 0xb5, 0x28, 0x33, 0xc8, 0x20, 0x06, 0x0f, 0x58, 0x3c, 0x09, 0x0f, 0x68, 0xff, 0x74, 0x01, - 0x26, 0x65, 0x77, 0x1a, 0x9d, 0xcd, 0x88, 0xc4, 0x68, 0x03, 0xca, 0x0e, 0x1f, 0x72, 0x22, 0x57, - 0xec, 0x33, 0xd9, 0xc2, 0x87, 0x31, 0x3f, 0xc9, 0xb5, 0xbc, 0x28, 0x6b, 0xe3, 0x84, 0x10, 0xf2, - 0x60, 0xc6, 0x0f, 0x62, 0x76, 0x44, 0x2b, 0x78, 0xaf, 0x27, 0x90, 0x34, 0xf5, 0x8b, 0x82, 0xfa, - 0xcc, 0x7a, 0x9a, 0x0a, 0xee, 0x26, 0x8c, 0x56, 0xa4, 0xc2, 0xa3, 0x98, 0x2f, 0x6e, 0xe8, 0xb3, - 0x90, 0xad, 0xef, 0xb0, 0x7f, 0xc3, 0x82, 0xb2, 0x44, 0x3b, 0x8b, 0xd7, 0xae, 0x35, 0x18, 0x89, - 0xd8, 0x24, 0xc8, 0xa1, 0xb1, 0x7b, 0x75, 0x9c, 0xcf, 0x57, 0x72, 0xf3, 0xf0, 0xff, 0x11, 0x96, - 0x34, 0x98, 0xbe, 0x5b, 0x75, 0xff, 0x63, 0xa2, 0xef, 0x56, 0xfd, 0xc9, 0xb9, 0x61, 0xfe, 0x1b, - 0xeb, 0xb3, 0x26, 0xd6, 0x52, 0x06, 0xa9, 0x1d, 0x92, 0x2d, 0xf7, 0x41, 0x9a, 0x41, 0xaa, 0xb3, - 0x52, 0x2c, 0xa0, 0xe8, 0x1d, 0x18, 0x6f, 0x4a, 0x45, 0x67, 0x72, 0x0c, 0x5c, 0xe9, 0xa9, 0x74, - 0x57, 0xef, 0x33, 0xdc, 0x16, 0x74, 0x59, 0xab, 0x8f, 0x0d, 0x6a, 0xa6, 0x0d, 0x42, 0xb1, 0x9f, - 0x0d, 0x42, 0x42, 0x37, 0xf7, 0x15, 0xdd, 0xfe, 0x59, 0x0b, 0x86, 0xb9, 0xba, 0x6c, 0x30, 0xfd, - 0xa2, 0xf6, 0x5c, 0x95, 0x8c, 0xdd, 0x5d, 0x5a, 0x28, 0x9e, 0x9f, 0xd0, 0x1a, 0x94, 0xd9, 0x0f, - 0xa6, 0x36, 0x28, 0xe6, 0x1b, 0xc1, 0xf2, 0x56, 0xf5, 0x0e, 0xde, 0x95, 0xd5, 0x70, 0x42, 0xc1, - 0xfe, 0x89, 0x22, 0x3d, 0xaa, 0x12, 0x54, 0xe3, 0x06, 0xb7, 0x1e, 0xdd, 0x0d, 0x5e, 0x78, 0x54, - 0x37, 0xf8, 0x36, 0x4c, 0x35, 0xb5, 0xc7, 0xad, 0x64, 0x26, 0xaf, 0xf6, 0x5c, 0x24, 0xda, 0x3b, - 0x18, 0x57, 0x19, 0x2d, 0x9b, 0x44, 0x70, 0x9a, 0x2a, 0xfa, 0x3e, 0x18, 0xe7, 0xf3, 0x2c, 0x5a, - 0x29, 0xb1, 0x56, 0x3e, 0x95, 0xbf, 0x5e, 0xf4, 0x26, 0xd8, 0x4a, 0x6c, 0x68, 0xd5, 0xb1, 0x41, - 0xcc, 0xfe, 0xb5, 0x51, 0x18, 0x5a, 0xd9, 0x27, 0x7e, 0x7c, 0x06, 0x07, 0x52, 0x13, 0x26, 0x5d, - 0x7f, 0x3f, 0xf0, 0xf6, 0x49, 0x8b, 0xc3, 0x4f, 0x72, 0xb9, 0x3e, 0x26, 0x48, 0x4f, 0xd6, 0x0c, - 0x12, 0x38, 0x45, 0xf2, 0x51, 0x48, 0x98, 0xd7, 0x61, 0x98, 0xcf, 0xbd, 0x10, 0x2f, 0x33, 0x95, - 0xc1, 0x6c, 0x10, 0xc5, 0x2e, 0x48, 0xa4, 0x5f, 0xae, 0x7d, 0x16, 0xd5, 0xd1, 0xbb, 0x30, 0xb9, - 0xe5, 0x86, 0x51, 0x4c, 0x45, 0xc3, 0x28, 0x76, 0xf6, 0xda, 0x0f, 0x21, 0x51, 0xaa, 0x71, 0x58, - 0x35, 0x28, 0xe1, 0x14, 0x65, 0xb4, 0x0d, 0x13, 0x54, 0xc8, 0x49, 0x9a, 0x1a, 0x39, 0x71, 0x53, - 0x4a, 0x65, 0x74, 0x4b, 0x27, 0x84, 0x4d, 0xba, 0xf4, 0x30, 0x69, 0x32, 0xa1, 0x68, 0x94, 0x71, - 0x14, 0xea, 0x30, 0xe1, 0xd2, 0x10, 0x87, 0xd1, 0x33, 0x89, 0x99, 0xad, 0x94, 0xcd, 0x33, 0x49, - 0x33, 0x4e, 0xf9, 0x2a, 0x94, 0x09, 0x1d, 0x42, 0x4a, 0x58, 0x28, 0xc6, 0x17, 0x06, 0xeb, 0xeb, - 0x9a, 0xdb, 0x0c, 0x03, 0x53, 0x96, 0x5f, 0x91, 0x94, 0x70, 0x42, 0x14, 0x2d, 0xc3, 0x70, 0x44, - 0x42, 0x97, 0x44, 0x42, 0x45, 0xde, 0x63, 0x1a, 0x19, 0x1a, 0xb7, 0x96, 0xe6, 0xbf, 0xb1, 0xa8, - 0x4a, 0x97, 0x97, 0xc3, 0xa4, 0x21, 0xa6, 0x15, 0xd7, 0x96, 0xd7, 0x22, 0x2b, 0xc5, 0x02, 0x8a, - 0xde, 0x82, 0x91, 0x90, 0x78, 0x4c, 0x59, 0x34, 0x31, 0xf8, 0x22, 0xe7, 0xba, 0x27, 0x5e, 0x0f, - 0x4b, 0x02, 0xe8, 0x26, 0xa0, 0x90, 0x50, 0x1e, 0xc2, 0xf5, 0xb7, 0x95, 0x31, 0x87, 0xd0, 0x75, - 0x3f, 0x21, 0xda, 0x3f, 0x87, 0x13, 0x0c, 0x69, 0x47, 0x89, 0x33, 0xaa, 0xa1, 0xeb, 0x30, 0xa3, - 0x4a, 0x6b, 0x7e, 0x14, 0x3b, 0x7e, 0x93, 0x30, 0x35, 0x77, 0x39, 0xe1, 0x8a, 0x70, 0x1a, 0x01, - 0x77, 0xd7, 0xb1, 0xbf, 0x4e, 0xd9, 0x19, 0x3a, 0x5a, 0x67, 0xc0, 0x0b, 0xbc, 0x69, 0xf2, 0x02, - 0x17, 0x73, 0x67, 0x2e, 0x87, 0x0f, 0x38, 0xb2, 0x60, 0x4c, 0x9b, 0xd9, 0x64, 0xcd, 0x5a, 0x3d, - 0xd6, 0x6c, 0x07, 0xa6, 0xe9, 0x4a, 0xbf, 0xbd, 0xc9, 0x1c, 0x87, 0x5a, 0x6c, 0x61, 0x16, 0x1e, - 0x6e, 0x61, 0xaa, 0x57, 0xe6, 0x5b, 0x29, 0x82, 0xb8, 0xab, 0x09, 0xf4, 0x9a, 0xd4, 0x9c, 0x14, - 0x0d, 0x23, 0x2d, 0xae, 0x15, 0x39, 0x3e, 0xac, 0x4c, 0x6b, 0x1f, 0xa2, 0x6b, 0x4a, 0xec, 0xaf, - 0xca, 0x6f, 0x54, 0xaf, 0xf9, 0x4d, 0xb5, 0x58, 0x52, 0xaf, 0xf9, 0x6a, 0x39, 0xe0, 0x04, 0x87, - 0xee, 0x51, 0x2a, 0x82, 0xa4, 0x5f, 0xf3, 0xa9, 0x80, 0x82, 0x19, 0xc4, 0x7e, 0x19, 0x60, 0xe5, - 0x01, 0x69, 0xf2, 0xa5, 0xae, 0x3f, 0x40, 0x5a, 0xf9, 0x0f, 0x90, 0xf6, 0x7f, 0xb2, 0x60, 0x72, - 0x75, 0xd9, 0x10, 0x13, 0xe7, 0x01, 0xb8, 0x6c, 0x74, 0xef, 0xde, 0xba, 0xd4, 0xad, 0x73, 0xf5, - 0xa8, 0x2a, 0xc5, 0x1a, 0x06, 0xba, 0x08, 0x45, 0xaf, 0xe3, 0x0b, 0x91, 0x65, 0xe4, 0xe8, 0xb0, - 0x52, 0xbc, 0xd5, 0xf1, 0x31, 0x2d, 0xd3, 0x4c, 0xf9, 0x8a, 0x03, 0x9b, 0xf2, 0xf5, 0x75, 0x08, - 0x42, 0x15, 0x18, 0xba, 0x7f, 0xdf, 0x6d, 0x71, 0xb3, 0x6b, 0xa1, 0xf7, 0xbf, 0x77, 0xaf, 0x56, - 0x8d, 0x30, 0x2f, 0xb7, 0xbf, 0x56, 0x84, 0xb9, 0x55, 0x8f, 0x3c, 0xf8, 0x90, 0xa6, 0xe7, 0x83, - 0x1a, 0x22, 0x9e, 0x8c, 0x5f, 0x3c, 0xa9, 0xd5, 0x65, 0xff, 0xf1, 0xd8, 0x82, 0x11, 0xfe, 0x98, - 0x2d, 0x0d, 0xd1, 0xdf, 0xc8, 0x6a, 0x3d, 0x7f, 0x40, 0xe6, 0xf9, 0xa3, 0xb8, 0x30, 0x40, 0x57, - 0x37, 0xad, 0x28, 0xc5, 0x92, 0xf8, 0xdc, 0x67, 0x61, 0x5c, 0xc7, 0x3c, 0x91, 0xfd, 0xf3, 0xff, - 0x5f, 0x84, 0x69, 0xda, 0x83, 0x47, 0x3a, 0x11, 0x77, 0xba, 0x27, 0xe2, 0xb4, 0x6d, 0x60, 0xfb, - 0xcf, 0xc6, 0x3b, 0xe9, 0xd9, 0x78, 0x29, 0x6f, 0x36, 0xce, 0x7a, 0x0e, 0x7e, 0xc8, 0x82, 0x73, - 0xab, 0x5e, 0xd0, 0xdc, 0x4d, 0x99, 0xe7, 0xbe, 0x0a, 0x63, 0xf4, 0x1c, 0x8f, 0x0c, 0xbf, 0x17, - 0xc3, 0x13, 0x4a, 0x80, 0xb0, 0x8e, 0xa7, 0x55, 0xbb, 0x73, 0xa7, 0x56, 0xcd, 0x72, 0xa0, 0x12, - 0x20, 0xac, 0xe3, 0xd9, 0xdf, 0xb2, 0xe0, 0xa9, 0xeb, 0xcb, 0x2b, 0xc9, 0x52, 0xec, 0xf2, 0xe1, - 0xa2, 0x52, 0x60, 0x4b, 0xeb, 0x4a, 0x22, 0x05, 0x56, 0x59, 0x2f, 0x04, 0xf4, 0xe3, 0xe2, 0x9f, - 0xf8, 0x0b, 0x16, 0x9c, 0xbb, 0xee, 0xc6, 0xf4, 0x5a, 0x4e, 0x7b, 0x13, 0xd1, 0x7b, 0x39, 0x72, - 0xe3, 0x20, 0x3c, 0x48, 0x7b, 0x13, 0x61, 0x05, 0xc1, 0x1a, 0x16, 0x6f, 0x79, 0xdf, 0x65, 0x66, - 0x54, 0x05, 0x53, 0x15, 0x85, 0x45, 0x39, 0x56, 0x18, 0xf4, 0xc3, 0x5a, 0x6e, 0xc8, 0x44, 0x89, - 0x03, 0x71, 0xc2, 0xaa, 0x0f, 0xab, 0x4a, 0x00, 0x4e, 0x70, 0xec, 0x9f, 0xb1, 0xe0, 0xc2, 0x75, - 0xaf, 0x13, 0xc5, 0x24, 0xdc, 0x8a, 0x8c, 0xce, 0xbe, 0x0c, 0x65, 0x22, 0xc5, 0x75, 0xd1, 0x57, - 0xc5, 0x60, 0x2a, 0x39, 0x9e, 0xbb, 0x32, 0x29, 0xbc, 0x01, 0x6c, 0xdd, 0x4f, 0x66, 0xa3, 0xfd, - 0xcb, 0x05, 0x98, 0xb8, 0xb1, 0xb1, 0x51, 0xbf, 0x4e, 0x62, 0x71, 0x8b, 0xf5, 0x57, 0x35, 0x63, - 0x4d, 0x63, 0xd6, 0x4b, 0x28, 0xea, 0xc4, 0xae, 0x37, 0xcf, 0x7d, 0x67, 0xe7, 0x6b, 0x7e, 0x7c, - 0x3b, 0x6c, 0xc4, 0xa1, 0xeb, 0x6f, 0x67, 0xea, 0xd8, 0xe4, 0x5d, 0x5b, 0xcc, 0xbb, 0x6b, 0xd1, - 0xcb, 0x30, 0xcc, 0x9c, 0x77, 0xa5, 0x78, 0xf2, 0x84, 0x92, 0x29, 0x58, 0xe9, 0xf1, 0x61, 0xa5, - 0x7c, 0x07, 0xd7, 0xf8, 0x1f, 0x2c, 0x50, 0xd1, 0x1d, 0x18, 0xdb, 0x89, 0xe3, 0xf6, 0x0d, 0xe2, - 0xb4, 0x48, 0x28, 0x4f, 0x87, 0x4b, 0x59, 0xa7, 0x03, 0x1d, 0x04, 0x8e, 0x96, 0x6c, 0xa8, 0xa4, - 0x2c, 0xc2, 0x3a, 0x1d, 0xbb, 0x01, 0x90, 0xc0, 0x4e, 0x49, 0xbf, 0x60, 0xff, 0xa1, 0x05, 0x23, - 0xdc, 0x8f, 0x2a, 0x44, 0x9f, 0x83, 0x12, 0x79, 0x40, 0x9a, 0x82, 0x73, 0xcc, 0xec, 0x70, 0xc2, - 0x78, 0x70, 0x6d, 0x39, 0xfd, 0x8f, 0x59, 0x2d, 0x74, 0x03, 0x46, 0x68, 0x6f, 0xaf, 0x2b, 0xa7, - 0xb2, 0xa7, 0xf3, 0xbe, 0x58, 0x4d, 0x3b, 0xe7, 0x55, 0x44, 0x11, 0x96, 0xd5, 0x99, 0xe6, 0xb7, - 0xd9, 0x6e, 0xd0, 0x03, 0x2c, 0xee, 0x75, 0xcf, 0x6e, 0x2c, 0xd7, 0x39, 0x92, 0xa0, 0xc6, 0x35, - 0xbf, 0xb2, 0x10, 0x27, 0x44, 0xec, 0x0d, 0x28, 0xd3, 0x49, 0x5d, 0xf4, 0x5c, 0xa7, 0xb7, 0xd2, - 0xf9, 0x79, 0x28, 0x4b, 0x05, 0x70, 0x24, 0x5c, 0x71, 0x18, 0x55, 0xa9, 0x1f, 0x8e, 0x70, 0x02, - 0xb7, 0xb7, 0xe0, 0x3c, 0x7b, 0xf9, 0x77, 0xe2, 0x1d, 0x63, 0x8f, 0xf5, 0x5f, 0xcc, 0x2f, 0x08, - 0x41, 0x8c, 0xcf, 0xcc, 0xac, 0xe6, 0x3b, 0x30, 0x2e, 0x29, 0x26, 0x42, 0x99, 0xfd, 0xc7, 0x25, - 0x78, 0xa2, 0xd6, 0xc8, 0x77, 0xb1, 0x7b, 0x1d, 0xc6, 0x39, 0x9b, 0x46, 0x97, 0xb6, 0xe3, 0x89, - 0x76, 0xd5, 0xbb, 0xd8, 0x86, 0x06, 0xc3, 0x06, 0x26, 0x7a, 0x0a, 0x8a, 0xee, 0x7b, 0x7e, 0xda, - 0x0c, 0xb7, 0xf6, 0xf6, 0x3a, 0xa6, 0xe5, 0x14, 0x4c, 0x39, 0x3e, 0x7e, 0x94, 0x2a, 0xb0, 0xe2, - 0xfa, 0xde, 0x84, 0x49, 0x37, 0x6a, 0x46, 0x6e, 0xcd, 0xa7, 0xe7, 0x4c, 0xe2, 0x9e, 0x99, 0x28, - 0x09, 0x68, 0xa7, 0x15, 0x14, 0xa7, 0xb0, 0xb5, 0x73, 0x7d, 0x68, 0x60, 0xae, 0xb1, 0xaf, 0x6f, - 0x0a, 0x65, 0x88, 0xdb, 0xec, 0xeb, 0x22, 0x66, 0xd4, 0x26, 0x18, 0x62, 0xfe, 0xc1, 0x11, 0x96, - 0x30, 0x2a, 0x81, 0x35, 0x77, 0x9c, 0xf6, 0x62, 0x27, 0xde, 0xa9, 0xba, 0x51, 0x33, 0xd8, 0x27, - 0xe1, 0x01, 0x13, 0x9e, 0x47, 0x13, 0x09, 0x4c, 0x01, 0x96, 0x6f, 0x2c, 0xd6, 0x29, 0x26, 0xee, - 0xae, 0x63, 0x72, 0x85, 0x70, 0x1a, 0x5c, 0xe1, 0x22, 0x4c, 0xc9, 0x66, 0x1a, 0x24, 0x62, 0x77, - 0xc4, 0x18, 0xeb, 0x98, 0x32, 0xb5, 0x15, 0xc5, 0xaa, 0x5b, 0x69, 0x7c, 0xf4, 0x1a, 0x4c, 0xb8, - 0xbe, 0x1b, 0xbb, 0x4e, 0x1c, 0x84, 0xec, 0x86, 0xe5, 0x72, 0x32, 0xb3, 0x64, 0xab, 0xe9, 0x00, - 0x6c, 0xe2, 0xd9, 0x7f, 0x54, 0x82, 0x19, 0x36, 0x6d, 0xdf, 0x59, 0x61, 0x1f, 0x9b, 0x15, 0x76, - 0xa7, 0x7b, 0x85, 0x9d, 0x06, 0xbb, 0xfb, 0x51, 0x2e, 0xb3, 0x77, 0xa1, 0xac, 0x6c, 0x81, 0xa5, - 0x33, 0x80, 0x95, 0xe3, 0x0c, 0xd0, 0x9f, 0xfb, 0x90, 0xcf, 0xb8, 0xc5, 0xcc, 0x67, 0xdc, 0xbf, - 0x63, 0x41, 0x62, 0x12, 0x89, 0x6e, 0x40, 0xb9, 0x1d, 0x30, 0xb3, 0x83, 0x50, 0xda, 0xf2, 0x3c, - 0x91, 0x79, 0x51, 0xf1, 0x4b, 0x91, 0x8f, 0x5f, 0x5d, 0xd6, 0xc0, 0x49, 0x65, 0xb4, 0x04, 0x23, - 0xed, 0x90, 0x34, 0x62, 0xe6, 0xb4, 0xd9, 0x97, 0x0e, 0x5f, 0x23, 0x1c, 0x1f, 0xcb, 0x8a, 0xf6, - 0xaf, 0x58, 0x00, 0xfc, 0xa5, 0xd4, 0xf1, 0xb7, 0xc9, 0x19, 0x68, 0x7f, 0xab, 0x50, 0x8a, 0xda, - 0xa4, 0xd9, 0xcb, 0x20, 0x24, 0xe9, 0x4f, 0xa3, 0x4d, 0x9a, 0xc9, 0x80, 0xd3, 0x7f, 0x98, 0xd5, - 0xb6, 0xff, 0x2a, 0xc0, 0x64, 0x82, 0x56, 0x8b, 0xc9, 0x1e, 0x7a, 0xd1, 0x70, 0x89, 0xbb, 0x98, - 0x72, 0x89, 0x2b, 0x33, 0x6c, 0x4d, 0xd1, 0xf8, 0x2e, 0x14, 0xf7, 0x9c, 0x07, 0x42, 0x93, 0xf4, - 0x7c, 0xef, 0x6e, 0x50, 0xfa, 0xf3, 0x6b, 0xce, 0x03, 0x2e, 0x33, 0x3d, 0x2f, 0x17, 0xc8, 0x9a, - 0xf3, 0xe0, 0x98, 0x9b, 0x7d, 0xb0, 0x43, 0xea, 0x96, 0x1b, 0xc5, 0x1f, 0xfc, 0x97, 0xe4, 0x3f, - 0x5b, 0x76, 0xb4, 0x11, 0xd6, 0x96, 0xeb, 0x8b, 0x77, 0xc3, 0x81, 0xda, 0x72, 0xfd, 0x74, 0x5b, - 0xae, 0x3f, 0x40, 0x5b, 0xae, 0x8f, 0xde, 0x87, 0x11, 0xf1, 0x46, 0xcf, 0x6c, 0xbd, 0x4d, 0x2d, - 0x55, 0x5e, 0x7b, 0xe2, 0x89, 0x9f, 0xb7, 0xb9, 0x20, 0x65, 0x42, 0x51, 0xda, 0xb7, 0x5d, 0xd9, - 0x20, 0xfa, 0x5b, 0x16, 0x4c, 0x8a, 0xdf, 0x98, 0xbc, 0xd7, 0x21, 0x51, 0x2c, 0x78, 0xcf, 0xcf, - 0x0c, 0xde, 0x07, 0x51, 0x91, 0x77, 0xe5, 0x33, 0xf2, 0x98, 0x35, 0x81, 0x7d, 0x7b, 0x94, 0xea, - 0x05, 0xfa, 0x27, 0x16, 0x9c, 0xdf, 0x73, 0x1e, 0xf0, 0x16, 0x79, 0x19, 0x76, 0x62, 0x37, 0x10, - 0xb6, 0xeb, 0x9f, 0x1b, 0x6c, 0xfa, 0xbb, 0xaa, 0xf3, 0x4e, 0x4a, 0x33, 0xd7, 0xf3, 0x59, 0x28, - 0x7d, 0xbb, 0x9a, 0xd9, 0xaf, 0xb9, 0x2d, 0x18, 0x95, 0xeb, 0x2d, 0x43, 0xf2, 0xae, 0xea, 0x8c, - 0xf5, 0x89, 0x4d, 0x24, 0x74, 0xbf, 0x34, 0xda, 0x8e, 0x58, 0x6b, 0x8f, 0xb4, 0x9d, 0x77, 0x61, - 0x5c, 0x5f, 0x63, 0x8f, 0xb4, 0xad, 0xf7, 0xe0, 0x5c, 0xc6, 0x5a, 0x7a, 0xa4, 0x4d, 0xde, 0x87, - 0x8b, 0xb9, 0xeb, 0xe3, 0x51, 0x36, 0x6c, 0xff, 0xb2, 0xa5, 0x9f, 0x83, 0x67, 0xa0, 0x82, 0x5f, - 0x36, 0x55, 0xf0, 0x97, 0x7a, 0xef, 0x9c, 0x1c, 0x3d, 0xfc, 0x3b, 0x7a, 0xa7, 0xe9, 0xa9, 0x8e, - 0xde, 0x82, 0x61, 0x8f, 0x96, 0x48, 0xe3, 0x10, 0xbb, 0xff, 0x8e, 0x4c, 0x78, 0x29, 0x56, 0x1e, - 0x61, 0x41, 0xc1, 0xfe, 0x75, 0x0b, 0x4a, 0x67, 0x30, 0x12, 0xd8, 0x1c, 0x89, 0x17, 0x73, 0x49, - 0x8b, 0x20, 0x5c, 0xf3, 0xd8, 0xb9, 0xbf, 0x22, 0x03, 0x8d, 0xe5, 0x0c, 0xcc, 0xf7, 0xc3, 0xb9, - 0x5b, 0x81, 0xd3, 0x5a, 0x72, 0x3c, 0xc7, 0x6f, 0x92, 0xb0, 0xe6, 0x6f, 0xf7, 0xb5, 0x52, 0xd2, - 0x6d, 0x8a, 0x0a, 0xfd, 0x6c, 0x8a, 0xec, 0x1d, 0x40, 0x7a, 0x03, 0xc2, 0x8e, 0x13, 0xc3, 0x88, - 0xcb, 0x9b, 0x12, 0xc3, 0xff, 0x6c, 0x36, 0x77, 0xd7, 0xd5, 0x33, 0xcd, 0x42, 0x91, 0x17, 0x60, - 0x49, 0xc8, 0x7e, 0x1d, 0x32, 0x7d, 0xb7, 0xfa, 0xab, 0x0d, 0xec, 0x57, 0x61, 0x86, 0xd5, 0x3c, - 0x99, 0x48, 0x6b, 0xff, 0x88, 0x05, 0x53, 0xeb, 0xa9, 0x68, 0x0a, 0x57, 0xd8, 0x5b, 0x5f, 0x86, - 0xde, 0xb7, 0xc1, 0x4a, 0xb1, 0x80, 0x9e, 0xba, 0x7e, 0xe9, 0xcf, 0x2d, 0x48, 0x5c, 0x25, 0xcf, - 0x80, 0xa9, 0x5a, 0x36, 0x98, 0xaa, 0x4c, 0xbd, 0x87, 0xea, 0x4e, 0x1e, 0x4f, 0x85, 0x6e, 0xaa, - 0xb8, 0x00, 0x3d, 0x54, 0x1e, 0x09, 0x19, 0xee, 0x45, 0x3e, 0x69, 0x06, 0x0f, 0x90, 0x91, 0x02, - 0x98, 0x99, 0x90, 0xc2, 0xfd, 0x98, 0x98, 0x09, 0xa9, 0xfe, 0xe4, 0xec, 0xbe, 0xba, 0xd6, 0x65, - 0x76, 0x2a, 0x7d, 0x0f, 0x33, 0xfb, 0x76, 0x3c, 0xf7, 0x7d, 0xa2, 0xc2, 0x71, 0x54, 0x84, 0x19, - 0xb7, 0x28, 0x3d, 0x3e, 0xac, 0x4c, 0xa8, 0x7f, 0x3c, 0x66, 0x53, 0x52, 0xc5, 0xbe, 0x01, 0x53, - 0xa9, 0x01, 0x43, 0xaf, 0xc2, 0x50, 0x7b, 0xc7, 0x89, 0x48, 0xca, 0x34, 0x72, 0xa8, 0x4e, 0x0b, - 0x8f, 0x0f, 0x2b, 0x93, 0xaa, 0x02, 0x2b, 0xc1, 0x1c, 0xdb, 0xfe, 0x9f, 0x16, 0x94, 0xd6, 0x83, - 0xd6, 0x59, 0x2c, 0xa6, 0x37, 0x8d, 0xc5, 0xf4, 0x64, 0x5e, 0xc4, 0xbb, 0xdc, 0x75, 0xb4, 0x9a, - 0x5a, 0x47, 0x97, 0x72, 0x29, 0xf4, 0x5e, 0x42, 0x7b, 0x30, 0xc6, 0xe2, 0xe8, 0x09, 0x53, 0xcd, - 0x97, 0x0d, 0xfe, 0xbe, 0x92, 0xe2, 0xef, 0xa7, 0x34, 0x54, 0x8d, 0xcb, 0x7f, 0x0e, 0x46, 0x84, - 0xb9, 0x60, 0xda, 0xc0, 0x5d, 0xe0, 0x62, 0x09, 0xb7, 0x7f, 0xb6, 0x08, 0x46, 0xdc, 0x3e, 0xf4, - 0x1b, 0x16, 0xcc, 0x87, 0xdc, 0x63, 0xb0, 0x55, 0xed, 0x84, 0xae, 0xbf, 0xdd, 0x68, 0xee, 0x90, - 0x56, 0xc7, 0x73, 0xfd, 0xed, 0xda, 0xb6, 0x1f, 0xa8, 0xe2, 0x95, 0x07, 0xa4, 0xd9, 0x61, 0x3a, - 0xff, 0x3e, 0x41, 0x02, 0x95, 0x39, 0xce, 0xb5, 0xa3, 0xc3, 0xca, 0x3c, 0x3e, 0x11, 0x6d, 0x7c, - 0xc2, 0xbe, 0xa0, 0x6f, 0x59, 0xb0, 0xc0, 0xc3, 0xd9, 0x0d, 0xde, 0xff, 0x1e, 0xd2, 0x50, 0x5d, - 0x92, 0x4a, 0x88, 0x6c, 0x90, 0x70, 0x6f, 0xe9, 0x35, 0x31, 0xa0, 0x0b, 0xf5, 0x93, 0xb5, 0x85, - 0x4f, 0xda, 0x39, 0xfb, 0xdf, 0x14, 0x61, 0x42, 0x38, 0xab, 0x8b, 0x28, 0x28, 0xaf, 0x1a, 0x4b, - 0xe2, 0xe9, 0xd4, 0x92, 0x98, 0x31, 0x90, 0x4f, 0x27, 0x00, 0x4a, 0x04, 0x33, 0x9e, 0x13, 0xc5, - 0x37, 0x88, 0x13, 0xc6, 0x9b, 0xc4, 0xe1, 0x66, 0x2a, 0xc5, 0x13, 0x9b, 0xd4, 0x28, 0xf5, 0xcb, - 0xad, 0x34, 0x31, 0xdc, 0x4d, 0x1f, 0xed, 0x03, 0x62, 0xb6, 0x36, 0xa1, 0xe3, 0x47, 0xfc, 0x5b, - 0x5c, 0xf1, 0x1e, 0x70, 0xb2, 0x56, 0xe7, 0x44, 0xab, 0xe8, 0x56, 0x17, 0x35, 0x9c, 0xd1, 0x82, - 0x66, 0x43, 0x35, 0x34, 0xa8, 0x0d, 0xd5, 0x70, 0x1f, 0x2f, 0x12, 0x1f, 0xa6, 0xbb, 0xe2, 0x0d, - 0x7c, 0x09, 0xca, 0xca, 0xd6, 0x4d, 0x1c, 0x3a, 0xbd, 0xc3, 0x76, 0xa4, 0x29, 0x70, 0x15, 0x49, - 0x62, 0x67, 0x99, 0x90, 0xb3, 0xff, 0x69, 0xc1, 0x68, 0x90, 0x4f, 0xe2, 0x3a, 0x8c, 0x3a, 0x51, - 0xe4, 0x6e, 0xfb, 0xa4, 0x25, 0x76, 0xec, 0x27, 0xf3, 0x76, 0xac, 0xd1, 0x0c, 0xb3, 0x37, 0x5c, - 0x14, 0x35, 0xb1, 0xa2, 0x81, 0x6e, 0x70, 0x63, 0xa0, 0x7d, 0xc9, 0xcf, 0x0f, 0x46, 0x0d, 0xa4, - 0xb9, 0xd0, 0x3e, 0xc1, 0xa2, 0x3e, 0xfa, 0x32, 0xb7, 0xd6, 0xba, 0xe9, 0x07, 0xf7, 0xfd, 0xeb, - 0x41, 0x20, 0x3d, 0xcc, 0x06, 0x23, 0x38, 0x23, 0x6d, 0xb4, 0x54, 0x75, 0x6c, 0x52, 0x1b, 0x2c, - 0x26, 0xcf, 0x0f, 0xc0, 0x39, 0x4a, 0xda, 0xf4, 0x13, 0x89, 0x10, 0x81, 0x29, 0x11, 0x09, 0x41, - 0x96, 0x89, 0xb1, 0xcb, 0x64, 0xd5, 0xcd, 0xda, 0x89, 0x42, 0xef, 0xa6, 0x49, 0x02, 0xa7, 0x69, - 0xda, 0x3f, 0x6f, 0x01, 0xb3, 0x70, 0x3f, 0x03, 0x96, 0xe1, 0xf3, 0x26, 0xcb, 0x30, 0x9b, 0x37, - 0xc8, 0x39, 0xdc, 0xc2, 0x2b, 0x7c, 0x65, 0xd5, 0xc3, 0xe0, 0xc1, 0x81, 0x78, 0x29, 0x1f, 0x80, - 0x4b, 0xfd, 0x3f, 0x16, 0x3f, 0xc4, 0x94, 0xd3, 0x39, 0xfa, 0x41, 0x18, 0x6d, 0x3a, 0x6d, 0xa7, - 0xc9, 0x83, 0xcc, 0xe6, 0x6a, 0x6c, 0x8c, 0x4a, 0xf3, 0xcb, 0xa2, 0x06, 0xd7, 0x40, 0xc8, 0x88, - 0x1a, 0xa3, 0xb2, 0xb8, 0xaf, 0xd6, 0x41, 0x35, 0x39, 0xb7, 0x0b, 0x13, 0x06, 0xb1, 0x47, 0x2a, - 0xae, 0xfe, 0x20, 0xbf, 0x62, 0x55, 0x04, 0x98, 0x3d, 0x98, 0xf1, 0xb5, 0xff, 0xf4, 0x42, 0x91, - 0x22, 0xc8, 0x27, 0xfb, 0x5d, 0xa2, 0xec, 0xf6, 0xd1, 0x2c, 0xf8, 0x53, 0x64, 0x70, 0x37, 0x65, - 0xfb, 0xef, 0x59, 0xf0, 0xb8, 0x8e, 0xa8, 0xc5, 0x03, 0xe8, 0xa7, 0x03, 0xae, 0xc2, 0x68, 0xd0, - 0x26, 0xa1, 0x13, 0x07, 0xa1, 0xb8, 0x35, 0xae, 0xca, 0x41, 0xbf, 0x2d, 0xca, 0x8f, 0x45, 0xb4, - 0x3f, 0x49, 0x5d, 0x96, 0x63, 0x55, 0x13, 0xd9, 0x30, 0xcc, 0x06, 0x23, 0x12, 0xb1, 0x1a, 0xd8, - 0x19, 0xc0, 0x9e, 0x43, 0x23, 0x2c, 0x20, 0xf6, 0x1f, 0x5b, 0x7c, 0x61, 0xe9, 0x5d, 0x47, 0xef, - 0xc1, 0xf4, 0x9e, 0x13, 0x37, 0x77, 0x56, 0x1e, 0xb4, 0x43, 0xae, 0xfa, 0x96, 0xe3, 0xf4, 0x7c, - 0xbf, 0x71, 0xd2, 0x3e, 0x32, 0x31, 0x40, 0x5b, 0x4b, 0x11, 0xc3, 0x5d, 0xe4, 0xd1, 0x26, 0x8c, - 0xb1, 0x32, 0x66, 0xe9, 0x1c, 0xf5, 0x62, 0x0d, 0xf2, 0x5a, 0x53, 0x2f, 0xca, 0x6b, 0x09, 0x1d, - 0xac, 0x13, 0xb5, 0x3f, 0x28, 0xf2, 0xdd, 0xce, 0xb8, 0xed, 0xe7, 0x60, 0xa4, 0x1d, 0xb4, 0x96, - 0x6b, 0x55, 0x2c, 0x66, 0x41, 0x5d, 0x23, 0x75, 0x5e, 0x8c, 0x25, 0x1c, 0xbd, 0x01, 0x40, 0x1e, - 0xc4, 0x24, 0xf4, 0x1d, 0x4f, 0x19, 0x84, 0x28, 0x13, 0xc8, 0x6a, 0xb0, 0x1e, 0xc4, 0x77, 0x22, - 0xf2, 0xfd, 0x2b, 0x0a, 0x05, 0x6b, 0xe8, 0xe8, 0x1a, 0x40, 0x3b, 0x0c, 0xf6, 0xdd, 0x16, 0x73, - 0x9d, 0x2b, 0x9a, 0xe6, 0x12, 0x75, 0x05, 0xc1, 0x1a, 0x16, 0x7a, 0x03, 0x26, 0x3a, 0x7e, 0xc4, - 0x39, 0x14, 0x67, 0x53, 0xc4, 0xca, 0x1b, 0x4d, 0x2c, 0x17, 0xee, 0xe8, 0x40, 0x6c, 0xe2, 0xa2, - 0x45, 0x18, 0x8e, 0x1d, 0x66, 0xef, 0x30, 0x94, 0x6f, 0xb7, 0xb8, 0x41, 0x31, 0xf4, 0x10, 0xa7, - 0xb4, 0x02, 0x16, 0x15, 0xd1, 0x97, 0xa4, 0x1f, 0x02, 0x3f, 0xeb, 0x85, 0xc1, 0xf0, 0x60, 0xf7, - 0x82, 0xe6, 0x85, 0x20, 0x0c, 0x91, 0x0d, 0x5a, 0xf6, 0xb7, 0xca, 0x00, 0x09, 0x3b, 0x8e, 0xde, - 0xef, 0x3a, 0x8f, 0x5e, 0xe8, 0xcd, 0xc0, 0x9f, 0xde, 0x61, 0x84, 0x7e, 0xd8, 0x82, 0x31, 0xc7, - 0xf3, 0x82, 0xa6, 0x13, 0xb3, 0x51, 0x2e, 0xf4, 0x3e, 0x0f, 0x45, 0xfb, 0x8b, 0x49, 0x0d, 0xde, - 0x85, 0x97, 0xe5, 0xc2, 0xd3, 0x20, 0x7d, 0x7b, 0xa1, 0x37, 0x8c, 0xbe, 0x4b, 0x4a, 0x69, 0x7c, - 0x79, 0xcc, 0xa5, 0xa5, 0xb4, 0x32, 0x3b, 0xfa, 0x35, 0x01, 0x0d, 0xdd, 0x31, 0x82, 0xca, 0x95, - 0xf2, 0xe3, 0x2b, 0x18, 0x5c, 0x69, 0xbf, 0x78, 0x72, 0xa8, 0xae, 0x3b, 0x4e, 0x0d, 0xe5, 0x07, - 0x21, 0xd1, 0xc4, 0x9f, 0x3e, 0x4e, 0x53, 0xef, 0xc2, 0x54, 0xcb, 0xbc, 0xdb, 0xc5, 0x6a, 0x7a, - 0x36, 0x8f, 0x6e, 0x8a, 0x15, 0x48, 0x6e, 0xf3, 0x14, 0x00, 0xa7, 0x09, 0xa3, 0x3a, 0x77, 0x61, - 0xab, 0xf9, 0x5b, 0x81, 0x30, 0x3c, 0xb7, 0x73, 0xe7, 0xf2, 0x20, 0x8a, 0xc9, 0x1e, 0xc5, 0x4c, - 0x2e, 0xed, 0x75, 0x51, 0x17, 0x2b, 0x2a, 0xe8, 0x2d, 0x18, 0x66, 0x3e, 0xb0, 0xd1, 0xec, 0x68, - 0xbe, 0xa2, 0xd0, 0x0c, 0xdf, 0x90, 0x6c, 0x2a, 0xf6, 0x37, 0xc2, 0x82, 0x02, 0xba, 0x21, 0x63, - 0xbc, 0x44, 0x35, 0xff, 0x4e, 0x44, 0x58, 0x8c, 0x97, 0xf2, 0xd2, 0x27, 0x93, 0xf0, 0x2d, 0xbc, - 0x3c, 0x33, 0x98, 0xb9, 0x51, 0x93, 0x32, 0x47, 0xe2, 0xbf, 0x8c, 0x91, 0x3e, 0x0b, 0xf9, 0xdd, - 0x33, 0xe3, 0xa8, 0x27, 0xc3, 0x79, 0xd7, 0x24, 0x81, 0xd3, 0x34, 0x29, 0xa3, 0xc9, 0x77, 0xae, - 0x30, 0x5d, 0xef, 0xb7, 0xff, 0xb9, 0x7c, 0xcd, 0x2e, 0x19, 0x5e, 0x82, 0x45, 0xfd, 0x33, 0xbd, - 0xf5, 0xe7, 0x7c, 0x98, 0x4e, 0x6f, 0xd1, 0x47, 0xca, 0x65, 0xfc, 0x61, 0x09, 0x26, 0xcd, 0x25, - 0x85, 0x16, 0xa0, 0x2c, 0x88, 0xa8, 0xc8, 0xa0, 0x6a, 0x97, 0xac, 0x49, 0x00, 0x4e, 0x70, 0x58, - 0x64, 0x54, 0x56, 0x5d, 0x33, 0x39, 0x4c, 0x22, 0xa3, 0x2a, 0x08, 0xd6, 0xb0, 0xa8, 0xbc, 0xb4, - 0x19, 0x04, 0xb1, 0xba, 0x54, 0xd4, 0xba, 0x5b, 0x62, 0xa5, 0x58, 0x40, 0xe9, 0x65, 0xb2, 0x4b, - 0x42, 0x9f, 0x78, 0x66, 0x1c, 0x33, 0x75, 0x99, 0xdc, 0xd4, 0x81, 0xd8, 0xc4, 0xa5, 0xb7, 0x64, - 0x10, 0xb1, 0x85, 0x2c, 0xa4, 0xb2, 0xc4, 0x84, 0xb3, 0xc1, 0xbd, 0xc9, 0x25, 0x1c, 0x7d, 0x11, - 0x1e, 0x57, 0xce, 0xdf, 0x98, 0x2b, 0xa1, 0x65, 0x8b, 0xc3, 0x86, 0x12, 0xe5, 0xf1, 0xe5, 0x6c, - 0x34, 0x9c, 0x57, 0x1f, 0xbd, 0x09, 0x93, 0x82, 0x73, 0x97, 0x14, 0x47, 0x4c, 0xbb, 0x88, 0x9b, - 0x06, 0x14, 0xa7, 0xb0, 0x65, 0x24, 0x36, 0xc6, 0x3c, 0x4b, 0x0a, 0xa3, 0xdd, 0x91, 0xd8, 0x74, - 0x38, 0xee, 0xaa, 0x81, 0x16, 0x61, 0x8a, 0xb3, 0x56, 0xae, 0xbf, 0xcd, 0xe7, 0x44, 0x78, 0x96, - 0xa8, 0x2d, 0x75, 0xdb, 0x04, 0xe3, 0x34, 0x3e, 0x7a, 0x1d, 0xc6, 0x9d, 0xb0, 0xb9, 0xe3, 0xc6, - 0xa4, 0x19, 0x77, 0x42, 0xee, 0x72, 0xa2, 0x19, 0x96, 0x2c, 0x6a, 0x30, 0x6c, 0x60, 0xda, 0xef, - 0xc3, 0xb9, 0x0c, 0xa7, 0x34, 0xba, 0x70, 0x9c, 0xb6, 0x2b, 0xbf, 0x29, 0x65, 0x8c, 0xb9, 0x58, - 0xaf, 0xc9, 0xaf, 0xd1, 0xb0, 0xe8, 0xea, 0x64, 0xce, 0x6b, 0x5a, 0x4a, 0x04, 0xb5, 0x3a, 0x57, - 0x25, 0x00, 0x27, 0x38, 0xf6, 0xff, 0x2a, 0xc0, 0x54, 0x86, 0x62, 0x9d, 0x85, 0xe5, 0x4f, 0xc9, - 0x1e, 0x49, 0x14, 0x7e, 0x33, 0xb0, 0x5f, 0xe1, 0x04, 0x81, 0xfd, 0x8a, 0xfd, 0x02, 0xfb, 0x95, - 0x3e, 0x4c, 0x60, 0x3f, 0x73, 0xc4, 0x86, 0x06, 0x1a, 0xb1, 0x8c, 0x60, 0x80, 0xc3, 0x27, 0x0c, - 0x06, 0x68, 0x0c, 0xfa, 0xc8, 0x00, 0x83, 0xfe, 0x13, 0x05, 0x98, 0x4e, 0x1b, 0xc0, 0x9d, 0x81, - 0x3a, 0xf6, 0x2d, 0x43, 0x1d, 0x9b, 0x9d, 0xe4, 0x22, 0x6d, 0x96, 0x97, 0xa7, 0x9a, 0xc5, 0x29, - 0xd5, 0xec, 0xa7, 0x07, 0xa2, 0xd6, 0x5b, 0x4d, 0xfb, 0xf7, 0x0b, 0x70, 0x21, 0x5d, 0x65, 0xd9, - 0x73, 0xdc, 0xbd, 0x33, 0x18, 0x9b, 0xdb, 0xc6, 0xd8, 0xbc, 0x38, 0xc8, 0xd7, 0xb0, 0xae, 0xe5, - 0x0e, 0xd0, 0xbd, 0xd4, 0x00, 0x2d, 0x0c, 0x4e, 0xb2, 0xf7, 0x28, 0x7d, 0xbb, 0x08, 0x97, 0x32, - 0xeb, 0x25, 0xda, 0xcc, 0x55, 0x43, 0x9b, 0x79, 0x2d, 0xa5, 0xcd, 0xb4, 0x7b, 0xd7, 0x3e, 0x1d, - 0xf5, 0xa6, 0xf0, 0x16, 0x64, 0xc1, 0xdf, 0x1e, 0x52, 0xb5, 0x69, 0x78, 0x0b, 0x2a, 0x42, 0xd8, - 0xa4, 0xfb, 0x97, 0x49, 0xa5, 0xf9, 0xef, 0x2d, 0xb8, 0x98, 0x39, 0x37, 0x67, 0xa0, 0xc2, 0x5a, - 0x37, 0x55, 0x58, 0xcf, 0x0d, 0xbc, 0x5a, 0x73, 0x74, 0x5a, 0x7f, 0x54, 0xcc, 0xf9, 0x16, 0x26, - 0xa0, 0xdf, 0x86, 0x31, 0xa7, 0xd9, 0x24, 0x51, 0xb4, 0x16, 0xb4, 0x54, 0x30, 0xb4, 0x17, 0x99, - 0x9c, 0x95, 0x14, 0x1f, 0x1f, 0x56, 0xe6, 0xd2, 0x24, 0x12, 0x30, 0xd6, 0x29, 0x98, 0xf1, 0x1b, - 0x0b, 0xa7, 0x1a, 0xbf, 0xf1, 0x1a, 0xc0, 0xbe, 0xe2, 0xd6, 0xd3, 0x42, 0xbe, 0xc6, 0xc7, 0x6b, - 0x58, 0xe8, 0xcb, 0x30, 0x1a, 0x89, 0x6b, 0x5c, 0x2c, 0xc5, 0x97, 0x07, 0x9c, 0x2b, 0x67, 0x93, - 0x78, 0xa6, 0x5b, 0xba, 0xd2, 0x87, 0x28, 0x92, 0xe8, 0x7b, 0x61, 0x3a, 0xe2, 0x51, 0x4f, 0x96, - 0x3d, 0x27, 0x62, 0x3e, 0x0e, 0x62, 0x15, 0x32, 0x5f, 0xf3, 0x46, 0x0a, 0x86, 0xbb, 0xb0, 0xd1, - 0xaa, 0xfc, 0x28, 0x16, 0xa2, 0x85, 0x2f, 0xcc, 0x2b, 0xc9, 0x07, 0x89, 0xa4, 0x40, 0xe7, 0xd3, - 0xc3, 0xcf, 0x06, 0x5e, 0xab, 0x69, 0xff, 0x44, 0x09, 0x9e, 0xe8, 0x71, 0x88, 0xa1, 0x45, 0xf3, - 0x8d, 0xf2, 0xf9, 0xb4, 0xf4, 0x3b, 0x97, 0x59, 0xd9, 0x10, 0x87, 0x53, 0x6b, 0xa5, 0xf0, 0xa1, - 0xd7, 0xca, 0x8f, 0x5a, 0x9a, 0x5e, 0x82, 0x5b, 0xd2, 0x7d, 0xfe, 0x84, 0x87, 0xf3, 0x29, 0x2a, - 0x2a, 0xb6, 0x32, 0xa4, 0xfd, 0x6b, 0x03, 0x77, 0x67, 0x60, 0xf1, 0xff, 0x6c, 0xb5, 0xb3, 0x1f, - 0x58, 0xf0, 0x74, 0x66, 0x7f, 0x0d, 0x9b, 0x8a, 0x05, 0x28, 0x37, 0x69, 0xa1, 0xe6, 0x37, 0x95, - 0x38, 0x94, 0x4a, 0x00, 0x4e, 0x70, 0x0c, 0xd3, 0x89, 0x42, 0x5f, 0xd3, 0x89, 0x7f, 0x6d, 0x41, - 0xd7, 0x02, 0x3e, 0x83, 0x93, 0xb4, 0x66, 0x9e, 0xa4, 0x9f, 0x1c, 0x64, 0x2e, 0x73, 0x0e, 0xd1, - 0xdf, 0x9b, 0x82, 0xc7, 0x72, 0x1c, 0x25, 0xf6, 0x61, 0x66, 0xbb, 0x49, 0x4c, 0x8f, 0x34, 0xf1, - 0x31, 0x99, 0xce, 0x7b, 0x3d, 0xdd, 0xd7, 0x58, 0x36, 0x97, 0x99, 0x2e, 0x14, 0xdc, 0xdd, 0x04, - 0xfa, 0xc0, 0x82, 0xf3, 0xce, 0xfd, 0xa8, 0x2b, 0x67, 0x9f, 0x58, 0x33, 0xaf, 0x64, 0x6a, 0x29, - 0xfa, 0xe4, 0xf8, 0xe3, 0xe9, 0x6d, 0xb2, 0xb0, 0x70, 0x66, 0x5b, 0x08, 0x8b, 0xf8, 0x95, 0x94, - 0xdf, 0xee, 0xe1, 0x33, 0x99, 0xe5, 0xd1, 0xc2, 0xcf, 0x54, 0x09, 0xc1, 0x8a, 0x0e, 0xba, 0x0b, - 0xe5, 0x6d, 0xe9, 0x66, 0x26, 0xce, 0xec, 0xcc, 0x4b, 0x30, 0xd3, 0x17, 0x8d, 0xbf, 0x1b, 0x2a, - 0x10, 0x4e, 0x48, 0xa1, 0x37, 0xa1, 0xe8, 0x6f, 0x45, 0xbd, 0xf2, 0xc2, 0xa4, 0x4c, 0x8d, 0xb8, - 0x3f, 0xf2, 0xfa, 0x6a, 0x03, 0xd3, 0x8a, 0xe8, 0x06, 0x14, 0xc3, 0xcd, 0x96, 0x50, 0xac, 0x65, - 0xf2, 0xa5, 0x78, 0xa9, 0x9a, 0xbd, 0x48, 0x38, 0x25, 0xbc, 0x54, 0xc5, 0x94, 0x04, 0xaa, 0xc3, - 0x10, 0xf3, 0x29, 0x10, 0xfa, 0xb3, 0x4c, 0x86, 0xb4, 0x87, 0x6f, 0x0e, 0x77, 0x5a, 0x66, 0x08, - 0x98, 0x13, 0x42, 0x6f, 0xc1, 0x70, 0x93, 0xa5, 0x4e, 0x11, 0x21, 0x93, 0xb3, 0xa3, 0xd9, 0x74, - 0x25, 0x57, 0x11, 0x7a, 0x24, 0x56, 0x8e, 0x05, 0x05, 0xb4, 0x01, 0xc3, 0x4d, 0xd2, 0xde, 0xd9, - 0x8a, 0x98, 0xe0, 0x6d, 0x32, 0xf8, 0x09, 0xad, 0x1e, 0x99, 0x82, 0x04, 0x55, 0x86, 0x81, 0x05, - 0x2d, 0xf4, 0x59, 0x28, 0x6c, 0x35, 0x85, 0xa3, 0x41, 0xa6, 0x06, 0xcd, 0x74, 0x24, 0x5f, 0x1a, - 0x3e, 0x3a, 0xac, 0x14, 0x56, 0x97, 0x71, 0x61, 0xab, 0x89, 0xd6, 0x61, 0x64, 0x8b, 0xbb, 0x9e, - 0x0a, 0x25, 0xd9, 0xb3, 0xd9, 0x5e, 0xb1, 0x5d, 0xde, 0xa9, 0xdc, 0x40, 0x5e, 0x00, 0xb0, 0x24, - 0xc2, 0x42, 0x3f, 0x2a, 0x17, 0x5a, 0x11, 0x03, 0x79, 0xfe, 0x64, 0x6e, 0xcf, 0xdc, 0xa9, 0x3d, - 0x71, 0xc4, 0xc5, 0x1a, 0x45, 0xf4, 0x55, 0x28, 0x3b, 0x32, 0x47, 0x9c, 0x88, 0x11, 0xf1, 0x72, - 0xe6, 0x76, 0xec, 0x9d, 0x3e, 0x8f, 0xaf, 0x65, 0x85, 0x84, 0x13, 0xa2, 0x68, 0x17, 0x26, 0xf6, - 0xa3, 0xf6, 0x0e, 0x91, 0xdb, 0x97, 0x85, 0x8c, 0xc8, 0xb9, 0xae, 0xee, 0x0a, 0x44, 0x37, 0x8c, - 0x3b, 0x8e, 0xd7, 0x75, 0xe2, 0xb0, 0x27, 0xe6, 0xbb, 0x3a, 0x31, 0x6c, 0xd2, 0xa6, 0xc3, 0xff, - 0x5e, 0x27, 0xd8, 0x3c, 0x88, 0x89, 0x08, 0x9a, 0x9c, 0x39, 0xfc, 0x6f, 0x73, 0x94, 0xee, 0xe1, - 0x17, 0x00, 0x2c, 0x89, 0xd0, 0x0d, 0xee, 0xc8, 0xfc, 0x8b, 0x2c, 0x58, 0x72, 0xce, 0x06, 0xcf, - 0x4c, 0xd2, 0xa8, 0x0d, 0x0a, 0x3b, 0x19, 0x13, 0x52, 0xec, 0x44, 0x6c, 0xef, 0x04, 0x71, 0xe0, - 0xa7, 0x4e, 0xe3, 0x99, 0xfc, 0x13, 0xb1, 0x9e, 0x81, 0xdf, 0x7d, 0x22, 0x66, 0x61, 0xe1, 0xcc, - 0xb6, 0x50, 0x0b, 0x26, 0xdb, 0x41, 0x18, 0xdf, 0x0f, 0x42, 0xb9, 0xbe, 0x50, 0x0f, 0x21, 0xdf, - 0xc0, 0x14, 0x2d, 0xb2, 0x20, 0xde, 0x26, 0x04, 0xa7, 0x68, 0xa2, 0x2f, 0xc0, 0x48, 0xd4, 0x74, - 0x3c, 0x52, 0xbb, 0x3d, 0x7b, 0x2e, 0xff, 0xaa, 0x69, 0x70, 0x94, 0x9c, 0xd5, 0xc5, 0x26, 0x47, - 0xa0, 0x60, 0x49, 0x0e, 0xad, 0xc2, 0x10, 0x8b, 0xc4, 0xcf, 0xe2, 0x3d, 0xe7, 0xc4, 0x22, 0xea, - 0x32, 0xe5, 0xe4, 0x27, 0x12, 0x2b, 0xc6, 0xbc, 0x3a, 0xdd, 0x03, 0x82, 0xd7, 0x0d, 0xa2, 0xd9, - 0x0b, 0xf9, 0x7b, 0x40, 0xb0, 0xc8, 0xb7, 0x1b, 0xbd, 0xf6, 0x80, 0x42, 0xc2, 0x09, 0x51, 0x7a, - 0x1e, 0xd3, 0x33, 0xf4, 0xb1, 0x1e, 0xd6, 0x25, 0xb9, 0x27, 0x28, 0x3b, 0x8f, 0xe9, 0xf9, 0x49, - 0x49, 0xd8, 0xbf, 0x3f, 0xd2, 0xcd, 0x9f, 0x30, 0xe9, 0xe8, 0xaf, 0x58, 0x5d, 0x0f, 0x67, 0x9f, - 0x19, 0x54, 0x59, 0x73, 0x8a, 0x9c, 0xe9, 0x07, 0x16, 0x3c, 0xd6, 0xce, 0xfc, 0x10, 0x71, 0xd9, - 0x0f, 0xa6, 0xf3, 0xe1, 0x9f, 0xae, 0x62, 0xb2, 0x67, 0xc3, 0x71, 0x4e, 0x4b, 0x69, 0xee, 0xbf, - 0xf8, 0xa1, 0xb9, 0xff, 0x35, 0x18, 0x65, 0x0c, 0x65, 0x12, 0xf8, 0x6a, 0xa0, 0x40, 0x3a, 0x8c, - 0x6d, 0x58, 0x16, 0x15, 0xb1, 0x22, 0x81, 0x7e, 0xcc, 0x82, 0xa7, 0xd2, 0x5d, 0xc7, 0x84, 0x81, - 0x45, 0x04, 0x73, 0x2e, 0x98, 0xad, 0x8a, 0xef, 0x7f, 0xaa, 0xde, 0x0b, 0xf9, 0xb8, 0x1f, 0x02, - 0xee, 0xdd, 0x18, 0xaa, 0x66, 0x48, 0x86, 0xc3, 0xa6, 0x36, 0x7c, 0x00, 0xe9, 0xf0, 0x15, 0x18, - 0xdf, 0x0b, 0x3a, 0x7e, 0x2c, 0x8c, 0x51, 0x84, 0x6b, 0x20, 0x7b, 0xfd, 0x5d, 0xd3, 0xca, 0xb1, - 0x81, 0x95, 0x92, 0x29, 0x47, 0x1f, 0x56, 0xa6, 0x44, 0xef, 0xa4, 0xf2, 0x25, 0x97, 0xf3, 0x79, - 0x0b, 0x21, 0x7e, 0x9f, 0x20, 0x6b, 0xf2, 0xd9, 0xca, 0x41, 0x5f, 0xb7, 0x32, 0x18, 0x78, 0x2e, - 0x19, 0x7f, 0xce, 0x94, 0x8c, 0xaf, 0xa4, 0x25, 0xe3, 0x2e, 0x4d, 0xa8, 0x21, 0x14, 0x0f, 0x1e, - 0x6e, 0x79, 0xd0, 0xf8, 0x65, 0xb6, 0x07, 0x97, 0xfb, 0x5d, 0x4b, 0xcc, 0x2a, 0xa9, 0xa5, 0xde, - 0xbd, 0x12, 0xab, 0xa4, 0x56, 0xad, 0x8a, 0x19, 0x64, 0xd0, 0x00, 0x17, 0xf6, 0x7f, 0xb7, 0xa0, - 0x58, 0x0f, 0x5a, 0x67, 0xa0, 0xd9, 0xfd, 0xbc, 0xa1, 0xd9, 0x7d, 0x22, 0x27, 0x8f, 0x75, 0xae, - 0x1e, 0x77, 0x25, 0xa5, 0xc7, 0x7d, 0x2a, 0x8f, 0x40, 0x6f, 0xad, 0xed, 0xcf, 0x15, 0x41, 0xcf, - 0xba, 0x8d, 0xfe, 0xed, 0xc3, 0x98, 0x04, 0x17, 0x7b, 0x25, 0xe2, 0x16, 0x94, 0x99, 0x31, 0x93, - 0xf4, 0x76, 0xfb, 0x0b, 0x66, 0x19, 0x7c, 0x8f, 0xb8, 0xdb, 0x3b, 0x31, 0x69, 0xa5, 0x3f, 0xe7, - 0xec, 0x2c, 0x83, 0xff, 0xab, 0x05, 0x53, 0xa9, 0xd6, 0x91, 0x07, 0x13, 0x9e, 0xae, 0x96, 0x13, - 0xeb, 0xf4, 0xa1, 0x34, 0x7a, 0xc2, 0xb2, 0x52, 0x2b, 0xc2, 0x26, 0x71, 0x34, 0x0f, 0xa0, 0x9e, - 0xcd, 0xa4, 0xb6, 0x8b, 0x71, 0xfd, 0xea, 0x5d, 0x2d, 0xc2, 0x1a, 0x06, 0x7a, 0x15, 0xc6, 0xe2, - 0xa0, 0x1d, 0x78, 0xc1, 0xf6, 0xc1, 0x4d, 0x22, 0x43, 0xaa, 0x28, 0x7b, 0xa9, 0x8d, 0x04, 0x84, - 0x75, 0x3c, 0xfb, 0x17, 0x8a, 0x90, 0xce, 0xd4, 0xfe, 0x9d, 0x35, 0xf9, 0xf1, 0x5c, 0x93, 0xdf, - 0xb6, 0x60, 0x9a, 0xb6, 0xce, 0x6c, 0x37, 0xe4, 0x65, 0xab, 0xd2, 0xbe, 0x58, 0x3d, 0xd2, 0xbe, - 0x5c, 0xa1, 0x67, 0x57, 0x2b, 0xe8, 0xc4, 0x42, 0x5b, 0xa6, 0x1d, 0x4e, 0xb4, 0x14, 0x0b, 0xa8, - 0xc0, 0x23, 0x61, 0x28, 0x1c, 0x92, 0x74, 0x3c, 0x12, 0x86, 0x58, 0x40, 0x65, 0x56, 0x98, 0x52, - 0x4e, 0x56, 0x18, 0x16, 0x20, 0x4e, 0xbc, 0xf2, 0x0b, 0xb6, 0x47, 0x0b, 0x10, 0x27, 0x9f, 0xff, - 0x13, 0x1c, 0xfb, 0x97, 0x8b, 0x30, 0x5e, 0x0f, 0x5a, 0xc9, 0xc3, 0xd5, 0x2b, 0xc6, 0xc3, 0xd5, - 0xe5, 0xd4, 0xc3, 0xd5, 0xb4, 0x8e, 0xfb, 0x9d, 0x67, 0xaa, 0x8f, 0xea, 0x99, 0xea, 0x5f, 0x59, - 0x6c, 0xd6, 0xaa, 0xeb, 0x0d, 0x91, 0x95, 0xf6, 0x25, 0x18, 0x63, 0x07, 0x12, 0xf3, 0x80, 0x93, - 0xaf, 0x39, 0x2c, 0xe0, 0xfb, 0x7a, 0x52, 0x8c, 0x75, 0x1c, 0x74, 0x15, 0x46, 0x23, 0xe2, 0x84, - 0xcd, 0x1d, 0x75, 0xc6, 0x89, 0xb7, 0x0e, 0x5e, 0x86, 0x15, 0x14, 0xbd, 0x9d, 0xc4, 0x26, 0x2b, - 0xe6, 0xe7, 0x57, 0xd5, 0xfb, 0xc3, 0xb7, 0x48, 0x7e, 0x40, 0x32, 0xfb, 0x1e, 0xa0, 0x6e, 0xfc, - 0x01, 0xa2, 0x10, 0x55, 0xcc, 0x28, 0x44, 0xe5, 0xae, 0x08, 0x44, 0x7f, 0x66, 0xc1, 0x64, 0x3d, - 0x68, 0xd1, 0xad, 0xfb, 0x97, 0x69, 0x9f, 0xea, 0x81, 0x19, 0x87, 0x7b, 0x04, 0x66, 0xfc, 0x07, - 0x16, 0x8c, 0xd4, 0x83, 0xd6, 0x19, 0xe8, 0xd8, 0x3f, 0x67, 0xea, 0xd8, 0x1f, 0xcf, 0x59, 0x12, - 0x39, 0x6a, 0xf5, 0x5f, 0x2d, 0xc2, 0x04, 0xed, 0x67, 0xb0, 0x2d, 0x67, 0xc9, 0x18, 0x11, 0x6b, - 0x80, 0x11, 0xa1, 0x6c, 0x6e, 0xe0, 0x79, 0xc1, 0xfd, 0xf4, 0x8c, 0xad, 0xb2, 0x52, 0x2c, 0xa0, - 0xe8, 0x05, 0x18, 0x6d, 0x87, 0x64, 0xdf, 0x0d, 0x04, 0xff, 0xa8, 0xbd, 0x58, 0xd4, 0x45, 0x39, - 0x56, 0x18, 0x54, 0xee, 0x8a, 0x5c, 0xbf, 0x49, 0x64, 0x72, 0xe7, 0x12, 0xcb, 0xff, 0xc4, 0x23, - 0x2e, 0x6b, 0xe5, 0xd8, 0xc0, 0x42, 0xf7, 0xa0, 0xcc, 0xfe, 0xb3, 0x13, 0xe5, 0xe4, 0xf9, 0x6a, - 0x44, 0x9a, 0x03, 0x41, 0x00, 0x27, 0xb4, 0xd0, 0x35, 0x80, 0x58, 0x46, 0xe5, 0x8d, 0x44, 0x30, - 0x19, 0xc5, 0x6b, 0xab, 0x78, 0xbd, 0x11, 0xd6, 0xb0, 0xd0, 0xf3, 0x50, 0x8e, 0x1d, 0xd7, 0xbb, - 0xe5, 0xfa, 0x24, 0x62, 0x8a, 0xe6, 0xa2, 0xcc, 0x62, 0x20, 0x0a, 0x71, 0x02, 0xa7, 0xbc, 0x0e, - 0xf3, 0xb4, 0xe6, 0xd9, 0xae, 0x46, 0x19, 0x36, 0xe3, 0x75, 0x6e, 0xa9, 0x52, 0xac, 0x61, 0xd8, - 0xaf, 0xc3, 0x85, 0x7a, 0xd0, 0xaa, 0x07, 0x61, 0xbc, 0x1a, 0x84, 0xf7, 0x9d, 0xb0, 0x25, 0xe7, - 0xaf, 0x22, 0x03, 0xea, 0xd3, 0xb3, 0x67, 0x88, 0xef, 0x4c, 0x23, 0x54, 0xfe, 0xcb, 0x8c, 0xdb, - 0x39, 0xa1, 0x87, 0xc5, 0xff, 0x2e, 0xb0, 0x83, 0x22, 0x95, 0x82, 0x0d, 0x7d, 0x05, 0x26, 0x23, - 0x72, 0xcb, 0xf5, 0x3b, 0x0f, 0xa4, 0x7c, 0xdc, 0xc3, 0x7d, 0xa5, 0xb1, 0xa2, 0x63, 0x72, 0x2d, - 0x9b, 0x59, 0x86, 0x53, 0xd4, 0xe8, 0x10, 0x86, 0x1d, 0x7f, 0x31, 0xba, 0x13, 0x91, 0x50, 0xa4, - 0x00, 0x63, 0x43, 0x88, 0x65, 0x21, 0x4e, 0xe0, 0x74, 0xc9, 0xb0, 0x3f, 0xeb, 0x81, 0x8f, 0x83, - 0x20, 0x96, 0x8b, 0x8c, 0x25, 0x91, 0xd1, 0xca, 0xb1, 0x81, 0x85, 0x56, 0x01, 0x45, 0x9d, 0x76, - 0xdb, 0x63, 0x0f, 0xe0, 0x8e, 0x77, 0x3d, 0x0c, 0x3a, 0x6d, 0xfe, 0xf8, 0x58, 0x64, 0xf9, 0xfa, - 0x51, 0xa3, 0x0b, 0x8a, 0x33, 0x6a, 0xd0, 0x83, 0x61, 0x2b, 0x62, 0xbf, 0xd9, 0xc2, 0x2b, 0x0a, - 0xcd, 0x77, 0x83, 0x15, 0x61, 0x09, 0xa3, 0xf3, 0xcc, 0x9a, 0xe7, 0x98, 0xc3, 0xc9, 0x3c, 0x63, - 0x55, 0x8a, 0x35, 0x0c, 0xfb, 0x07, 0xd9, 0x05, 0xc3, 0x32, 0x3d, 0xc5, 0x9d, 0x90, 0xa0, 0x3d, - 0x98, 0x68, 0xb3, 0xab, 0x5f, 0xc4, 0x21, 0x16, 0x03, 0xfe, 0xca, 0x80, 0x92, 0xe2, 0x7d, 0xba, - 0x79, 0x95, 0x26, 0x87, 0xb1, 0xe0, 0x75, 0x9d, 0x1c, 0x36, 0xa9, 0xdb, 0x3f, 0x37, 0xcd, 0xce, - 0xb1, 0x06, 0x17, 0xff, 0x46, 0x84, 0xed, 0xac, 0xe0, 0x75, 0xe7, 0xf2, 0xf5, 0x10, 0xc9, 0x95, - 0x23, 0xec, 0x6f, 0xb1, 0xac, 0x8b, 0xde, 0x66, 0xaf, 0xbc, 0xfc, 0xf0, 0xe8, 0x97, 0x70, 0x97, - 0x63, 0x19, 0x0f, 0xba, 0xa2, 0x22, 0xd6, 0x88, 0xa0, 0x5b, 0x30, 0x21, 0x12, 0x03, 0x09, 0x45, - 0x53, 0xd1, 0x50, 0x24, 0x4c, 0x60, 0x1d, 0x78, 0x9c, 0x2e, 0xc0, 0x66, 0x65, 0xb4, 0x0d, 0x4f, - 0x69, 0x59, 0xf2, 0xae, 0x87, 0x0e, 0x7b, 0xf9, 0x73, 0xd9, 0xea, 0xd7, 0xce, 0xa2, 0xa7, 0x8f, - 0x0e, 0x2b, 0x4f, 0x6d, 0xf4, 0x42, 0xc4, 0xbd, 0xe9, 0xa0, 0xdb, 0x70, 0x81, 0xbb, 0xa8, 0x55, - 0x89, 0xd3, 0xf2, 0x5c, 0x5f, 0x1d, 0x76, 0x7c, 0x01, 0x5d, 0x3c, 0x3a, 0xac, 0x5c, 0x58, 0xcc, - 0x42, 0xc0, 0xd9, 0xf5, 0xd0, 0xe7, 0xa0, 0xdc, 0xf2, 0x23, 0x31, 0x06, 0xc3, 0x46, 0x02, 0xc8, - 0x72, 0x75, 0xbd, 0xa1, 0xbe, 0x3f, 0xf9, 0x83, 0x93, 0x0a, 0x68, 0x9b, 0x2b, 0x9b, 0x94, 0x6c, - 0x37, 0x92, 0x9f, 0xec, 0x5b, 0x2c, 0x09, 0xc3, 0x49, 0x85, 0x6b, 0x59, 0x95, 0x91, 0xa7, 0xe1, - 0xbf, 0x62, 0x10, 0x46, 0x6f, 0x01, 0xa2, 0xcc, 0x8f, 0xdb, 0x24, 0x8b, 0x4d, 0x16, 0x0e, 0x9a, - 0xe9, 0xe6, 0x46, 0x0d, 0xa7, 0x00, 0xd4, 0xe8, 0xc2, 0xc0, 0x19, 0xb5, 0xd0, 0x0d, 0x7a, 0x02, - 0xe9, 0xa5, 0xc2, 0x58, 0x55, 0x32, 0xcc, 0xb3, 0x55, 0xd2, 0x0e, 0x49, 0xd3, 0x89, 0x49, 0xcb, - 0xa4, 0x88, 0x53, 0xf5, 0xe8, 0xfd, 0xa4, 0x32, 0xc3, 0x80, 0x19, 0xf3, 0xa1, 0x3b, 0x3b, 0x0c, - 0x95, 0x35, 0x77, 0x82, 0x28, 0x5e, 0x27, 0xf1, 0xfd, 0x20, 0xdc, 0x15, 0x21, 0xb6, 0x92, 0x68, - 0x8f, 0x09, 0x08, 0xeb, 0x78, 0x94, 0xb7, 0x64, 0xcf, 0xac, 0xb5, 0x2a, 0x7b, 0xf5, 0x1a, 0x4d, - 0xf6, 0xc9, 0x0d, 0x5e, 0x8c, 0x25, 0x5c, 0xa2, 0xd6, 0xea, 0xcb, 0xec, 0x05, 0x2b, 0x85, 0x5a, - 0xab, 0x2f, 0x63, 0x09, 0x47, 0xa4, 0x3b, 0xb9, 0xe6, 0x64, 0xbe, 0xa6, 0xb0, 0xfb, 0x1c, 0x1f, - 0x30, 0xbf, 0xa6, 0x0f, 0xd3, 0x2a, 0xad, 0x27, 0x8f, 0x3d, 0x16, 0xcd, 0x4e, 0xb1, 0x45, 0x32, - 0x78, 0xe0, 0x32, 0xa5, 0x7b, 0xad, 0xa5, 0x28, 0xe1, 0x2e, 0xda, 0x46, 0x14, 0x8e, 0xe9, 0xbe, - 0x99, 0x7d, 0x16, 0xa0, 0x1c, 0x75, 0x36, 0x5b, 0xc1, 0x9e, 0xe3, 0xfa, 0xec, 0xc1, 0x49, 0x63, - 0x5c, 0x1a, 0x12, 0x80, 0x13, 0x1c, 0xb4, 0x0a, 0xa3, 0x8e, 0x54, 0xac, 0xa2, 0x7c, 0xb7, 0x7c, - 0xa5, 0x4e, 0xe5, 0x9e, 0xaa, 0x52, 0x95, 0xaa, 0xea, 0xa2, 0x37, 0x60, 0x42, 0x38, 0x26, 0xf1, - 0x60, 0x05, 0xec, 0x41, 0x48, 0xb3, 0x3c, 0x6f, 0xe8, 0x40, 0x6c, 0xe2, 0xa2, 0x2f, 0xc3, 0x24, - 0xa5, 0x92, 0x1c, 0x6c, 0xb3, 0xe7, 0x07, 0x39, 0x11, 0xb5, 0x8c, 0x0d, 0x7a, 0x65, 0x9c, 0x22, - 0x86, 0x5a, 0xf0, 0xa4, 0xd3, 0x89, 0x03, 0xa6, 0x9c, 0x36, 0xd7, 0xff, 0x46, 0xb0, 0x4b, 0x7c, - 0xf6, 0x2e, 0x34, 0xba, 0x74, 0xf9, 0xe8, 0xb0, 0xf2, 0xe4, 0x62, 0x0f, 0x3c, 0xdc, 0x93, 0x0a, - 0xba, 0x03, 0x63, 0x71, 0xe0, 0x31, 0x1b, 0x70, 0xca, 0x03, 0x3c, 0x96, 0x1f, 0xc5, 0x66, 0x43, - 0xa1, 0xe9, 0x8a, 0x19, 0x55, 0x15, 0xeb, 0x74, 0xd0, 0x06, 0xdf, 0x63, 0x2c, 0xbe, 0x27, 0x89, - 0x66, 0x1f, 0xcf, 0x1f, 0x18, 0x15, 0x06, 0xd4, 0xdc, 0x82, 0xa2, 0x26, 0xd6, 0xc9, 0xa0, 0xeb, - 0x30, 0xd3, 0x0e, 0xdd, 0x80, 0x2d, 0x6c, 0xf5, 0x30, 0x30, 0x6b, 0x06, 0xe9, 0xaf, 0xa7, 0x11, - 0x70, 0x77, 0x1d, 0x2a, 0xb8, 0xc9, 0xc2, 0xd9, 0x8b, 0x3c, 0xe3, 0x13, 0x67, 0x66, 0x79, 0x19, - 0x56, 0x50, 0xb4, 0xc6, 0xce, 0x65, 0x2e, 0x62, 0xcd, 0xce, 0xe5, 0x87, 0x33, 0xd0, 0x45, 0x31, - 0xce, 0xe8, 0xa8, 0xbf, 0x38, 0xa1, 0x40, 0xef, 0x8d, 0x68, 0xc7, 0x09, 0x49, 0x3d, 0x0c, 0x9a, - 0x84, 0x77, 0x86, 0x9b, 0x9f, 0x3f, 0xc1, 0xc3, 0x10, 0xd2, 0x7b, 0xa3, 0x91, 0x85, 0x80, 0xb3, - 0xeb, 0xcd, 0x7d, 0x0f, 0xcc, 0x74, 0x9d, 0xe4, 0x27, 0x8a, 0x4d, 0xfd, 0xa7, 0x43, 0x50, 0x56, - 0x8a, 0x5f, 0xb4, 0x60, 0xea, 0xf3, 0x2f, 0xa6, 0xf5, 0xf9, 0xa3, 0x94, 0xff, 0xd4, 0x55, 0xf8, - 0x1b, 0x86, 0xe1, 0x57, 0x21, 0x3f, 0x13, 0x94, 0xae, 0xf5, 0xe8, 0xeb, 0xe5, 0xa5, 0xc9, 0xf1, - 0xc5, 0x81, 0x1f, 0x06, 0x4a, 0x3d, 0x55, 0x03, 0x03, 0x26, 0x62, 0xa5, 0xa2, 0x6e, 0x3b, 0x68, - 0xd5, 0xea, 0xe9, 0xcc, 0x84, 0x75, 0x5a, 0x88, 0x39, 0x8c, 0x09, 0x2b, 0x94, 0xed, 0x60, 0xc2, - 0xca, 0xc8, 0x43, 0x0a, 0x2b, 0x92, 0x00, 0x4e, 0x68, 0x21, 0x0f, 0x66, 0x9a, 0x66, 0x52, 0x49, - 0xe5, 0xd9, 0xf5, 0x4c, 0xdf, 0xf4, 0x8e, 0x1d, 0x2d, 0x83, 0xd7, 0x72, 0x9a, 0x0a, 0xee, 0x26, - 0x8c, 0xde, 0x80, 0xd1, 0xf7, 0x82, 0x88, 0x6d, 0x0b, 0x71, 0xf7, 0x4a, 0x0f, 0x98, 0xd1, 0xb7, - 0x6f, 0x37, 0x58, 0xf9, 0xf1, 0x61, 0x65, 0xac, 0x1e, 0xb4, 0xe4, 0x5f, 0xac, 0x2a, 0xa0, 0x07, - 0x70, 0xc1, 0x38, 0xb1, 0x54, 0x77, 0x61, 0xf0, 0xee, 0x3e, 0x25, 0x9a, 0xbb, 0x50, 0xcb, 0xa2, - 0x84, 0xb3, 0x1b, 0xa0, 0xc7, 0x80, 0x1f, 0x88, 0x84, 0xac, 0xf2, 0x7e, 0x67, 0xd7, 0x78, 0x59, - 0xf7, 0x7f, 0x4e, 0x21, 0xe0, 0xee, 0x3a, 0xf6, 0x37, 0xb8, 0x9e, 0x5c, 0x68, 0xd3, 0x48, 0xd4, - 0xf1, 0xce, 0x22, 0xdf, 0xcf, 0x8a, 0xa1, 0xe8, 0x7b, 0xe8, 0xb7, 0x98, 0xdf, 0xb2, 0xd8, 0x5b, - 0xcc, 0x06, 0xd9, 0x6b, 0x7b, 0x4e, 0x7c, 0x16, 0x9e, 0x17, 0x6f, 0xc3, 0x68, 0x2c, 0x5a, 0xeb, - 0x95, 0xa2, 0x48, 0xeb, 0x14, 0x7b, 0x8f, 0x52, 0x37, 0xbf, 0x2c, 0xc5, 0x8a, 0x8c, 0xfd, 0xcf, - 0xf9, 0x0c, 0x48, 0xc8, 0x19, 0x28, 0x5d, 0xaa, 0xa6, 0xd2, 0xa5, 0xd2, 0xe7, 0x0b, 0x72, 0x94, - 0x2f, 0xff, 0xcc, 0xec, 0x37, 0x13, 0xb2, 0x3e, 0xee, 0x8f, 0x80, 0xf6, 0x4f, 0x59, 0x70, 0x3e, - 0xcb, 0x6a, 0x86, 0x72, 0x6b, 0x5c, 0xc4, 0x53, 0x8f, 0xa2, 0x6a, 0x04, 0xef, 0x8a, 0x72, 0xac, - 0x30, 0x06, 0x8e, 0xfe, 0x7f, 0xb2, 0x10, 0x61, 0xb7, 0x61, 0xa2, 0x1e, 0x12, 0xed, 0x0e, 0x78, - 0x93, 0xbb, 0x52, 0xf1, 0xfe, 0xbc, 0x70, 0x62, 0x37, 0x2a, 0xfb, 0x17, 0x0b, 0x70, 0x9e, 0xbf, - 0x6a, 0x2c, 0xee, 0x07, 0x6e, 0xab, 0x1e, 0xb4, 0x44, 0xe6, 0x86, 0x2f, 0xc1, 0x78, 0x5b, 0x93, - 0xcb, 0x7b, 0x05, 0x29, 0xd2, 0xe5, 0xf7, 0x44, 0x3e, 0xd2, 0x4b, 0xb1, 0x41, 0x0b, 0xb5, 0x60, - 0x9c, 0xec, 0xbb, 0x4d, 0xa5, 0x1a, 0x2f, 0x9c, 0xf8, 0x6e, 0x50, 0xad, 0xac, 0x68, 0x74, 0xb0, - 0x41, 0xf5, 0x11, 0x24, 0xf3, 0xb2, 0x7f, 0xda, 0x82, 0xc7, 0x73, 0x42, 0x1a, 0xd1, 0xe6, 0xee, - 0xb3, 0xf7, 0x23, 0x91, 0x17, 0x48, 0x35, 0xc7, 0x5f, 0x95, 0xb0, 0x80, 0xa2, 0x2f, 0x00, 0xf0, - 0x57, 0x21, 0x2a, 0x2e, 0xf4, 0x8b, 0xfd, 0x62, 0x84, 0xad, 0xd0, 0xc2, 0x0d, 0xc8, 0xfa, 0x58, - 0xa3, 0x65, 0xff, 0x7c, 0x11, 0x86, 0xd8, 0x2b, 0x04, 0x5a, 0x85, 0x91, 0x1d, 0x1e, 0xc0, 0x77, - 0x90, 0x58, 0xc1, 0x89, 0xdc, 0xc5, 0x0b, 0xb0, 0xac, 0x8c, 0xd6, 0xe0, 0x1c, 0x0f, 0x80, 0xec, - 0x55, 0x89, 0xe7, 0x1c, 0x48, 0xf1, 0x9d, 0xe7, 0xd2, 0x51, 0xa1, 0x13, 0x6a, 0xdd, 0x28, 0x38, - 0xab, 0x1e, 0x7a, 0x13, 0x26, 0x63, 0x77, 0x8f, 0x04, 0x9d, 0x58, 0x52, 0xe2, 0xa1, 0x8f, 0x15, - 0xb3, 0xbf, 0x61, 0x40, 0x71, 0x0a, 0x9b, 0x0a, 0x22, 0xed, 0x2e, 0x45, 0x85, 0x96, 0x9d, 0xde, - 0x54, 0x4e, 0x98, 0xb8, 0xcc, 0x5c, 0xa6, 0xc3, 0x8c, 0x83, 0x36, 0x76, 0x42, 0x12, 0xed, 0x04, - 0x5e, 0x4b, 0xa4, 0x62, 0x4e, 0xcc, 0x65, 0x52, 0x70, 0xdc, 0x55, 0x83, 0x52, 0xd9, 0x72, 0x5c, - 0xaf, 0x13, 0x92, 0x84, 0xca, 0xb0, 0x49, 0x65, 0x35, 0x05, 0xc7, 0x5d, 0x35, 0xe8, 0x3a, 0xba, - 0x20, 0x72, 0x23, 0x4b, 0x87, 0x6e, 0x65, 0x03, 0x35, 0x22, 0x5d, 0x5b, 0x7a, 0x44, 0x34, 0x11, - 0x56, 0x22, 0x2a, 0xbb, 0xb2, 0x96, 0x79, 0x53, 0x38, 0xb5, 0x48, 0x2a, 0x0f, 0x93, 0xa1, 0xf7, - 0xf7, 0x2d, 0x38, 0x97, 0x61, 0x6b, 0xc9, 0x8f, 0xaa, 0x6d, 0x37, 0x8a, 0x55, 0xbe, 0x10, 0xed, - 0xa8, 0xe2, 0xe5, 0x58, 0x61, 0xd0, 0xfd, 0xc0, 0x0f, 0xc3, 0xf4, 0x01, 0x28, 0x6c, 0x99, 0x04, - 0xf4, 0x64, 0x07, 0x20, 0xba, 0x0c, 0xa5, 0x4e, 0x44, 0x64, 0x2c, 0x22, 0x75, 0x7e, 0x33, 0x55, - 0x29, 0x83, 0x50, 0xd6, 0x74, 0x5b, 0x69, 0x29, 0x35, 0xd6, 0x94, 0xab, 0x1e, 0x39, 0xcc, 0xfe, - 0x5a, 0x11, 0x2e, 0xe6, 0xda, 0x52, 0xd3, 0x2e, 0xed, 0x05, 0xbe, 0x1b, 0x07, 0xea, 0x85, 0x8b, - 0x47, 0xc3, 0x20, 0xed, 0x9d, 0x35, 0x51, 0x8e, 0x15, 0x06, 0xba, 0x22, 0xb3, 0x74, 0xa7, 0x33, - 0xa2, 0x2c, 0x55, 0x8d, 0x44, 0xdd, 0x83, 0x66, 0x9b, 0x7a, 0x06, 0x4a, 0xed, 0x20, 0xf0, 0xd2, - 0x87, 0x11, 0xed, 0x6e, 0x10, 0x78, 0x98, 0x01, 0xd1, 0xa7, 0xc4, 0x38, 0xa4, 0x9e, 0x74, 0xb0, - 0xd3, 0x0a, 0x22, 0x6d, 0x30, 0x9e, 0x83, 0x91, 0x5d, 0x72, 0x10, 0xba, 0xfe, 0x76, 0xfa, 0xa9, - 0xef, 0x26, 0x2f, 0xc6, 0x12, 0x6e, 0x26, 0x04, 0x18, 0x39, 0xed, 0x34, 0x51, 0xa3, 0x7d, 0xaf, - 0xb6, 0x1f, 0x2d, 0xc2, 0x14, 0x5e, 0xaa, 0x7e, 0x67, 0x22, 0xee, 0x74, 0x4f, 0xc4, 0x69, 0xa7, - 0x89, 0xea, 0x3f, 0x1b, 0xbf, 0x6a, 0xc1, 0x14, 0x0b, 0x9a, 0x2b, 0x62, 0x30, 0xb8, 0x81, 0x7f, - 0x06, 0xac, 0xdb, 0x33, 0x30, 0x14, 0xd2, 0x46, 0xd3, 0xb9, 0x5f, 0x58, 0x4f, 0x30, 0x87, 0xa1, - 0x27, 0xa1, 0xc4, 0xba, 0x40, 0x27, 0x6f, 0x9c, 0x87, 0xcd, 0xaf, 0x3a, 0xb1, 0x83, 0x59, 0x29, - 0x73, 0x2c, 0xc6, 0xa4, 0xed, 0xb9, 0xbc, 0xd3, 0x89, 0xaa, 0xff, 0xe3, 0xe1, 0x58, 0x9c, 0xd9, - 0xb5, 0x0f, 0xe7, 0x58, 0x9c, 0x4d, 0xb2, 0xb7, 0x58, 0xf4, 0x3f, 0x0a, 0x70, 0x29, 0xb3, 0xde, - 0xc0, 0x8e, 0xc5, 0xbd, 0x6b, 0x9f, 0x8e, 0xc5, 0x46, 0xb6, 0x21, 0x45, 0xf1, 0x0c, 0x0d, 0x29, - 0x4a, 0x83, 0x72, 0x8e, 0x43, 0x03, 0xf8, 0xfb, 0x66, 0x0e, 0xd9, 0xc7, 0xc4, 0xdf, 0x37, 0xb3, - 0x6f, 0x39, 0x62, 0xdd, 0x9f, 0x17, 0x72, 0xbe, 0x85, 0x09, 0x78, 0x57, 0xe9, 0x39, 0xc3, 0x80, - 0x91, 0xe0, 0x84, 0xc7, 0xf9, 0x19, 0xc3, 0xcb, 0xb0, 0x82, 0x22, 0x57, 0xf3, 0x9c, 0x2d, 0xe4, - 0x67, 0x06, 0xcc, 0x6d, 0x6a, 0xde, 0x7c, 0x99, 0x51, 0x43, 0x90, 0xe1, 0x45, 0xbb, 0xa6, 0x09, - 0xe5, 0xc5, 0xc1, 0x85, 0xf2, 0xf1, 0x6c, 0x81, 0x1c, 0x2d, 0xc2, 0xd4, 0x9e, 0xeb, 0xb3, 0x4c, - 0xef, 0x26, 0x2b, 0xaa, 0x02, 0x49, 0xac, 0x99, 0x60, 0x9c, 0xc6, 0x9f, 0x7b, 0x03, 0x26, 0x1e, - 0x5e, 0x1d, 0xf9, 0xed, 0x22, 0x3c, 0xd1, 0x63, 0xdb, 0xf3, 0xb3, 0xde, 0x98, 0x03, 0xed, 0xac, - 0xef, 0x9a, 0x87, 0x3a, 0x9c, 0xdf, 0xea, 0x78, 0xde, 0x01, 0xb3, 0x55, 0x24, 0x2d, 0x89, 0x21, - 0x78, 0x45, 0x99, 0xbf, 0xff, 0xfc, 0x6a, 0x06, 0x0e, 0xce, 0xac, 0x89, 0xde, 0x02, 0x14, 0x88, - 0xb4, 0xa4, 0xd7, 0x89, 0x2f, 0xf4, 0xdd, 0x6c, 0xe0, 0x8b, 0xc9, 0x66, 0xbc, 0xdd, 0x85, 0x81, - 0x33, 0x6a, 0x51, 0xa6, 0x9f, 0xde, 0x4a, 0x07, 0xaa, 0x5b, 0x29, 0xa6, 0x1f, 0xeb, 0x40, 0x6c, - 0xe2, 0xa2, 0xeb, 0x30, 0xe3, 0xec, 0x3b, 0x2e, 0x0f, 0xb0, 0x26, 0x09, 0x70, 0xae, 0x5f, 0x29, - 0xc1, 0x16, 0xd3, 0x08, 0xb8, 0xbb, 0x4e, 0xca, 0x75, 0x77, 0x38, 0xdf, 0x75, 0xb7, 0xf7, 0xb9, - 0xd8, 0x4f, 0xa7, 0x6b, 0xff, 0x67, 0x8b, 0x5e, 0x5f, 0x19, 0xa9, 0xc5, 0xe9, 0x38, 0x28, 0xdd, - 0xa4, 0xe6, 0x45, 0xab, 0xc6, 0x61, 0x59, 0x07, 0x62, 0x13, 0x97, 0x2f, 0x88, 0x28, 0x71, 0xe8, - 0x30, 0x58, 0x77, 0xe1, 0x26, 0xaf, 0x30, 0xd0, 0x17, 0x61, 0xa4, 0xe5, 0xee, 0xbb, 0x51, 0x10, - 0x8a, 0xcd, 0x72, 0x42, 0xb3, 0xf8, 0xe4, 0x1c, 0xac, 0x72, 0x32, 0x58, 0xd2, 0xb3, 0x7f, 0xb4, - 0x00, 0x13, 0xb2, 0xc5, 0xb7, 0x3b, 0x41, 0xec, 0x9c, 0xc1, 0xb5, 0x7c, 0xdd, 0xb8, 0x96, 0x3f, - 0xd5, 0x2b, 0x56, 0x00, 0xeb, 0x52, 0xee, 0x75, 0x7c, 0x3b, 0x75, 0x1d, 0x3f, 0xdb, 0x9f, 0x54, - 0xef, 0x6b, 0xf8, 0x5f, 0x58, 0x30, 0x63, 0xe0, 0x9f, 0xc1, 0x6d, 0xb0, 0x6a, 0xde, 0x06, 0x4f, - 0xf7, 0xfd, 0x86, 0x9c, 0x5b, 0xe0, 0xeb, 0x85, 0x54, 0xdf, 0xd9, 0xe9, 0xff, 0x1e, 0x94, 0x76, - 0x9c, 0xb0, 0xd5, 0x2b, 0x26, 0x69, 0x57, 0xa5, 0xf9, 0x1b, 0x4e, 0xd8, 0xe2, 0x67, 0xf8, 0x0b, - 0x2a, 0x99, 0xa1, 0x13, 0xb6, 0xfa, 0xfa, 0x2f, 0xb1, 0xa6, 0xd0, 0xeb, 0x30, 0x1c, 0x35, 0x83, - 0xb6, 0xb2, 0x2e, 0xbc, 0xcc, 0x13, 0x1d, 0xd2, 0x92, 0xe3, 0xc3, 0x0a, 0x32, 0x9b, 0xa3, 0xc5, - 0x58, 0xe0, 0xcf, 0x6d, 0x43, 0x59, 0x35, 0xfd, 0x48, 0x7d, 0x43, 0xfe, 0x63, 0x11, 0xce, 0x65, - 0xac, 0x0b, 0x14, 0x19, 0xa3, 0xf5, 0xd2, 0x80, 0xcb, 0xe9, 0x43, 0x8e, 0x57, 0xc4, 0x24, 0x96, - 0x96, 0x98, 0xff, 0x81, 0x1b, 0xbd, 0x13, 0x91, 0x74, 0xa3, 0xb4, 0xa8, 0x7f, 0xa3, 0xb4, 0xb1, - 0x33, 0x1b, 0x6a, 0xda, 0x90, 0xea, 0xe9, 0x23, 0x9d, 0xd3, 0x3f, 0x29, 0xc2, 0xf9, 0xac, 0x10, - 0x23, 0xe8, 0x07, 0x52, 0x59, 0x49, 0x5e, 0x19, 0x34, 0x38, 0x09, 0x4f, 0x55, 0x22, 0x72, 0xec, - 0xce, 0x9b, 0x79, 0x4a, 0xfa, 0x0e, 0xb3, 0x68, 0x93, 0x39, 0x14, 0x86, 0x3c, 0x9b, 0x8c, 0xdc, - 0xe2, 0x9f, 0x19, 0xb8, 0x03, 0x22, 0x0d, 0x4d, 0x94, 0x72, 0x28, 0x94, 0xc5, 0xfd, 0x1d, 0x0a, - 0x65, 0xcb, 0x73, 0x2e, 0x8c, 0x69, 0x5f, 0xf3, 0x48, 0x67, 0x7c, 0x97, 0xde, 0x28, 0x5a, 0xbf, - 0x1f, 0xe9, 0xac, 0xff, 0xb4, 0x05, 0x29, 0x9b, 0x3e, 0xa5, 0x92, 0xb2, 0x72, 0x55, 0x52, 0x97, - 0xa1, 0x14, 0x06, 0x1e, 0x49, 0x27, 0x0a, 0xc1, 0x81, 0x47, 0x30, 0x83, 0x50, 0x8c, 0x38, 0x51, - 0x48, 0x8c, 0xeb, 0xc2, 0x96, 0x10, 0xa3, 0x9e, 0x81, 0x21, 0x8f, 0xec, 0x13, 0x2f, 0x1d, 0x85, - 0xfb, 0x16, 0x2d, 0xc4, 0x1c, 0x66, 0xff, 0x6a, 0x09, 0x9e, 0xea, 0xe9, 0x92, 0x4b, 0x45, 0x96, - 0x6d, 0x27, 0x26, 0xf7, 0x9d, 0x83, 0x74, 0xb8, 0xdc, 0xeb, 0xbc, 0x18, 0x4b, 0x38, 0xb3, 0x40, - 0xe6, 0xe1, 0xf1, 0x52, 0x0a, 0x3c, 0x11, 0x15, 0x4f, 0x40, 0x1f, 0x41, 0x7e, 0xf1, 0x6b, 0x00, - 0x51, 0xe4, 0xad, 0xf8, 0x94, 0x03, 0x6b, 0x09, 0xd3, 0xe6, 0x24, 0x8c, 0x62, 0xe3, 0x96, 0x80, - 0x60, 0x0d, 0x0b, 0x55, 0x61, 0xba, 0x1d, 0x06, 0x31, 0xd7, 0x87, 0x56, 0xb9, 0x91, 0xcc, 0x90, - 0xe9, 0x0d, 0x59, 0x4f, 0xc1, 0x71, 0x57, 0x0d, 0xf4, 0x2a, 0x8c, 0x09, 0x0f, 0xc9, 0x7a, 0x10, - 0x78, 0x42, 0x55, 0xa3, 0x4c, 0x2e, 0x1a, 0x09, 0x08, 0xeb, 0x78, 0x5a, 0x35, 0xa6, 0x64, 0x1d, - 0xc9, 0xac, 0xc6, 0x15, 0xad, 0x1a, 0x5e, 0x2a, 0xdc, 0xd0, 0xe8, 0x40, 0xe1, 0x86, 0x12, 0xe5, - 0x55, 0x79, 0xe0, 0x77, 0x25, 0xe8, 0xab, 0xee, 0xf9, 0xa5, 0x12, 0x9c, 0x13, 0x0b, 0xe7, 0x51, - 0x2f, 0x97, 0x47, 0x94, 0x05, 0xfd, 0x3b, 0x6b, 0xe6, 0xac, 0xd7, 0xcc, 0x37, 0x8a, 0x30, 0xcc, - 0xa7, 0xe2, 0x0c, 0x78, 0xf8, 0x55, 0xa1, 0xf4, 0xeb, 0x11, 0x68, 0x87, 0xf7, 0x65, 0xbe, 0xea, - 0xc4, 0x0e, 0xbf, 0xbf, 0xd4, 0x31, 0x9a, 0xa8, 0x07, 0xd1, 0xbc, 0x71, 0xd0, 0xce, 0xa5, 0xb4, - 0x5a, 0xc0, 0x69, 0x68, 0xc7, 0xee, 0x57, 0x00, 0x22, 0x96, 0x89, 0x9b, 0xd2, 0x10, 0x21, 0x9b, - 0x3e, 0xdd, 0xa3, 0xf5, 0x86, 0x42, 0xe6, 0x7d, 0x48, 0x96, 0xa0, 0x02, 0x60, 0x8d, 0xe2, 0xdc, - 0x6b, 0x50, 0x56, 0xc8, 0xfd, 0x54, 0x00, 0xe3, 0xfa, 0xad, 0xf7, 0x79, 0x98, 0x4a, 0xb5, 0x75, - 0x22, 0x0d, 0xc2, 0xaf, 0x59, 0x30, 0xc5, 0xbb, 0xbc, 0xe2, 0xef, 0x8b, 0xcd, 0xfe, 0x3e, 0x9c, - 0xf7, 0x32, 0x36, 0x9d, 0x98, 0xd1, 0xc1, 0x37, 0xa9, 0xd2, 0x18, 0x64, 0x41, 0x71, 0x66, 0x1b, - 0xe8, 0x2a, 0x8c, 0x72, 0x97, 0x1d, 0xc7, 0x13, 0x6e, 0x16, 0xe3, 0x3c, 0x4a, 0x3e, 0x2f, 0xc3, - 0x0a, 0x6a, 0xff, 0xae, 0x05, 0x33, 0xbc, 0xe7, 0x37, 0xc9, 0x81, 0x92, 0x8e, 0x3f, 0xca, 0xbe, - 0x8b, 0x24, 0x00, 0x85, 0x9c, 0x24, 0x00, 0xfa, 0xa7, 0x15, 0x7b, 0x7e, 0xda, 0x2f, 0x5a, 0x20, - 0x56, 0xe0, 0x19, 0xc8, 0x81, 0xdf, 0x63, 0xca, 0x81, 0x73, 0xf9, 0x8b, 0x3a, 0x47, 0x00, 0xfc, - 0x33, 0x0b, 0xa6, 0x39, 0x42, 0xf2, 0x10, 0xf9, 0x91, 0xce, 0xc3, 0x20, 0xd9, 0xbc, 0x54, 0xfa, - 0xde, 0xec, 0x8f, 0x32, 0x26, 0xab, 0xd4, 0x73, 0xb2, 0x5a, 0x72, 0x03, 0x9d, 0x20, 0x4b, 0xdd, - 0x89, 0x83, 0xe9, 0xda, 0x7f, 0x6c, 0x01, 0xe2, 0xcd, 0x18, 0xf7, 0x32, 0xbd, 0xed, 0x58, 0xa9, - 0xa6, 0x09, 0x4a, 0x8e, 0x1a, 0x05, 0xc1, 0x1a, 0xd6, 0xa9, 0x0c, 0x4f, 0xea, 0x35, 0xb9, 0xd8, - 0xff, 0x35, 0xf9, 0x04, 0x23, 0xfa, 0x8d, 0x12, 0xa4, 0x6d, 0xb4, 0xd1, 0x5d, 0x18, 0x6f, 0x3a, - 0x6d, 0x67, 0xd3, 0xf5, 0xdc, 0xd8, 0x25, 0x51, 0x2f, 0x33, 0x94, 0x65, 0x0d, 0x4f, 0xbc, 0x13, - 0x6a, 0x25, 0xd8, 0xa0, 0x83, 0xe6, 0x01, 0xda, 0xa1, 0xbb, 0xef, 0x7a, 0x64, 0x9b, 0x89, 0xc2, - 0xcc, 0xb1, 0x8b, 0xdb, 0x56, 0xc8, 0x52, 0xac, 0x61, 0x64, 0x38, 0x02, 0x15, 0x1f, 0x9d, 0x23, - 0x50, 0xe9, 0x84, 0x8e, 0x40, 0x43, 0x03, 0x39, 0x02, 0x61, 0x78, 0x4c, 0xde, 0xdd, 0xf4, 0xff, - 0xaa, 0xeb, 0x11, 0xc1, 0xb0, 0x71, 0x77, 0xaf, 0xb9, 0xa3, 0xc3, 0xca, 0x63, 0x38, 0x13, 0x03, - 0xe7, 0xd4, 0x44, 0x5f, 0x80, 0x59, 0xc7, 0xf3, 0x82, 0xfb, 0x6a, 0xd4, 0x56, 0xa2, 0xa6, 0xe3, - 0x71, 0x75, 0xef, 0x08, 0xa3, 0xfa, 0xe4, 0xd1, 0x61, 0x65, 0x76, 0x31, 0x07, 0x07, 0xe7, 0xd6, - 0x4e, 0xf9, 0x11, 0x8d, 0xf6, 0xf5, 0x23, 0xda, 0x85, 0x73, 0x0d, 0x12, 0xba, 0x2c, 0x87, 0x5e, - 0x2b, 0xd9, 0x92, 0x1b, 0x50, 0x0e, 0x53, 0x87, 0xd0, 0x40, 0x31, 0x60, 0xb4, 0x38, 0xa1, 0xf2, - 0xd0, 0x49, 0x08, 0xd9, 0x7f, 0x6a, 0xc1, 0x88, 0xb0, 0x13, 0x3f, 0x03, 0xde, 0x67, 0xd1, 0xd0, - 0x5f, 0x56, 0xb2, 0x0f, 0x6a, 0xd6, 0x99, 0x5c, 0xcd, 0x65, 0x2d, 0xa5, 0xb9, 0x7c, 0xba, 0x17, - 0x91, 0xde, 0x3a, 0xcb, 0x9f, 0x2c, 0xc2, 0xa4, 0x69, 0x23, 0x7f, 0x06, 0x43, 0xb0, 0x0e, 0x23, - 0x91, 0x70, 0xc8, 0x28, 0xe4, 0x1b, 0xce, 0xa6, 0x27, 0x31, 0xb1, 0x8a, 0x11, 0x2e, 0x18, 0x92, - 0x48, 0xa6, 0xa7, 0x47, 0xf1, 0x11, 0x7a, 0x7a, 0xf4, 0x73, 0x53, 0x28, 0x9d, 0x86, 0x9b, 0x82, - 0xfd, 0x4d, 0x76, 0x59, 0xe8, 0xe5, 0x67, 0xc0, 0x47, 0x5c, 0x37, 0xaf, 0x15, 0xbb, 0xc7, 0xca, - 0x12, 0x9d, 0xca, 0xe1, 0x27, 0xfe, 0xb1, 0x05, 0x63, 0x02, 0xf1, 0x0c, 0xba, 0xfd, 0xbd, 0x66, - 0xb7, 0x9f, 0xe8, 0xd1, 0xed, 0x9c, 0xfe, 0xfe, 0xdd, 0x82, 0xea, 0x6f, 0x3d, 0x08, 0xe3, 0x01, - 0x6e, 0xff, 0xd7, 0x61, 0x94, 0x4a, 0x8f, 0x41, 0x33, 0xf0, 0xc4, 0xe5, 0xff, 0x64, 0xe2, 0x21, - 0xcc, 0xcb, 0x8f, 0xb5, 0xdf, 0x58, 0x61, 0x33, 0x07, 0xd6, 0x20, 0x8c, 0xc5, 0x85, 0x9b, 0x38, - 0xb0, 0x06, 0x61, 0x8c, 0x19, 0x04, 0xb5, 0x00, 0x62, 0x27, 0xdc, 0x26, 0x31, 0x2d, 0x13, 0xc1, - 0x06, 0xf2, 0x77, 0x61, 0x27, 0x76, 0xbd, 0x79, 0xd7, 0x8f, 0xa3, 0x38, 0x9c, 0xaf, 0xf9, 0xf1, - 0xed, 0x90, 0xcb, 0x12, 0x9a, 0xcb, 0xaf, 0xa2, 0x85, 0x35, 0xba, 0xd2, 0x87, 0x8c, 0xb5, 0x31, - 0x64, 0x3e, 0x2c, 0xae, 0x8b, 0x72, 0xac, 0x30, 0xec, 0xd7, 0xd8, 0x99, 0xcc, 0x06, 0xe8, 0x64, - 0xde, 0xb8, 0xdf, 0x1a, 0x55, 0x43, 0xcb, 0x5e, 0x15, 0xaa, 0xba, 0xcf, 0x6f, 0xef, 0x23, 0x90, - 0x36, 0xac, 0xfb, 0x23, 0x24, 0x8e, 0xc1, 0xe8, 0xfb, 0xba, 0xde, 0x9b, 0x5f, 0xec, 0x73, 0x96, - 0x9e, 0xe0, 0x85, 0x99, 0x05, 0xb8, 0x65, 0x81, 0x40, 0x6b, 0x75, 0x21, 0x5d, 0x6a, 0x01, 0x6e, - 0x05, 0x00, 0x27, 0x38, 0x68, 0x41, 0x48, 0xa2, 0x25, 0x23, 0x0f, 0x95, 0x94, 0x44, 0xe5, 0xe7, - 0x6b, 0xa2, 0xe8, 0x4b, 0x30, 0xa6, 0xf2, 0x51, 0xd5, 0x79, 0x5a, 0x1f, 0x11, 0x7a, 0x61, 0x25, - 0x29, 0xc6, 0x3a, 0x0e, 0xda, 0x80, 0xa9, 0x88, 0x67, 0xe6, 0x52, 0x11, 0xb6, 0xb8, 0x9e, 0xe1, - 0xd3, 0xf2, 0x9d, 0xba, 0x61, 0x82, 0x8f, 0x59, 0x11, 0xdf, 0xac, 0xd2, 0x11, 0x2c, 0x4d, 0x02, - 0xbd, 0x09, 0x93, 0x9e, 0x9e, 0xd5, 0xb9, 0x2e, 0xd4, 0x10, 0xca, 0x8c, 0xd3, 0xc8, 0xf9, 0x5c, - 0xc7, 0x29, 0x6c, 0xca, 0x34, 0xe8, 0x25, 0x22, 0x2a, 0x9c, 0xe3, 0x6f, 0x93, 0x48, 0x64, 0xd3, - 0x61, 0x4c, 0xc3, 0xad, 0x1c, 0x1c, 0x9c, 0x5b, 0x1b, 0xbd, 0x0e, 0xe3, 0xf2, 0xf3, 0x35, 0x37, - 0xc7, 0xc4, 0x58, 0x58, 0x83, 0x61, 0x03, 0x13, 0xdd, 0x87, 0x0b, 0xf2, 0xff, 0x46, 0xe8, 0x6c, - 0x6d, 0xb9, 0x4d, 0xe1, 0x65, 0xca, 0x3d, 0x26, 0x16, 0xa5, 0x0b, 0xc6, 0x4a, 0x16, 0xd2, 0xf1, - 0x61, 0xe5, 0xb2, 0x18, 0xb5, 0x4c, 0x38, 0x9b, 0xc4, 0x6c, 0xfa, 0x68, 0x0d, 0xce, 0xed, 0x10, - 0xc7, 0x8b, 0x77, 0x96, 0x77, 0x48, 0x73, 0x57, 0x6e, 0x22, 0xe6, 0x3c, 0xa9, 0x99, 0xd8, 0xde, - 0xe8, 0x46, 0xc1, 0x59, 0xf5, 0xd0, 0x3b, 0x30, 0xdb, 0xee, 0x6c, 0x7a, 0x6e, 0xb4, 0xb3, 0x1e, - 0xc4, 0xec, 0x69, 0x5c, 0xa5, 0x73, 0x12, 0x5e, 0x96, 0xca, 0x71, 0xb4, 0x9e, 0x83, 0x87, 0x73, - 0x29, 0xa0, 0xf7, 0xe1, 0x42, 0x6a, 0x31, 0x08, 0x9f, 0xaf, 0xc9, 0xfc, 0x18, 0x9b, 0x8d, 0xac, - 0x0a, 0xc2, 0x87, 0x2b, 0x0b, 0x84, 0xb3, 0x9b, 0xf8, 0x70, 0x06, 0x13, 0xef, 0xd1, 0xca, 0x1a, - 0x77, 0x83, 0xbe, 0x0a, 0xe3, 0xfa, 0x2a, 0x12, 0x17, 0xcc, 0x95, 0x7e, 0x19, 0xcc, 0x05, 0x6f, - 0xa4, 0x56, 0x94, 0x0e, 0xc3, 0x06, 0x45, 0x9b, 0x40, 0xf6, 0xf7, 0xa1, 0x5b, 0x30, 0xda, 0xf4, - 0x5c, 0xe2, 0xc7, 0xb5, 0x7a, 0xaf, 0x68, 0x02, 0xcb, 0x02, 0x47, 0x0c, 0x98, 0x08, 0x4a, 0xc8, - 0xcb, 0xb0, 0xa2, 0x60, 0xff, 0x66, 0x01, 0x2a, 0x7d, 0x22, 0x5c, 0xa6, 0x74, 0x86, 0xd6, 0x40, - 0x3a, 0xc3, 0x45, 0x99, 0x9c, 0x6a, 0x3d, 0x25, 0xaf, 0xa6, 0x12, 0x4f, 0x25, 0x52, 0x6b, 0x1a, - 0x7f, 0x60, 0x3b, 0x4b, 0x5d, 0xed, 0x58, 0xea, 0x6b, 0x01, 0x6c, 0x3c, 0x37, 0x0c, 0x0d, 0xce, - 0xd1, 0xe7, 0xaa, 0x8e, 0xed, 0x6f, 0x16, 0xe0, 0x82, 0x1a, 0xc2, 0xbf, 0xbc, 0x03, 0x77, 0xa7, - 0x7b, 0xe0, 0x4e, 0x41, 0xf1, 0x6e, 0xdf, 0x86, 0xe1, 0xc6, 0x41, 0xd4, 0x8c, 0xbd, 0x01, 0x18, - 0xa0, 0x67, 0xcc, 0xa8, 0x3a, 0xea, 0x9a, 0x36, 0x22, 0xeb, 0xfc, 0x35, 0x0b, 0xa6, 0x36, 0x96, - 0xeb, 0x8d, 0xa0, 0xb9, 0x4b, 0xe2, 0x45, 0xae, 0x56, 0xc2, 0x82, 0xff, 0xb1, 0x1e, 0x92, 0xaf, - 0xc9, 0xe2, 0x98, 0x2e, 0x43, 0x69, 0x27, 0x88, 0xe2, 0xf4, 0xab, 0xdc, 0x8d, 0x20, 0x8a, 0x31, - 0x83, 0xd8, 0xbf, 0x67, 0xc1, 0x10, 0x4b, 0xa9, 0xd8, 0x2f, 0xcf, 0xe7, 0x20, 0xdf, 0x85, 0x5e, - 0x85, 0x61, 0xb2, 0xb5, 0x45, 0x9a, 0xb1, 0x98, 0x55, 0xe9, 0xd6, 0x37, 0xbc, 0xc2, 0x4a, 0xe9, - 0xa5, 0xcf, 0x1a, 0xe3, 0x7f, 0xb1, 0x40, 0x46, 0xf7, 0xa0, 0x1c, 0xbb, 0x7b, 0x64, 0xb1, 0xd5, - 0x12, 0xef, 0x1a, 0x0f, 0xe1, 0x45, 0xb9, 0x21, 0x09, 0xe0, 0x84, 0x96, 0xfd, 0xb5, 0x02, 0x40, - 0xe2, 0x9a, 0xdc, 0xef, 0x13, 0x97, 0xba, 0x52, 0x99, 0x5e, 0xc9, 0x48, 0x65, 0x8a, 0x12, 0x82, - 0x19, 0x89, 0x4c, 0xd5, 0x30, 0x15, 0x07, 0x1a, 0xa6, 0xd2, 0x49, 0x86, 0x69, 0x19, 0x66, 0x12, - 0xd7, 0x6a, 0x33, 0xce, 0x04, 0x8b, 0x78, 0xbf, 0x91, 0x06, 0xe2, 0x6e, 0x7c, 0xfb, 0x87, 0x2d, - 0x10, 0xee, 0x09, 0x03, 0x2c, 0xe6, 0x2f, 0xc9, 0x44, 0x80, 0x46, 0xa0, 0xdc, 0xcb, 0xf9, 0xfe, - 0x1a, 0x22, 0x3c, 0xae, 0xba, 0x3c, 0x8c, 0xa0, 0xb8, 0x06, 0x2d, 0xbb, 0x05, 0x02, 0x5a, 0x25, - 0x4c, 0xc9, 0xd0, 0xbf, 0x37, 0xd7, 0x00, 0x5a, 0x0c, 0x57, 0x4b, 0x07, 0xa6, 0x8e, 0xaa, 0xaa, - 0x82, 0x60, 0x0d, 0xcb, 0xfe, 0xf1, 0x02, 0x8c, 0xc9, 0xc0, 0xac, 0x54, 0x8e, 0xef, 0xdf, 0xca, - 0x89, 0xb2, 0x32, 0xb0, 0xfc, 0x79, 0x94, 0xb0, 0x0a, 0xde, 0xaf, 0xe7, 0xcf, 0x93, 0x00, 0x9c, - 0xe0, 0xa0, 0xe7, 0x60, 0x24, 0xea, 0x6c, 0x32, 0xf4, 0x94, 0xd1, 0x7d, 0x83, 0x17, 0x63, 0x09, - 0x47, 0x5f, 0x80, 0x69, 0x5e, 0x2f, 0x0c, 0xda, 0xce, 0x36, 0xd7, 0x38, 0x0d, 0x29, 0x2f, 0xb8, - 0xe9, 0xb5, 0x14, 0xec, 0xf8, 0xb0, 0x72, 0x3e, 0x5d, 0xc6, 0x74, 0x95, 0x5d, 0x54, 0xec, 0xaf, - 0x02, 0xea, 0x8e, 0x35, 0x8b, 0xde, 0xe2, 0x66, 0x15, 0x6e, 0xa8, 0xd2, 0x7f, 0xf7, 0x4f, 0xd8, - 0x3f, 0x2e, 0x8d, 0x27, 0x68, 0x2d, 0xac, 0xea, 0xd3, 0x9d, 0x37, 0x9d, 0x76, 0xe1, 0x41, 0x37, - 0x60, 0x98, 0x1f, 0xaa, 0xbd, 0xb2, 0x8b, 0xa7, 0xf5, 0xed, 0x3c, 0x10, 0xbe, 0x38, 0x97, 0x45, - 0x7d, 0xf4, 0x0e, 0x8c, 0xb5, 0x82, 0xfb, 0xfe, 0x7d, 0x27, 0x6c, 0x2d, 0xd6, 0x6b, 0x62, 0x5d, - 0x66, 0xf2, 0x66, 0xd5, 0x04, 0x4d, 0x77, 0x26, 0x62, 0xfa, 0xdc, 0x04, 0x84, 0x75, 0x72, 0x68, - 0x43, 0x4f, 0xbc, 0xde, 0xc3, 0x0e, 0x4e, 0x65, 0x56, 0xd7, 0x28, 0xe7, 0xa7, 0x5c, 0xff, 0xe0, - 0x1c, 0x18, 0xfb, 0xc1, 0xc8, 0xfb, 0x60, 0x9d, 0x52, 0xde, 0x07, 0x0c, 0xa3, 0x64, 0xaf, 0x1d, - 0x1f, 0x54, 0xdd, 0xb0, 0x57, 0xe2, 0xa0, 0x15, 0x81, 0xd3, 0x4d, 0x53, 0x42, 0xb0, 0xa2, 0x93, - 0x9d, 0x9c, 0xa3, 0xf8, 0x11, 0x26, 0xe7, 0x28, 0x9d, 0x61, 0x72, 0x8e, 0x75, 0x18, 0xd9, 0x76, - 0x63, 0x4c, 0xda, 0x81, 0x60, 0x28, 0x32, 0x57, 0xc2, 0x75, 0x8e, 0xd2, 0x1d, 0x1a, 0x5e, 0x00, - 0xb0, 0x24, 0x82, 0xde, 0x52, 0x7b, 0x60, 0x38, 0x9f, 0x1f, 0xef, 0x7e, 0x0e, 0xc9, 0xdc, 0x05, - 0x22, 0x19, 0xc7, 0xc8, 0xc3, 0x26, 0xe3, 0x58, 0x95, 0x29, 0x34, 0x46, 0xf3, 0xcd, 0x46, 0x59, - 0x86, 0x8c, 0x3e, 0x89, 0x33, 0x8c, 0x64, 0x23, 0xe5, 0xd3, 0x4b, 0x36, 0xf2, 0xc3, 0x16, 0x5c, - 0x68, 0x67, 0xe5, 0xdd, 0x11, 0x29, 0x30, 0x5e, 0x1d, 0x38, 0xb1, 0x90, 0xd1, 0x20, 0x13, 0xcc, - 0x32, 0xd1, 0x70, 0x76, 0x73, 0x74, 0xa0, 0xc3, 0xcd, 0x96, 0xc8, 0x9b, 0xf1, 0x4c, 0x4e, 0xd6, - 0x92, 0x1e, 0xb9, 0x4a, 0x36, 0x32, 0x72, 0x65, 0x7c, 0x32, 0x2f, 0x57, 0xc6, 0xc0, 0x19, 0x32, - 0x92, 0x7c, 0x25, 0x13, 0x1f, 0x3a, 0x5f, 0xc9, 0x5b, 0x2a, 0x5f, 0x49, 0x8f, 0xa8, 0x43, 0x3c, - 0x1b, 0x49, 0xdf, 0x2c, 0x25, 0x5a, 0xa6, 0x91, 0xa9, 0xd3, 0xc9, 0x34, 0x62, 0x1c, 0xf6, 0x3c, - 0xd9, 0xc5, 0xf3, 0x7d, 0x0e, 0x7b, 0x83, 0x6e, 0xef, 0xe3, 0x9e, 0x67, 0x55, 0x99, 0x79, 0xa8, - 0xac, 0x2a, 0x77, 0xf5, 0x2c, 0x25, 0xa8, 0x4f, 0x1a, 0x0e, 0x8a, 0x34, 0x60, 0x6e, 0x92, 0xbb, - 0xfa, 0x15, 0x74, 0x2e, 0x9f, 0xae, 0xba, 0x69, 0xba, 0xe9, 0x66, 0x5d, 0x42, 0xdd, 0x39, 0x4f, - 0xce, 0x9f, 0x4d, 0xce, 0x93, 0x0b, 0xa7, 0x9e, 0xf3, 0xe4, 0xb1, 0x33, 0xc8, 0x79, 0xf2, 0xf8, - 0x47, 0x9a, 0xf3, 0x64, 0xf6, 0x11, 0xe4, 0x3c, 0x59, 0x4f, 0x72, 0x9e, 0x5c, 0xcc, 0x9f, 0x92, - 0x0c, 0x3b, 0xb9, 0x9c, 0x4c, 0x27, 0x77, 0xa1, 0xdc, 0x96, 0x5e, 0xde, 0x22, 0x2c, 0x52, 0x76, - 0xb2, 0xc5, 0x2c, 0x57, 0x70, 0x3e, 0x25, 0x0a, 0x84, 0x13, 0x52, 0x94, 0x6e, 0x92, 0xf9, 0xe4, - 0x89, 0x1e, 0xaa, 0xb7, 0x2c, 0xa5, 0x46, 0x7e, 0xbe, 0x13, 0xfb, 0xaf, 0x17, 0xe0, 0x52, 0xef, - 0x75, 0x9d, 0x68, 0x44, 0xea, 0x89, 0x06, 0x3f, 0xa5, 0x11, 0xe1, 0x62, 0x46, 0x82, 0x35, 0x70, - 0x28, 0x8c, 0xeb, 0x30, 0xa3, 0x0c, 0xe4, 0x3c, 0xb7, 0x79, 0xa0, 0x25, 0x61, 0x54, 0xce, 0x3a, - 0x8d, 0x34, 0x02, 0xee, 0xae, 0x83, 0x16, 0x61, 0xca, 0x28, 0xac, 0x55, 0x85, 0x38, 0xa1, 0x54, - 0x30, 0x0d, 0x13, 0x8c, 0xd3, 0xf8, 0xf6, 0xd7, 0x2d, 0x78, 0x3c, 0x27, 0x1c, 0xf8, 0xc0, 0x91, - 0x1e, 0xb6, 0x60, 0xaa, 0x6d, 0x56, 0xed, 0x13, 0x10, 0xc6, 0x08, 0x3a, 0xae, 0xfa, 0x9a, 0x02, - 0xe0, 0x34, 0xd1, 0xa5, 0xab, 0xbf, 0xfd, 0x07, 0x97, 0x3e, 0xf1, 0x3b, 0x7f, 0x70, 0xe9, 0x13, - 0xbf, 0xfb, 0x07, 0x97, 0x3e, 0xf1, 0xff, 0x1d, 0x5d, 0xb2, 0x7e, 0xfb, 0xe8, 0x92, 0xf5, 0x3b, - 0x47, 0x97, 0xac, 0xdf, 0x3d, 0xba, 0x64, 0xfd, 0xfe, 0xd1, 0x25, 0xeb, 0x6b, 0x7f, 0x78, 0xe9, - 0x13, 0x5f, 0x2a, 0xec, 0xbf, 0xf4, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xa2, 0x14, 0x11, 0x2e, - 0x5f, 0xdf, 0x00, 0x00, + // 12696 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x6b, 0x6c, 0x24, 0x57, + 0x76, 0x18, 0xbc, 0xd5, 0xdd, 0x7c, 0xf4, 0xe1, 0xfb, 0xce, 0x70, 0xc4, 0xa1, 0x34, 0xd3, 0xa3, + 0xd2, 0xee, 0x68, 0xb4, 0x92, 0xc8, 0xd5, 0x48, 0x5a, 0xc9, 0xab, 0x5d, 0xd9, 0x24, 0x9b, 0x9c, + 0xa1, 0x66, 0xc8, 0x69, 0xdd, 0xe6, 0x8c, 0x76, 0x65, 0xed, 0x7a, 0x8b, 0xdd, 0x97, 0x64, 0x89, + 0xc5, 0xaa, 0x56, 0x55, 0x35, 0x67, 0xa8, 0xcf, 0x06, 0xbe, 0xac, 0x63, 0x27, 0x7e, 0x20, 0x58, + 0xc4, 0x46, 0x1e, 0xb6, 0xe1, 0x00, 0x8e, 0x03, 0xdb, 0x71, 0x12, 0xc4, 0xb1, 0x63, 0x3b, 0xbb, + 0x76, 0xe2, 0x38, 0xf9, 0xe1, 0xfc, 0xd9, 0x38, 0x01, 0x82, 0x35, 0x60, 0x84, 0xb1, 0x69, 0x27, + 0x81, 0x7f, 0xe4, 0x81, 0x38, 0x7f, 0xcc, 0x18, 0x71, 0x70, 0x9f, 0x75, 0x6f, 0x75, 0x55, 0x77, + 0x73, 0xc4, 0xa1, 0x64, 0x63, 0xff, 0x75, 0xdf, 0x73, 0xee, 0xb9, 0xb7, 0xee, 0xf3, 0x9c, 0x73, + 0xcf, 0x03, 0x5e, 0xdb, 0x7d, 0x35, 0x9a, 0x73, 0x83, 0xf9, 0xdd, 0xf6, 0x26, 0x09, 0x7d, 0x12, + 0x93, 0x68, 0x7e, 0x9f, 0xf8, 0xcd, 0x20, 0x9c, 0x17, 0x00, 0xa7, 0xe5, 0xce, 0x37, 0x82, 0x90, + 0xcc, 0xef, 0xbf, 0x30, 0xbf, 0x4d, 0x7c, 0x12, 0x3a, 0x31, 0x69, 0xce, 0xb5, 0xc2, 0x20, 0x0e, + 0x10, 0xe2, 0x38, 0x73, 0x4e, 0xcb, 0x9d, 0xa3, 0x38, 0x73, 0xfb, 0x2f, 0xcc, 0x3e, 0xbf, 0xed, + 0xc6, 0x3b, 0xed, 0xcd, 0xb9, 0x46, 0xb0, 0x37, 0xbf, 0x1d, 0x6c, 0x07, 0xf3, 0x0c, 0x75, 0xb3, + 0xbd, 0xc5, 0xfe, 0xb1, 0x3f, 0xec, 0x17, 0x27, 0x31, 0xbb, 0x96, 0x34, 0x43, 0x1e, 0xc4, 0xc4, + 0x8f, 0xdc, 0xc0, 0x8f, 0x9e, 0x77, 0x5a, 0x6e, 0x44, 0xc2, 0x7d, 0x12, 0xce, 0xb7, 0x76, 0xb7, + 0x29, 0x2c, 0x32, 0x11, 0xe6, 0xf7, 0x5f, 0xd8, 0x24, 0xb1, 0xd3, 0xd1, 0xa3, 0xd9, 0x97, 0x12, + 0x72, 0x7b, 0x4e, 0x63, 0xc7, 0xf5, 0x49, 0x78, 0x20, 0x69, 0xcc, 0x87, 0x24, 0x0a, 0xda, 0x61, + 0x83, 0x9c, 0xa8, 0x56, 0x34, 0xbf, 0x47, 0x62, 0x27, 0xe3, 0xeb, 0x67, 0xe7, 0xf3, 0x6a, 0x85, + 0x6d, 0x3f, 0x76, 0xf7, 0x3a, 0x9b, 0xf9, 0x74, 0xaf, 0x0a, 0x51, 0x63, 0x87, 0xec, 0x39, 0x1d, + 0xf5, 0x5e, 0xcc, 0xab, 0xd7, 0x8e, 0x5d, 0x6f, 0xde, 0xf5, 0xe3, 0x28, 0x0e, 0xd3, 0x95, 0xec, + 0x6f, 0x5a, 0x70, 0x65, 0xe1, 0xad, 0xfa, 0xb2, 0xe7, 0x44, 0xb1, 0xdb, 0x58, 0xf4, 0x82, 0xc6, + 0x6e, 0x3d, 0x0e, 0x42, 0x72, 0x2f, 0xf0, 0xda, 0x7b, 0xa4, 0xce, 0x06, 0x02, 0x3d, 0x07, 0xc3, + 0xfb, 0xec, 0xff, 0x6a, 0x75, 0xc6, 0xba, 0x62, 0x5d, 0x2b, 0x2f, 0x4e, 0xfe, 0xd6, 0x61, 0xe5, + 0x63, 0x47, 0x87, 0x95, 0xe1, 0x7b, 0xa2, 0x1c, 0x2b, 0x0c, 0x74, 0x15, 0x06, 0xb7, 0xa2, 0x8d, + 0x83, 0x16, 0x99, 0x29, 0x30, 0xdc, 0x71, 0x81, 0x3b, 0xb8, 0x52, 0xa7, 0xa5, 0x58, 0x40, 0xd1, + 0x3c, 0x94, 0x5b, 0x4e, 0x18, 0xbb, 0xb1, 0x1b, 0xf8, 0x33, 0xc5, 0x2b, 0xd6, 0xb5, 0x81, 0xc5, + 0x29, 0x81, 0x5a, 0xae, 0x49, 0x00, 0x4e, 0x70, 0x68, 0x37, 0x42, 0xe2, 0x34, 0xef, 0xf8, 0xde, + 0xc1, 0x4c, 0xe9, 0x8a, 0x75, 0x6d, 0x38, 0xe9, 0x06, 0x16, 0xe5, 0x58, 0x61, 0xd8, 0x3f, 0x56, + 0x80, 0xe1, 0x85, 0xad, 0x2d, 0xd7, 0x77, 0xe3, 0x03, 0x74, 0x0f, 0x46, 0xfd, 0xa0, 0x49, 0xe4, + 0x7f, 0xf6, 0x15, 0x23, 0xd7, 0xaf, 0xcc, 0x75, 0xae, 0xcc, 0xb9, 0x75, 0x0d, 0x6f, 0x71, 0xf2, + 0xe8, 0xb0, 0x32, 0xaa, 0x97, 0x60, 0x83, 0x0e, 0xc2, 0x30, 0xd2, 0x0a, 0x9a, 0x8a, 0x6c, 0x81, + 0x91, 0xad, 0x64, 0x91, 0xad, 0x25, 0x68, 0x8b, 0x13, 0x47, 0x87, 0x95, 0x11, 0xad, 0x00, 0xeb, + 0x44, 0xd0, 0x26, 0x4c, 0xd0, 0xbf, 0x7e, 0xec, 0x2a, 0xba, 0x45, 0x46, 0xf7, 0xa9, 0x3c, 0xba, + 0x1a, 0xea, 0xe2, 0xb9, 0xa3, 0xc3, 0xca, 0x44, 0xaa, 0x10, 0xa7, 0x09, 0xda, 0xef, 0xc3, 0xf8, + 0x42, 0x1c, 0x3b, 0x8d, 0x1d, 0xd2, 0xe4, 0x33, 0x88, 0x5e, 0x82, 0x92, 0xef, 0xec, 0x11, 0x31, + 0xbf, 0x57, 0xc4, 0xc0, 0x96, 0xd6, 0x9d, 0x3d, 0x72, 0x7c, 0x58, 0x99, 0xbc, 0xeb, 0xbb, 0xef, + 0xb5, 0xc5, 0xaa, 0xa0, 0x65, 0x98, 0x61, 0xa3, 0xeb, 0x00, 0x4d, 0xb2, 0xef, 0x36, 0x48, 0xcd, + 0x89, 0x77, 0xc4, 0x7c, 0x23, 0x51, 0x17, 0xaa, 0x0a, 0x82, 0x35, 0x2c, 0xfb, 0x01, 0x94, 0x17, + 0xf6, 0x03, 0xb7, 0x59, 0x0b, 0x9a, 0x11, 0xda, 0x85, 0x89, 0x56, 0x48, 0xb6, 0x48, 0xa8, 0x8a, + 0x66, 0xac, 0x2b, 0xc5, 0x6b, 0x23, 0xd7, 0xaf, 0x65, 0x7e, 0xac, 0x89, 0xba, 0xec, 0xc7, 0xe1, + 0xc1, 0xe2, 0x63, 0xa2, 0xbd, 0x89, 0x14, 0x14, 0xa7, 0x29, 0xdb, 0xff, 0xba, 0x00, 0xd3, 0x0b, + 0xef, 0xb7, 0x43, 0x52, 0x75, 0xa3, 0xdd, 0xf4, 0x0a, 0x6f, 0xba, 0xd1, 0xee, 0x7a, 0x32, 0x02, + 0x6a, 0x69, 0x55, 0x45, 0x39, 0x56, 0x18, 0xe8, 0x79, 0x18, 0xa2, 0xbf, 0xef, 0xe2, 0x55, 0xf1, + 0xc9, 0xe7, 0x04, 0xf2, 0x48, 0xd5, 0x89, 0x9d, 0x2a, 0x07, 0x61, 0x89, 0x83, 0xd6, 0x60, 0xa4, + 0xc1, 0x36, 0xe4, 0xf6, 0x5a, 0xd0, 0x24, 0x6c, 0x32, 0xcb, 0x8b, 0xcf, 0x52, 0xf4, 0xa5, 0xa4, + 0xf8, 0xf8, 0xb0, 0x32, 0xc3, 0xfb, 0x26, 0x48, 0x68, 0x30, 0xac, 0xd7, 0x47, 0xb6, 0xda, 0x5f, + 0x25, 0x46, 0x09, 0x32, 0xf6, 0xd6, 0x35, 0x6d, 0xab, 0x0c, 0xb0, 0xad, 0x32, 0x9a, 0xbd, 0x4d, + 0xd0, 0x0b, 0x50, 0xda, 0x75, 0xfd, 0xe6, 0xcc, 0x20, 0xa3, 0x75, 0x89, 0xce, 0xf9, 0x2d, 0xd7, + 0x6f, 0x1e, 0x1f, 0x56, 0xa6, 0x8c, 0xee, 0xd0, 0x42, 0xcc, 0x50, 0xed, 0x3f, 0xb6, 0xa0, 0xc2, + 0x60, 0x2b, 0xae, 0x47, 0x6a, 0x24, 0x8c, 0xdc, 0x28, 0x26, 0x7e, 0x6c, 0x0c, 0xe8, 0x75, 0x80, + 0x88, 0x34, 0x42, 0x12, 0x6b, 0x43, 0xaa, 0x16, 0x46, 0x5d, 0x41, 0xb0, 0x86, 0x45, 0x0f, 0x84, + 0x68, 0xc7, 0x09, 0xd9, 0xfa, 0x12, 0x03, 0xab, 0x0e, 0x84, 0xba, 0x04, 0xe0, 0x04, 0xc7, 0x38, + 0x10, 0x8a, 0xbd, 0x0e, 0x04, 0xf4, 0x39, 0x98, 0x48, 0x1a, 0x8b, 0x5a, 0x4e, 0x43, 0x0e, 0x20, + 0xdb, 0x32, 0x75, 0x13, 0x84, 0xd3, 0xb8, 0xf6, 0xdf, 0xb7, 0xc4, 0xe2, 0xa1, 0x5f, 0xfd, 0x11, + 0xff, 0x56, 0xfb, 0x57, 0x2d, 0x18, 0x5a, 0x74, 0xfd, 0xa6, 0xeb, 0x6f, 0xa3, 0x2f, 0xc3, 0x30, + 0xbd, 0x9b, 0x9a, 0x4e, 0xec, 0x88, 0x73, 0xef, 0x53, 0xda, 0xde, 0x52, 0x57, 0xc5, 0x5c, 0x6b, + 0x77, 0x9b, 0x16, 0x44, 0x73, 0x14, 0x9b, 0xee, 0xb6, 0x3b, 0x9b, 0xef, 0x92, 0x46, 0xbc, 0x46, + 0x62, 0x27, 0xf9, 0x9c, 0xa4, 0x0c, 0x2b, 0xaa, 0xe8, 0x16, 0x0c, 0xc6, 0x4e, 0xb8, 0x4d, 0x62, + 0x71, 0x00, 0x66, 0x1e, 0x54, 0xbc, 0x26, 0xa6, 0x3b, 0x92, 0xf8, 0x0d, 0x92, 0x5c, 0x0b, 0x1b, + 0xac, 0x2a, 0x16, 0x24, 0xec, 0x1f, 0x1c, 0x84, 0x8b, 0x4b, 0xf5, 0xd5, 0x9c, 0x75, 0x75, 0x15, + 0x06, 0x9b, 0xa1, 0xbb, 0x4f, 0x42, 0x31, 0xce, 0x8a, 0x4a, 0x95, 0x95, 0x62, 0x01, 0x45, 0xaf, + 0xc2, 0x28, 0xbf, 0x90, 0x6e, 0x3a, 0x7e, 0xd3, 0x93, 0x43, 0x7c, 0x5e, 0x60, 0x8f, 0xde, 0xd3, + 0x60, 0xd8, 0xc0, 0x3c, 0xe1, 0xa2, 0xba, 0x9a, 0xda, 0x8c, 0x79, 0x97, 0xdd, 0x0f, 0x58, 0x30, + 0xc9, 0x9b, 0x59, 0x88, 0xe3, 0xd0, 0xdd, 0x6c, 0xc7, 0x24, 0x9a, 0x19, 0x60, 0x27, 0xdd, 0x52, + 0xd6, 0x68, 0xe5, 0x8e, 0xc0, 0xdc, 0xbd, 0x14, 0x15, 0x7e, 0x08, 0xce, 0x88, 0x76, 0x27, 0xd3, + 0x60, 0xdc, 0xd1, 0x2c, 0xfa, 0x5e, 0x0b, 0x66, 0x1b, 0x81, 0x1f, 0x87, 0x81, 0xe7, 0x91, 0xb0, + 0xd6, 0xde, 0xf4, 0xdc, 0x68, 0x87, 0xaf, 0x53, 0x4c, 0xb6, 0xd8, 0x49, 0x90, 0x33, 0x87, 0x0a, + 0x49, 0xcc, 0xe1, 0xe5, 0xa3, 0xc3, 0xca, 0xec, 0x52, 0x2e, 0x29, 0xdc, 0xa5, 0x19, 0xb4, 0x0b, + 0x88, 0x5e, 0xa5, 0xf5, 0xd8, 0xd9, 0x26, 0x49, 0xe3, 0x43, 0xfd, 0x37, 0x7e, 0xe1, 0xe8, 0xb0, + 0x82, 0xd6, 0x3b, 0x48, 0xe0, 0x0c, 0xb2, 0xe8, 0x3d, 0x38, 0x4f, 0x4b, 0x3b, 0xbe, 0x75, 0xb8, + 0xff, 0xe6, 0x66, 0x8e, 0x0e, 0x2b, 0xe7, 0xd7, 0x33, 0x88, 0xe0, 0x4c, 0xd2, 0xb3, 0x4b, 0x30, + 0x9d, 0x39, 0x55, 0x68, 0x12, 0x8a, 0xbb, 0x84, 0xb3, 0x20, 0x65, 0x4c, 0x7f, 0xa2, 0xf3, 0x30, + 0xb0, 0xef, 0x78, 0x6d, 0xb1, 0x4a, 0x31, 0xff, 0xf3, 0x99, 0xc2, 0xab, 0x96, 0xdd, 0x80, 0xd1, + 0x25, 0xa7, 0xe5, 0x6c, 0xba, 0x9e, 0x1b, 0xbb, 0x24, 0x42, 0x4f, 0x43, 0xd1, 0x69, 0x36, 0xd9, + 0x15, 0x59, 0x5e, 0x9c, 0x3e, 0x3a, 0xac, 0x14, 0x17, 0x9a, 0xf4, 0xac, 0x06, 0x85, 0x75, 0x80, + 0x29, 0x06, 0xfa, 0x24, 0x94, 0x9a, 0x61, 0xd0, 0x9a, 0x29, 0x30, 0x4c, 0x3a, 0x54, 0xa5, 0x6a, + 0x18, 0xb4, 0x52, 0xa8, 0x0c, 0xc7, 0xfe, 0x8d, 0x02, 0x3c, 0xb1, 0x44, 0x5a, 0x3b, 0x2b, 0xf5, + 0x9c, 0x4d, 0x77, 0x0d, 0x86, 0xf7, 0x02, 0xdf, 0x8d, 0x83, 0x30, 0x12, 0x4d, 0xb3, 0xdb, 0x64, + 0x4d, 0x94, 0x61, 0x05, 0x45, 0x57, 0xa0, 0xd4, 0x4a, 0x38, 0x81, 0x51, 0xc9, 0x45, 0x30, 0x1e, + 0x80, 0x41, 0x28, 0x46, 0x3b, 0x22, 0xa1, 0xb8, 0x05, 0x15, 0xc6, 0xdd, 0x88, 0x84, 0x98, 0x41, + 0x92, 0xe3, 0x94, 0x1e, 0xb4, 0x62, 0x5b, 0xa5, 0x8e, 0x53, 0x0a, 0xc1, 0x1a, 0x16, 0xaa, 0x41, + 0x39, 0x52, 0x93, 0x3a, 0xd0, 0xff, 0xa4, 0x8e, 0xb1, 0xf3, 0x56, 0xcd, 0x64, 0x42, 0xc4, 0x38, + 0x06, 0x06, 0x7b, 0x9e, 0xb7, 0x5f, 0x2f, 0x00, 0xe2, 0x43, 0xf8, 0xe7, 0x6c, 0xe0, 0xee, 0x76, + 0x0e, 0x5c, 0x26, 0xe7, 0x75, 0x3b, 0x68, 0x38, 0x5e, 0xfa, 0x08, 0x3f, 0xad, 0xd1, 0xfb, 0xdf, + 0x16, 0x3c, 0xb1, 0xe4, 0xfa, 0x4d, 0x12, 0xe6, 0x2c, 0xc0, 0x47, 0x23, 0x80, 0x9c, 0xec, 0xa4, + 0x37, 0x96, 0x58, 0xe9, 0x14, 0x96, 0x98, 0xfd, 0x3f, 0x2c, 0x40, 0xfc, 0xb3, 0x3f, 0x72, 0x1f, + 0x7b, 0xb7, 0xf3, 0x63, 0x4f, 0x61, 0x59, 0xd8, 0xb7, 0x61, 0x7c, 0xc9, 0x73, 0x89, 0x1f, 0xaf, + 0xd6, 0x96, 0x02, 0x7f, 0xcb, 0xdd, 0x46, 0x9f, 0x81, 0x71, 0x2a, 0xd3, 0x06, 0xed, 0xb8, 0x4e, + 0x1a, 0x81, 0xcf, 0xd8, 0x7f, 0x2a, 0x09, 0xa2, 0xa3, 0xc3, 0xca, 0xf8, 0x86, 0x01, 0xc1, 0x29, + 0x4c, 0xfb, 0x77, 0xe9, 0xf8, 0x05, 0x7b, 0xad, 0xc0, 0x27, 0x7e, 0xbc, 0x14, 0xf8, 0x4d, 0x2e, + 0x26, 0x7e, 0x06, 0x4a, 0x31, 0x1d, 0x0f, 0x3e, 0x76, 0x57, 0xe5, 0x46, 0xa1, 0xa3, 0x70, 0x7c, + 0x58, 0xb9, 0xd0, 0x59, 0x83, 0x8d, 0x13, 0xab, 0x83, 0xbe, 0x0d, 0x06, 0xa3, 0xd8, 0x89, 0xdb, + 0x91, 0x18, 0xcd, 0x27, 0xe5, 0x68, 0xd6, 0x59, 0xe9, 0xf1, 0x61, 0x65, 0x42, 0x55, 0xe3, 0x45, + 0x58, 0x54, 0x40, 0xcf, 0xc0, 0xd0, 0x1e, 0x89, 0x22, 0x67, 0x5b, 0x72, 0xf8, 0x13, 0xa2, 0xee, + 0xd0, 0x1a, 0x2f, 0xc6, 0x12, 0x8e, 0x9e, 0x82, 0x01, 0x12, 0x86, 0x41, 0x28, 0xf6, 0xe8, 0x98, + 0x40, 0x1c, 0x58, 0xa6, 0x85, 0x98, 0xc3, 0xec, 0x7f, 0x6b, 0xc1, 0x84, 0xea, 0x2b, 0x6f, 0xeb, + 0x0c, 0x58, 0xb9, 0xb7, 0x01, 0x1a, 0xf2, 0x03, 0x23, 0x76, 0x7b, 0x8c, 0x5c, 0xbf, 0x9a, 0xc9, + 0xa0, 0x74, 0x0c, 0x63, 0x42, 0x59, 0x15, 0x45, 0x58, 0xa3, 0x66, 0xff, 0xba, 0x05, 0xe7, 0x52, + 0x5f, 0x74, 0xdb, 0x8d, 0x62, 0xf4, 0x4e, 0xc7, 0x57, 0xcd, 0xf5, 0xf7, 0x55, 0xb4, 0x36, 0xfb, + 0x26, 0xb5, 0x94, 0x65, 0x89, 0xf6, 0x45, 0x37, 0x61, 0xc0, 0x8d, 0xc9, 0x9e, 0xfc, 0x98, 0xa7, + 0xba, 0x7e, 0x0c, 0xef, 0x55, 0x32, 0x23, 0xab, 0xb4, 0x26, 0xe6, 0x04, 0xec, 0x1f, 0x29, 0x42, + 0x99, 0x2f, 0xdb, 0x35, 0xa7, 0x75, 0x06, 0x73, 0xb1, 0x0a, 0x25, 0x46, 0x9d, 0x77, 0xfc, 0xe9, + 0xec, 0x8e, 0x8b, 0xee, 0xcc, 0x51, 0x39, 0x8d, 0xb3, 0x82, 0xea, 0x6a, 0xa0, 0x45, 0x98, 0x91, + 0x40, 0x0e, 0xc0, 0xa6, 0xeb, 0x3b, 0xe1, 0x01, 0x2d, 0x9b, 0x29, 0x32, 0x82, 0xcf, 0x77, 0x27, + 0xb8, 0xa8, 0xf0, 0x39, 0x59, 0xd5, 0xd7, 0x04, 0x80, 0x35, 0xa2, 0xb3, 0xaf, 0x40, 0x59, 0x21, + 0x9f, 0x84, 0xc7, 0x99, 0xfd, 0x1c, 0x4c, 0xa4, 0xda, 0xea, 0x55, 0x7d, 0x54, 0x67, 0x91, 0xbe, + 0xc6, 0x4e, 0x01, 0xd1, 0xeb, 0x65, 0x7f, 0x5f, 0x9c, 0xa2, 0xef, 0xc3, 0x79, 0x2f, 0xe3, 0x70, + 0x12, 0x53, 0xd5, 0xff, 0x61, 0xf6, 0x84, 0xf8, 0xec, 0xf3, 0x59, 0x50, 0x9c, 0xd9, 0x06, 0xbd, + 0xf6, 0x83, 0x16, 0x5d, 0xf3, 0x8e, 0xc7, 0xfa, 0x2b, 0xa4, 0xef, 0x3b, 0xa2, 0x0c, 0x2b, 0x28, + 0x3d, 0xc2, 0xce, 0xab, 0xce, 0xdf, 0x22, 0x07, 0x75, 0xe2, 0x91, 0x46, 0x1c, 0x84, 0x1f, 0x6a, + 0xf7, 0x2f, 0xf1, 0xd1, 0xe7, 0x27, 0xe0, 0x88, 0x20, 0x50, 0xbc, 0x45, 0x0e, 0xf8, 0x54, 0xe8, + 0x5f, 0x57, 0xec, 0xfa, 0x75, 0xbf, 0x60, 0xc1, 0x98, 0xfa, 0xba, 0x33, 0xd8, 0xea, 0x8b, 0xe6, + 0x56, 0xbf, 0xd4, 0x75, 0x81, 0xe7, 0x6c, 0xf2, 0xaf, 0x17, 0xe0, 0xa2, 0xc2, 0xa1, 0xec, 0x3e, + 0xff, 0x23, 0x56, 0xd5, 0x3c, 0x94, 0x7d, 0xa5, 0x3d, 0xb0, 0x4c, 0xb1, 0x3d, 0xd1, 0x1d, 0x24, + 0x38, 0x94, 0x6b, 0xf3, 0x13, 0x11, 0x7f, 0x54, 0x57, 0xab, 0x09, 0x15, 0xda, 0x22, 0x14, 0xdb, + 0x6e, 0x53, 0xdc, 0x19, 0x9f, 0x92, 0xa3, 0x7d, 0x77, 0xb5, 0x7a, 0x7c, 0x58, 0x79, 0x32, 0x4f, + 0xa5, 0x4b, 0x2f, 0xab, 0x68, 0xee, 0xee, 0x6a, 0x15, 0xd3, 0xca, 0x68, 0x01, 0x26, 0xa4, 0xd6, + 0xfa, 0x1e, 0xe5, 0xa0, 0x02, 0x5f, 0x5c, 0x2d, 0x4a, 0x37, 0x86, 0x4d, 0x30, 0x4e, 0xe3, 0xa3, + 0x2a, 0x4c, 0xee, 0xb6, 0x37, 0x89, 0x47, 0x62, 0xfe, 0xc1, 0xb7, 0x08, 0xd7, 0x1c, 0x95, 0x13, + 0xd1, 0xf2, 0x56, 0x0a, 0x8e, 0x3b, 0x6a, 0xd8, 0x7f, 0xc6, 0x8e, 0x78, 0x31, 0x7a, 0xb5, 0x30, + 0xa0, 0x0b, 0x8b, 0x52, 0xff, 0x30, 0x97, 0x73, 0x3f, 0xab, 0xe2, 0x16, 0x39, 0xd8, 0x08, 0x28, + 0xb3, 0x9d, 0xbd, 0x2a, 0x8c, 0x35, 0x5f, 0xea, 0xba, 0xe6, 0x7f, 0xa9, 0x00, 0xd3, 0x6a, 0x04, + 0x0c, 0xbe, 0xee, 0xcf, 0xfb, 0x18, 0xbc, 0x00, 0x23, 0x4d, 0xb2, 0xe5, 0xb4, 0xbd, 0x58, 0xa9, + 0x31, 0x07, 0xb8, 0x2a, 0xbb, 0x9a, 0x14, 0x63, 0x1d, 0xe7, 0x04, 0xc3, 0xf6, 0xd3, 0x23, 0xec, + 0x6e, 0x8d, 0x1d, 0xba, 0xc6, 0xd5, 0xae, 0xb1, 0x72, 0x77, 0xcd, 0x53, 0x30, 0xe0, 0xee, 0x51, + 0x5e, 0xab, 0x60, 0xb2, 0x50, 0xab, 0xb4, 0x10, 0x73, 0x18, 0xfa, 0x04, 0x0c, 0x35, 0x82, 0xbd, + 0x3d, 0xc7, 0x6f, 0xb2, 0x2b, 0xaf, 0xbc, 0x38, 0x42, 0xd9, 0xb1, 0x25, 0x5e, 0x84, 0x25, 0x0c, + 0x3d, 0x01, 0x25, 0x27, 0xdc, 0x8e, 0x66, 0x4a, 0x0c, 0x67, 0x98, 0xb6, 0xb4, 0x10, 0x6e, 0x47, + 0x98, 0x95, 0x52, 0xa9, 0xea, 0x7e, 0x10, 0xee, 0xba, 0xfe, 0x76, 0xd5, 0x0d, 0xc5, 0x96, 0x50, + 0x77, 0xe1, 0x5b, 0x0a, 0x82, 0x35, 0x2c, 0xb4, 0x02, 0x03, 0xad, 0x20, 0x8c, 0xa3, 0x99, 0x41, + 0x36, 0xdc, 0x4f, 0xe6, 0x1c, 0x44, 0xfc, 0x6b, 0x6b, 0x41, 0x18, 0x27, 0x1f, 0x40, 0xff, 0x45, + 0x98, 0x57, 0x47, 0xdf, 0x06, 0x45, 0xe2, 0xef, 0xcf, 0x0c, 0x31, 0x2a, 0xb3, 0x59, 0x54, 0x96, + 0xfd, 0xfd, 0x7b, 0x4e, 0x98, 0x9c, 0xd2, 0xcb, 0xfe, 0x3e, 0xa6, 0x75, 0xd0, 0x17, 0xa0, 0x2c, + 0xb7, 0x78, 0x24, 0xd4, 0x1c, 0x99, 0x4b, 0x4c, 0x1e, 0x0c, 0x98, 0xbc, 0xd7, 0x76, 0x43, 0xb2, + 0x47, 0xfc, 0x38, 0x4a, 0xce, 0x34, 0x09, 0x8d, 0x70, 0x42, 0x0d, 0x7d, 0x41, 0xea, 0xd6, 0xd6, + 0x82, 0xb6, 0x1f, 0x47, 0x33, 0x65, 0xd6, 0xbd, 0xcc, 0x57, 0x8f, 0x7b, 0x09, 0x5e, 0x5a, 0xf9, + 0xc6, 0x2b, 0x63, 0x83, 0x14, 0xc2, 0x30, 0xe6, 0xb9, 0xfb, 0xc4, 0x27, 0x51, 0x54, 0x0b, 0x83, + 0x4d, 0x32, 0x03, 0xac, 0xe7, 0x17, 0xb3, 0x1f, 0x03, 0x82, 0x4d, 0xb2, 0x38, 0x75, 0x74, 0x58, + 0x19, 0xbb, 0xad, 0xd7, 0xc1, 0x26, 0x09, 0x74, 0x17, 0xc6, 0xa9, 0x5c, 0xe3, 0x26, 0x44, 0x47, + 0x7a, 0x11, 0x65, 0xd2, 0x07, 0x36, 0x2a, 0xe1, 0x14, 0x11, 0xf4, 0x06, 0x94, 0x3d, 0x77, 0x8b, + 0x34, 0x0e, 0x1a, 0x1e, 0x99, 0x19, 0x65, 0x14, 0x33, 0xb7, 0xd5, 0x6d, 0x89, 0xc4, 0xe5, 0x22, + 0xf5, 0x17, 0x27, 0xd5, 0xd1, 0x3d, 0xb8, 0x10, 0x93, 0x70, 0xcf, 0xf5, 0x1d, 0xba, 0x1d, 0x84, + 0xbc, 0xc0, 0x9e, 0x54, 0xc6, 0xd8, 0x7a, 0xbb, 0x2c, 0x86, 0xee, 0xc2, 0x46, 0x26, 0x16, 0xce, + 0xa9, 0x8d, 0xee, 0xc0, 0x04, 0xdb, 0x09, 0xb5, 0xb6, 0xe7, 0xd5, 0x02, 0xcf, 0x6d, 0x1c, 0xcc, + 0x8c, 0x33, 0x82, 0x9f, 0x90, 0xf7, 0xc2, 0xaa, 0x09, 0x3e, 0x3e, 0xac, 0x40, 0xf2, 0x0f, 0xa7, + 0x6b, 0xa3, 0x4d, 0xa6, 0x43, 0x6f, 0x87, 0x6e, 0x7c, 0x40, 0xd7, 0x2f, 0x79, 0x10, 0xcf, 0x4c, + 0x74, 0x15, 0x85, 0x75, 0x54, 0xa5, 0x68, 0xd7, 0x0b, 0x71, 0x9a, 0x20, 0xdd, 0xda, 0x51, 0xdc, + 0x74, 0xfd, 0x99, 0x49, 0x76, 0x62, 0xa8, 0x9d, 0x51, 0xa7, 0x85, 0x98, 0xc3, 0x98, 0xfe, 0x9c, + 0xfe, 0xb8, 0x43, 0x4f, 0xd0, 0x29, 0x86, 0x98, 0xe8, 0xcf, 0x25, 0x00, 0x27, 0x38, 0x94, 0xa9, + 0x89, 0xe3, 0x83, 0x19, 0xc4, 0x50, 0xd5, 0x76, 0xd9, 0xd8, 0xf8, 0x02, 0xa6, 0xe5, 0xe8, 0x36, + 0x0c, 0x11, 0x7f, 0x7f, 0x25, 0x0c, 0xf6, 0x66, 0xce, 0xe5, 0xef, 0xd9, 0x65, 0x8e, 0xc2, 0x0f, + 0xf4, 0x44, 0xc0, 0x13, 0xc5, 0x58, 0x92, 0x40, 0x0f, 0x60, 0x26, 0x63, 0x46, 0xf8, 0x04, 0x9c, + 0x67, 0x13, 0xf0, 0x59, 0x51, 0x77, 0x66, 0x23, 0x07, 0xef, 0xb8, 0x0b, 0x0c, 0xe7, 0x52, 0x47, + 0x5f, 0x84, 0x31, 0xbe, 0xa1, 0xf8, 0xe3, 0x5b, 0x34, 0x33, 0xcd, 0xbe, 0xe6, 0x4a, 0xfe, 0xe6, + 0xe4, 0x88, 0x8b, 0xd3, 0xa2, 0x43, 0x63, 0x7a, 0x69, 0x84, 0x4d, 0x6a, 0xf6, 0x26, 0x8c, 0xab, + 0x73, 0x8b, 0x2d, 0x1d, 0x54, 0x81, 0x01, 0xc6, 0xed, 0x08, 0xfd, 0x56, 0x99, 0xce, 0x14, 0xe3, + 0x84, 0x30, 0x2f, 0x67, 0x33, 0xe5, 0xbe, 0x4f, 0x16, 0x0f, 0x62, 0xc2, 0xa5, 0xea, 0xa2, 0x36, + 0x53, 0x12, 0x80, 0x13, 0x1c, 0xfb, 0xff, 0x72, 0xae, 0x31, 0x39, 0x1c, 0xfb, 0xb8, 0x0e, 0x9e, + 0x83, 0xe1, 0x9d, 0x20, 0x8a, 0x29, 0x36, 0x6b, 0x63, 0x20, 0xe1, 0x13, 0x6f, 0x8a, 0x72, 0xac, + 0x30, 0xd0, 0x6b, 0x30, 0xd6, 0xd0, 0x1b, 0x10, 0x77, 0x99, 0x1a, 0x02, 0xa3, 0x75, 0x6c, 0xe2, + 0xa2, 0x57, 0x61, 0x98, 0x3d, 0x9d, 0x37, 0x02, 0x4f, 0x30, 0x59, 0xf2, 0x42, 0x1e, 0xae, 0x89, + 0xf2, 0x63, 0xed, 0x37, 0x56, 0xd8, 0xe8, 0x2a, 0x0c, 0xd2, 0x2e, 0xac, 0xd6, 0xc4, 0x2d, 0xa2, + 0x54, 0x35, 0x37, 0x59, 0x29, 0x16, 0x50, 0xfb, 0xaf, 0x17, 0xb4, 0x51, 0xa6, 0x12, 0x29, 0x41, + 0x35, 0x18, 0xba, 0xef, 0xb8, 0xb1, 0xeb, 0x6f, 0x0b, 0x76, 0xe1, 0x99, 0xae, 0x57, 0x0a, 0xab, + 0xf4, 0x16, 0xaf, 0xc0, 0x2f, 0x3d, 0xf1, 0x07, 0x4b, 0x32, 0x94, 0x62, 0xd8, 0xf6, 0x7d, 0x4a, + 0xb1, 0xd0, 0x2f, 0x45, 0xcc, 0x2b, 0x70, 0x8a, 0xe2, 0x0f, 0x96, 0x64, 0xd0, 0x3b, 0x00, 0x72, + 0x59, 0x92, 0xa6, 0x78, 0xb2, 0x7e, 0xae, 0x37, 0xd1, 0x0d, 0x55, 0x67, 0x71, 0x9c, 0x5e, 0xa9, + 0xc9, 0x7f, 0xac, 0xd1, 0xb3, 0x63, 0xc6, 0x56, 0x75, 0x76, 0x06, 0x7d, 0x27, 0x3d, 0x09, 0x9c, + 0x30, 0x26, 0xcd, 0x85, 0x58, 0x0c, 0xce, 0x27, 0xfb, 0x93, 0x29, 0x36, 0xdc, 0x3d, 0xa2, 0x9f, + 0x1a, 0x82, 0x08, 0x4e, 0xe8, 0xd9, 0xbf, 0x52, 0x84, 0x99, 0xbc, 0xee, 0xd2, 0x45, 0x47, 0x1e, + 0xb8, 0xf1, 0x12, 0xe5, 0x86, 0x2c, 0x73, 0xd1, 0x2d, 0x8b, 0x72, 0xac, 0x30, 0xe8, 0xec, 0x47, + 0xee, 0xb6, 0x14, 0x09, 0x07, 0x92, 0xd9, 0xaf, 0xb3, 0x52, 0x2c, 0xa0, 0x14, 0x2f, 0x24, 0x4e, + 0x24, 0x6c, 0x22, 0xb4, 0x55, 0x82, 0x59, 0x29, 0x16, 0x50, 0x5d, 0xdf, 0x54, 0xea, 0xa1, 0x6f, + 0x32, 0x86, 0x68, 0xe0, 0x74, 0x87, 0x08, 0x7d, 0x09, 0x60, 0xcb, 0xf5, 0xdd, 0x68, 0x87, 0x51, + 0x1f, 0x3c, 0x31, 0x75, 0xc5, 0x4b, 0xad, 0x28, 0x2a, 0x58, 0xa3, 0x88, 0x5e, 0x86, 0x11, 0xb5, + 0x01, 0x57, 0xab, 0xec, 0x81, 0x48, 0x7b, 0x70, 0x4f, 0x4e, 0xa3, 0x2a, 0xd6, 0xf1, 0xec, 0x77, + 0xd3, 0xeb, 0x45, 0xec, 0x00, 0x6d, 0x7c, 0xad, 0x7e, 0xc7, 0xb7, 0xd0, 0x7d, 0x7c, 0xed, 0xdf, + 0x2c, 0xc2, 0x84, 0xd1, 0x58, 0x3b, 0xea, 0xe3, 0xcc, 0xba, 0x41, 0xef, 0x39, 0x27, 0x26, 0x62, + 0xff, 0xd9, 0xbd, 0xb7, 0x8a, 0x7e, 0x17, 0xd2, 0x1d, 0xc0, 0xeb, 0xa3, 0x2f, 0x41, 0xd9, 0x73, + 0x22, 0xa6, 0xbb, 0x22, 0x62, 0xdf, 0xf5, 0x43, 0x2c, 0x91, 0x23, 0x9c, 0x28, 0xd6, 0xae, 0x1a, + 0x4e, 0x3b, 0x21, 0x49, 0x2f, 0x64, 0xca, 0xfb, 0x48, 0xa3, 0x1b, 0xd5, 0x09, 0xca, 0x20, 0x1d, + 0x60, 0x0e, 0x43, 0xaf, 0xc2, 0x68, 0x48, 0xd8, 0xaa, 0x58, 0xa2, 0xac, 0x1c, 0x5b, 0x66, 0x03, + 0x09, 0xcf, 0x87, 0x35, 0x18, 0x36, 0x30, 0x13, 0x56, 0x7e, 0xb0, 0x0b, 0x2b, 0xff, 0x0c, 0x0c, + 0xb1, 0x1f, 0x6a, 0x05, 0xa8, 0xd9, 0x58, 0xe5, 0xc5, 0x58, 0xc2, 0xd3, 0x0b, 0x66, 0xb8, 0xcf, + 0x05, 0xf3, 0x49, 0x18, 0xaf, 0x3a, 0x64, 0x2f, 0xf0, 0x97, 0xfd, 0x66, 0x2b, 0x70, 0xfd, 0x18, + 0xcd, 0x40, 0x89, 0xdd, 0x0e, 0x7c, 0x6f, 0x97, 0x28, 0x05, 0x5c, 0xa2, 0x8c, 0xb9, 0xbd, 0x0d, + 0xd3, 0xd5, 0xe0, 0xbe, 0x7f, 0xdf, 0x09, 0x9b, 0x0b, 0xb5, 0x55, 0x4d, 0xce, 0x5d, 0x97, 0x72, + 0x16, 0x37, 0x62, 0xc9, 0x3c, 0x53, 0xb5, 0x9a, 0xfc, 0xae, 0x5d, 0x71, 0x3d, 0x92, 0xa3, 0x8d, + 0xf8, 0x9b, 0x05, 0xa3, 0xa5, 0x04, 0x5f, 0x3d, 0x18, 0x59, 0xb9, 0x0f, 0x46, 0x6f, 0xc2, 0xf0, + 0x96, 0x4b, 0xbc, 0x26, 0x26, 0x5b, 0x62, 0x89, 0x3d, 0x9d, 0xff, 0x2e, 0xbf, 0x42, 0x31, 0xa5, + 0xf6, 0x89, 0x4b, 0x69, 0x2b, 0xa2, 0x32, 0x56, 0x64, 0xd0, 0x2e, 0x4c, 0x4a, 0x31, 0x40, 0x42, + 0xc5, 0x82, 0x7b, 0xa6, 0x9b, 0x6c, 0x61, 0x12, 0x3f, 0x7f, 0x74, 0x58, 0x99, 0xc4, 0x29, 0x32, + 0xb8, 0x83, 0x30, 0x15, 0xcb, 0xf6, 0xe8, 0xd1, 0x5a, 0x62, 0xc3, 0xcf, 0xc4, 0x32, 0x26, 0x61, + 0xb2, 0x52, 0xfb, 0x27, 0x2c, 0x78, 0xac, 0x63, 0x64, 0x84, 0xa4, 0x7d, 0xca, 0xb3, 0x90, 0x96, + 0x7c, 0x0b, 0xbd, 0x25, 0x5f, 0xfb, 0x1f, 0x58, 0x70, 0x7e, 0x79, 0xaf, 0x15, 0x1f, 0x54, 0x5d, + 0xf3, 0x75, 0xe7, 0x15, 0x18, 0xdc, 0x23, 0x4d, 0xb7, 0xbd, 0x27, 0x66, 0xae, 0x22, 0x8f, 0x9f, + 0x35, 0x56, 0x7a, 0x7c, 0x58, 0x19, 0xab, 0xc7, 0x41, 0xe8, 0x6c, 0x13, 0x5e, 0x80, 0x05, 0x3a, + 0x3b, 0xc4, 0xdd, 0xf7, 0xc9, 0x6d, 0x77, 0xcf, 0x95, 0x76, 0x16, 0x5d, 0x75, 0x67, 0x73, 0x72, + 0x40, 0xe7, 0xde, 0x6c, 0x3b, 0x7e, 0xec, 0xc6, 0x07, 0xe2, 0x61, 0x46, 0x12, 0xc1, 0x09, 0x3d, + 0xfb, 0x9b, 0x16, 0x4c, 0xc8, 0x75, 0xbf, 0xd0, 0x6c, 0x86, 0x24, 0x8a, 0xd0, 0x2c, 0x14, 0xdc, + 0x96, 0xe8, 0x25, 0x88, 0x5e, 0x16, 0x56, 0x6b, 0xb8, 0xe0, 0xb6, 0x50, 0x0d, 0xca, 0xdc, 0x5c, + 0x23, 0x59, 0x5c, 0x7d, 0x19, 0x7d, 0xb0, 0x1e, 0x6c, 0xc8, 0x9a, 0x38, 0x21, 0x22, 0x39, 0x38, + 0x76, 0x66, 0x16, 0xcd, 0x57, 0xaf, 0x9b, 0xa2, 0x1c, 0x2b, 0x0c, 0x74, 0x0d, 0x86, 0xfd, 0xa0, + 0xc9, 0xad, 0x67, 0xf8, 0xed, 0xc7, 0x96, 0xec, 0xba, 0x28, 0xc3, 0x0a, 0x6a, 0xff, 0xb0, 0x05, + 0xa3, 0xf2, 0xcb, 0xfa, 0x64, 0x26, 0xe9, 0xd6, 0x4a, 0x18, 0xc9, 0x64, 0x6b, 0x51, 0x66, 0x90, + 0x41, 0x0c, 0x1e, 0xb0, 0x78, 0x12, 0x1e, 0xd0, 0xfe, 0xf1, 0x02, 0x8c, 0xcb, 0xee, 0xd4, 0xdb, + 0x9b, 0x11, 0x89, 0xd1, 0x06, 0x94, 0x1d, 0x3e, 0xe4, 0x44, 0xae, 0xd8, 0xa7, 0xb2, 0x85, 0x0f, + 0x63, 0x7e, 0x92, 0x6b, 0x79, 0x41, 0xd6, 0xc6, 0x09, 0x21, 0xe4, 0xc1, 0x94, 0x1f, 0xc4, 0xec, + 0x88, 0x56, 0xf0, 0x6e, 0x4f, 0x20, 0x69, 0xea, 0x17, 0x05, 0xf5, 0xa9, 0xf5, 0x34, 0x15, 0xdc, + 0x49, 0x18, 0x2d, 0x4b, 0x85, 0x47, 0x31, 0x5f, 0xdc, 0xd0, 0x67, 0x21, 0x5b, 0xdf, 0x61, 0xff, + 0x9a, 0x05, 0x65, 0x89, 0x76, 0x16, 0xaf, 0x5d, 0x6b, 0x30, 0x14, 0xb1, 0x49, 0x90, 0x43, 0x63, + 0x77, 0xeb, 0x38, 0x9f, 0xaf, 0xe4, 0xe6, 0xe1, 0xff, 0x23, 0x2c, 0x69, 0x30, 0x7d, 0xb7, 0xea, + 0xfe, 0x47, 0x44, 0xdf, 0xad, 0xfa, 0x93, 0x73, 0xc3, 0xfc, 0x57, 0xd6, 0x67, 0x4d, 0xac, 0xa5, + 0x0c, 0x52, 0x2b, 0x24, 0x5b, 0xee, 0x83, 0x34, 0x83, 0x54, 0x63, 0xa5, 0x58, 0x40, 0xd1, 0x3b, + 0x30, 0xda, 0x90, 0x8a, 0xce, 0xe4, 0x18, 0xb8, 0xda, 0x55, 0xe9, 0xae, 0xde, 0x67, 0xb8, 0x65, + 0xed, 0x92, 0x56, 0x1f, 0x1b, 0xd4, 0xcc, 0xe7, 0xf6, 0x62, 0xaf, 0xe7, 0xf6, 0x84, 0x6e, 0xfe, + 0xe3, 0xf3, 0x4f, 0x5a, 0x30, 0xc8, 0xd5, 0x65, 0xfd, 0xe9, 0x17, 0xb5, 0xe7, 0xaa, 0x64, 0xec, + 0xee, 0xd1, 0x42, 0xf1, 0xfc, 0x84, 0xd6, 0xa0, 0xcc, 0x7e, 0x30, 0xb5, 0x41, 0x31, 0xdf, 0xa4, + 0x98, 0xb7, 0xaa, 0x77, 0xf0, 0x9e, 0xac, 0x86, 0x13, 0x0a, 0xf6, 0x8f, 0x16, 0xe9, 0x51, 0x95, + 0xa0, 0x1a, 0x37, 0xb8, 0xf5, 0xe8, 0x6e, 0xf0, 0xc2, 0xa3, 0xba, 0xc1, 0xb7, 0x61, 0xa2, 0xa1, + 0x3d, 0x6e, 0x25, 0x33, 0x79, 0xad, 0xeb, 0x22, 0xd1, 0xde, 0xc1, 0xb8, 0xca, 0x68, 0xc9, 0x24, + 0x82, 0xd3, 0x54, 0xd1, 0x77, 0xc2, 0x28, 0x9f, 0x67, 0xd1, 0x0a, 0xb7, 0x58, 0xf8, 0x44, 0xfe, + 0x7a, 0xd1, 0x9b, 0x60, 0x2b, 0xb1, 0xae, 0x55, 0xc7, 0x06, 0x31, 0xfb, 0x57, 0x86, 0x61, 0x60, + 0x79, 0x9f, 0xf8, 0xf1, 0x19, 0x1c, 0x48, 0x0d, 0x18, 0x77, 0xfd, 0xfd, 0xc0, 0xdb, 0x27, 0x4d, + 0x0e, 0x3f, 0xc9, 0xe5, 0x7a, 0x41, 0x90, 0x1e, 0x5f, 0x35, 0x48, 0xe0, 0x14, 0xc9, 0x47, 0x21, + 0x61, 0xde, 0x80, 0x41, 0x3e, 0xf7, 0x42, 0xbc, 0xcc, 0x54, 0x06, 0xb3, 0x41, 0x14, 0xbb, 0x20, + 0x91, 0x7e, 0xb9, 0xf6, 0x59, 0x54, 0x47, 0xef, 0xc2, 0xf8, 0x96, 0x1b, 0x46, 0x31, 0x15, 0x0d, + 0xa3, 0xd8, 0xd9, 0x6b, 0x3d, 0x84, 0x44, 0xa9, 0xc6, 0x61, 0xc5, 0xa0, 0x84, 0x53, 0x94, 0xd1, + 0x36, 0x8c, 0x51, 0x21, 0x27, 0x69, 0x6a, 0xe8, 0xc4, 0x4d, 0x29, 0x95, 0xd1, 0x6d, 0x9d, 0x10, + 0x36, 0xe9, 0xd2, 0xc3, 0xa4, 0xc1, 0x84, 0xa2, 0x61, 0xc6, 0x51, 0xa8, 0xc3, 0x84, 0x4b, 0x43, + 0x1c, 0x46, 0xcf, 0x24, 0x66, 0xb6, 0x52, 0x36, 0xcf, 0x24, 0xcd, 0x38, 0xe5, 0xcb, 0x50, 0x26, + 0x74, 0x08, 0x29, 0x61, 0xa1, 0x18, 0x9f, 0xef, 0xaf, 0xaf, 0x6b, 0x6e, 0x23, 0x0c, 0x4c, 0x59, + 0x7e, 0x59, 0x52, 0xc2, 0x09, 0x51, 0xb4, 0x04, 0x83, 0x11, 0x09, 0x5d, 0x12, 0x09, 0x15, 0x79, + 0x97, 0x69, 0x64, 0x68, 0xdc, 0xf6, 0x9c, 0xff, 0xc6, 0xa2, 0x2a, 0x5d, 0x5e, 0x0e, 0x93, 0x86, + 0x98, 0x56, 0x5c, 0x5b, 0x5e, 0x0b, 0xac, 0x14, 0x0b, 0x28, 0x7a, 0x03, 0x86, 0x42, 0xe2, 0x31, + 0x65, 0xd1, 0x58, 0xff, 0x8b, 0x9c, 0xeb, 0x9e, 0x78, 0x3d, 0x2c, 0x09, 0xa0, 0x5b, 0x80, 0x42, + 0x42, 0x79, 0x08, 0xd7, 0xdf, 0x56, 0xc6, 0x1c, 0x42, 0xd7, 0xfd, 0xb8, 0x68, 0xff, 0x1c, 0x4e, + 0x30, 0xa4, 0x55, 0x2a, 0xce, 0xa8, 0x86, 0x6e, 0xc0, 0x94, 0x2a, 0x5d, 0xf5, 0xa3, 0xd8, 0xf1, + 0x1b, 0x84, 0xa9, 0xb9, 0xcb, 0x09, 0x57, 0x84, 0xd3, 0x08, 0xb8, 0xb3, 0x8e, 0xfd, 0x73, 0x94, + 0x9d, 0xa1, 0xa3, 0x75, 0x06, 0xbc, 0xc0, 0xeb, 0x26, 0x2f, 0x70, 0x31, 0x77, 0xe6, 0x72, 0xf8, + 0x80, 0x23, 0x0b, 0x46, 0xb4, 0x99, 0x4d, 0xd6, 0xac, 0xd5, 0x65, 0xcd, 0xb6, 0x61, 0x92, 0xae, + 0xf4, 0x3b, 0x9b, 0xcc, 0x0d, 0xab, 0xc9, 0x16, 0x66, 0xe1, 0xe1, 0x16, 0xa6, 0x7a, 0x65, 0xbe, + 0x9d, 0x22, 0x88, 0x3b, 0x9a, 0x40, 0xaf, 0x48, 0xcd, 0x49, 0xd1, 0x30, 0xd2, 0xe2, 0x5a, 0x91, + 0xe3, 0xc3, 0xca, 0xa4, 0xf6, 0x21, 0xba, 0xa6, 0xc4, 0xfe, 0xb2, 0xfc, 0x46, 0xf5, 0x9a, 0xdf, + 0x50, 0x8b, 0x25, 0xf5, 0x9a, 0xaf, 0x96, 0x03, 0x4e, 0x70, 0xe8, 0x1e, 0xa5, 0x22, 0x48, 0xfa, + 0x35, 0x9f, 0x0a, 0x28, 0x98, 0x41, 0xec, 0x17, 0x01, 0x96, 0x1f, 0x90, 0x06, 0x5f, 0xea, 0xfa, + 0x03, 0xa4, 0x95, 0xff, 0x00, 0x69, 0xff, 0x7b, 0x0b, 0xc6, 0x57, 0x96, 0x0c, 0x31, 0x71, 0x0e, + 0x80, 0xcb, 0x46, 0x6f, 0xbd, 0xb5, 0x2e, 0x75, 0xeb, 0x5c, 0x3d, 0xaa, 0x4a, 0xb1, 0x86, 0x81, + 0x2e, 0x42, 0xd1, 0x6b, 0xfb, 0x42, 0x64, 0x19, 0x3a, 0x3a, 0xac, 0x14, 0x6f, 0xb7, 0x7d, 0x4c, + 0xcb, 0x34, 0x0b, 0xc1, 0x62, 0xdf, 0x16, 0x82, 0x3d, 0xdd, 0xab, 0x50, 0x05, 0x06, 0xee, 0xdf, + 0x77, 0x9b, 0xdc, 0x88, 0x5d, 0xe8, 0xfd, 0xdf, 0x7a, 0x6b, 0xb5, 0x1a, 0x61, 0x5e, 0x6e, 0x7f, + 0xb5, 0x08, 0xb3, 0x2b, 0x1e, 0x79, 0xf0, 0x01, 0x0d, 0xf9, 0xfb, 0xb5, 0x6f, 0x3c, 0x19, 0xbf, + 0x78, 0x52, 0x1b, 0xd6, 0xde, 0xe3, 0xb1, 0x05, 0x43, 0xfc, 0x31, 0x5b, 0x9a, 0xf5, 0xbf, 0x96, + 0xd5, 0x7a, 0xfe, 0x80, 0xcc, 0xf1, 0x47, 0x71, 0x61, 0xce, 0xaf, 0x6e, 0x5a, 0x51, 0x8a, 0x25, + 0xf1, 0xd9, 0xcf, 0xc0, 0xa8, 0x8e, 0x79, 0x22, 0x6b, 0xf2, 0xbf, 0x54, 0x84, 0x49, 0xda, 0x83, + 0x47, 0x3a, 0x11, 0x77, 0x3b, 0x27, 0xe2, 0xb4, 0x2d, 0x8a, 0x7b, 0xcf, 0xc6, 0x3b, 0xe9, 0xd9, + 0x78, 0x21, 0x6f, 0x36, 0xce, 0x7a, 0x0e, 0xbe, 0xd7, 0x82, 0x73, 0x2b, 0x5e, 0xd0, 0xd8, 0x4d, + 0x59, 0xfd, 0xbe, 0x0c, 0x23, 0xf4, 0x1c, 0x8f, 0x0c, 0x2f, 0x22, 0xc3, 0xaf, 0x4c, 0x80, 0xb0, + 0x8e, 0xa7, 0x55, 0xbb, 0x7b, 0x77, 0xb5, 0x9a, 0xe5, 0x8e, 0x26, 0x40, 0x58, 0xc7, 0xb3, 0xbf, + 0x61, 0xc1, 0xa5, 0x1b, 0x4b, 0xcb, 0xc9, 0x52, 0xec, 0xf0, 0x88, 0xa3, 0x52, 0x60, 0x53, 0xeb, + 0x4a, 0x22, 0x05, 0x56, 0x59, 0x2f, 0x04, 0xf4, 0xa3, 0xe2, 0xed, 0xf9, 0xb3, 0x16, 0x9c, 0xbb, + 0xe1, 0xc6, 0xf4, 0x5a, 0x4e, 0xfb, 0x66, 0xd1, 0x7b, 0x39, 0x72, 0xe3, 0x20, 0x3c, 0x48, 0xfb, + 0x66, 0x61, 0x05, 0xc1, 0x1a, 0x16, 0x6f, 0x79, 0xdf, 0x65, 0x66, 0x54, 0x05, 0x53, 0x15, 0x85, + 0x45, 0x39, 0x56, 0x18, 0xf4, 0xc3, 0x9a, 0x6e, 0xc8, 0x44, 0x89, 0x03, 0x71, 0xc2, 0xaa, 0x0f, + 0xab, 0x4a, 0x00, 0x4e, 0x70, 0xec, 0x9f, 0xb0, 0x60, 0xfa, 0x86, 0xd7, 0x8e, 0x62, 0x12, 0x6e, + 0x45, 0x46, 0x67, 0x5f, 0x84, 0x32, 0x91, 0xe2, 0xba, 0xe8, 0xab, 0x62, 0x30, 0x95, 0x1c, 0xcf, + 0x1d, 0xc3, 0x14, 0x5e, 0x1f, 0x9e, 0x03, 0x27, 0x73, 0x1d, 0xfb, 0xc5, 0x02, 0x8c, 0xdd, 0xdc, + 0xd8, 0xa8, 0xdd, 0x20, 0xb1, 0xb8, 0xc5, 0x7a, 0xab, 0x9a, 0xb1, 0xa6, 0x31, 0xeb, 0x26, 0x14, + 0xb5, 0x63, 0xd7, 0x9b, 0xe3, 0x9e, 0xc8, 0x73, 0xab, 0x7e, 0x7c, 0x27, 0xac, 0xc7, 0xa1, 0xeb, + 0x6f, 0x67, 0xea, 0xd8, 0xe4, 0x5d, 0x5b, 0xcc, 0xbb, 0x6b, 0xd1, 0x8b, 0x30, 0xc8, 0x5c, 0xa1, + 0xa5, 0x78, 0xf2, 0xb8, 0x92, 0x29, 0x58, 0xe9, 0xf1, 0x61, 0xa5, 0x7c, 0x17, 0xaf, 0xf2, 0x3f, + 0x58, 0xa0, 0xa2, 0xbb, 0x30, 0xb2, 0x13, 0xc7, 0xad, 0x9b, 0xc4, 0x69, 0x92, 0x50, 0x9e, 0x0e, + 0x97, 0xb3, 0x4e, 0x07, 0x3a, 0x08, 0x1c, 0x2d, 0xd9, 0x50, 0x49, 0x59, 0x84, 0x75, 0x3a, 0x76, + 0x1d, 0x20, 0x81, 0x9d, 0x92, 0x7e, 0xc1, 0xfe, 0x03, 0x0b, 0x86, 0xb8, 0x57, 0x5a, 0x88, 0x3e, + 0x0b, 0x25, 0xf2, 0x80, 0x34, 0x04, 0xe7, 0x98, 0xd9, 0xe1, 0x84, 0xf1, 0xe0, 0xda, 0x72, 0xfa, + 0x1f, 0xb3, 0x5a, 0xe8, 0x26, 0x0c, 0xd1, 0xde, 0xde, 0x50, 0x2e, 0x7a, 0x4f, 0xe6, 0x7d, 0xb1, + 0x9a, 0x76, 0xce, 0xab, 0x88, 0x22, 0x2c, 0xab, 0x33, 0xcd, 0x6f, 0xa3, 0x55, 0xa7, 0x07, 0x58, + 0xdc, 0xed, 0x9e, 0xdd, 0x58, 0xaa, 0x71, 0x24, 0x41, 0x8d, 0x6b, 0x7e, 0x65, 0x21, 0x4e, 0x88, + 0xd8, 0x1b, 0x50, 0xa6, 0x93, 0xba, 0xe0, 0xb9, 0x4e, 0x77, 0xa5, 0xf3, 0xb3, 0x50, 0x96, 0x0a, + 0xe0, 0x48, 0x38, 0x36, 0x31, 0xaa, 0x52, 0x3f, 0x1c, 0xe1, 0x04, 0x6e, 0x6f, 0xc1, 0x79, 0xf6, + 0xf2, 0xef, 0xc4, 0x3b, 0xc6, 0x1e, 0xeb, 0xbd, 0x98, 0x9f, 0x13, 0x82, 0x18, 0x9f, 0x99, 0x19, + 0xcd, 0x77, 0x60, 0x54, 0x52, 0x4c, 0x84, 0x32, 0xfb, 0x8f, 0x4a, 0xf0, 0xf8, 0x6a, 0x3d, 0xdf, + 0x61, 0xf1, 0x55, 0x18, 0xe5, 0x6c, 0x1a, 0x5d, 0xda, 0x8e, 0x27, 0xda, 0x55, 0xef, 0x62, 0x1b, + 0x1a, 0x0c, 0x1b, 0x98, 0xe8, 0x12, 0x14, 0xdd, 0xf7, 0xfc, 0xb4, 0x19, 0xee, 0xea, 0x9b, 0xeb, + 0x98, 0x96, 0x53, 0x30, 0xe5, 0xf8, 0xf8, 0x51, 0xaa, 0xc0, 0x8a, 0xeb, 0x7b, 0x1d, 0xc6, 0xdd, + 0xa8, 0x11, 0xb9, 0xab, 0x3e, 0x3d, 0x67, 0x12, 0x67, 0xd7, 0x44, 0x49, 0x40, 0x3b, 0xad, 0xa0, + 0x38, 0x85, 0xad, 0x9d, 0xeb, 0x03, 0x7d, 0x73, 0x8d, 0x3d, 0x3d, 0x7d, 0x28, 0x43, 0xdc, 0x62, + 0x5f, 0x17, 0x31, 0xa3, 0x36, 0xc1, 0x10, 0xf3, 0x0f, 0x8e, 0xb0, 0x84, 0x51, 0x09, 0xac, 0xb1, + 0xe3, 0xb4, 0x16, 0xda, 0xf1, 0x4e, 0xd5, 0x8d, 0x1a, 0xc1, 0x3e, 0x09, 0x0f, 0x98, 0xf0, 0x3c, + 0x9c, 0x48, 0x60, 0x0a, 0xb0, 0x74, 0x73, 0xa1, 0x46, 0x31, 0x71, 0x67, 0x1d, 0x93, 0x2b, 0x84, + 0xd3, 0xe0, 0x0a, 0x17, 0x60, 0x42, 0x36, 0x53, 0x27, 0x11, 0xbb, 0x23, 0x46, 0x58, 0xc7, 0x94, + 0xa9, 0xad, 0x28, 0x56, 0xdd, 0x4a, 0xe3, 0xa3, 0x57, 0x60, 0xcc, 0xf5, 0xdd, 0xd8, 0x75, 0xe2, + 0x20, 0x64, 0x37, 0x2c, 0x97, 0x93, 0x99, 0x25, 0xdb, 0xaa, 0x0e, 0xc0, 0x26, 0x9e, 0xfd, 0x87, + 0x25, 0x98, 0x62, 0xd3, 0xf6, 0xad, 0x15, 0xf6, 0x91, 0x59, 0x61, 0x77, 0x3b, 0x57, 0xd8, 0x69, + 0xb0, 0xbb, 0x1f, 0xe6, 0x32, 0x7b, 0x17, 0xca, 0xca, 0x16, 0x58, 0x3a, 0x03, 0x58, 0x39, 0xce, + 0x00, 0xbd, 0xb9, 0x0f, 0xf9, 0x8c, 0x5b, 0xcc, 0x7c, 0xc6, 0xfd, 0xdb, 0x16, 0x24, 0x26, 0x91, + 0xe8, 0x26, 0x94, 0x5b, 0x01, 0x33, 0x3b, 0x08, 0xa5, 0x2d, 0xcf, 0xe3, 0x99, 0x17, 0x15, 0xbf, + 0x14, 0xf9, 0xf8, 0xd5, 0x64, 0x0d, 0x9c, 0x54, 0x46, 0x8b, 0x30, 0xd4, 0x0a, 0x49, 0x3d, 0x66, + 0x2e, 0xb0, 0x3d, 0xe9, 0xf0, 0x35, 0xc2, 0xf1, 0xb1, 0xac, 0x68, 0xff, 0x92, 0x05, 0xc0, 0x5f, + 0x4a, 0x1d, 0x7f, 0x9b, 0x9c, 0x81, 0xf6, 0xb7, 0x0a, 0xa5, 0xa8, 0x45, 0x1a, 0xdd, 0x0c, 0x42, + 0x92, 0xfe, 0xd4, 0x5b, 0xa4, 0x91, 0x0c, 0x38, 0xfd, 0x87, 0x59, 0x6d, 0xfb, 0xfb, 0x00, 0xc6, + 0x13, 0xb4, 0xd5, 0x98, 0xec, 0xa1, 0xe7, 0x0d, 0x97, 0xb8, 0x8b, 0x29, 0x97, 0xb8, 0x32, 0xc3, + 0xd6, 0x14, 0x8d, 0xef, 0x42, 0x71, 0xcf, 0x79, 0x20, 0x34, 0x49, 0xcf, 0x76, 0xef, 0x06, 0xa5, + 0x3f, 0xb7, 0xe6, 0x3c, 0xe0, 0x32, 0xd3, 0xb3, 0x72, 0x81, 0xac, 0x39, 0x0f, 0x8e, 0xb9, 0xd9, + 0x07, 0x3b, 0xa4, 0x6e, 0xbb, 0x51, 0xfc, 0x95, 0xff, 0x94, 0xfc, 0x67, 0xcb, 0x8e, 0x36, 0xc2, + 0xda, 0x72, 0x7d, 0xf1, 0x6e, 0xd8, 0x57, 0x5b, 0xae, 0x9f, 0x6e, 0xcb, 0xf5, 0xfb, 0x68, 0xcb, + 0xf5, 0xd1, 0xfb, 0x30, 0x24, 0xde, 0xe8, 0x99, 0xad, 0xb7, 0xa9, 0xa5, 0xca, 0x6b, 0x4f, 0x3c, + 0xf1, 0xf3, 0x36, 0xe7, 0xa5, 0x4c, 0x28, 0x4a, 0x7b, 0xb6, 0x2b, 0x1b, 0x44, 0x7f, 0xc3, 0x82, + 0x71, 0xf1, 0x1b, 0x93, 0xf7, 0xda, 0x24, 0x8a, 0x05, 0xef, 0xf9, 0xe9, 0xfe, 0xfb, 0x20, 0x2a, + 0xf2, 0xae, 0x7c, 0x5a, 0x1e, 0xb3, 0x26, 0xb0, 0x67, 0x8f, 0x52, 0xbd, 0x40, 0xff, 0xc8, 0x82, + 0xf3, 0x7b, 0xce, 0x03, 0xde, 0x22, 0x2f, 0xc3, 0x4e, 0xec, 0x06, 0xc2, 0x76, 0xfd, 0xb3, 0xfd, + 0x4d, 0x7f, 0x47, 0x75, 0xde, 0x49, 0x69, 0xe6, 0x7a, 0x3e, 0x0b, 0xa5, 0x67, 0x57, 0x33, 0xfb, + 0x35, 0xbb, 0x05, 0xc3, 0x72, 0xbd, 0x65, 0x48, 0xde, 0x55, 0x9d, 0xb1, 0x3e, 0xb1, 0x89, 0x84, + 0xee, 0x97, 0x46, 0xdb, 0x11, 0x6b, 0xed, 0x91, 0xb6, 0xf3, 0x2e, 0x8c, 0xea, 0x6b, 0xec, 0x91, + 0xb6, 0xf5, 0x1e, 0x9c, 0xcb, 0x58, 0x4b, 0x8f, 0xb4, 0xc9, 0xfb, 0x70, 0x31, 0x77, 0x7d, 0x3c, + 0xca, 0x86, 0xed, 0x5f, 0xb4, 0xf4, 0x73, 0xf0, 0x0c, 0x54, 0xf0, 0x4b, 0xa6, 0x0a, 0xfe, 0x72, + 0xf7, 0x9d, 0x93, 0xa3, 0x87, 0x7f, 0x47, 0xef, 0x34, 0x3d, 0xd5, 0xd1, 0x1b, 0x30, 0xe8, 0xd1, + 0x12, 0x69, 0x1c, 0x62, 0xf7, 0xde, 0x91, 0x09, 0x2f, 0xc5, 0xca, 0x23, 0x2c, 0x28, 0xd8, 0xbf, + 0x6a, 0x41, 0xe9, 0x0c, 0x46, 0x02, 0x9b, 0x23, 0xf1, 0x7c, 0x2e, 0x69, 0x11, 0xd2, 0x6c, 0x0e, + 0x3b, 0xf7, 0x97, 0x65, 0xd8, 0xb6, 0x9c, 0x81, 0xf9, 0x2e, 0x38, 0x77, 0x3b, 0x70, 0x9a, 0x8b, + 0x8e, 0xe7, 0xf8, 0x0d, 0x12, 0xae, 0xfa, 0xdb, 0x3d, 0xad, 0x94, 0x74, 0x9b, 0xa2, 0x42, 0x2f, + 0x9b, 0x22, 0x7b, 0x07, 0x90, 0xde, 0x80, 0xb0, 0xe3, 0xc4, 0x30, 0xe4, 0xf2, 0xa6, 0xc4, 0xf0, + 0x3f, 0x9d, 0xcd, 0xdd, 0x75, 0xf4, 0x4c, 0xb3, 0x50, 0xe4, 0x05, 0x58, 0x12, 0xb2, 0x5f, 0x85, + 0x4c, 0xdf, 0xad, 0xde, 0x6a, 0x03, 0xfb, 0x65, 0x98, 0x62, 0x35, 0x4f, 0x26, 0xd2, 0xda, 0x3f, + 0x60, 0xc1, 0xc4, 0x7a, 0x2a, 0x36, 0xc5, 0x55, 0xf6, 0xd6, 0x97, 0xa1, 0xf7, 0xad, 0xb3, 0x52, + 0x2c, 0xa0, 0xa7, 0xae, 0x5f, 0xfa, 0x33, 0x0b, 0x12, 0x57, 0xc9, 0x33, 0x60, 0xaa, 0x96, 0x0c, + 0xa6, 0x2a, 0x53, 0xef, 0xa1, 0xba, 0x93, 0xc7, 0x53, 0xa1, 0x5b, 0x2a, 0x2e, 0x40, 0x17, 0x95, + 0x47, 0x42, 0x86, 0x7b, 0x91, 0x8f, 0x9b, 0xc1, 0x03, 0x64, 0xa4, 0x00, 0x66, 0x26, 0xa4, 0x70, + 0x3f, 0x22, 0x66, 0x42, 0xaa, 0x3f, 0x39, 0xbb, 0xaf, 0xa6, 0x75, 0x99, 0x9d, 0x4a, 0xdf, 0xce, + 0xcc, 0xbe, 0x1d, 0xcf, 0x7d, 0x9f, 0xa8, 0xe0, 0x26, 0x15, 0x61, 0xc6, 0x2d, 0x4a, 0x8f, 0x0f, + 0x2b, 0x63, 0xea, 0x1f, 0x8f, 0x80, 0x95, 0x54, 0xb1, 0x6f, 0xc2, 0x44, 0x6a, 0xc0, 0xd0, 0xcb, + 0x30, 0xd0, 0xda, 0x71, 0x22, 0x92, 0x32, 0x8d, 0x1c, 0xa8, 0xd1, 0xc2, 0xe3, 0xc3, 0xca, 0xb8, + 0xaa, 0xc0, 0x4a, 0x30, 0xc7, 0xb6, 0xff, 0xa7, 0x05, 0xa5, 0xf5, 0xa0, 0x79, 0x16, 0x8b, 0xe9, + 0x75, 0x63, 0x31, 0x3d, 0x91, 0x17, 0x3f, 0x30, 0x77, 0x1d, 0xad, 0xa4, 0xd6, 0xd1, 0xe5, 0x5c, + 0x0a, 0xdd, 0x97, 0xd0, 0x1e, 0x8c, 0xb0, 0xa8, 0x84, 0xc2, 0x54, 0xf3, 0x45, 0x83, 0xbf, 0xaf, + 0xa4, 0xf8, 0xfb, 0x09, 0x0d, 0x55, 0xe3, 0xf2, 0x9f, 0x81, 0x21, 0x61, 0x2e, 0x98, 0x36, 0x70, + 0x17, 0xb8, 0x58, 0xc2, 0xed, 0x9f, 0x2c, 0x82, 0x11, 0x05, 0x11, 0xfd, 0x9a, 0x05, 0x73, 0x21, + 0xf7, 0x18, 0x6c, 0x56, 0xdb, 0xa1, 0xeb, 0x6f, 0xd7, 0x1b, 0x3b, 0xa4, 0xd9, 0xf6, 0x5c, 0x7f, + 0x7b, 0x75, 0xdb, 0x0f, 0x54, 0xf1, 0xf2, 0x03, 0xd2, 0x68, 0x33, 0x9d, 0x7f, 0x8f, 0x90, 0x8b, + 0xca, 0x1c, 0xe7, 0xfa, 0xd1, 0x61, 0x65, 0x0e, 0x9f, 0x88, 0x36, 0x3e, 0x61, 0x5f, 0xd0, 0x37, + 0x2c, 0x98, 0xe7, 0xc1, 0x01, 0xfb, 0xef, 0x7f, 0x17, 0x69, 0xa8, 0x26, 0x49, 0x25, 0x44, 0x36, + 0x48, 0xb8, 0xb7, 0xf8, 0x8a, 0x18, 0xd0, 0xf9, 0xda, 0xc9, 0xda, 0xc2, 0x27, 0xed, 0x9c, 0xfd, + 0x2f, 0x8b, 0x30, 0x26, 0x9c, 0xd5, 0x45, 0x14, 0x94, 0x97, 0x8d, 0x25, 0xf1, 0x64, 0x6a, 0x49, + 0x4c, 0x19, 0xc8, 0xa7, 0x13, 0x00, 0x25, 0x82, 0x29, 0xcf, 0x89, 0xe2, 0x9b, 0xc4, 0x09, 0xe3, + 0x4d, 0xe2, 0x70, 0x33, 0x95, 0xe2, 0x89, 0x4d, 0x6a, 0x94, 0xfa, 0xe5, 0x76, 0x9a, 0x18, 0xee, + 0xa4, 0x8f, 0xf6, 0x01, 0x31, 0x5b, 0x9b, 0xd0, 0xf1, 0x23, 0xfe, 0x2d, 0xae, 0x78, 0x0f, 0x38, + 0x59, 0xab, 0xb3, 0xa2, 0x55, 0x74, 0xbb, 0x83, 0x1a, 0xce, 0x68, 0x41, 0xb3, 0xa1, 0x1a, 0xe8, + 0xd7, 0x86, 0x6a, 0xb0, 0x87, 0x17, 0x89, 0x0f, 0x93, 0x1d, 0xf1, 0x06, 0xde, 0x86, 0xb2, 0xb2, + 0x75, 0x13, 0x87, 0x4e, 0xf7, 0xb0, 0x1d, 0x69, 0x0a, 0x5c, 0x45, 0x92, 0xd8, 0x59, 0x26, 0xe4, + 0xec, 0x7f, 0x5c, 0x30, 0x1a, 0xe4, 0x93, 0xb8, 0x0e, 0xc3, 0x4e, 0x14, 0xb9, 0xdb, 0x3e, 0x69, + 0x8a, 0x1d, 0xfb, 0xf1, 0xbc, 0x1d, 0x6b, 0x34, 0xc3, 0xec, 0x0d, 0x17, 0x44, 0x4d, 0xac, 0x68, + 0xa0, 0x9b, 0xdc, 0x18, 0x68, 0x5f, 0xf2, 0xf3, 0xfd, 0x51, 0x03, 0x69, 0x2e, 0xb4, 0x4f, 0xb0, + 0xa8, 0x8f, 0xbe, 0xc8, 0xad, 0xb5, 0x6e, 0xf9, 0xc1, 0x7d, 0xff, 0x46, 0x10, 0x48, 0x0f, 0xb3, + 0xfe, 0x08, 0x4e, 0x49, 0x1b, 0x2d, 0x55, 0x1d, 0x9b, 0xd4, 0xfa, 0x8b, 0xc9, 0xf3, 0xdd, 0x70, + 0x8e, 0x92, 0x36, 0xfd, 0x44, 0x22, 0x44, 0x60, 0x42, 0x44, 0x42, 0x90, 0x65, 0x62, 0xec, 0x32, + 0x59, 0x75, 0xb3, 0x76, 0xa2, 0xd0, 0xbb, 0x65, 0x92, 0xc0, 0x69, 0x9a, 0xf6, 0xcf, 0x58, 0xc0, + 0x2c, 0xdc, 0xcf, 0x80, 0x65, 0xf8, 0x9c, 0xc9, 0x32, 0xcc, 0xe4, 0x0d, 0x72, 0x0e, 0xb7, 0xf0, + 0x12, 0x5f, 0x59, 0xb5, 0x30, 0x78, 0x70, 0x20, 0x5e, 0xca, 0xfb, 0xe0, 0x52, 0xff, 0x8f, 0xc5, + 0x0f, 0x31, 0xe5, 0x74, 0x8e, 0xbe, 0x07, 0x86, 0x1b, 0x4e, 0xcb, 0x69, 0xf0, 0x90, 0xbd, 0xb9, + 0x1a, 0x1b, 0xa3, 0xd2, 0xdc, 0x92, 0xa8, 0xc1, 0x35, 0x10, 0x32, 0xa2, 0xc6, 0xb0, 0x2c, 0xee, + 0xa9, 0x75, 0x50, 0x4d, 0xce, 0xee, 0xc2, 0x98, 0x41, 0xec, 0x91, 0x8a, 0xab, 0xdf, 0xc3, 0xaf, + 0x58, 0x15, 0x01, 0x66, 0x0f, 0xa6, 0x7c, 0xed, 0x3f, 0xbd, 0x50, 0xa4, 0x08, 0xf2, 0xf1, 0x5e, + 0x97, 0x28, 0xbb, 0x7d, 0x34, 0x0b, 0xfe, 0x14, 0x19, 0xdc, 0x49, 0xd9, 0xfe, 0x29, 0x0b, 0x1e, + 0xd3, 0x11, 0xb5, 0x78, 0x00, 0xbd, 0x74, 0xc0, 0x55, 0x18, 0x0e, 0x5a, 0x24, 0x74, 0xe2, 0x20, + 0x14, 0xb7, 0xc6, 0x35, 0x39, 0xe8, 0x77, 0x44, 0xf9, 0xb1, 0x88, 0x9d, 0x28, 0xa9, 0xcb, 0x72, + 0xac, 0x6a, 0x22, 0x1b, 0x06, 0xd9, 0x60, 0x44, 0x22, 0x56, 0x03, 0x3b, 0x03, 0xd8, 0x73, 0x68, + 0x84, 0x05, 0xc4, 0xfe, 0x23, 0x8b, 0x2f, 0x2c, 0xbd, 0xeb, 0xe8, 0x3d, 0x98, 0xdc, 0x73, 0xe2, + 0xc6, 0xce, 0xf2, 0x83, 0x56, 0xc8, 0x55, 0xdf, 0x72, 0x9c, 0x9e, 0xed, 0x35, 0x4e, 0xda, 0x47, + 0x26, 0x06, 0x68, 0x6b, 0x29, 0x62, 0xb8, 0x83, 0x3c, 0xda, 0x84, 0x11, 0x56, 0xc6, 0x2c, 0x9d, + 0xa3, 0x6e, 0xac, 0x41, 0x5e, 0x6b, 0xea, 0x45, 0x79, 0x2d, 0xa1, 0x83, 0x75, 0xa2, 0xf6, 0x57, + 0x8a, 0x7c, 0xb7, 0x33, 0x6e, 0xfb, 0x19, 0x18, 0x6a, 0x05, 0xcd, 0xa5, 0xd5, 0x2a, 0x16, 0xb3, + 0xa0, 0xae, 0x91, 0x1a, 0x2f, 0xc6, 0x12, 0x8e, 0x5e, 0x03, 0x20, 0x0f, 0x62, 0x12, 0xfa, 0x8e, + 0xa7, 0x0c, 0x42, 0x94, 0x09, 0x64, 0x35, 0x58, 0x0f, 0xe2, 0xbb, 0x11, 0xf9, 0xae, 0x65, 0x85, + 0x82, 0x35, 0x74, 0x74, 0x1d, 0xa0, 0x15, 0x06, 0xfb, 0x6e, 0x93, 0xb9, 0xce, 0x15, 0x4d, 0x73, + 0x89, 0x9a, 0x82, 0x60, 0x0d, 0x0b, 0xbd, 0x06, 0x63, 0x6d, 0x3f, 0xe2, 0x1c, 0x8a, 0xb3, 0x29, + 0x22, 0x0f, 0x0e, 0x27, 0x96, 0x0b, 0x77, 0x75, 0x20, 0x36, 0x71, 0xd1, 0x02, 0x0c, 0xc6, 0x0e, + 0xb3, 0x77, 0x18, 0xc8, 0xb7, 0x5b, 0xdc, 0xa0, 0x18, 0x7a, 0xc0, 0x58, 0x5a, 0x01, 0x8b, 0x8a, + 0xe8, 0x6d, 0xe9, 0x87, 0xc0, 0xcf, 0x7a, 0x61, 0x30, 0xdc, 0xdf, 0xbd, 0xa0, 0x79, 0x21, 0x08, + 0x43, 0x64, 0x83, 0x96, 0xfd, 0x8d, 0x32, 0x40, 0xc2, 0x8e, 0xa3, 0xf7, 0x3b, 0xce, 0xa3, 0xe7, + 0xba, 0x33, 0xf0, 0xa7, 0x77, 0x18, 0xa1, 0xef, 0xb7, 0x60, 0xc4, 0xf1, 0xbc, 0xa0, 0xe1, 0xc4, + 0x6c, 0x94, 0x0b, 0xdd, 0xcf, 0x43, 0xd1, 0xfe, 0x42, 0x52, 0x83, 0x77, 0xe1, 0x45, 0xb9, 0xf0, + 0x34, 0x48, 0xcf, 0x5e, 0xe8, 0x0d, 0xa3, 0x4f, 0x49, 0x29, 0x8d, 0x2f, 0x8f, 0xd9, 0xb4, 0x94, + 0x56, 0x66, 0x47, 0xbf, 0x26, 0xa0, 0xa1, 0xbb, 0x46, 0x50, 0xb9, 0x52, 0x7e, 0x7c, 0x05, 0x83, + 0x2b, 0xed, 0x15, 0x4f, 0x0e, 0xd5, 0x74, 0xc7, 0xa9, 0x81, 0xfc, 0x20, 0x24, 0x9a, 0xf8, 0xd3, + 0xc3, 0x69, 0xea, 0x5d, 0x98, 0x68, 0x9a, 0x77, 0xbb, 0x58, 0x4d, 0x4f, 0xe7, 0xd1, 0x4d, 0xb1, + 0x02, 0xc9, 0x6d, 0x9e, 0x02, 0xe0, 0x34, 0x61, 0x54, 0xe3, 0x2e, 0x6c, 0xab, 0xfe, 0x56, 0x20, + 0x0c, 0xcf, 0xed, 0xdc, 0xb9, 0x3c, 0x88, 0x62, 0xb2, 0x47, 0x31, 0x93, 0x4b, 0x7b, 0x5d, 0xd4, + 0xc5, 0x8a, 0x0a, 0x7a, 0x03, 0x06, 0x99, 0x0f, 0x6c, 0x34, 0x33, 0x9c, 0xaf, 0x28, 0x34, 0xc3, + 0x37, 0x24, 0x9b, 0x8a, 0xfd, 0x8d, 0xb0, 0xa0, 0x80, 0x6e, 0xca, 0x18, 0x2f, 0xd1, 0xaa, 0x7f, + 0x37, 0x22, 0x2c, 0xc6, 0x4b, 0x79, 0xf1, 0xe3, 0x49, 0xf8, 0x16, 0x5e, 0x9e, 0x19, 0x1a, 0xde, + 0xa8, 0x49, 0x99, 0x23, 0xf1, 0x5f, 0x46, 0x9c, 0x9f, 0x81, 0xfc, 0xee, 0x99, 0x51, 0xe9, 0x93, + 0xe1, 0xbc, 0x67, 0x92, 0xc0, 0x69, 0x9a, 0x94, 0xd1, 0xe4, 0x3b, 0x57, 0x98, 0xae, 0xf7, 0xda, + 0xff, 0x5c, 0xbe, 0x66, 0x97, 0x0c, 0x2f, 0xc1, 0xa2, 0xfe, 0x99, 0xde, 0xfa, 0xb3, 0x3e, 0x4c, + 0xa6, 0xb7, 0xe8, 0x23, 0xe5, 0x32, 0xfe, 0xa0, 0x04, 0xe3, 0xe6, 0x92, 0x42, 0xf3, 0x50, 0x16, + 0x44, 0x54, 0xc0, 0x51, 0xb5, 0x4b, 0xd6, 0x24, 0x00, 0x27, 0x38, 0x2c, 0xce, 0x2c, 0xab, 0xae, + 0x99, 0x1c, 0x26, 0x71, 0x66, 0x15, 0x04, 0x6b, 0x58, 0x54, 0x5e, 0xda, 0x0c, 0x82, 0x58, 0x5d, + 0x2a, 0x6a, 0xdd, 0x2d, 0xb2, 0x52, 0x2c, 0xa0, 0xf4, 0x32, 0xd9, 0x25, 0xa1, 0x4f, 0x3c, 0x33, + 0x8e, 0x99, 0xba, 0x4c, 0x6e, 0xe9, 0x40, 0x6c, 0xe2, 0xd2, 0x5b, 0x32, 0x88, 0xd8, 0x42, 0x16, + 0x52, 0x59, 0x62, 0xc2, 0x59, 0xe7, 0xde, 0xe4, 0x12, 0x8e, 0xbe, 0x00, 0x8f, 0x29, 0xe7, 0x6f, + 0xcc, 0x95, 0xd0, 0xb2, 0xc5, 0x41, 0x43, 0x89, 0xf2, 0xd8, 0x52, 0x36, 0x1a, 0xce, 0xab, 0x8f, + 0x5e, 0x87, 0x71, 0xc1, 0xb9, 0x4b, 0x8a, 0x43, 0xa6, 0x5d, 0xc4, 0x2d, 0x03, 0x8a, 0x53, 0xd8, + 0x32, 0x12, 0x1b, 0x63, 0x9e, 0x25, 0x85, 0xe1, 0xce, 0x48, 0x6c, 0x3a, 0x1c, 0x77, 0xd4, 0x40, + 0x0b, 0x30, 0xc1, 0x59, 0x2b, 0xd7, 0xdf, 0xe6, 0x73, 0x22, 0x3c, 0x4b, 0xd4, 0x96, 0xba, 0x63, + 0x82, 0x71, 0x1a, 0x1f, 0xbd, 0x0a, 0xa3, 0x4e, 0xd8, 0xd8, 0x71, 0x63, 0xd2, 0x88, 0xdb, 0x21, + 0x77, 0x39, 0xd1, 0x0c, 0x4b, 0x16, 0x34, 0x18, 0x36, 0x30, 0xed, 0xf7, 0xe1, 0x5c, 0x86, 0x53, + 0x1a, 0x5d, 0x38, 0x4e, 0xcb, 0x95, 0xdf, 0x94, 0x32, 0xc6, 0x5c, 0xa8, 0xad, 0xca, 0xaf, 0xd1, + 0xb0, 0xe8, 0xea, 0x64, 0xce, 0x6b, 0x5a, 0x82, 0x09, 0xb5, 0x3a, 0x57, 0x24, 0x00, 0x27, 0x38, + 0xf6, 0xff, 0x2a, 0xc0, 0x44, 0x86, 0x62, 0x9d, 0x25, 0x39, 0x48, 0xc9, 0x1e, 0x49, 0x4e, 0x03, + 0x33, 0xb0, 0x5f, 0xe1, 0x04, 0x81, 0xfd, 0x8a, 0xbd, 0x02, 0xfb, 0x95, 0x3e, 0x48, 0x60, 0x3f, + 0x73, 0xc4, 0x06, 0xfa, 0x1a, 0xb1, 0x8c, 0x60, 0x80, 0x83, 0x27, 0x0c, 0x06, 0x68, 0x0c, 0xfa, + 0x50, 0x1f, 0x83, 0xfe, 0xa3, 0x05, 0x98, 0x4c, 0x1b, 0xc0, 0x9d, 0x81, 0x3a, 0xf6, 0x0d, 0x43, + 0x1d, 0x9b, 0x9d, 0x32, 0x24, 0x6d, 0x96, 0x97, 0xa7, 0x9a, 0xc5, 0x29, 0xd5, 0xec, 0x27, 0xfb, + 0xa2, 0xd6, 0x5d, 0x4d, 0xfb, 0x77, 0x0b, 0x30, 0x9d, 0xae, 0xb2, 0xe4, 0x39, 0xee, 0xde, 0x19, + 0x8c, 0xcd, 0x1d, 0x63, 0x6c, 0x9e, 0xef, 0xe7, 0x6b, 0x58, 0xd7, 0x72, 0x07, 0xe8, 0xad, 0xd4, + 0x00, 0xcd, 0xf7, 0x4f, 0xb2, 0xfb, 0x28, 0x7d, 0xb3, 0x08, 0x97, 0x33, 0xeb, 0x25, 0xda, 0xcc, + 0x15, 0x43, 0x9b, 0x79, 0x3d, 0xa5, 0xcd, 0xb4, 0xbb, 0xd7, 0x3e, 0x1d, 0xf5, 0xa6, 0xf0, 0x16, + 0x64, 0xc1, 0xdf, 0x1e, 0x52, 0xb5, 0x69, 0x78, 0x0b, 0x2a, 0x42, 0xd8, 0xa4, 0xfb, 0x17, 0x49, + 0xa5, 0xf9, 0x6f, 0x2c, 0xb8, 0x98, 0x39, 0x37, 0x67, 0xa0, 0xc2, 0x5a, 0x37, 0x55, 0x58, 0xcf, + 0xf4, 0xbd, 0x5a, 0x73, 0x74, 0x5a, 0x7f, 0x58, 0xcc, 0xf9, 0x16, 0x26, 0xa0, 0xdf, 0x81, 0x11, + 0xa7, 0xd1, 0x20, 0x51, 0xb4, 0x16, 0x34, 0x55, 0x30, 0xb4, 0xe7, 0x99, 0x9c, 0x95, 0x14, 0x1f, + 0x1f, 0x56, 0x66, 0xd3, 0x24, 0x12, 0x30, 0xd6, 0x29, 0x98, 0xf1, 0x1b, 0x0b, 0xa7, 0x1a, 0xbf, + 0xf1, 0x3a, 0xc0, 0xbe, 0xe2, 0xd6, 0xd3, 0x42, 0xbe, 0xc6, 0xc7, 0x6b, 0x58, 0xe8, 0x8b, 0x30, + 0x1c, 0x89, 0x6b, 0x5c, 0x2c, 0xc5, 0x17, 0xfb, 0x9c, 0x2b, 0x67, 0x93, 0x78, 0xa6, 0x5b, 0xba, + 0xd2, 0x87, 0x28, 0x92, 0xe8, 0x3b, 0x60, 0x32, 0xe2, 0x51, 0x4f, 0x96, 0x3c, 0x27, 0x62, 0x3e, + 0x0e, 0x62, 0x15, 0x32, 0x5f, 0xf3, 0x7a, 0x0a, 0x86, 0x3b, 0xb0, 0xd1, 0x8a, 0xfc, 0x28, 0x16, + 0xa2, 0x85, 0x2f, 0xcc, 0xab, 0xc9, 0x07, 0x89, 0x14, 0x4b, 0xe7, 0xd3, 0xc3, 0xcf, 0x06, 0x5e, + 0xab, 0x69, 0xff, 0x68, 0x09, 0x1e, 0xef, 0x72, 0x88, 0xa1, 0x05, 0xf3, 0x8d, 0xf2, 0xd9, 0xb4, + 0xf4, 0x3b, 0x9b, 0x59, 0xd9, 0x10, 0x87, 0x53, 0x6b, 0xa5, 0xf0, 0x81, 0xd7, 0xca, 0x0f, 0x59, + 0x9a, 0x5e, 0x82, 0x5b, 0xd2, 0x7d, 0xee, 0x84, 0x87, 0xf3, 0x29, 0x2a, 0x2a, 0xb6, 0x32, 0xa4, + 0xfd, 0xeb, 0x7d, 0x77, 0xa7, 0x6f, 0xf1, 0xff, 0x6c, 0xb5, 0xb3, 0x5f, 0xb1, 0xe0, 0xc9, 0xcc, + 0xfe, 0x1a, 0x36, 0x15, 0xf3, 0x50, 0x6e, 0xd0, 0x42, 0xcd, 0x6f, 0x2a, 0x71, 0x28, 0x95, 0x00, + 0x9c, 0xe0, 0x18, 0xa6, 0x13, 0x85, 0x9e, 0xa6, 0x13, 0xff, 0xc2, 0x82, 0x8e, 0x05, 0x7c, 0x06, + 0x27, 0xe9, 0xaa, 0x79, 0x92, 0x7e, 0xbc, 0x9f, 0xb9, 0xcc, 0x39, 0x44, 0xff, 0xf3, 0x04, 0x5c, + 0xc8, 0x71, 0x94, 0xd8, 0x87, 0xa9, 0xed, 0x06, 0x31, 0x3d, 0xd2, 0xc4, 0xc7, 0x64, 0x3a, 0xef, + 0x75, 0x75, 0x5f, 0x63, 0xb9, 0x71, 0xa6, 0x3a, 0x50, 0x70, 0x67, 0x13, 0xe8, 0x2b, 0x16, 0x9c, + 0x77, 0xee, 0x47, 0x1d, 0x19, 0x10, 0xc5, 0x9a, 0x79, 0x29, 0x53, 0x4b, 0xd1, 0x23, 0x63, 0x22, + 0x4f, 0x16, 0x94, 0x85, 0x85, 0x33, 0xdb, 0x42, 0x58, 0xc4, 0xaf, 0xa4, 0xfc, 0x76, 0x17, 0x9f, + 0xc9, 0x2c, 0x8f, 0x16, 0x7e, 0xa6, 0x4a, 0x08, 0x56, 0x74, 0xd0, 0x3d, 0x28, 0x6f, 0x4b, 0x37, + 0x33, 0x71, 0x66, 0x67, 0x5e, 0x82, 0x99, 0xbe, 0x68, 0xfc, 0xdd, 0x50, 0x81, 0x70, 0x42, 0x0a, + 0xbd, 0x0e, 0x45, 0x7f, 0x2b, 0xea, 0x96, 0x65, 0x27, 0x65, 0x6a, 0xc4, 0xfd, 0x91, 0xd7, 0x57, + 0xea, 0x98, 0x56, 0x44, 0x37, 0xa1, 0x18, 0x6e, 0x36, 0x85, 0x62, 0x2d, 0x93, 0x2f, 0xc5, 0x8b, + 0xd5, 0xec, 0x45, 0xc2, 0x29, 0xe1, 0xc5, 0x2a, 0xa6, 0x24, 0x50, 0x0d, 0x06, 0x98, 0x4f, 0x81, + 0xd0, 0x9f, 0x65, 0x32, 0xa4, 0x5d, 0x7c, 0x73, 0xb8, 0xd3, 0x32, 0x43, 0xc0, 0x9c, 0x10, 0xda, + 0x80, 0xc1, 0x06, 0xcb, 0xc8, 0x22, 0x42, 0x26, 0x7f, 0x2a, 0x53, 0x85, 0xd6, 0x25, 0x55, 0x8d, + 0xd0, 0x28, 0x31, 0x0c, 0x2c, 0x68, 0x31, 0xaa, 0xa4, 0xb5, 0xb3, 0x15, 0x31, 0x11, 0x3c, 0x8f, + 0x6a, 0x97, 0x0c, 0x4c, 0x82, 0x2a, 0xc3, 0xc0, 0x82, 0x16, 0xfa, 0x0c, 0x14, 0xb6, 0x1a, 0xc2, + 0xe5, 0x20, 0x53, 0x97, 0x66, 0xba, 0x94, 0x2f, 0x0e, 0x1e, 0x1d, 0x56, 0x0a, 0x2b, 0x4b, 0xb8, + 0xb0, 0xd5, 0x40, 0xeb, 0x30, 0xb4, 0xc5, 0x9d, 0x50, 0x85, 0xba, 0xec, 0xe9, 0x6c, 0xff, 0xd8, + 0x0e, 0x3f, 0x55, 0x6e, 0x2a, 0x2f, 0x00, 0x58, 0x12, 0x61, 0x41, 0x20, 0x95, 0x33, 0xad, 0x88, + 0x86, 0x3c, 0x77, 0x32, 0x07, 0x68, 0xee, 0xde, 0x9e, 0xb8, 0xe4, 0x62, 0x8d, 0x22, 0xfa, 0x32, + 0x94, 0x1d, 0x99, 0x7b, 0x4f, 0x44, 0x8b, 0x78, 0x31, 0x73, 0x63, 0x76, 0x4f, 0x4b, 0xc8, 0x57, + 0xb5, 0x42, 0xc2, 0x09, 0x51, 0xb4, 0x0b, 0x63, 0xfb, 0x51, 0x6b, 0x87, 0xc8, 0x8d, 0xcc, 0x82, + 0x47, 0xe4, 0x5c, 0x5c, 0xf7, 0x04, 0xa2, 0x1b, 0xc6, 0x6d, 0xc7, 0xeb, 0x38, 0x7b, 0xd8, 0x63, + 0xf3, 0x3d, 0x9d, 0x18, 0x36, 0x69, 0xd3, 0xe1, 0x7f, 0xaf, 0x1d, 0x6c, 0x1e, 0xc4, 0x44, 0x84, + 0x4f, 0xce, 0x1c, 0xfe, 0x37, 0x39, 0x4a, 0xe7, 0xf0, 0x0b, 0x00, 0x96, 0x44, 0xe8, 0x56, 0x77, + 0x64, 0x5e, 0x4b, 0x16, 0x36, 0x39, 0x67, 0xab, 0x67, 0x26, 0xbf, 0xd4, 0x06, 0x85, 0x9d, 0x91, + 0x09, 0x29, 0x76, 0x36, 0xb6, 0x76, 0x82, 0x38, 0xf0, 0x53, 0xe7, 0xf2, 0x54, 0xfe, 0xd9, 0x58, + 0xcb, 0xc0, 0xef, 0x3c, 0x1b, 0xb3, 0xb0, 0x70, 0x66, 0x5b, 0xa8, 0x09, 0xe3, 0xad, 0x20, 0x8c, + 0xef, 0x07, 0xa1, 0x5c, 0x5f, 0xa8, 0x8b, 0xb8, 0x6f, 0x60, 0x8a, 0x16, 0x59, 0x38, 0x6f, 0x13, + 0x82, 0x53, 0x34, 0xd1, 0xe7, 0x61, 0x28, 0x6a, 0x38, 0x1e, 0x59, 0xbd, 0x33, 0x73, 0x2e, 0xff, + 0xd2, 0xa9, 0x73, 0x94, 0x9c, 0xd5, 0xc5, 0x26, 0x47, 0xa0, 0x60, 0x49, 0x0e, 0xad, 0xc0, 0x00, + 0x8b, 0xc9, 0xcf, 0x22, 0x3f, 0xe7, 0x44, 0x25, 0xea, 0x30, 0xea, 0xe4, 0x67, 0x13, 0x2b, 0xc6, + 0xbc, 0x3a, 0xdd, 0x03, 0x82, 0xeb, 0x0d, 0xa2, 0x99, 0xe9, 0xfc, 0x3d, 0x20, 0x98, 0xe5, 0x3b, + 0xf5, 0x6e, 0x7b, 0x40, 0x21, 0xe1, 0x84, 0x28, 0x3d, 0x99, 0xe9, 0x69, 0x7a, 0xa1, 0x8b, 0x9d, + 0x49, 0xee, 0x59, 0xca, 0x4e, 0x66, 0x7a, 0x92, 0x52, 0x12, 0xf6, 0xef, 0x0d, 0x75, 0x72, 0x2a, + 0x4c, 0x4e, 0xfa, 0xcb, 0x56, 0xc7, 0x13, 0xda, 0xa7, 0xfb, 0x55, 0xdb, 0x9c, 0x22, 0x8f, 0xfa, + 0x15, 0x0b, 0x2e, 0xb4, 0x32, 0x3f, 0x44, 0x5c, 0xfb, 0xfd, 0x69, 0x7f, 0xf8, 0xa7, 0xab, 0xe8, + 0xec, 0xd9, 0x70, 0x9c, 0xd3, 0x52, 0x5a, 0x0e, 0x28, 0x7e, 0x60, 0x39, 0x60, 0x0d, 0x86, 0x19, + 0x6b, 0xd9, 0x23, 0x43, 0x59, 0xda, 0x0b, 0x8d, 0x31, 0x10, 0x4b, 0xa2, 0x22, 0x56, 0x24, 0xd0, + 0x0f, 0x5b, 0x70, 0x29, 0xdd, 0x75, 0x4c, 0x18, 0x58, 0xc4, 0x32, 0xe7, 0x22, 0xda, 0x8a, 0xf8, + 0xfe, 0x4b, 0xb5, 0x6e, 0xc8, 0xc7, 0xbd, 0x10, 0x70, 0xf7, 0xc6, 0x50, 0x35, 0x43, 0x46, 0x1c, + 0x34, 0xf5, 0xe2, 0x7d, 0xc8, 0x89, 0x2f, 0xc1, 0xe8, 0x5e, 0xd0, 0xf6, 0x63, 0x61, 0x96, 0x22, + 0x9c, 0x04, 0xd9, 0x3b, 0xf0, 0x9a, 0x56, 0x8e, 0x0d, 0xac, 0x94, 0x74, 0x39, 0xfc, 0xb0, 0xd2, + 0x25, 0x7a, 0x27, 0x95, 0x87, 0xba, 0x9c, 0x1f, 0x33, 0x4f, 0x08, 0xe2, 0x27, 0xc8, 0x46, 0x7d, + 0xb6, 0x12, 0xd1, 0xcf, 0x59, 0x19, 0xac, 0x3c, 0x97, 0x91, 0x3f, 0x6b, 0xca, 0xc8, 0x57, 0xd3, + 0x32, 0x72, 0x87, 0x4e, 0xd4, 0x10, 0x8f, 0xfb, 0x0f, 0xbc, 0xdc, 0x6f, 0x24, 0x33, 0xdb, 0x83, + 0x2b, 0xbd, 0xae, 0x25, 0x66, 0x9f, 0xd4, 0x54, 0x2f, 0x60, 0x89, 0x7d, 0x52, 0x73, 0xb5, 0x8a, + 0x19, 0xa4, 0xdf, 0x50, 0x17, 0xf6, 0x7f, 0xb3, 0xa0, 0x58, 0x0b, 0x9a, 0x67, 0xa0, 0xe3, 0xfd, + 0x9c, 0xa1, 0xe3, 0x7d, 0x3c, 0x27, 0x3f, 0x78, 0xae, 0x46, 0x77, 0x39, 0xa5, 0xd1, 0xbd, 0x94, + 0x47, 0xa0, 0xbb, 0xfe, 0xf6, 0xa7, 0x8b, 0xa0, 0x67, 0x33, 0x47, 0xff, 0xea, 0x61, 0x8c, 0x83, + 0x8b, 0xdd, 0x12, 0x9c, 0x0b, 0xca, 0xcc, 0xac, 0x49, 0xfa, 0xbd, 0xfd, 0x39, 0xb3, 0x11, 0x7e, + 0x8b, 0xb8, 0xdb, 0x3b, 0x31, 0x69, 0xa6, 0x3f, 0xe7, 0xec, 0x6c, 0x84, 0xff, 0x8b, 0x05, 0x13, + 0xa9, 0xd6, 0x91, 0x07, 0x63, 0x9e, 0xae, 0xa0, 0x13, 0xeb, 0xf4, 0xa1, 0x74, 0x7b, 0xc2, 0xc6, + 0x52, 0x2b, 0xc2, 0x26, 0x71, 0x34, 0x07, 0xa0, 0x1e, 0xd0, 0xa4, 0xde, 0x8b, 0x71, 0xfd, 0xea, + 0x85, 0x2d, 0xc2, 0x1a, 0x06, 0x7a, 0x19, 0x46, 0xe2, 0xa0, 0x15, 0x78, 0xc1, 0xf6, 0xc1, 0x2d, + 0x22, 0x83, 0xab, 0x28, 0xcb, 0xa9, 0x8d, 0x04, 0x84, 0x75, 0x3c, 0xfb, 0x67, 0x8b, 0x90, 0xce, + 0x80, 0xff, 0xad, 0x35, 0xf9, 0xd1, 0x5c, 0x93, 0xdf, 0xb4, 0x60, 0x92, 0xb6, 0xce, 0xac, 0x38, + 0xe4, 0x65, 0xab, 0x12, 0xc0, 0x58, 0x5d, 0x12, 0xc0, 0x5c, 0xa5, 0x67, 0x57, 0x33, 0x68, 0xc7, + 0x42, 0x6f, 0xa6, 0x1d, 0x4e, 0xb4, 0x14, 0x0b, 0xa8, 0xc0, 0x23, 0x61, 0x28, 0x5c, 0x93, 0x74, + 0x3c, 0x12, 0x86, 0x58, 0x40, 0x65, 0x7e, 0x98, 0x52, 0x4e, 0x7e, 0x18, 0x16, 0x2a, 0x4e, 0xbc, + 0xf7, 0x0b, 0xb6, 0x47, 0x0b, 0x15, 0x27, 0x0d, 0x01, 0x12, 0x1c, 0xfb, 0x17, 0x8b, 0x30, 0x5a, + 0x0b, 0x9a, 0xc9, 0x13, 0xd6, 0x4b, 0xc6, 0x13, 0xd6, 0x95, 0xd4, 0x13, 0xd6, 0xa4, 0x8e, 0xfb, + 0xad, 0x07, 0xab, 0x0f, 0xeb, 0xc1, 0xea, 0x9f, 0x5b, 0x6c, 0xd6, 0xaa, 0xeb, 0x75, 0x91, 0x9f, + 0xf6, 0x05, 0x18, 0x61, 0x07, 0x12, 0xf3, 0x85, 0x93, 0xef, 0x3a, 0x2c, 0xf4, 0xfb, 0x7a, 0x52, + 0x8c, 0x75, 0x1c, 0x74, 0x0d, 0x86, 0x23, 0xe2, 0x84, 0x8d, 0x1d, 0x75, 0xc6, 0x89, 0x57, 0x0f, + 0x5e, 0x86, 0x15, 0x14, 0xbd, 0x99, 0x44, 0x29, 0x2b, 0xe6, 0x67, 0x5a, 0xd5, 0xfb, 0xc3, 0xb7, + 0x48, 0x7e, 0x68, 0x32, 0xfb, 0x2d, 0x40, 0x9d, 0xf8, 0x7d, 0xc4, 0x23, 0xaa, 0x98, 0xf1, 0x88, + 0xca, 0x1d, 0xb1, 0x88, 0xfe, 0xd4, 0x82, 0xf1, 0x5a, 0xd0, 0xa4, 0x5b, 0xf7, 0x2f, 0xd2, 0x3e, + 0xd5, 0x43, 0x34, 0x0e, 0x76, 0x09, 0xd1, 0xf8, 0xf7, 0x2c, 0x18, 0xaa, 0x05, 0xcd, 0x33, 0xd0, + 0xb6, 0x7f, 0xd6, 0xd4, 0xb6, 0x3f, 0x96, 0xb3, 0x24, 0x72, 0x14, 0xec, 0xbf, 0x5c, 0x84, 0x31, + 0xda, 0xcf, 0x60, 0x5b, 0xce, 0x92, 0x31, 0x22, 0x56, 0x1f, 0x23, 0x42, 0xd9, 0xdc, 0xc0, 0xf3, + 0x82, 0xfb, 0xe9, 0x19, 0x5b, 0x61, 0xa5, 0x58, 0x40, 0xd1, 0x73, 0x30, 0xdc, 0x0a, 0xc9, 0xbe, + 0x1b, 0x08, 0xfe, 0x51, 0x7b, 0xbb, 0xa8, 0x89, 0x72, 0xac, 0x30, 0xa8, 0xdc, 0x15, 0xb9, 0x7e, + 0x83, 0xc8, 0x34, 0xcf, 0x25, 0x96, 0x09, 0x8a, 0xc7, 0x5e, 0xd6, 0xca, 0xb1, 0x81, 0x85, 0xde, + 0x82, 0x32, 0xfb, 0xcf, 0x4e, 0x94, 0x93, 0x67, 0xae, 0x11, 0x09, 0x0f, 0x04, 0x01, 0x9c, 0xd0, + 0x42, 0xd7, 0x01, 0x62, 0x19, 0x9f, 0x37, 0x12, 0x61, 0x65, 0x14, 0xaf, 0xad, 0x22, 0xf7, 0x46, + 0x58, 0xc3, 0x42, 0xcf, 0x42, 0x39, 0x76, 0x5c, 0xef, 0xb6, 0xeb, 0x93, 0x88, 0xa9, 0x9c, 0x8b, + 0x32, 0x9f, 0x81, 0x28, 0xc4, 0x09, 0x9c, 0xf2, 0x3a, 0xcc, 0xe7, 0x9a, 0xe7, 0xbd, 0x1a, 0x66, + 0xd8, 0x8c, 0xd7, 0xb9, 0xad, 0x4a, 0xb1, 0x86, 0x61, 0xbf, 0x0a, 0xd3, 0xb5, 0xa0, 0x59, 0x0b, + 0xc2, 0x78, 0x25, 0x08, 0xef, 0x3b, 0x61, 0x53, 0xce, 0x5f, 0x45, 0x86, 0xd6, 0xa7, 0x67, 0xcf, + 0x00, 0xdf, 0x99, 0x46, 0xd0, 0xfc, 0x17, 0x19, 0xb7, 0x73, 0x42, 0x5f, 0x8b, 0x06, 0xbb, 0x77, + 0x55, 0x8a, 0xbb, 0x1b, 0x4e, 0x4c, 0xd0, 0x1d, 0x96, 0x16, 0x2b, 0xb9, 0x82, 0x44, 0xf5, 0x67, + 0xb4, 0xb4, 0x58, 0x09, 0x30, 0xf3, 0xce, 0x32, 0xeb, 0xdb, 0xbf, 0x5e, 0x64, 0xa7, 0x51, 0x2a, + 0xe3, 0x1b, 0xfa, 0x12, 0x8c, 0x47, 0xe4, 0xb6, 0xeb, 0xb7, 0x1f, 0x48, 0x21, 0xbc, 0x8b, 0xb7, + 0x4c, 0x7d, 0x59, 0xc7, 0xe4, 0xaa, 0x3c, 0xb3, 0x0c, 0xa7, 0xa8, 0xd1, 0x79, 0x0a, 0xdb, 0xfe, + 0x42, 0x74, 0x37, 0x22, 0xa1, 0xc8, 0x38, 0xc6, 0xe6, 0x09, 0xcb, 0x42, 0x9c, 0xc0, 0xe9, 0xba, + 0x64, 0x7f, 0xd6, 0x03, 0x1f, 0x07, 0x41, 0x2c, 0x57, 0x32, 0xcb, 0x59, 0xa3, 0x95, 0x63, 0x03, + 0x0b, 0xad, 0x00, 0x8a, 0xda, 0xad, 0x96, 0xc7, 0xde, 0xdb, 0x1d, 0xef, 0x46, 0x18, 0xb4, 0x5b, + 0xfc, 0xad, 0xb3, 0xb8, 0x78, 0x81, 0x5e, 0x61, 0xf5, 0x0e, 0x28, 0xce, 0xa8, 0x41, 0x4f, 0x9f, + 0xad, 0x88, 0xfd, 0x66, 0xab, 0xbb, 0x28, 0xd4, 0xeb, 0x75, 0x56, 0x84, 0x25, 0x8c, 0x2e, 0x26, + 0xd6, 0x3c, 0xc7, 0x1c, 0x4c, 0x16, 0x13, 0x56, 0xa5, 0x58, 0xc3, 0x40, 0xcb, 0x30, 0x14, 0x1d, + 0x44, 0x8d, 0x58, 0x04, 0x41, 0xca, 0xc9, 0x1d, 0x59, 0x67, 0x28, 0x5a, 0x3e, 0x03, 0x5e, 0x05, + 0xcb, 0xba, 0xf6, 0xf7, 0xb0, 0xcb, 0x90, 0xe5, 0xa7, 0x8a, 0xdb, 0x21, 0x41, 0x7b, 0x30, 0xd6, + 0x62, 0x53, 0x2e, 0xa2, 0x27, 0x8b, 0x79, 0x7b, 0xa9, 0x4f, 0xa9, 0xf6, 0x3e, 0x3d, 0x68, 0x94, + 0xd6, 0x89, 0x89, 0x0b, 0x35, 0x9d, 0x1c, 0x36, 0xa9, 0xdb, 0x3f, 0x38, 0xc5, 0xce, 0xdc, 0x3a, + 0x17, 0x55, 0x87, 0x84, 0xc5, 0xaf, 0xe0, 0xcb, 0x67, 0xf3, 0x75, 0x26, 0xc9, 0x17, 0x09, 0xab, + 0x61, 0x2c, 0xeb, 0xa2, 0x37, 0xd9, 0xdb, 0x34, 0x3f, 0xe8, 0x7a, 0xa5, 0x09, 0xe6, 0x58, 0xc6, + 0x33, 0xb4, 0xa8, 0x88, 0x35, 0x22, 0xe8, 0x36, 0x8c, 0x89, 0x74, 0x46, 0x42, 0x29, 0x56, 0x34, + 0x94, 0x1e, 0x63, 0x58, 0x07, 0x1e, 0xa7, 0x0b, 0xb0, 0x59, 0x19, 0x6d, 0xc3, 0x25, 0x2d, 0xb7, + 0xdf, 0x8d, 0xd0, 0x61, 0xef, 0x95, 0x2e, 0xdb, 0x44, 0xda, 0xb9, 0xf9, 0xe4, 0xd1, 0x61, 0xe5, + 0xd2, 0x46, 0x37, 0x44, 0xdc, 0x9d, 0x0e, 0xba, 0x03, 0xd3, 0xdc, 0xb1, 0xae, 0x4a, 0x9c, 0xa6, + 0xe7, 0xfa, 0xea, 0x60, 0xe6, 0xeb, 0xf0, 0xe2, 0xd1, 0x61, 0x65, 0x7a, 0x21, 0x0b, 0x01, 0x67, + 0xd7, 0x43, 0x9f, 0x85, 0x72, 0xd3, 0x8f, 0xc4, 0x18, 0x0c, 0x1a, 0x69, 0x2b, 0xcb, 0xd5, 0xf5, + 0xba, 0xfa, 0xfe, 0xe4, 0x0f, 0x4e, 0x2a, 0xa0, 0x6d, 0xae, 0x18, 0x53, 0x72, 0xe8, 0x50, 0x7e, + 0x8a, 0x72, 0xb1, 0x24, 0x0c, 0xd7, 0x1a, 0xae, 0x11, 0x56, 0xa6, 0xa9, 0x86, 0xd7, 0x8d, 0x41, + 0x18, 0xbd, 0x01, 0x88, 0x32, 0x6a, 0x6e, 0x83, 0x2c, 0x34, 0x58, 0x10, 0x6b, 0xa6, 0x47, 0x1c, + 0x36, 0x5c, 0x19, 0x50, 0xbd, 0x03, 0x03, 0x67, 0xd4, 0x42, 0x37, 0xe9, 0x41, 0xa6, 0x97, 0x0a, + 0x13, 0x5b, 0xc9, 0xdc, 0xcf, 0x54, 0x49, 0x2b, 0x24, 0x0d, 0x27, 0x26, 0x4d, 0x93, 0x22, 0x4e, + 0xd5, 0xa3, 0x77, 0xa9, 0xca, 0x67, 0x03, 0x66, 0xa4, 0x8a, 0xce, 0x9c, 0x36, 0x54, 0x2e, 0xde, + 0x09, 0xa2, 0x78, 0x9d, 0xc4, 0xf7, 0x83, 0x70, 0x57, 0x04, 0x06, 0x4b, 0x62, 0x54, 0x26, 0x20, + 0xac, 0xe3, 0x51, 0x3e, 0x98, 0x3d, 0x0e, 0xaf, 0x56, 0xd9, 0x0b, 0xdd, 0x70, 0xb2, 0x4f, 0x6e, + 0xf2, 0x62, 0x2c, 0xe1, 0x12, 0x75, 0xb5, 0xb6, 0xc4, 0x5e, 0xdb, 0x52, 0xa8, 0xab, 0xb5, 0x25, + 0x2c, 0xe1, 0x88, 0x74, 0xa6, 0x04, 0x1d, 0xcf, 0xd7, 0x6a, 0x76, 0x5e, 0x07, 0x7d, 0x66, 0x05, + 0xf5, 0x61, 0x52, 0x25, 0x23, 0xe5, 0x11, 0xd3, 0xa2, 0x99, 0x09, 0xb6, 0x48, 0xfa, 0x0f, 0xb7, + 0xa6, 0xf4, 0xc4, 0xab, 0x29, 0x4a, 0xb8, 0x83, 0xb6, 0x11, 0x3b, 0x64, 0xb2, 0x67, 0x3e, 0xa2, + 0x79, 0x28, 0x47, 0xed, 0xcd, 0x66, 0xb0, 0xe7, 0xb8, 0x3e, 0x7b, 0x1c, 0xd3, 0x98, 0xac, 0xba, + 0x04, 0xe0, 0x04, 0x07, 0xad, 0xc0, 0xb0, 0x23, 0x95, 0xc0, 0x28, 0x3f, 0x98, 0x80, 0x52, 0xfd, + 0x72, 0xff, 0x5a, 0xa9, 0xf6, 0x55, 0x75, 0xd1, 0x6b, 0x30, 0x26, 0xdc, 0xa9, 0x78, 0x88, 0x05, + 0xf6, 0x78, 0xa5, 0xd9, 0xcb, 0xd7, 0x75, 0x20, 0x36, 0x71, 0xd1, 0x17, 0x61, 0x9c, 0x52, 0x49, + 0x0e, 0xb6, 0x99, 0xf3, 0xfd, 0x9c, 0x88, 0x5a, 0x9e, 0x09, 0xbd, 0x32, 0x4e, 0x11, 0x43, 0x4d, + 0x78, 0xc2, 0x69, 0xc7, 0x01, 0x53, 0xa4, 0x9b, 0xeb, 0x7f, 0x23, 0xd8, 0x25, 0x3e, 0x7b, 0xc3, + 0x1a, 0x5e, 0xbc, 0x72, 0x74, 0x58, 0x79, 0x62, 0xa1, 0x0b, 0x1e, 0xee, 0x4a, 0x05, 0xdd, 0x85, + 0x91, 0x38, 0xf0, 0x98, 0xe5, 0x3a, 0x65, 0x25, 0x2e, 0xe4, 0xc7, 0xde, 0xd9, 0x50, 0x68, 0xba, + 0x12, 0x49, 0x55, 0xc5, 0x3a, 0x1d, 0xb4, 0xc1, 0xf7, 0x18, 0x8b, 0x4a, 0x4a, 0xa2, 0x99, 0xc7, + 0xf2, 0x07, 0x46, 0x05, 0x2f, 0x35, 0xb7, 0xa0, 0xa8, 0x89, 0x75, 0x32, 0xe8, 0x06, 0x4c, 0xb5, + 0x42, 0x37, 0x60, 0x0b, 0x5b, 0x3d, 0x62, 0xcc, 0x98, 0xa9, 0x05, 0x6a, 0x69, 0x04, 0xdc, 0x59, + 0x87, 0x0a, 0x99, 0xb2, 0x70, 0xe6, 0x22, 0xcf, 0x53, 0xc5, 0x19, 0x6f, 0x5e, 0x86, 0x15, 0x14, + 0xad, 0xb1, 0x73, 0x99, 0x8b, 0x83, 0x33, 0xb3, 0xf9, 0x41, 0x18, 0x74, 0xb1, 0x91, 0xf3, 0x4b, + 0xea, 0x2f, 0x4e, 0x28, 0xd0, 0x7b, 0x23, 0xda, 0x71, 0x42, 0x52, 0x0b, 0x83, 0x06, 0xe1, 0x9d, + 0xe1, 0x46, 0xf3, 0x8f, 0xf3, 0xe0, 0x89, 0xf4, 0xde, 0xa8, 0x67, 0x21, 0xe0, 0xec, 0x7a, 0xa8, + 0xa9, 0xa5, 0x67, 0xa6, 0x6c, 0x68, 0x34, 0xf3, 0x44, 0x17, 0x33, 0xa3, 0x14, 0xcf, 0x9a, 0xac, + 0x45, 0xa3, 0x38, 0xc2, 0x29, 0x9a, 0xb3, 0xdf, 0x0e, 0x53, 0x1d, 0xf7, 0xc5, 0x89, 0xe2, 0x76, + 0xff, 0xc9, 0x00, 0x94, 0x95, 0x2a, 0x1c, 0xcd, 0x9b, 0x2f, 0x1c, 0x17, 0xd3, 0x2f, 0x1c, 0xc3, + 0x94, 0x23, 0xd7, 0x1f, 0x35, 0x36, 0x0c, 0xa3, 0xb8, 0x42, 0x7e, 0x96, 0x2c, 0x9d, 0xa7, 0xee, + 0xe9, 0x01, 0xa7, 0x69, 0x36, 0x8a, 0x7d, 0x3f, 0x95, 0x94, 0xba, 0x2a, 0x4b, 0xfa, 0x4c, 0x52, + 0x4b, 0x85, 0xff, 0x56, 0xd0, 0x5c, 0xad, 0xa5, 0xb3, 0x36, 0xd6, 0x68, 0x21, 0xe6, 0x30, 0x26, + 0xbe, 0x51, 0xe6, 0x86, 0x89, 0x6f, 0x43, 0x0f, 0x29, 0xbe, 0x49, 0x02, 0x38, 0xa1, 0x85, 0x3c, + 0x98, 0x6a, 0x98, 0x09, 0x37, 0x95, 0xd7, 0xdb, 0x53, 0x3d, 0x53, 0x5f, 0xb6, 0xb5, 0xec, 0x66, + 0x4b, 0x69, 0x2a, 0xb8, 0x93, 0x30, 0x7a, 0x0d, 0x86, 0xdf, 0x0b, 0x22, 0xb6, 0xf9, 0xc4, 0x0d, + 0x2f, 0xbd, 0x83, 0x86, 0xdf, 0xbc, 0x53, 0x67, 0xe5, 0xc7, 0x87, 0x95, 0x91, 0x5a, 0xd0, 0x94, + 0x7f, 0xb1, 0xaa, 0x80, 0x1e, 0xc0, 0xb4, 0x71, 0x2e, 0xaa, 0xee, 0x42, 0xff, 0xdd, 0xbd, 0x24, + 0x9a, 0x9b, 0x5e, 0xcd, 0xa2, 0x84, 0xb3, 0x1b, 0xa0, 0x87, 0x8d, 0x1f, 0x88, 0x64, 0xb5, 0x92, + 0x8b, 0x60, 0xcc, 0x42, 0x59, 0xf7, 0x0d, 0x4f, 0x21, 0xe0, 0xce, 0x3a, 0xf6, 0xd7, 0xf8, 0xcb, + 0x81, 0xd0, 0x2f, 0x92, 0xa8, 0xed, 0x9d, 0x45, 0x2e, 0xa4, 0x65, 0x43, 0xf5, 0xf9, 0xd0, 0xaf, + 0x53, 0xbf, 0x69, 0xb1, 0xd7, 0xa9, 0x0d, 0xb2, 0xd7, 0xf2, 0xa8, 0x94, 0xfb, 0xe8, 0x3b, 0xfe, + 0x26, 0x0c, 0xc7, 0xa2, 0xb5, 0x6e, 0xe9, 0x9b, 0xb4, 0x4e, 0xb1, 0x17, 0x3a, 0xc5, 0x5f, 0xc8, + 0x52, 0xac, 0xc8, 0xd8, 0xff, 0x94, 0xcf, 0x80, 0x84, 0x9c, 0x81, 0x1a, 0xaa, 0x6a, 0xaa, 0xa1, + 0x2a, 0x3d, 0xbe, 0x20, 0x47, 0x1d, 0xf5, 0x4f, 0xcc, 0x7e, 0x33, 0x51, 0xee, 0xa3, 0xfe, 0x2c, + 0x6a, 0xff, 0x98, 0x05, 0xe7, 0xb3, 0xec, 0x88, 0x28, 0x4f, 0xc8, 0x05, 0x49, 0xf5, 0x4c, 0xac, + 0x46, 0xf0, 0x9e, 0x28, 0xc7, 0x0a, 0xa3, 0xef, 0xcc, 0x08, 0x27, 0x0b, 0x9f, 0x76, 0x07, 0xc6, + 0x6a, 0x21, 0xd1, 0xee, 0x80, 0xd7, 0xb9, 0x9b, 0x19, 0xef, 0xcf, 0x73, 0x27, 0x76, 0x31, 0xb3, + 0x7f, 0xbe, 0x00, 0xe7, 0xf9, 0x3b, 0xcf, 0xc2, 0x7e, 0xe0, 0x36, 0x6b, 0x41, 0x53, 0x64, 0xb5, + 0x78, 0x1b, 0x46, 0x5b, 0x9a, 0xf4, 0xdf, 0x2d, 0x80, 0x93, 0xae, 0x25, 0x48, 0xa4, 0x30, 0xbd, + 0x14, 0x1b, 0xb4, 0x50, 0x13, 0x46, 0xc9, 0xbe, 0xdb, 0x50, 0x8f, 0x05, 0x85, 0x13, 0xdf, 0x0d, + 0xaa, 0x95, 0x65, 0x8d, 0x0e, 0x36, 0xa8, 0x3e, 0x82, 0x44, 0x67, 0xf6, 0x8f, 0x5b, 0xf0, 0x58, + 0x4e, 0xb8, 0x27, 0xda, 0xdc, 0x7d, 0xf6, 0xa2, 0x26, 0x72, 0x26, 0xa9, 0xe6, 0xf8, 0x3b, 0x1b, + 0x16, 0x50, 0xf4, 0x79, 0x00, 0xfe, 0x4e, 0x46, 0x85, 0x92, 0x5e, 0x71, 0x71, 0x8c, 0x90, 0x1e, + 0x5a, 0x28, 0x06, 0x59, 0x1f, 0x6b, 0xb4, 0xec, 0x9f, 0x29, 0xc2, 0x00, 0x7b, 0x97, 0x41, 0x2b, + 0x30, 0xb4, 0xc3, 0x83, 0x1b, 0xf7, 0x13, 0x47, 0x39, 0x91, 0xee, 0x78, 0x01, 0x96, 0x95, 0xd1, + 0x1a, 0x9c, 0xe3, 0xc1, 0xa1, 0xbd, 0x2a, 0xf1, 0x9c, 0x03, 0xa9, 0x24, 0xe0, 0x79, 0x86, 0x54, + 0x58, 0x89, 0xd5, 0x4e, 0x14, 0x9c, 0x55, 0x0f, 0xbd, 0x0e, 0xe3, 0xb1, 0xbb, 0x47, 0x82, 0x76, + 0x2c, 0x29, 0xf1, 0xb0, 0xd0, 0x8a, 0x8d, 0xdb, 0x30, 0xa0, 0x38, 0x85, 0x4d, 0xc5, 0x9d, 0x56, + 0x87, 0x3a, 0x44, 0xcb, 0xdc, 0x6f, 0xaa, 0x40, 0x4c, 0x5c, 0x66, 0x40, 0xd4, 0x66, 0xe6, 0x52, + 0x1b, 0x3b, 0x21, 0x89, 0x76, 0x02, 0xaf, 0x29, 0xd2, 0x54, 0x27, 0x06, 0x44, 0x29, 0x38, 0xee, + 0xa8, 0x41, 0xa9, 0x6c, 0x39, 0xae, 0xd7, 0x0e, 0x49, 0x42, 0x65, 0xd0, 0xa4, 0xb2, 0x92, 0x82, + 0xe3, 0x8e, 0x1a, 0x74, 0x1d, 0x4d, 0x8b, 0xbc, 0xd1, 0xd2, 0xd9, 0x5d, 0x59, 0x85, 0x0d, 0x49, + 0xb7, 0x9f, 0x2e, 0xd1, 0x5e, 0x84, 0xdd, 0x8c, 0xca, 0x3c, 0xad, 0x69, 0xf1, 0x84, 0xc3, 0x8f, + 0xa4, 0xf2, 0x30, 0xd9, 0x8b, 0x7f, 0xcf, 0x82, 0x73, 0x19, 0xd6, 0xa7, 0xfc, 0xa8, 0xda, 0x76, + 0xa3, 0x58, 0xe5, 0x52, 0xd1, 0x8e, 0x2a, 0x5e, 0x8e, 0x15, 0x06, 0xdd, 0x0f, 0xfc, 0x30, 0x4c, + 0x1f, 0x80, 0xc2, 0xba, 0x4b, 0x40, 0x4f, 0x76, 0x00, 0xa2, 0x2b, 0x50, 0x6a, 0x47, 0x44, 0xc6, + 0x69, 0x52, 0xe7, 0x37, 0xd3, 0xeb, 0x32, 0x08, 0x65, 0x4d, 0xb7, 0x95, 0x4a, 0x55, 0x63, 0x4d, + 0xb9, 0x9e, 0x94, 0xc3, 0xec, 0xaf, 0x16, 0xe1, 0x62, 0xae, 0x9d, 0x39, 0xed, 0xd2, 0x5e, 0xe0, + 0xbb, 0x71, 0xa0, 0xde, 0xfc, 0x78, 0xa4, 0x10, 0xd2, 0xda, 0x59, 0x13, 0xe5, 0x58, 0x61, 0xa0, + 0xab, 0x32, 0x83, 0x79, 0x3a, 0x5b, 0xcc, 0x62, 0xd5, 0x48, 0x62, 0xde, 0x6f, 0x26, 0xae, 0xa7, + 0xa0, 0xd4, 0x0a, 0x02, 0x2f, 0x7d, 0x18, 0xd1, 0xee, 0x06, 0x81, 0x87, 0x19, 0x10, 0x7d, 0x42, + 0x8c, 0x43, 0xea, 0x91, 0x0b, 0x3b, 0xcd, 0x20, 0xd2, 0x06, 0xe3, 0x19, 0x18, 0xda, 0x25, 0x07, + 0xa1, 0xeb, 0x6f, 0xa7, 0x1f, 0x3f, 0x6f, 0xf1, 0x62, 0x2c, 0xe1, 0x66, 0xb2, 0x84, 0xa1, 0xd3, + 0x4e, 0xa1, 0x35, 0xdc, 0xf3, 0x6a, 0xfb, 0xa1, 0x22, 0x4c, 0xe0, 0xc5, 0xea, 0xb7, 0x26, 0xe2, + 0x6e, 0xe7, 0x44, 0x9c, 0x76, 0x0a, 0xad, 0xde, 0xb3, 0xf1, 0xcb, 0x16, 0x4c, 0xb0, 0x80, 0xc2, + 0x22, 0x3e, 0x85, 0x1b, 0xf8, 0x67, 0xc0, 0xba, 0x3d, 0x05, 0x03, 0x21, 0x6d, 0x34, 0x9d, 0x17, + 0x87, 0xf5, 0x04, 0x73, 0x18, 0x7a, 0x02, 0x4a, 0xac, 0x0b, 0x74, 0xf2, 0x46, 0x79, 0x4a, 0x81, + 0xaa, 0x13, 0x3b, 0x98, 0x95, 0x32, 0xa7, 0x6b, 0x4c, 0x5a, 0x9e, 0xcb, 0x3b, 0x9d, 0x3c, 0x28, + 0x7c, 0x34, 0x9c, 0xae, 0x33, 0xbb, 0xf6, 0xc1, 0x9c, 0xae, 0xb3, 0x49, 0x76, 0x17, 0x8b, 0xfe, + 0x7b, 0x01, 0x2e, 0x67, 0xd6, 0xeb, 0xdb, 0xe9, 0xba, 0x7b, 0xed, 0xd3, 0xb1, 0x61, 0xc9, 0x36, + 0x2d, 0x29, 0x9e, 0xa1, 0x69, 0x49, 0xa9, 0x5f, 0xce, 0x71, 0xa0, 0x0f, 0x5f, 0xe8, 0xcc, 0x21, + 0xfb, 0x88, 0xf8, 0x42, 0x67, 0xf6, 0x2d, 0x47, 0xac, 0xfb, 0xb3, 0x42, 0xce, 0xb7, 0x30, 0x01, + 0xef, 0x1a, 0x3d, 0x67, 0x18, 0x30, 0x12, 0x9c, 0xf0, 0x28, 0x3f, 0x63, 0x78, 0x19, 0x56, 0x50, + 0xe4, 0x6a, 0x5e, 0xc5, 0x85, 0xfc, 0xac, 0x89, 0xb9, 0x4d, 0xcd, 0x99, 0xef, 0x3f, 0x6a, 0x08, + 0x32, 0x3c, 0x8c, 0xd7, 0x34, 0xa1, 0xbc, 0xd8, 0xbf, 0x50, 0x3e, 0x9a, 0x2d, 0x90, 0xa3, 0x05, + 0x98, 0xd8, 0x73, 0x7d, 0x96, 0x05, 0xdf, 0x64, 0x45, 0x55, 0x90, 0x8d, 0x35, 0x13, 0x8c, 0xd3, + 0xf8, 0xb3, 0xaf, 0xc1, 0xd8, 0xc3, 0xab, 0x23, 0xbf, 0x59, 0x84, 0xc7, 0xbb, 0x6c, 0x7b, 0x7e, + 0xd6, 0x1b, 0x73, 0xa0, 0x9d, 0xf5, 0x1d, 0xf3, 0x50, 0x83, 0xf3, 0x5b, 0x6d, 0xcf, 0x3b, 0x60, + 0xd6, 0x9b, 0xa4, 0x29, 0x31, 0x04, 0xaf, 0xf8, 0x84, 0x4c, 0xe2, 0xb0, 0x92, 0x81, 0x83, 0x33, + 0x6b, 0xa2, 0x37, 0x00, 0x05, 0x22, 0x65, 0xeb, 0x0d, 0xe2, 0x0b, 0xad, 0x3a, 0x1b, 0xf8, 0x62, + 0xb2, 0x19, 0xef, 0x74, 0x60, 0xe0, 0x8c, 0x5a, 0x94, 0xe9, 0xa7, 0xb7, 0xd2, 0x81, 0xea, 0x56, + 0x8a, 0xe9, 0xc7, 0x3a, 0x10, 0x9b, 0xb8, 0xe8, 0x06, 0x4c, 0x39, 0xfb, 0x8e, 0xcb, 0x83, 0xcf, + 0x49, 0x02, 0x9c, 0xeb, 0x57, 0x4a, 0xb0, 0x85, 0x34, 0x02, 0xee, 0xac, 0x93, 0x72, 0x6b, 0x1e, + 0xcc, 0x77, 0x6b, 0xee, 0x7e, 0x2e, 0xf6, 0xd2, 0xe9, 0xda, 0xff, 0xd1, 0xa2, 0xd7, 0x57, 0x46, + 0xda, 0x75, 0x3a, 0x0e, 0x4a, 0x37, 0xa9, 0x79, 0x18, 0x4f, 0x6b, 0xf6, 0x19, 0x09, 0x10, 0x9b, + 0xb8, 0x7c, 0x41, 0x44, 0x89, 0x8b, 0x8b, 0xc1, 0xba, 0x8b, 0x10, 0x02, 0x0a, 0x03, 0x7d, 0x01, + 0x86, 0x9a, 0xee, 0xbe, 0x1b, 0x05, 0xa1, 0xd8, 0x2c, 0x27, 0x74, 0x14, 0x48, 0xce, 0xc1, 0x2a, + 0x27, 0x83, 0x25, 0x3d, 0xfb, 0x87, 0x0a, 0x30, 0x26, 0x5b, 0x7c, 0xb3, 0x1d, 0xc4, 0xce, 0x19, + 0x5c, 0xcb, 0x37, 0x8c, 0x6b, 0xf9, 0x13, 0xdd, 0xe2, 0x28, 0xb0, 0x2e, 0xe5, 0x5e, 0xc7, 0x77, + 0x52, 0xd7, 0xf1, 0xd3, 0xbd, 0x49, 0x75, 0xbf, 0x86, 0xff, 0x99, 0x05, 0x53, 0x06, 0xfe, 0x19, + 0xdc, 0x06, 0x2b, 0xe6, 0x6d, 0xf0, 0x64, 0xcf, 0x6f, 0xc8, 0xb9, 0x05, 0xbe, 0xaf, 0x98, 0xea, + 0x3b, 0x3b, 0xfd, 0xdf, 0x83, 0xd2, 0x8e, 0x13, 0x36, 0xbb, 0xc5, 0x6b, 0xed, 0xa8, 0x34, 0x77, + 0xd3, 0x09, 0x9b, 0xfc, 0x0c, 0x7f, 0x4e, 0x25, 0x7a, 0x74, 0xc2, 0x66, 0x4f, 0x8f, 0x2e, 0xd6, + 0x14, 0x7a, 0x15, 0x06, 0xa3, 0x46, 0xd0, 0x52, 0xf6, 0x96, 0x57, 0x78, 0x12, 0x48, 0x5a, 0x72, + 0x7c, 0x58, 0x41, 0x66, 0x73, 0xb4, 0x18, 0x0b, 0x7c, 0xf4, 0x36, 0x8c, 0xb1, 0x5f, 0xca, 0xee, + 0xa0, 0x98, 0x9f, 0x25, 0xa0, 0xae, 0x23, 0x72, 0xf3, 0x15, 0xa3, 0x08, 0x9b, 0xa4, 0x66, 0xb7, + 0xa1, 0xac, 0x3e, 0xeb, 0x91, 0x7a, 0xe2, 0xfc, 0xbb, 0x22, 0x9c, 0xcb, 0x58, 0x73, 0x28, 0x32, + 0x66, 0xe2, 0x85, 0x3e, 0x97, 0xea, 0x07, 0x9c, 0x8b, 0x88, 0x49, 0x43, 0x4d, 0xb1, 0xb6, 0xfa, + 0x6e, 0xf4, 0x6e, 0x44, 0xd2, 0x8d, 0xd2, 0xa2, 0xde, 0x8d, 0xd2, 0xc6, 0xce, 0x6c, 0xa8, 0x69, + 0x43, 0xaa, 0xa7, 0x8f, 0x74, 0x4e, 0xff, 0xb8, 0x08, 0xe7, 0xb3, 0x42, 0xbb, 0xa0, 0xef, 0x4e, + 0x65, 0x83, 0x79, 0xa9, 0xdf, 0xa0, 0x30, 0x3c, 0x45, 0x8c, 0xc8, 0x6d, 0x3c, 0x67, 0xe6, 0x87, + 0xe9, 0x39, 0xcc, 0xa2, 0x4d, 0xe6, 0xbe, 0x19, 0xf2, 0x2c, 0x3e, 0xf2, 0xf8, 0xf8, 0x74, 0xdf, + 0x1d, 0x10, 0xe9, 0x7f, 0xa2, 0x94, 0xfb, 0xa6, 0x2c, 0xee, 0xed, 0xbe, 0x29, 0x5b, 0x9e, 0x75, + 0x61, 0x44, 0xfb, 0x9a, 0x47, 0x3a, 0xe3, 0xbb, 0xf4, 0xb6, 0xd2, 0xfa, 0xfd, 0x48, 0x67, 0xfd, + 0xc7, 0x2d, 0x48, 0x19, 0x37, 0x2a, 0x75, 0x97, 0x95, 0xab, 0xee, 0xba, 0x02, 0xa5, 0x30, 0xf0, + 0x48, 0x3a, 0x41, 0x0b, 0x0e, 0x3c, 0x82, 0x19, 0x84, 0x62, 0xc4, 0x89, 0xb2, 0x63, 0x54, 0x17, + 0xe4, 0x84, 0x88, 0xf6, 0x14, 0x0c, 0x78, 0x64, 0x9f, 0x78, 0xe9, 0xe8, 0xe7, 0xb7, 0x69, 0x21, + 0xe6, 0x30, 0xfb, 0x97, 0x4b, 0x70, 0xa9, 0xab, 0x03, 0x34, 0x15, 0x87, 0xb6, 0x9d, 0x98, 0xdc, + 0x77, 0x0e, 0xd2, 0x61, 0x8a, 0x6f, 0xf0, 0x62, 0x2c, 0xe1, 0xcc, 0xde, 0x9b, 0x87, 0x25, 0x4c, + 0x29, 0x07, 0x45, 0x34, 0x42, 0x01, 0x7d, 0x04, 0x79, 0xdd, 0xaf, 0x03, 0x44, 0x91, 0xb7, 0xec, + 0x53, 0xee, 0xae, 0x29, 0x0c, 0xc9, 0x93, 0xf0, 0x95, 0xf5, 0xdb, 0x02, 0x82, 0x35, 0x2c, 0x54, + 0x85, 0xc9, 0x56, 0x18, 0xc4, 0x5c, 0xd7, 0x5a, 0xe5, 0x66, 0x3e, 0x03, 0xa6, 0xef, 0x69, 0x2d, + 0x05, 0xc7, 0x1d, 0x35, 0xd0, 0xcb, 0x30, 0x22, 0xfc, 0x51, 0x6b, 0x41, 0xe0, 0x09, 0x35, 0x90, + 0x32, 0x1a, 0xa9, 0x27, 0x20, 0xac, 0xe3, 0x69, 0xd5, 0x98, 0x02, 0x77, 0x28, 0xb3, 0x1a, 0x57, + 0xe2, 0x6a, 0x78, 0xa9, 0x30, 0x4f, 0xc3, 0x7d, 0x85, 0x79, 0x4a, 0x14, 0x63, 0xe5, 0xbe, 0xdf, + 0xac, 0xa0, 0xa7, 0x2a, 0xe9, 0x17, 0x4a, 0x70, 0x4e, 0x2c, 0x9c, 0x47, 0xbd, 0x5c, 0x1e, 0x51, + 0xf6, 0xf9, 0x6f, 0xad, 0x99, 0xb3, 0x5e, 0x33, 0x3f, 0x6c, 0x81, 0xc9, 0x5e, 0xa1, 0xff, 0x2f, + 0x37, 0xce, 0xfb, 0xcb, 0xb9, 0xec, 0x5a, 0x53, 0x5e, 0x20, 0x1f, 0x30, 0xe2, 0xbb, 0xfd, 0x1f, + 0x2c, 0x78, 0xb2, 0x27, 0x45, 0xb4, 0x0c, 0x65, 0xc6, 0x03, 0x6a, 0xd2, 0xd9, 0xd3, 0xca, 0x0c, + 0x50, 0x02, 0x72, 0x58, 0xd2, 0xa4, 0x26, 0x5a, 0xee, 0x08, 0xa8, 0xff, 0x4c, 0x46, 0x40, 0xfd, + 0x69, 0x63, 0x78, 0x1e, 0x32, 0xa2, 0xfe, 0xd7, 0x8a, 0x30, 0xc8, 0x57, 0xfc, 0x19, 0x88, 0x61, + 0x2b, 0x42, 0x6f, 0xdb, 0x25, 0x8e, 0x14, 0xef, 0xcb, 0x5c, 0xd5, 0x89, 0x1d, 0xce, 0x26, 0xa8, + 0xdb, 0x2a, 0xd1, 0xf0, 0xa2, 0x39, 0xe3, 0x3e, 0x9b, 0x4d, 0x29, 0x26, 0x81, 0xd3, 0xd0, 0x6e, + 0xb7, 0x2f, 0x01, 0x44, 0x2c, 0xd1, 0x3c, 0xa5, 0x21, 0x22, 0x92, 0x7d, 0xb2, 0x4b, 0xeb, 0x75, + 0x85, 0xcc, 0xfb, 0x90, 0xec, 0x74, 0x05, 0xc0, 0x1a, 0xc5, 0xd9, 0x57, 0xa0, 0xac, 0x90, 0x7b, + 0x69, 0x71, 0x46, 0x75, 0xe6, 0xe2, 0x73, 0x30, 0x91, 0x6a, 0xeb, 0x44, 0x4a, 0xa0, 0x5f, 0xb1, + 0x60, 0x82, 0x77, 0x79, 0xd9, 0xdf, 0x17, 0x67, 0xea, 0xfb, 0x70, 0xde, 0xcb, 0x38, 0xdb, 0xc4, + 0x8c, 0xf6, 0x7f, 0x16, 0x2a, 0xa5, 0x4f, 0x16, 0x14, 0x67, 0xb6, 0x81, 0xae, 0xd1, 0x75, 0x4b, + 0xcf, 0x2e, 0xc7, 0x13, 0xbe, 0x43, 0xa3, 0x7c, 0xcd, 0xf2, 0x32, 0xac, 0xa0, 0xf6, 0xef, 0x58, + 0x30, 0xc5, 0x7b, 0x7e, 0x8b, 0x1c, 0xa8, 0x1d, 0xfe, 0x61, 0xf6, 0x5d, 0xe4, 0xb8, 0x28, 0xe4, + 0xe4, 0xb8, 0xd0, 0x3f, 0xad, 0xd8, 0xf5, 0xd3, 0x7e, 0xde, 0x02, 0xb1, 0x02, 0xcf, 0x40, 0x94, + 0xff, 0x76, 0x53, 0x94, 0x9f, 0xcd, 0x5f, 0xd4, 0x39, 0x32, 0xfc, 0x9f, 0x5a, 0x30, 0xc9, 0x11, + 0x92, 0xb7, 0xe4, 0x0f, 0x75, 0x1e, 0xfa, 0x49, 0x56, 0xa7, 0xb2, 0x53, 0x67, 0x7f, 0x94, 0x31, + 0x59, 0xa5, 0xae, 0x93, 0xd5, 0x94, 0x1b, 0xe8, 0x04, 0x49, 0x18, 0x4f, 0x1c, 0x2b, 0xda, 0xfe, + 0x23, 0x0b, 0x10, 0x6f, 0xc6, 0x60, 0x7f, 0x28, 0x53, 0xc1, 0x4a, 0xb5, 0xeb, 0x22, 0x39, 0x6a, + 0x14, 0x04, 0x6b, 0x58, 0xa7, 0x32, 0x3c, 0x29, 0x83, 0x80, 0x62, 0x6f, 0x83, 0x80, 0x13, 0x8c, + 0xe8, 0xd7, 0x4a, 0x90, 0x36, 0xe6, 0x47, 0xf7, 0x60, 0xb4, 0xe1, 0xb4, 0x9c, 0x4d, 0xd7, 0x73, + 0x63, 0x97, 0x44, 0xdd, 0x2c, 0x89, 0x96, 0x34, 0x3c, 0xf1, 0xd4, 0xab, 0x95, 0x60, 0x83, 0x0e, + 0x9a, 0x03, 0x68, 0x85, 0xee, 0xbe, 0xeb, 0x91, 0x6d, 0xa6, 0x71, 0x60, 0xde, 0x8a, 0xdc, 0x3c, + 0x46, 0x96, 0x62, 0x0d, 0x23, 0xc3, 0xf1, 0xac, 0xf8, 0xe8, 0x1c, 0xcf, 0x4a, 0x27, 0x74, 0x3c, + 0x1b, 0xe8, 0xcb, 0xf1, 0x0c, 0xc3, 0x05, 0xc9, 0x22, 0xd1, 0xff, 0x2b, 0xae, 0x47, 0x04, 0x5f, + 0xcc, 0x7d, 0x18, 0x67, 0x8f, 0x0e, 0x2b, 0x17, 0x70, 0x26, 0x06, 0xce, 0xa9, 0x89, 0x3e, 0x0f, + 0x33, 0x8e, 0xe7, 0x05, 0xf7, 0xd5, 0xa8, 0x2d, 0x47, 0x0d, 0xc7, 0xe3, 0x1a, 0xfb, 0x21, 0x46, + 0xf5, 0x89, 0xa3, 0xc3, 0xca, 0xcc, 0x42, 0x0e, 0x0e, 0xce, 0xad, 0x9d, 0xf2, 0x5b, 0x1b, 0xee, + 0xe5, 0xb7, 0x66, 0xef, 0xc2, 0xb9, 0x3a, 0x09, 0x5d, 0x96, 0x22, 0xb2, 0x99, 0x6c, 0xc9, 0x0d, + 0x28, 0x87, 0xa9, 0x43, 0xa8, 0xaf, 0xc0, 0x46, 0x5a, 0x18, 0x5c, 0x79, 0xe8, 0x24, 0x84, 0xec, + 0x3f, 0xb1, 0x60, 0x48, 0x38, 0x14, 0x9c, 0x01, 0xef, 0xb3, 0x60, 0xa8, 0xa0, 0x2b, 0xd9, 0x07, + 0x35, 0xeb, 0x4c, 0xae, 0xf2, 0x79, 0x35, 0xa5, 0x7c, 0x7e, 0xb2, 0x1b, 0x91, 0xee, 0x6a, 0xe7, + 0xbf, 0x55, 0x84, 0x71, 0xd3, 0x99, 0xe2, 0x0c, 0x86, 0x60, 0x1d, 0x86, 0x22, 0xe1, 0xb9, 0x53, + 0xc8, 0xb7, 0x7d, 0x4e, 0x4f, 0x62, 0x62, 0xd8, 0x24, 0x7c, 0x75, 0x24, 0x91, 0x4c, 0x97, 0xa0, + 0xe2, 0x23, 0x74, 0x09, 0xea, 0xe5, 0xcf, 0x52, 0x3a, 0x0d, 0x7f, 0x16, 0xfb, 0xeb, 0xec, 0xb2, + 0xd0, 0xcb, 0xcf, 0x80, 0x8f, 0xb8, 0x61, 0x5e, 0x2b, 0x76, 0x97, 0x95, 0x25, 0x3a, 0x95, 0xc3, + 0x4f, 0xfc, 0x92, 0x05, 0x97, 0x32, 0xbe, 0x4a, 0x63, 0x2e, 0x9e, 0x83, 0x61, 0xa7, 0xdd, 0x74, + 0xd5, 0x5e, 0xd6, 0x1e, 0xa2, 0x16, 0x44, 0x39, 0x56, 0x18, 0x68, 0x09, 0xa6, 0xc8, 0x83, 0x96, + 0xcb, 0x5f, 0x02, 0x75, 0xeb, 0xc3, 0x22, 0x0f, 0xf1, 0xba, 0x9c, 0x06, 0xe2, 0x4e, 0x7c, 0xe5, + 0x0e, 0x5d, 0xcc, 0x75, 0x87, 0xfe, 0x87, 0x16, 0x8c, 0x88, 0x6e, 0x9f, 0xc1, 0x68, 0x7f, 0x87, + 0x39, 0xda, 0x8f, 0x77, 0x19, 0xed, 0x9c, 0x61, 0xfe, 0x3b, 0x05, 0xd5, 0xdf, 0x5a, 0x10, 0xc6, + 0x7d, 0x30, 0x2d, 0xaf, 0xc2, 0x70, 0x2b, 0x0c, 0xe2, 0xa0, 0x11, 0x78, 0x82, 0x67, 0x79, 0x22, + 0xf1, 0xd6, 0xe7, 0xe5, 0xc7, 0xda, 0x6f, 0xac, 0xb0, 0xd9, 0xe8, 0x05, 0x61, 0x2c, 0xf8, 0x84, + 0x64, 0xf4, 0x82, 0x30, 0xc6, 0x0c, 0x82, 0x9a, 0x00, 0xb1, 0x13, 0x6e, 0x93, 0x98, 0x96, 0x89, + 0xc0, 0x1f, 0xf9, 0x87, 0x47, 0x3b, 0x76, 0xbd, 0x39, 0xd7, 0x8f, 0xa3, 0x38, 0x9c, 0x5b, 0xf5, + 0xe3, 0x3b, 0x21, 0x17, 0x81, 0x34, 0xf7, 0x7b, 0x45, 0x0b, 0x6b, 0x74, 0xa5, 0x8f, 0x24, 0x6b, + 0x63, 0xc0, 0x7c, 0xd2, 0x5e, 0x17, 0xe5, 0x58, 0x61, 0xd8, 0xaf, 0xb0, 0xab, 0x84, 0x0d, 0xd0, + 0xc9, 0x3c, 0xe3, 0xbf, 0x31, 0xac, 0x86, 0x96, 0xbd, 0x67, 0x55, 0x75, 0xff, 0xfb, 0xee, 0x27, + 0x37, 0x6d, 0x58, 0xf7, 0x84, 0x49, 0x9c, 0xf4, 0xd1, 0x77, 0x76, 0x58, 0x3a, 0x3c, 0xdf, 0xe3, + 0x0a, 0x38, 0x81, 0x6d, 0x03, 0x0b, 0x3b, 0xcd, 0xc2, 0xf3, 0xae, 0xd6, 0xc4, 0x22, 0xd7, 0xc2, + 0x4e, 0x0b, 0x00, 0x4e, 0x70, 0xd0, 0xbc, 0x10, 0xa0, 0x4b, 0x46, 0x76, 0x38, 0x29, 0x40, 0xcb, + 0xcf, 0xd7, 0x24, 0xe8, 0x17, 0x60, 0x44, 0x65, 0x89, 0xab, 0xf1, 0x64, 0x5b, 0x22, 0x0c, 0xca, + 0x72, 0x52, 0x8c, 0x75, 0x1c, 0xb4, 0x01, 0x13, 0x11, 0xd7, 0x9e, 0xa8, 0x68, 0x77, 0x5c, 0x0b, + 0xf5, 0x49, 0x69, 0x21, 0x51, 0x37, 0xc1, 0xc7, 0xac, 0x88, 0x1f, 0x1d, 0xd2, 0xd1, 0x31, 0x4d, + 0x02, 0xbd, 0x0e, 0xe3, 0x9e, 0x9e, 0x6b, 0xbd, 0x26, 0x94, 0x54, 0xca, 0x80, 0xd8, 0xc8, 0xc4, + 0x5e, 0xc3, 0x29, 0x6c, 0xca, 0xeb, 0xe8, 0x25, 0x22, 0x42, 0xa3, 0xe3, 0x6f, 0x93, 0x48, 0xe4, + 0xb8, 0x62, 0xbc, 0xce, 0xed, 0x1c, 0x1c, 0x9c, 0x5b, 0x1b, 0xbd, 0x0a, 0xa3, 0xf2, 0xf3, 0x35, + 0x37, 0xde, 0xc4, 0x4c, 0x5d, 0x83, 0x61, 0x03, 0x13, 0xdd, 0x87, 0x69, 0xf9, 0x7f, 0x23, 0x74, + 0xb6, 0xb6, 0xdc, 0x86, 0xf0, 0xa2, 0xe6, 0xbe, 0x3a, 0x0b, 0xd2, 0xf9, 0x67, 0x39, 0x0b, 0xe9, + 0xf8, 0xb0, 0x72, 0x45, 0x8c, 0x5a, 0x26, 0x9c, 0x4d, 0x62, 0x36, 0x7d, 0xb4, 0x06, 0xe7, 0x76, + 0x88, 0xe3, 0xc5, 0x3b, 0x4b, 0x3b, 0xa4, 0xb1, 0x2b, 0x37, 0x11, 0x73, 0x0e, 0xd6, 0x8c, 0xbb, + 0x6f, 0x76, 0xa2, 0xe0, 0xac, 0x7a, 0xe8, 0x1d, 0x98, 0x69, 0xb5, 0x37, 0x3d, 0x37, 0xda, 0x59, + 0x0f, 0x62, 0x66, 0x94, 0xa1, 0x92, 0xac, 0x09, 0x2f, 0x62, 0xe5, 0x18, 0x5d, 0xcb, 0xc1, 0xc3, + 0xb9, 0x14, 0xd0, 0xfb, 0x30, 0x9d, 0x5a, 0x0c, 0xc2, 0xa7, 0x71, 0x3c, 0x3f, 0xde, 0x6d, 0x3d, + 0xab, 0x82, 0xf0, 0x51, 0xcc, 0x02, 0xe1, 0xec, 0x26, 0x3e, 0x98, 0xa9, 0xce, 0x7b, 0xb4, 0xb2, + 0xc6, 0x94, 0xa1, 0x2f, 0xc3, 0xa8, 0xbe, 0x8a, 0xc4, 0x05, 0x73, 0x35, 0x9b, 0x67, 0xd1, 0x56, + 0x1b, 0x67, 0xe9, 0xd4, 0x8a, 0xd2, 0x61, 0xd8, 0xa0, 0x68, 0x13, 0xc8, 0xfe, 0x3e, 0x74, 0x1b, + 0x86, 0x1b, 0x9e, 0x4b, 0xfc, 0x78, 0xb5, 0xd6, 0x2d, 0xe8, 0xc6, 0x92, 0xc0, 0x11, 0x03, 0x26, + 0x02, 0x84, 0xf2, 0x32, 0xac, 0x28, 0xd8, 0xbf, 0x51, 0x80, 0x4a, 0x8f, 0x68, 0xb3, 0x29, 0x8d, + 0xb2, 0xd5, 0x97, 0x46, 0x79, 0x41, 0xa6, 0x8c, 0x5b, 0x4f, 0x89, 0xd9, 0xa9, 0x74, 0x70, 0x89, + 0xb0, 0x9d, 0xc6, 0xef, 0xdb, 0xc2, 0x57, 0x57, 0x4a, 0x97, 0x7a, 0xda, 0x9e, 0x1b, 0x8f, 0x51, + 0x03, 0xfd, 0x0b, 0x22, 0xb9, 0x0f, 0x0b, 0xf6, 0xd7, 0x0b, 0x30, 0xad, 0x86, 0xf0, 0x2f, 0xee, + 0xc0, 0xdd, 0xed, 0x1c, 0xb8, 0x53, 0x78, 0x96, 0xb1, 0xef, 0xc0, 0x20, 0x0f, 0x5a, 0xd2, 0x07, + 0x03, 0xf4, 0x94, 0x19, 0xe1, 0x4a, 0x5d, 0xd3, 0x46, 0x94, 0xab, 0xbf, 0x62, 0xc1, 0xc4, 0xc6, + 0x52, 0xad, 0x1e, 0x34, 0x76, 0x49, 0xbc, 0xc0, 0x19, 0x56, 0x2c, 0xf8, 0x1f, 0xeb, 0x21, 0xf9, + 0x9a, 0x2c, 0x8e, 0xe9, 0x0a, 0x94, 0x76, 0x82, 0x28, 0x4e, 0xbf, 0xd9, 0xde, 0x0c, 0xa2, 0x18, + 0x33, 0x88, 0xfd, 0xbb, 0x16, 0x0c, 0xb0, 0x44, 0xa7, 0xbd, 0xb2, 0xef, 0xf6, 0xf3, 0x5d, 0xe8, + 0x65, 0x18, 0x24, 0x5b, 0x5b, 0xa4, 0x11, 0x8b, 0x59, 0x95, 0x0e, 0xa5, 0x83, 0xcb, 0xac, 0x94, + 0x5e, 0xfa, 0xac, 0x31, 0xfe, 0x17, 0x0b, 0x64, 0xf4, 0x16, 0x94, 0x63, 0x77, 0x8f, 0x2c, 0x34, + 0x9b, 0xe2, 0xd5, 0xeb, 0x21, 0xfc, 0x77, 0x37, 0x24, 0x01, 0x9c, 0xd0, 0xb2, 0xbf, 0x5a, 0x00, + 0x48, 0x5c, 0xef, 0x7b, 0x7d, 0xe2, 0x62, 0xc7, 0x7b, 0xc8, 0xd5, 0x8c, 0xf7, 0x10, 0x94, 0x10, + 0xcc, 0x78, 0x0c, 0x51, 0xc3, 0x54, 0xec, 0x6b, 0x98, 0x4a, 0x27, 0x19, 0xa6, 0x25, 0x98, 0x4a, + 0x42, 0x07, 0x98, 0x71, 0x54, 0x98, 0x90, 0xb2, 0x91, 0x06, 0xe2, 0x4e, 0x7c, 0x9b, 0xc0, 0x15, + 0x19, 0xd1, 0x52, 0xde, 0x35, 0xcc, 0xa8, 0xf2, 0x04, 0x89, 0x98, 0x93, 0x07, 0x9f, 0x42, 0xee, + 0x83, 0xcf, 0x4f, 0x59, 0x70, 0x3e, 0xdd, 0x0e, 0xf3, 0x5e, 0xfb, 0x01, 0x0b, 0xa6, 0xd9, 0xb3, + 0x17, 0x6b, 0xb5, 0xf3, 0x91, 0xed, 0xa5, 0xec, 0x90, 0x0a, 0xdd, 0x7b, 0x9c, 0x78, 0x2e, 0xaf, + 0x65, 0x91, 0xc6, 0xd9, 0x2d, 0xda, 0xdf, 0x6f, 0x81, 0x70, 0x12, 0xea, 0x63, 0x63, 0xbf, 0x2d, + 0x53, 0x95, 0x1a, 0x01, 0xbc, 0xaf, 0xe4, 0x7b, 0x4d, 0x89, 0xb0, 0xdd, 0xea, 0x22, 0x35, 0x82, + 0x75, 0x1b, 0xb4, 0xec, 0x26, 0x08, 0x68, 0x95, 0x30, 0x3d, 0x51, 0xef, 0xde, 0x5c, 0x07, 0x68, + 0x32, 0x5c, 0x2d, 0x61, 0xa1, 0x3a, 0xb6, 0xab, 0x0a, 0x82, 0x35, 0x2c, 0xfb, 0x47, 0x0a, 0x30, + 0x22, 0x03, 0x46, 0xb7, 0xfd, 0x7e, 0xa4, 0xb9, 0x13, 0xe5, 0x8d, 0x61, 0x19, 0x3e, 0x29, 0xe1, + 0x5a, 0x22, 0x04, 0x27, 0x19, 0x3e, 0x25, 0x00, 0x27, 0x38, 0xe8, 0x19, 0x18, 0x8a, 0xda, 0x9b, + 0x0c, 0x3d, 0xe5, 0xfa, 0x52, 0xe7, 0xc5, 0x58, 0xc2, 0xd1, 0xe7, 0x61, 0x92, 0xd7, 0x0b, 0x83, + 0x96, 0xb3, 0xcd, 0x95, 0x86, 0x03, 0xca, 0x17, 0x75, 0x72, 0x2d, 0x05, 0x3b, 0x3e, 0xac, 0x9c, + 0x4f, 0x97, 0x31, 0x75, 0x73, 0x07, 0x15, 0xfb, 0xcb, 0x80, 0x3a, 0x63, 0x60, 0xa3, 0x37, 0xb8, + 0x01, 0x92, 0x1b, 0x92, 0x66, 0x37, 0x3d, 0xb2, 0xee, 0x3a, 0x29, 0xcd, 0xcf, 0x79, 0x2d, 0xac, + 0xea, 0xdb, 0x7f, 0xad, 0x08, 0x93, 0x69, 0x47, 0x3a, 0x74, 0x13, 0x06, 0xf9, 0x05, 0x23, 0xc8, + 0x77, 0x79, 0xa6, 0xd4, 0xdc, 0xef, 0xd8, 0x56, 0x13, 0x77, 0x94, 0xa8, 0x8f, 0xde, 0x81, 0x91, + 0x66, 0x70, 0xdf, 0xbf, 0xef, 0x84, 0xcd, 0x85, 0xda, 0xaa, 0x58, 0x97, 0x99, 0x7c, 0x6a, 0x35, + 0x41, 0xd3, 0x5d, 0xfa, 0x98, 0x4a, 0x3e, 0x01, 0x61, 0x9d, 0x1c, 0xda, 0x60, 0x71, 0xfd, 0xb6, + 0xdc, 0xed, 0x35, 0xa7, 0xd5, 0xcd, 0x1a, 0x75, 0x49, 0x22, 0x69, 0x94, 0xc7, 0x44, 0xf0, 0x3f, + 0x0e, 0xc0, 0x09, 0x21, 0xf4, 0xdd, 0x70, 0x2e, 0xca, 0x51, 0x6d, 0xe5, 0xa5, 0x44, 0xe8, 0xa6, + 0xed, 0x59, 0x7c, 0x8c, 0x4a, 0x10, 0x59, 0x4a, 0xb0, 0xac, 0x66, 0xec, 0xaf, 0x9c, 0x03, 0x63, + 0x37, 0x1a, 0x79, 0x71, 0xac, 0x53, 0xca, 0x8b, 0x83, 0x61, 0x98, 0xec, 0xb5, 0xe2, 0x83, 0xaa, + 0x1b, 0x76, 0x4b, 0xac, 0xb6, 0x2c, 0x70, 0x3a, 0x69, 0x4a, 0x08, 0x56, 0x74, 0xb2, 0x93, 0x17, + 0x15, 0x3f, 0xc4, 0xe4, 0x45, 0xa5, 0x33, 0x4c, 0x5e, 0xb4, 0x0e, 0x43, 0xdb, 0x6e, 0x8c, 0x49, + 0x2b, 0x10, 0xac, 0x5d, 0xe6, 0x3a, 0xbc, 0xc1, 0x51, 0x3a, 0x13, 0x66, 0x08, 0x00, 0x96, 0x44, + 0xd0, 0x1b, 0x6a, 0x07, 0x0e, 0xe6, 0x4b, 0x46, 0x9d, 0xef, 0x69, 0x99, 0x7b, 0x50, 0x24, 0x2b, + 0x1a, 0x7a, 0xd8, 0x64, 0x45, 0x2b, 0x32, 0xc5, 0xd0, 0x70, 0xbe, 0xe9, 0x38, 0xcb, 0x20, 0xd4, + 0x23, 0xb1, 0x90, 0x91, 0x8c, 0xa9, 0x7c, 0x7a, 0xc9, 0x98, 0xbe, 0xdf, 0x82, 0xe9, 0x56, 0x56, + 0x5e, 0x32, 0x91, 0x18, 0xe8, 0xe5, 0xbe, 0x13, 0xaf, 0x19, 0x0d, 0x32, 0x11, 0x39, 0x13, 0x0d, + 0x67, 0x37, 0x47, 0x07, 0x3a, 0xdc, 0x6c, 0x8a, 0x6c, 0x42, 0x4f, 0xe5, 0x64, 0x75, 0xea, 0x92, + 0xcb, 0x69, 0x23, 0x23, 0x83, 0xd0, 0xc7, 0xf3, 0x32, 0x08, 0xf5, 0x9d, 0x37, 0xe8, 0x0d, 0x95, + 0xcf, 0x69, 0x2c, 0x7f, 0x29, 0xf1, 0x6c, 0x4d, 0x3d, 0xb3, 0x38, 0xbd, 0xa1, 0xb2, 0x38, 0x75, + 0x89, 0x6f, 0xc6, 0x73, 0x34, 0xf5, 0xcc, 0xdd, 0xa4, 0xe5, 0x5f, 0x9a, 0x38, 0x9d, 0xfc, 0x4b, + 0xc6, 0x55, 0xc3, 0x53, 0x00, 0x3d, 0xdb, 0xe3, 0xaa, 0x31, 0xe8, 0x76, 0xbf, 0x6c, 0x78, 0xae, + 0xa9, 0xa9, 0x87, 0xca, 0x35, 0x75, 0x4f, 0xcf, 0xdd, 0x84, 0x7a, 0x24, 0x27, 0xa2, 0x48, 0x7d, + 0x66, 0x6c, 0xba, 0xa7, 0x5f, 0x80, 0xe7, 0xf2, 0xe9, 0xaa, 0x7b, 0xae, 0x93, 0x6e, 0xe6, 0x15, + 0xd8, 0x91, 0x09, 0xea, 0xfc, 0xd9, 0x64, 0x82, 0x9a, 0x3e, 0xf5, 0x4c, 0x50, 0x17, 0xce, 0x20, + 0x13, 0xd4, 0x63, 0x1f, 0x6a, 0x26, 0xa8, 0x99, 0x47, 0x90, 0x09, 0x6a, 0x3d, 0xc9, 0x04, 0x75, + 0x31, 0x7f, 0x4a, 0x32, 0xec, 0x59, 0x73, 0xf2, 0x3f, 0xdd, 0x83, 0x72, 0x4b, 0x46, 0x7a, 0x10, + 0x01, 0xd8, 0xb2, 0x93, 0xd1, 0x66, 0x85, 0x83, 0xe0, 0x53, 0xa2, 0x40, 0x38, 0x21, 0x45, 0xe9, + 0x26, 0xf9, 0xa0, 0x1e, 0xef, 0xa2, 0x04, 0xcd, 0x52, 0x2f, 0xe5, 0x67, 0x81, 0xb2, 0xff, 0x6a, + 0x01, 0x2e, 0x77, 0x5f, 0xd7, 0x89, 0x6e, 0xaa, 0x96, 0xbc, 0xa5, 0xa4, 0x74, 0x53, 0x5c, 0xc8, + 0x49, 0xb0, 0xfa, 0x0e, 0x87, 0x73, 0x03, 0xa6, 0x94, 0x21, 0xab, 0xe7, 0x36, 0x0e, 0xb4, 0x24, + 0xb5, 0xca, 0x61, 0xaf, 0x9e, 0x46, 0xc0, 0x9d, 0x75, 0xd0, 0x02, 0x4c, 0x18, 0x85, 0xab, 0x55, + 0x21, 0xcc, 0x28, 0x65, 0x58, 0xdd, 0x04, 0xe3, 0x34, 0xbe, 0xfd, 0x73, 0x16, 0x3c, 0x96, 0x93, + 0x24, 0xa1, 0xef, 0x68, 0x2f, 0x5b, 0x30, 0xd1, 0x32, 0xab, 0xf6, 0x08, 0x0a, 0x65, 0xa4, 0x62, + 0x50, 0x7d, 0x4d, 0x01, 0x70, 0x9a, 0xe8, 0xe2, 0xb5, 0xdf, 0xfa, 0xfd, 0xcb, 0x1f, 0xfb, 0xed, + 0xdf, 0xbf, 0xfc, 0xb1, 0xdf, 0xf9, 0xfd, 0xcb, 0x1f, 0xfb, 0xff, 0x8f, 0x2e, 0x5b, 0xbf, 0x75, + 0x74, 0xd9, 0xfa, 0xed, 0xa3, 0xcb, 0xd6, 0xef, 0x1c, 0x5d, 0xb6, 0x7e, 0xef, 0xe8, 0xb2, 0xf5, + 0xd5, 0x3f, 0xb8, 0xfc, 0xb1, 0xb7, 0x0b, 0xfb, 0x2f, 0xfc, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x67, 0xe8, 0x47, 0xf4, 0xcd, 0xe5, 0x00, 0x00, } diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index a92d7392c6e..b4d75069f7e 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -298,6 +298,34 @@ message CephFSVolumeSource { optional bool readOnly = 6; } +// Represents a cinder volume resource in Openstack. +// A Cinder volume must exist before mounting to a container. +// The volume must also be in the same region as the kubelet. +// Cinder volumes support ownership management and SELinux relabeling. +message CinderPersistentVolumeSource { + // volume id used to identify the volume in cinder + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + optional string volumeID = 1; + + // Filesystem type to mount. + // Must be a filesystem type supported by the host operating system. + // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + optional string fsType = 2; + + // Optional: Defaults to false (read/write). ReadOnly here will force + // the ReadOnly setting in VolumeMounts. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + optional bool readOnly = 3; + + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + optional SecretReference secretRef = 4; +} + // Represents a cinder volume resource in Openstack. // A Cinder volume must exist before mounting to a container. // The volume must also be in the same region as the kubelet. @@ -319,6 +347,11 @@ message CinderVolumeSource { // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional optional bool readOnly = 3; + + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + optional LocalObjectReference secretRef = 4; } // ClientIPConfig represents the configurations of Client IP based session affinity. @@ -1318,6 +1351,10 @@ message GCEPersistentDiskVolumeSource { // Represents a volume that is populated with the contents of a git repository. // Git repo volumes do not support ownership management. // Git repo volumes support SELinux relabeling. +// +// DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an +// EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir +// into the Pod's container. message GitRepoVolumeSource { // Repository URL optional string repository = 1; @@ -1955,6 +1992,7 @@ message NodeSelectorRequirement { // A null or empty node selector term matches no objects. The requirements of // them are ANDed. +// The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. message NodeSelectorTerm { // A list of node selector requirements by node's labels. // +optional @@ -2354,7 +2392,7 @@ message PersistentVolumeSource { // Cinder represents a cinder volume attached and mounted on kubelets host machine // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional - optional CinderVolumeSource cinder = 8; + optional CinderPersistentVolumeSource cinder = 8; // CephFS represents a Ceph FS mount on the host that shares a pod's lifetime // +optional @@ -2627,7 +2665,6 @@ message PodAttachOptions { // PodCondition contains details for the current condition of this pod. message PodCondition { // Type is the type of the condition. - // Currently only Ready. // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions optional string type = 1; @@ -2796,6 +2833,12 @@ message PodProxyOptions { optional string path = 1; } +// PodReadinessGate contains the reference to a pod condition +message PodReadinessGate { + // ConditionType refers to a condition in the pod's condition list with matching type. + optional string conditionType = 1; +} + // PodSecurityContext holds pod-level security attributes and common container settings. // Some fields are also present in container.securityContext. Field values of // container.securityContext take precedence over field values of PodSecurityContext. @@ -2850,6 +2893,11 @@ message PodSecurityContext { // If unset, the Kubelet will not modify the ownership and permissions of any volume. // +optional optional int64 fsGroup = 5; + + // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + // sysctls (by the container runtime) might fail to launch. + // +optional + repeated Sysctl sysctls = 7; } // Describes the class of pods that should avoid this node. @@ -3048,12 +3096,36 @@ message PodSpec { // configuration based on DNSPolicy. // +optional optional PodDNSConfig dnsConfig = 26; + + // If specified, all readiness gates will be evaluated for pod readiness. + // A pod is ready when all its containers are ready AND + // all conditions specified in the readiness gates have status equal to "True" + // More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md + // +optional + repeated PodReadinessGate readinessGates = 28; } // PodStatus represents information about the status of a pod. Status may trail the actual -// state of a system. +// state of a system, especially if the node that hosts the pod cannot contact the control +// plane. message PodStatus { - // Current condition of the pod. + // The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. + // The conditions array, the reason and message fields, and the individual container status + // arrays contain more detail about the pod's status. + // There are five possible phase values: + // + // Pending: The pod has been accepted by the Kubernetes system, but one or more of the + // container images has not been created. This includes time before being scheduled as + // well as time spent downloading images over the network, which could take a while. + // Running: The pod has been bound to a node, and all of the containers have been created. + // At least one container is still running, or is in the process of starting or restarting. + // Succeeded: All containers in the pod have terminated in success, and will not be restarted. + // Failed: All containers in the pod have terminated, and at least one container has + // terminated in failure. The container either exited with non-zero status or was terminated + // by the system. + // Unknown: For some reason the state of the pod could not be obtained, typically due to an + // error in communicating with the host of the pod. + // // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase // +optional optional string phase = 1; @@ -3573,7 +3645,7 @@ message ResourceQuotaList { // ResourceQuotaSpec defines the desired hard limits to enforce for Quota. message ResourceQuotaSpec { - // Hard is the set of desired hard limits for each named resource. + // hard is the set of desired hard limits for each named resource. // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/ // +optional map hard = 1; @@ -3582,6 +3654,12 @@ message ResourceQuotaSpec { // If not specified, the quota matches all objects. // +optional repeated string scopes = 2; + + // scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota + // but expressed using ScopeSelectorOperator in combination with possible values. + // For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched. + // +optional + optional ScopeSelector scopeSelector = 3; } // ResourceQuotaStatus defines the enforced hard limits and observed use. @@ -3718,6 +3796,32 @@ message ScaleIOVolumeSource { optional bool readOnly = 10; } +// A scope selector represents the AND of the selectors represented +// by the scoped-resource selector requirements. +message ScopeSelector { + // A list of scope selector requirements by scope of the resources. + // +optional + repeated ScopedResourceSelectorRequirement matchExpressions = 1; +} + +// A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator +// that relates the scope name and values. +message ScopedResourceSelectorRequirement { + // The name of the scope that the selector applies to. + optional string scopeName = 1; + + // Represents a scope's relationship to a set of values. + // Valid operators are In, NotIn, Exists, DoesNotExist. + optional string operator = 2; + + // 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. + // +optional + repeated string values = 3; +} + // Secret holds secret data of a certain type. The total bytes of the values in // the Data field must be less than MaxSecretSize bytes. message Secret { @@ -3986,6 +4090,32 @@ message ServiceAccountList { repeated ServiceAccount items = 2; } +// ServiceAccountTokenProjection represents a projected service account token +// volume. This projection can be used to insert a service account token into +// the pods runtime filesystem for use against APIs (Kubernetes API Server or +// otherwise). +message ServiceAccountTokenProjection { + // Audience is the intended audience of the token. A recipient of a token + // must identify itself with an identifier specified in the audience of the + // token, and otherwise should reject the token. The audience defaults to the + // identifier of the apiserver. + // +optional + optional string audience = 1; + + // ExpirationSeconds is the requested duration of validity of the service + // account token. As the token approaches expiration, the kubelet volume + // plugin will proactively rotate the service account token. The kubelet will + // start trying to rotate the token if the token is older than 80 percent of + // its time to live or if the token is older than 24 hours.Defaults to 1 hour + // and must be at least 10 minutes. + // +optional + optional int64 expirationSeconds = 2; + + // Path is the path relative to the mount point of the file to project the + // token into. + optional string path = 3; +} + // ServiceList holds a list of services. message ServiceList { // Standard list metadata. @@ -4314,6 +4444,28 @@ message Toleration { optional int64 tolerationSeconds = 5; } +// A topology selector requirement is a selector that matches given label. +// This is an alpha feature and may change in the future. +message TopologySelectorLabelRequirement { + // The label key that the selector applies to. + optional string key = 1; + + // An array of string values. One value must match the label to be selected. + // Each entry in Values is ORed. + repeated string values = 2; +} + +// A topology selector term represents the result of label queries. +// A null or empty topology selector term matches no objects. +// The requirements of them are ANDed. +// It provides a subset of functionality as NodeSelectorTerm. +// This is an alpha feature and may change in the future. +message TopologySelectorTerm { + // A list of topology selector requirements by labels. + // +optional + repeated TopologySelectorLabelRequirement matchLabelExpressions = 1; +} + // Volume represents a named volume in a pod that may be accessed by any container in the pod. message Volume { // Volume's name. @@ -4372,13 +4524,20 @@ message VolumeNodeAffinity { // Projection that may be projected along with other supported volume types message VolumeProjection { // information about the secret data to project + // +optional optional SecretProjection secret = 1; // information about the downwardAPI data to project + // +optional optional DownwardAPIProjection downwardAPI = 2; // information about the configMap data to project + // +optional optional ConfigMapProjection configMap = 3; + + // information about the serviceAccountToken data to project + // +optional + optional ServiceAccountTokenProjection serviceAccountToken = 4; } // Represents the source of a volume to mount. @@ -4413,6 +4572,9 @@ message VolumeSource { optional AWSElasticBlockStoreVolumeSource awsElasticBlockStore = 4; // GitRepo represents a git repository at a particular revision. + // DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an + // EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir + // into the Pod's container. // +optional optional GitRepoVolumeSource gitRepo = 5; diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index e46e9db0a7f..b941e0ac2e0 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -70,6 +70,9 @@ type VolumeSource struct { // +optional AWSElasticBlockStore *AWSElasticBlockStoreVolumeSource `json:"awsElasticBlockStore,omitempty" protobuf:"bytes,4,opt,name=awsElasticBlockStore"` // GitRepo represents a git repository at a particular revision. + // DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an + // EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir + // into the Pod's container. // +optional GitRepo *GitRepoVolumeSource `json:"gitRepo,omitempty" protobuf:"bytes,5,opt,name=gitRepo"` // Secret represents a secret that should populate this volume. @@ -202,7 +205,7 @@ type PersistentVolumeSource struct { // Cinder represents a cinder volume attached and mounted on kubelets host machine // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional - Cinder *CinderVolumeSource `json:"cinder,omitempty" protobuf:"bytes,8,opt,name=cinder"` + Cinder *CinderPersistentVolumeSource `json:"cinder,omitempty" protobuf:"bytes,8,opt,name=cinder"` // CephFS represents a Ceph FS mount on the host that shares a pod's lifetime // +optional CephFS *CephFSPersistentVolumeSource `json:"cephfs,omitempty" protobuf:"bytes,9,opt,name=cephfs"` @@ -728,6 +731,35 @@ type CinderVolumeSource struct { // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"` + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + SecretRef *LocalObjectReference `json:"secretRef,omitempty" protobuf:"bytes,4,opt,name=secretRef"` +} + +// Represents a cinder volume resource in Openstack. +// A Cinder volume must exist before mounting to a container. +// The volume must also be in the same region as the kubelet. +// Cinder volumes support ownership management and SELinux relabeling. +type CinderPersistentVolumeSource struct { + // volume id used to identify the volume in cinder + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + VolumeID string `json:"volumeID" protobuf:"bytes,1,opt,name=volumeID"` + // Filesystem type to mount. + // Must be a filesystem type supported by the host operating system. + // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + FSType string `json:"fsType,omitempty" protobuf:"bytes,2,opt,name=fsType"` + // Optional: Defaults to false (read/write). ReadOnly here will force + // the ReadOnly setting in VolumeMounts. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"` + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + SecretRef *SecretReference `json:"secretRef,omitempty" protobuf:"bytes,4,opt,name=secretRef"` } // Represents a Ceph Filesystem mount that lasts the lifetime of a pod @@ -972,6 +1004,10 @@ type AWSElasticBlockStoreVolumeSource struct { // Represents a volume that is populated with the contents of a git repository. // Git repo volumes do not support ownership management. // Git repo volumes support SELinux relabeling. +// +// DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an +// EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir +// into the Pod's container. type GitRepoVolumeSource struct { // Repository URL Repository string `json:"repository" protobuf:"bytes,1,opt,name=repository"` @@ -1466,6 +1502,30 @@ type ConfigMapProjection struct { Optional *bool `json:"optional,omitempty" protobuf:"varint,4,opt,name=optional"` } +// ServiceAccountTokenProjection represents a projected service account token +// volume. This projection can be used to insert a service account token into +// the pods runtime filesystem for use against APIs (Kubernetes API Server or +// otherwise). +type ServiceAccountTokenProjection struct { + // Audience is the intended audience of the token. A recipient of a token + // must identify itself with an identifier specified in the audience of the + // token, and otherwise should reject the token. The audience defaults to the + // identifier of the apiserver. + //+optional + Audience string `json:"audience,omitempty" protobuf:"bytes,1,rep,name=audience"` + // ExpirationSeconds is the requested duration of validity of the service + // account token. As the token approaches expiration, the kubelet volume + // plugin will proactively rotate the service account token. The kubelet will + // start trying to rotate the token if the token is older than 80 percent of + // its time to live or if the token is older than 24 hours.Defaults to 1 hour + // and must be at least 10 minutes. + //+optional + ExpirationSeconds *int64 `json:"expirationSeconds,omitempty" protobuf:"varint,2,opt,name=expirationSeconds"` + // Path is the path relative to the mount point of the file to project the + // token into. + Path string `json:"path" protobuf:"bytes,3,opt,name=path"` +} + // Represents a projected volume source type ProjectedVolumeSource struct { // list of volume projections @@ -1484,11 +1544,17 @@ type VolumeProjection struct { // all types below are the supported types for projection into the same volume // information about the secret data to project + // +optional Secret *SecretProjection `json:"secret,omitempty" protobuf:"bytes,1,opt,name=secret"` // information about the downwardAPI data to project + // +optional DownwardAPI *DownwardAPIProjection `json:"downwardAPI,omitempty" protobuf:"bytes,2,opt,name=downwardAPI"` // information about the configMap data to project + // +optional ConfigMap *ConfigMapProjection `json:"configMap,omitempty" protobuf:"bytes,3,opt,name=configMap"` + // information about the serviceAccountToken data to project + // +optional + ServiceAccountToken *ServiceAccountTokenProjection `json:"serviceAccountToken,omitempty" protobuf:"bytes,4,opt,name=serviceAccountToken"` } const ( @@ -2246,12 +2312,13 @@ const ( // PodReasonUnschedulable reason in PodScheduled PodCondition means that the scheduler // can't schedule the pod right now, for example due to insufficient resources in the cluster. PodReasonUnschedulable = "Unschedulable" + // ContainersReady indicates whether all containers in the pod are ready. + ContainersReady PodConditionType = "ContainersReady" ) // PodCondition contains details for the current condition of this pod. type PodCondition struct { // Type is the type of the condition. - // Currently only Ready. // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions Type PodConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=PodConditionType"` // Status is the status of the condition. @@ -2324,6 +2391,7 @@ type NodeSelector struct { // A null or empty node selector term matches no objects. The requirements of // them are ANDed. +// The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. type NodeSelectorTerm struct { // A list of node selector requirements by node's labels. // +optional @@ -2363,6 +2431,27 @@ const ( NodeSelectorOpLt NodeSelectorOperator = "Lt" ) +// A topology selector term represents the result of label queries. +// A null or empty topology selector term matches no objects. +// The requirements of them are ANDed. +// It provides a subset of functionality as NodeSelectorTerm. +// This is an alpha feature and may change in the future. +type TopologySelectorTerm struct { + // A list of topology selector requirements by labels. + // +optional + MatchLabelExpressions []TopologySelectorLabelRequirement `json:"matchLabelExpressions,omitempty" protobuf:"bytes,1,rep,name=matchLabelExpressions"` +} + +// A topology selector requirement is a selector that matches given label. +// This is an alpha feature and may change in the future. +type TopologySelectorLabelRequirement struct { + // The label key that the selector applies to. + Key string `json:"key" protobuf:"bytes,1,opt,name=key"` + // An array of string values. One value must match the label to be selected. + // Each entry in Values is ORed. + Values []string `json:"values" protobuf:"bytes,2,rep,name=values"` +} + // Affinity is a group of affinity scheduling rules. type Affinity struct { // Describes node affinity scheduling rules for the pod. @@ -2595,6 +2684,12 @@ const ( TolerationOpEqual TolerationOperator = "Equal" ) +// PodReadinessGate contains the reference to a pod condition +type PodReadinessGate struct { + // ConditionType refers to a condition in the pod's condition list with matching type. + ConditionType PodConditionType `json:"conditionType" protobuf:"bytes,1,opt,name=conditionType,casttype=PodConditionType"` +} + // PodSpec is a description of a pod. type PodSpec struct { // List of volumes that can be mounted by containers belonging to the pod. @@ -2759,6 +2854,13 @@ type PodSpec struct { // configuration based on DNSPolicy. // +optional DNSConfig *PodDNSConfig `json:"dnsConfig,omitempty" protobuf:"bytes,26,opt,name=dnsConfig"` + + // If specified, all readiness gates will be evaluated for pod readiness. + // A pod is ready when all its containers are ready AND + // all conditions specified in the readiness gates have status equal to "True" + // More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md + // +optional + ReadinessGates []PodReadinessGate `json:"readinessGates,omitempty" protobuf:"bytes,28,opt,name=readinessGates"` } // HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the @@ -2819,6 +2921,10 @@ type PodSecurityContext struct { // If unset, the Kubelet will not modify the ownership and permissions of any volume. // +optional FSGroup *int64 `json:"fsGroup,omitempty" protobuf:"varint,5,opt,name=fsGroup"` + // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + // sysctls (by the container runtime) might fail to launch. + // +optional + Sysctls []Sysctl `json:"sysctls,omitempty" protobuf:"bytes,7,rep,name=sysctls"` } // PodQOSClass defines the supported qos classes of Pods. @@ -2863,9 +2969,26 @@ type PodDNSConfigOption struct { } // PodStatus represents information about the status of a pod. Status may trail the actual -// state of a system. +// state of a system, especially if the node that hosts the pod cannot contact the control +// plane. type PodStatus struct { - // Current condition of the pod. + // The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. + // The conditions array, the reason and message fields, and the individual container status + // arrays contain more detail about the pod's status. + // There are five possible phase values: + // + // Pending: The pod has been accepted by the Kubernetes system, but one or more of the + // container images has not been created. This includes time before being scheduled as + // well as time spent downloading images over the network, which could take a while. + // Running: The pod has been bound to a node, and all of the containers have been created. + // At least one container is still running, or is in the process of starting or restarting. + // Succeeded: All containers in the pod have terminated in success, and will not be restarted. + // Failed: All containers in the pod have terminated, and at least one container has + // terminated in failure. The container either exited with non-zero status or was terminated + // by the system. + // Unknown: For some reason the state of the pod could not be obtained, typically due to an + // error in communicating with the host of the pod. + // // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase // +optional Phase PodPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase,casttype=PodPhase"` @@ -3974,6 +4097,8 @@ const ( ResourceDefaultNamespacePrefix = "kubernetes.io/" // Name prefix for huge page resources (alpha). ResourceHugePagesPrefix = "hugepages-" + // Name prefix for storage resource limits + ResourceAttachableVolumesPrefix = "attachable-volumes-" ) // ResourceList is a set of (resource name, quantity) pairs. @@ -4601,11 +4726,13 @@ const ( ResourceQuotaScopeBestEffort ResourceQuotaScope = "BestEffort" // Match all pod objects that do not have best effort quality of service ResourceQuotaScopeNotBestEffort ResourceQuotaScope = "NotBestEffort" + // Match all pod objects that have priority class mentioned + ResourceQuotaScopePriorityClass ResourceQuotaScope = "PriorityClass" ) // ResourceQuotaSpec defines the desired hard limits to enforce for Quota. type ResourceQuotaSpec struct { - // Hard is the set of desired hard limits for each named resource. + // hard is the set of desired hard limits for each named resource. // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/ // +optional Hard ResourceList `json:"hard,omitempty" protobuf:"bytes,1,rep,name=hard,casttype=ResourceList,castkey=ResourceName"` @@ -4613,8 +4740,48 @@ type ResourceQuotaSpec struct { // If not specified, the quota matches all objects. // +optional Scopes []ResourceQuotaScope `json:"scopes,omitempty" protobuf:"bytes,2,rep,name=scopes,casttype=ResourceQuotaScope"` + // scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota + // but expressed using ScopeSelectorOperator in combination with possible values. + // For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched. + // +optional + ScopeSelector *ScopeSelector `json:"scopeSelector,omitempty" protobuf:"bytes,3,opt,name=scopeSelector"` } +// A scope selector represents the AND of the selectors represented +// by the scoped-resource selector requirements. +type ScopeSelector struct { + // A list of scope selector requirements by scope of the resources. + // +optional + MatchExpressions []ScopedResourceSelectorRequirement `json:"matchExpressions,omitempty" protobuf:"bytes,1,rep,name=matchExpressions"` +} + +// A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator +// that relates the scope name and values. +type ScopedResourceSelectorRequirement struct { + // The name of the scope that the selector applies to. + ScopeName ResourceQuotaScope `json:"scopeName" protobuf:"bytes,1,opt,name=scopeName"` + // Represents a scope's relationship to a set of values. + // Valid operators are In, NotIn, Exists, DoesNotExist. + Operator ScopeSelectorOperator `json:"operator" protobuf:"bytes,2,opt,name=operator,casttype=ScopedResourceSelectorOperator"` + // 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. + // +optional + Values []string `json:"values,omitempty" protobuf:"bytes,3,rep,name=values"` +} + +// A scope selector operator is the set of operators that can be used in +// a scope selector requirement. +type ScopeSelectorOperator string + +const ( + ScopeSelectorOpIn ScopeSelectorOperator = "In" + ScopeSelectorOpNotIn ScopeSelectorOperator = "NotIn" + ScopeSelectorOpExists ScopeSelectorOperator = "Exists" + ScopeSelectorOpDoesNotExist ScopeSelectorOperator = "DoesNotExist" +) + // ResourceQuotaStatus defines the enforced hard limits and observed use. type ResourceQuotaStatus struct { // Hard is the set of enforced hard limits for each named resource. @@ -5042,9 +5209,9 @@ const ( // Sysctl defines a kernel parameter to be set type Sysctl struct { // Name of a property to set - Name string `protobuf:"bytes,1,opt,name=name"` + Name string `json:"name" protobuf:"bytes,1,opt,name=name"` // Value of a property to set - Value string `protobuf:"bytes,2,opt,name=value"` + Value string `json:"value" protobuf:"bytes,2,opt,name=value"` } // NodeResources is an object for conveying resource information about a node. diff --git a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go index 567f37dd22d..5b4e173db24 100644 --- a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -170,11 +170,24 @@ func (CephFSVolumeSource) SwaggerDoc() map[string]string { return map_CephFSVolumeSource } +var map_CinderPersistentVolumeSource = map[string]string{ + "": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "volumeID": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "readOnly": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "secretRef": "Optional: points to a secret object containing parameters used to connect to OpenStack.", +} + +func (CinderPersistentVolumeSource) SwaggerDoc() map[string]string { + return map_CinderPersistentVolumeSource +} + var map_CinderVolumeSource = map[string]string{ - "": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", - "volumeID": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - "readOnly": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "volumeID": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "readOnly": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "secretRef": "Optional: points to a secret object containing parameters used to connect to OpenStack.", } func (CinderVolumeSource) SwaggerDoc() map[string]string { @@ -672,7 +685,7 @@ func (GCEPersistentDiskVolumeSource) SwaggerDoc() map[string]string { } var map_GitRepoVolumeSource = map[string]string{ - "": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "repository": "Repository URL", "revision": "Commit hash for the specified revision.", "directory": "Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name.", @@ -1060,7 +1073,7 @@ func (NodeSelectorRequirement) SwaggerDoc() map[string]string { } var map_NodeSelectorTerm = map[string]string{ - "": "A null or empty node selector term matches no objects. The requirements of them are ANDed.", + "": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "matchExpressions": "A list of node selector requirements by node's labels.", "matchFields": "A list of node selector requirements by node's fields.", } @@ -1359,7 +1372,7 @@ func (PodAttachOptions) SwaggerDoc() map[string]string { var map_PodCondition = map[string]string{ "": "PodCondition contains details for the current condition of this pod.", - "type": "Type is the type of the condition. Currently only Ready. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", + "type": "Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", "status": "Status is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", "lastProbeTime": "Last time we probed the condition.", "lastTransitionTime": "Last time the condition transitioned from one status to another.", @@ -1449,6 +1462,15 @@ func (PodProxyOptions) SwaggerDoc() map[string]string { return map_PodProxyOptions } +var map_PodReadinessGate = map[string]string{ + "": "PodReadinessGate contains the reference to a pod condition", + "conditionType": "ConditionType refers to a condition in the pod's condition list with matching type.", +} + +func (PodReadinessGate) SwaggerDoc() map[string]string { + return map_PodReadinessGate +} + var map_PodSecurityContext = map[string]string{ "": "PodSecurityContext holds pod-level security attributes and common container settings. Some fields are also present in container.securityContext. Field values of container.securityContext take precedence over field values of PodSecurityContext.", "seLinuxOptions": "The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.", @@ -1457,6 +1479,7 @@ var map_PodSecurityContext = map[string]string{ "runAsNonRoot": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", "supplementalGroups": "A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container.", "fsGroup": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw ", + "sysctls": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.", } func (PodSecurityContext) SwaggerDoc() map[string]string { @@ -1501,6 +1524,7 @@ var map_PodSpec = map[string]string{ "priorityClassName": "If specified, indicates the pod's priority. \"system-node-critical\" and \"system-cluster-critical\" are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default.", "priority": "The priority value. Various system components use this field to find the priority of the pod. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.", "dnsConfig": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.", + "readinessGates": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md", } func (PodSpec) SwaggerDoc() map[string]string { @@ -1508,8 +1532,8 @@ func (PodSpec) SwaggerDoc() map[string]string { } var map_PodStatus = map[string]string{ - "": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system.", - "phase": "Current condition of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", + "": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system, especially if the node that hosts the pod cannot contact the control plane.", + "phase": "The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. The conditions array, the reason and message fields, and the individual container status arrays contain more detail about the pod's status. There are five possible phase values:\n\nPending: The pod has been accepted by the Kubernetes system, but one or more of the container images has not been created. This includes time before being scheduled as well as time spent downloading images over the network, which could take a while. Running: The pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting. Succeeded: All containers in the pod have terminated in success, and will not be restarted. Failed: All containers in the pod have terminated, and at least one container has terminated in failure. The container either exited with non-zero status or was terminated by the system. Unknown: For some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod.\n\nMore info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", "conditions": "Current service state of pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", "message": "A human readable message indicating details about why the pod is in this condition.", "reason": "A brief CamelCase message indicating details about why the pod is in this state. e.g. 'Evicted'", @@ -1780,9 +1804,10 @@ func (ResourceQuotaList) SwaggerDoc() map[string]string { } var map_ResourceQuotaSpec = map[string]string{ - "": "ResourceQuotaSpec defines the desired hard limits to enforce for Quota.", - "hard": "Hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/", - "scopes": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects.", + "": "ResourceQuotaSpec defines the desired hard limits to enforce for Quota.", + "hard": "hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/", + "scopes": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects.", + "scopeSelector": "scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota but expressed using ScopeSelectorOperator in combination with possible values. For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched.", } func (ResourceQuotaSpec) SwaggerDoc() map[string]string { @@ -1857,6 +1882,26 @@ func (ScaleIOVolumeSource) SwaggerDoc() map[string]string { return map_ScaleIOVolumeSource } +var map_ScopeSelector = map[string]string{ + "": "A scope selector represents the AND of the selectors represented by the scoped-resource selector requirements.", + "matchExpressions": "A list of scope selector requirements by scope of the resources.", +} + +func (ScopeSelector) SwaggerDoc() map[string]string { + return map_ScopeSelector +} + +var map_ScopedResourceSelectorRequirement = map[string]string{ + "": "A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator that relates the scope name and values.", + "scopeName": "The name of the scope that the selector applies to.", + "operator": "Represents a scope's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist.", + "values": "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.", +} + +func (ScopedResourceSelectorRequirement) SwaggerDoc() map[string]string { + return map_ScopedResourceSelectorRequirement +} + var map_Secret = map[string]string{ "": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -1988,6 +2033,17 @@ func (ServiceAccountList) SwaggerDoc() map[string]string { return map_ServiceAccountList } +var map_ServiceAccountTokenProjection = map[string]string{ + "": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "audience": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.", + "expirationSeconds": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.", + "path": "Path is the path relative to the mount point of the file to project the token into.", +} + +func (ServiceAccountTokenProjection) SwaggerDoc() map[string]string { + return map_ServiceAccountTokenProjection +} + var map_ServiceList = map[string]string{ "": "ServiceList holds a list of services.", "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", @@ -2087,8 +2143,8 @@ func (StorageOSVolumeSource) SwaggerDoc() map[string]string { var map_Sysctl = map[string]string{ "": "Sysctl defines a kernel parameter to be set", - "Name": "Name of a property to set", - "Value": "Value of a property to set", + "name": "Name of a property to set", + "value": "Value of a property to set", } func (Sysctl) SwaggerDoc() map[string]string { @@ -2130,6 +2186,25 @@ func (Toleration) SwaggerDoc() map[string]string { return map_Toleration } +var map_TopologySelectorLabelRequirement = map[string]string{ + "": "A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.", + "key": "The label key that the selector applies to.", + "values": "An array of string values. One value must match the label to be selected. Each entry in Values is ORed.", +} + +func (TopologySelectorLabelRequirement) SwaggerDoc() map[string]string { + return map_TopologySelectorLabelRequirement +} + +var map_TopologySelectorTerm = map[string]string{ + "": "A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.", + "matchLabelExpressions": "A list of topology selector requirements by labels.", +} + +func (TopologySelectorTerm) SwaggerDoc() map[string]string { + return map_TopologySelectorTerm +} + var map_Volume = map[string]string{ "": "Volume represents a named volume in a pod that may be accessed by any container in the pod.", "name": "Volume's name. Must be a DNS_LABEL and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", @@ -2172,10 +2247,11 @@ func (VolumeNodeAffinity) SwaggerDoc() map[string]string { } var map_VolumeProjection = map[string]string{ - "": "Projection that may be projected along with other supported volume types", - "secret": "information about the secret data to project", - "downwardAPI": "information about the downwardAPI data to project", - "configMap": "information about the configMap data to project", + "": "Projection that may be projected along with other supported volume types", + "secret": "information about the secret data to project", + "downwardAPI": "information about the downwardAPI data to project", + "configMap": "information about the configMap data to project", + "serviceAccountToken": "information about the serviceAccountToken data to project", } func (VolumeProjection) SwaggerDoc() map[string]string { @@ -2188,7 +2264,7 @@ var map_VolumeSource = map[string]string{ "emptyDir": "EmptyDir represents a temporary directory that shares a pod's lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir", "gcePersistentDisk": "GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", "awsElasticBlockStore": "AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", - "gitRepo": "GitRepo represents a git repository at a particular revision.", + "gitRepo": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "secret": "Secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret", "nfs": "NFS represents an NFS mount on the host that shares a pod's lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", "iscsi": "ISCSI represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://releases.k8s.io/HEAD/examples/volumes/iscsi/README.md", diff --git a/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go index 0fbcc9a7f31..0501bbcb50b 100644 --- a/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go @@ -380,9 +380,43 @@ func (in *CephFSVolumeSource) DeepCopy() *CephFSVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CinderPersistentVolumeSource) DeepCopyInto(out *CinderPersistentVolumeSource) { + *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + if *in == nil { + *out = nil + } else { + *out = new(SecretReference) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CinderPersistentVolumeSource. +func (in *CinderPersistentVolumeSource) DeepCopy() *CinderPersistentVolumeSource { + if in == nil { + return nil + } + out := new(CinderPersistentVolumeSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CinderVolumeSource) DeepCopyInto(out *CinderVolumeSource) { *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + if *in == nil { + *out = nil + } else { + *out = new(LocalObjectReference) + **out = **in + } + } return } @@ -3082,8 +3116,8 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) { if *in == nil { *out = nil } else { - *out = new(CinderVolumeSource) - **out = **in + *out = new(CinderPersistentVolumeSource) + (*in).DeepCopyInto(*out) } } if in.CephFS != nil { @@ -3715,6 +3749,22 @@ func (in *PodProxyOptions) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodReadinessGate) DeepCopyInto(out *PodReadinessGate) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodReadinessGate. +func (in *PodReadinessGate) DeepCopy() *PodReadinessGate { + if in == nil { + return nil + } + out := new(PodReadinessGate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) { *out = *in @@ -3768,6 +3818,11 @@ func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) { **out = **in } } + if in.Sysctls != nil { + in, out := &in.Sysctls, &out.Sysctls + *out = make([]Sysctl, len(*in)) + copy(*out, *in) + } return } @@ -3928,6 +3983,11 @@ func (in *PodSpec) DeepCopyInto(out *PodSpec) { (*in).DeepCopyInto(*out) } } + if in.ReadinessGates != nil { + in, out := &in.ReadinessGates, &out.ReadinessGates + *out = make([]PodReadinessGate, len(*in)) + copy(*out, *in) + } return } @@ -4580,6 +4640,15 @@ func (in *ResourceQuotaSpec) DeepCopyInto(out *ResourceQuotaSpec) { *out = make([]ResourceQuotaScope, len(*in)) copy(*out, *in) } + if in.ScopeSelector != nil { + in, out := &in.ScopeSelector, &out.ScopeSelector + if *in == nil { + *out = nil + } else { + *out = new(ScopeSelector) + (*in).DeepCopyInto(*out) + } + } return } @@ -4719,6 +4788,50 @@ func (in *ScaleIOVolumeSource) DeepCopy() *ScaleIOVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopeSelector) DeepCopyInto(out *ScopeSelector) { + *out = *in + if in.MatchExpressions != nil { + in, out := &in.MatchExpressions, &out.MatchExpressions + *out = make([]ScopedResourceSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopeSelector. +func (in *ScopeSelector) DeepCopy() *ScopeSelector { + if in == nil { + return nil + } + out := new(ScopeSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopedResourceSelectorRequirement) DeepCopyInto(out *ScopedResourceSelectorRequirement) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopedResourceSelectorRequirement. +func (in *ScopedResourceSelectorRequirement) DeepCopy() *ScopedResourceSelectorRequirement { + if in == nil { + return nil + } + out := new(ScopedResourceSelectorRequirement) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Secret) DeepCopyInto(out *Secret) { *out = *in @@ -5159,6 +5272,31 @@ func (in *ServiceAccountList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceAccountTokenProjection) DeepCopyInto(out *ServiceAccountTokenProjection) { + *out = *in + if in.ExpirationSeconds != nil { + in, out := &in.ExpirationSeconds, &out.ExpirationSeconds + if *in == nil { + *out = nil + } else { + *out = new(int64) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccountTokenProjection. +func (in *ServiceAccountTokenProjection) DeepCopy() *ServiceAccountTokenProjection { + if in == nil { + return nil + } + out := new(ServiceAccountTokenProjection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceList) DeepCopyInto(out *ServiceList) { *out = *in @@ -5455,6 +5593,50 @@ func (in *Toleration) DeepCopy() *Toleration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TopologySelectorLabelRequirement) DeepCopyInto(out *TopologySelectorLabelRequirement) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologySelectorLabelRequirement. +func (in *TopologySelectorLabelRequirement) DeepCopy() *TopologySelectorLabelRequirement { + if in == nil { + return nil + } + out := new(TopologySelectorLabelRequirement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TopologySelectorTerm) DeepCopyInto(out *TopologySelectorTerm) { + *out = *in + if in.MatchLabelExpressions != nil { + in, out := &in.MatchLabelExpressions, &out.MatchLabelExpressions + *out = make([]TopologySelectorLabelRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologySelectorTerm. +func (in *TopologySelectorTerm) DeepCopy() *TopologySelectorTerm { + if in == nil { + return nil + } + out := new(TopologySelectorTerm) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Volume) DeepCopyInto(out *Volume) { *out = *in @@ -5568,6 +5750,15 @@ func (in *VolumeProjection) DeepCopyInto(out *VolumeProjection) { (*in).DeepCopyInto(*out) } } + if in.ServiceAccountToken != nil { + in, out := &in.ServiceAccountToken, &out.ServiceAccountToken + if *in == nil { + *out = nil + } else { + *out = new(ServiceAccountTokenProjection) + (*in).DeepCopyInto(*out) + } + } return } @@ -5698,7 +5889,7 @@ func (in *VolumeSource) DeepCopyInto(out *VolumeSource) { *out = nil } else { *out = new(CinderVolumeSource) - **out = **in + (*in).DeepCopyInto(*out) } } if in.CephFS != nil { diff --git a/staging/src/k8s.io/api/extensions/v1beta1/generated.pb.go b/staging/src/k8s.io/api/extensions/v1beta1/generated.pb.go index 565d0a5244f..0604fb95787 100644 --- a/staging/src/k8s.io/api/extensions/v1beta1/generated.pb.go +++ b/staging/src/k8s.io/api/extensions/v1beta1/generated.pb.go @@ -465,6 +465,14 @@ func (m *AllowedHostPath) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.PathPrefix))) i += copy(dAtA[i:], m.PathPrefix) + dAtA[i] = 0x10 + i++ + if m.ReadOnly { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ return i, nil } @@ -2249,6 +2257,40 @@ func (m *PodSecurityPolicySpec) MarshalTo(dAtA []byte) (int, error) { i += n } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + dAtA[i] = 0x9a + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + dAtA[i] = 0xa2 + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } return i, nil } @@ -2818,6 +2860,7 @@ func (m *AllowedHostPath) Size() (n int) { _ = l l = len(m.PathPrefix) n += 1 + l + sovGenerated(uint64(l)) + n += 2 return n } @@ -3457,6 +3500,18 @@ func (m *PodSecurityPolicySpec) Size() (n int) { n += 2 + l + sovGenerated(uint64(l)) } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } return n } @@ -3677,6 +3732,7 @@ func (this *AllowedHostPath) String() string { } s := strings.Join([]string{`&AllowedHostPath{`, `PathPrefix:` + fmt.Sprintf("%v", this.PathPrefix) + `,`, + `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, `}`, }, "") return s @@ -4189,6 +4245,8 @@ func (this *PodSecurityPolicySpec) String() string { `AllowPrivilegeEscalation:` + valueToStringGenerated(this.AllowPrivilegeEscalation) + `,`, `AllowedHostPaths:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedHostPaths), "AllowedHostPath", "AllowedHostPath", 1), `&`, ``, 1) + `,`, `AllowedFlexVolumes:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedFlexVolumes), "AllowedFlexVolume", "AllowedFlexVolume", 1), `&`, ``, 1) + `,`, + `AllowedUnsafeSysctls:` + fmt.Sprintf("%v", this.AllowedUnsafeSysctls) + `,`, + `ForbiddenSysctls:` + fmt.Sprintf("%v", this.ForbiddenSysctls) + `,`, `}`, }, "") return s @@ -4520,6 +4578,26 @@ func (m *AllowedHostPath) Unmarshal(dAtA []byte) error { } m.PathPrefix = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ReadOnly = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -10306,6 +10384,64 @@ func (m *PodSecurityPolicySpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedUnsafeSysctls", 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 + } + m.AllowedUnsafeSysctls = append(m.AllowedUnsafeSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 20: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ForbiddenSysctls", 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 + } + m.ForbiddenSysctls = append(m.ForbiddenSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -12285,229 +12421,233 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 3571 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5b, 0xcd, 0x6f, 0x1c, 0x47, - 0x76, 0x57, 0xcf, 0x0c, 0x39, 0xc3, 0x47, 0xf1, 0xab, 0x28, 0x93, 0x63, 0xca, 0xe2, 0xc8, 0x6d, - 0x40, 0x91, 0x1c, 0x69, 0xc6, 0x92, 0x2d, 0x59, 0xb1, 0x10, 0x3b, 0x1c, 0x52, 0x1f, 0x74, 0xf8, - 0xa5, 0x1a, 0x52, 0x71, 0x8c, 0xc8, 0x71, 0x73, 0xa6, 0x38, 0x6c, 0xb1, 0xa7, 0xbb, 0xdd, 0x5d, - 0x4d, 0x73, 0x80, 0x20, 0xc8, 0x21, 0x08, 0x10, 0x20, 0x41, 0x92, 0x83, 0xf3, 0x71, 0x8b, 0x2f, - 0x39, 0x25, 0x48, 0x6e, 0xc9, 0xc1, 0x30, 0x10, 0xc0, 0x0b, 0x08, 0x0b, 0x2f, 0xe0, 0xdb, 0xfa, - 0x44, 0xac, 0xe9, 0xd3, 0x62, 0xff, 0x81, 0x85, 0x0e, 0x8b, 0x45, 0x55, 0x57, 0x7f, 0x77, 0x73, - 0x66, 0x68, 0x89, 0x58, 0x2c, 0xf6, 0xc6, 0xa9, 0xf7, 0xde, 0xef, 0xbd, 0x7a, 0xf5, 0xea, 0xbd, - 0xd7, 0x55, 0x45, 0xb8, 0xb7, 0x77, 0xdb, 0xae, 0xaa, 0x46, 0x6d, 0xcf, 0xd9, 0x26, 0x96, 0x4e, - 0x28, 0xb1, 0x6b, 0xfb, 0x44, 0x6f, 0x19, 0x56, 0x4d, 0x10, 0x14, 0x53, 0xad, 0x91, 0x03, 0x4a, - 0x74, 0x5b, 0x35, 0x74, 0xbb, 0xb6, 0x7f, 0x7d, 0x9b, 0x50, 0xe5, 0x7a, 0xad, 0x4d, 0x74, 0x62, - 0x29, 0x94, 0xb4, 0xaa, 0xa6, 0x65, 0x50, 0x03, 0x5d, 0x70, 0xd9, 0xab, 0x8a, 0xa9, 0x56, 0x03, - 0xf6, 0xaa, 0x60, 0x9f, 0xbb, 0xd6, 0x56, 0xe9, 0xae, 0xb3, 0x5d, 0x6d, 0x1a, 0x9d, 0x5a, 0xdb, - 0x68, 0x1b, 0x35, 0x2e, 0xb5, 0xed, 0xec, 0xf0, 0x5f, 0xfc, 0x07, 0xff, 0xcb, 0x45, 0x9b, 0x93, - 0x43, 0xca, 0x9b, 0x86, 0x45, 0x6a, 0xfb, 0x09, 0x8d, 0x73, 0x57, 0x42, 0x3c, 0xa6, 0xa1, 0xa9, - 0xcd, 0x6e, 0x96, 0x71, 0x73, 0x6f, 0x05, 0xac, 0x1d, 0xa5, 0xb9, 0xab, 0xea, 0xc4, 0xea, 0xd6, - 0xcc, 0xbd, 0x36, 0x97, 0xb5, 0x88, 0x6d, 0x38, 0x56, 0x93, 0x0c, 0x24, 0x65, 0xd7, 0x3a, 0x84, - 0x2a, 0x69, 0x66, 0xd5, 0xb2, 0xa4, 0x2c, 0x47, 0xa7, 0x6a, 0x27, 0xa9, 0xe6, 0x56, 0x2f, 0x01, - 0xbb, 0xb9, 0x4b, 0x3a, 0x4a, 0x42, 0xee, 0xcd, 0x2c, 0x39, 0x87, 0xaa, 0x5a, 0x4d, 0xd5, 0xa9, - 0x4d, 0xad, 0xb8, 0x90, 0x7c, 0x07, 0xa6, 0x16, 0x34, 0xcd, 0xf8, 0x94, 0xb4, 0xee, 0x69, 0xe4, - 0xe0, 0x91, 0xa1, 0x39, 0x1d, 0x82, 0x2e, 0xc1, 0x70, 0xcb, 0x52, 0xf7, 0x89, 0x55, 0x96, 0x2e, - 0x4a, 0x97, 0x47, 0xea, 0xe3, 0x4f, 0x0f, 0x2b, 0x67, 0x8e, 0x0e, 0x2b, 0xc3, 0x4b, 0x7c, 0x14, - 0x0b, 0xaa, 0x7c, 0x17, 0x26, 0x84, 0xf0, 0x03, 0xc3, 0xa6, 0x1b, 0x0a, 0xdd, 0x45, 0x37, 0x00, - 0x4c, 0x85, 0xee, 0x6e, 0x58, 0x64, 0x47, 0x3d, 0x10, 0xe2, 0x48, 0x88, 0xc3, 0x86, 0x4f, 0xc1, - 0x21, 0x2e, 0xf9, 0xdf, 0x24, 0x78, 0x79, 0xd1, 0xb1, 0xa9, 0xd1, 0x59, 0x25, 0xd4, 0x52, 0x9b, - 0x8b, 0x8e, 0x65, 0x11, 0x9d, 0x36, 0xa8, 0x42, 0x1d, 0x1b, 0x5d, 0x84, 0x82, 0xae, 0x74, 0x88, - 0xc0, 0x3a, 0x2b, 0xb0, 0x0a, 0x6b, 0x4a, 0x87, 0x60, 0x4e, 0x41, 0x1f, 0xc2, 0xd0, 0xbe, 0xa2, - 0x39, 0xa4, 0x9c, 0xbb, 0x28, 0x5d, 0x1e, 0xbd, 0x51, 0xad, 0x06, 0xa1, 0xe7, 0x3b, 0xa2, 0x6a, - 0xee, 0xb5, 0x79, 0x2c, 0x7a, 0xab, 0x5b, 0x7d, 0xe8, 0x28, 0x3a, 0x55, 0x69, 0xb7, 0x7e, 0x4e, - 0x40, 0x9e, 0x15, 0x7a, 0x1f, 0x31, 0x2c, 0xec, 0x42, 0xca, 0x7f, 0x09, 0x17, 0x32, 0x4d, 0x5b, - 0x51, 0x6d, 0x8a, 0x1e, 0xc3, 0x90, 0x4a, 0x49, 0xc7, 0x2e, 0x4b, 0x17, 0xf3, 0x97, 0x47, 0x6f, - 0xdc, 0xae, 0x1e, 0x1b, 0xf7, 0xd5, 0x4c, 0xb0, 0xfa, 0x98, 0x30, 0x63, 0x68, 0x99, 0xc1, 0x61, - 0x17, 0x55, 0xfe, 0x27, 0x09, 0x50, 0x58, 0x66, 0x53, 0xb1, 0xda, 0x84, 0xf6, 0xe1, 0x94, 0x3f, - 0xfd, 0x61, 0x4e, 0x99, 0x16, 0x90, 0xa3, 0xae, 0xc2, 0x88, 0x4f, 0x4c, 0x98, 0x49, 0x9a, 0xc4, - 0x9d, 0xf1, 0x28, 0xea, 0x8c, 0xeb, 0x03, 0x38, 0xc3, 0x45, 0xc9, 0xf0, 0xc2, 0x67, 0x39, 0x18, - 0x59, 0x52, 0x48, 0xc7, 0xd0, 0x1b, 0x84, 0xa2, 0x8f, 0xa1, 0xc4, 0x36, 0x5b, 0x4b, 0xa1, 0x0a, - 0x77, 0xc0, 0xe8, 0x8d, 0x37, 0x8e, 0x9b, 0x9d, 0x5d, 0x65, 0xdc, 0xd5, 0xfd, 0xeb, 0xd5, 0xf5, - 0xed, 0x27, 0xa4, 0x49, 0x57, 0x09, 0x55, 0x82, 0x98, 0x0c, 0xc6, 0xb0, 0x8f, 0x8a, 0xd6, 0xa0, - 0x60, 0x9b, 0xa4, 0x29, 0x7c, 0x77, 0xb5, 0xc7, 0x34, 0x7c, 0xcb, 0x1a, 0x26, 0x69, 0x06, 0x8b, - 0xc1, 0x7e, 0x61, 0x8e, 0x83, 0x1e, 0xc1, 0xb0, 0xcd, 0x57, 0xb9, 0x9c, 0x4f, 0xac, 0xc6, 0xf1, - 0x88, 0x6e, 0x6c, 0xf8, 0x1b, 0xd0, 0xfd, 0x8d, 0x05, 0x9a, 0xfc, 0xf3, 0x1c, 0x20, 0x9f, 0x77, - 0xd1, 0xd0, 0x5b, 0x2a, 0x55, 0x0d, 0x1d, 0xbd, 0x03, 0x05, 0xda, 0x35, 0xbd, 0xe8, 0xb8, 0xe4, - 0x19, 0xb4, 0xd9, 0x35, 0xc9, 0xb3, 0xc3, 0xca, 0x4c, 0x52, 0x82, 0x51, 0x30, 0x97, 0x41, 0x2b, - 0xbe, 0xa9, 0x39, 0x2e, 0xfd, 0x56, 0x54, 0xf5, 0xb3, 0xc3, 0x4a, 0x4a, 0x2e, 0xae, 0xfa, 0x48, - 0x51, 0x03, 0xd1, 0x3e, 0x20, 0x4d, 0xb1, 0xe9, 0xa6, 0xa5, 0xe8, 0xb6, 0xab, 0x49, 0xed, 0x10, - 0xe1, 0x84, 0xd7, 0xfb, 0x5b, 0x34, 0x26, 0x51, 0x9f, 0x13, 0x56, 0xa0, 0x95, 0x04, 0x1a, 0x4e, - 0xd1, 0xc0, 0x32, 0x98, 0x45, 0x14, 0xdb, 0xd0, 0xcb, 0x85, 0x68, 0x06, 0xc3, 0x7c, 0x14, 0x0b, - 0x2a, 0xba, 0x02, 0xc5, 0x0e, 0xb1, 0x6d, 0xa5, 0x4d, 0xca, 0x43, 0x9c, 0x71, 0x42, 0x30, 0x16, - 0x57, 0xdd, 0x61, 0xec, 0xd1, 0xe5, 0x2f, 0x24, 0x18, 0xf3, 0x3d, 0xc7, 0xa3, 0xfd, 0xcf, 0x12, - 0x71, 0x58, 0xed, 0x6f, 0x4a, 0x4c, 0x9a, 0x47, 0xe1, 0xa4, 0xd0, 0x56, 0xf2, 0x46, 0x42, 0x31, - 0xb8, 0xea, 0xed, 0xa5, 0x1c, 0xdf, 0x4b, 0x97, 0xfb, 0x0d, 0x99, 0x8c, 0x2d, 0xf4, 0xcf, 0x85, - 0x90, 0xf9, 0x2c, 0x34, 0xd1, 0x63, 0x28, 0xd9, 0x44, 0x23, 0x4d, 0x6a, 0x58, 0xc2, 0xfc, 0x37, - 0xfb, 0x34, 0x5f, 0xd9, 0x26, 0x5a, 0x43, 0x88, 0xd6, 0xcf, 0x32, 0xfb, 0xbd, 0x5f, 0xd8, 0x87, - 0x44, 0x0f, 0xa1, 0x44, 0x49, 0xc7, 0xd4, 0x14, 0xea, 0xe5, 0xa0, 0xd7, 0xc2, 0x53, 0x60, 0x91, - 0xc3, 0xc0, 0x36, 0x8c, 0xd6, 0xa6, 0x60, 0xe3, 0xdb, 0xc7, 0x77, 0x89, 0x37, 0x8a, 0x7d, 0x18, - 0xb4, 0x0f, 0xe3, 0x8e, 0xd9, 0x62, 0x9c, 0x94, 0xd5, 0xb0, 0x76, 0x57, 0x44, 0xd2, 0xad, 0x7e, - 0x7d, 0xb3, 0x15, 0x91, 0xae, 0xcf, 0x08, 0x5d, 0xe3, 0xd1, 0x71, 0x1c, 0xd3, 0x82, 0x16, 0x60, - 0xa2, 0xa3, 0xea, 0x98, 0x28, 0xad, 0x6e, 0x83, 0x34, 0x0d, 0xbd, 0x65, 0xf3, 0xb0, 0x1a, 0xaa, - 0xcf, 0x0a, 0x80, 0x89, 0xd5, 0x28, 0x19, 0xc7, 0xf9, 0xd1, 0xfb, 0x80, 0xbc, 0x69, 0xdc, 0x77, - 0x4b, 0xb0, 0x6a, 0xe8, 0x3c, 0xe6, 0xf2, 0x41, 0x70, 0x6f, 0x26, 0x38, 0x70, 0x8a, 0x14, 0x5a, - 0x81, 0x73, 0x16, 0xd9, 0x57, 0xd9, 0x1c, 0x1f, 0xa8, 0x36, 0x35, 0xac, 0xee, 0x8a, 0xda, 0x51, - 0x69, 0x79, 0x98, 0xdb, 0x54, 0x3e, 0x3a, 0xac, 0x9c, 0xc3, 0x29, 0x74, 0x9c, 0x2a, 0x25, 0xff, - 0xcb, 0x30, 0x4c, 0xc4, 0xf2, 0x0d, 0x7a, 0x04, 0x33, 0x4d, 0xb7, 0x38, 0xad, 0x39, 0x9d, 0x6d, - 0x62, 0x35, 0x9a, 0xbb, 0xa4, 0xe5, 0x68, 0xa4, 0xc5, 0x03, 0x65, 0xa8, 0x3e, 0x2f, 0x2c, 0x9e, - 0x59, 0x4c, 0xe5, 0xc2, 0x19, 0xd2, 0xcc, 0x0b, 0x3a, 0x1f, 0x5a, 0x55, 0x6d, 0xdb, 0xc7, 0xcc, - 0x71, 0x4c, 0xdf, 0x0b, 0x6b, 0x09, 0x0e, 0x9c, 0x22, 0xc5, 0x6c, 0x6c, 0x11, 0x5b, 0xb5, 0x48, - 0x2b, 0x6e, 0x63, 0x3e, 0x6a, 0xe3, 0x52, 0x2a, 0x17, 0xce, 0x90, 0x46, 0x37, 0x61, 0xd4, 0xd5, - 0xc6, 0xd7, 0x4f, 0x2c, 0xb4, 0x5f, 0x0e, 0xd7, 0x02, 0x12, 0x0e, 0xf3, 0xb1, 0xa9, 0x19, 0xdb, - 0x36, 0xb1, 0xf6, 0x49, 0x2b, 0x7b, 0x81, 0xd7, 0x13, 0x1c, 0x38, 0x45, 0x8a, 0x4d, 0xcd, 0x8d, - 0xc0, 0xc4, 0xd4, 0x86, 0xa3, 0x53, 0xdb, 0x4a, 0xe5, 0xc2, 0x19, 0xd2, 0x2c, 0x8e, 0x5d, 0x93, - 0x17, 0xf6, 0x15, 0x55, 0x53, 0xb6, 0x35, 0x52, 0x2e, 0x46, 0xe3, 0x78, 0x2d, 0x4a, 0xc6, 0x71, - 0x7e, 0x74, 0x1f, 0xa6, 0xdc, 0xa1, 0x2d, 0x5d, 0xf1, 0x41, 0x4a, 0x1c, 0xe4, 0x65, 0x01, 0x32, - 0xb5, 0x16, 0x67, 0xc0, 0x49, 0x19, 0xf4, 0x0e, 0x8c, 0x37, 0x0d, 0x4d, 0xe3, 0xf1, 0xb8, 0x68, - 0x38, 0x3a, 0x2d, 0x8f, 0x70, 0x14, 0xc4, 0xf6, 0xe3, 0x62, 0x84, 0x82, 0x63, 0x9c, 0x88, 0x00, - 0x34, 0xbd, 0x82, 0x63, 0x97, 0xa1, 0xaf, 0x5e, 0x23, 0x59, 0xf4, 0x82, 0x1e, 0xc0, 0x1f, 0xb2, - 0x71, 0x08, 0x58, 0xfe, 0xb1, 0x04, 0xb3, 0x19, 0xa9, 0x03, 0xbd, 0x17, 0x29, 0xb1, 0xbf, 0x1f, - 0x2b, 0xb1, 0xe7, 0x33, 0xc4, 0x42, 0x75, 0x56, 0x87, 0x31, 0x8b, 0xcd, 0x4a, 0x6f, 0xbb, 0x2c, - 0x22, 0x47, 0xde, 0xec, 0x31, 0x0d, 0x1c, 0x96, 0x09, 0x72, 0xfe, 0xd4, 0xd1, 0x61, 0x65, 0x2c, - 0x42, 0xc3, 0x51, 0x78, 0xf9, 0x5f, 0x73, 0x00, 0x4b, 0xc4, 0xd4, 0x8c, 0x6e, 0x87, 0xe8, 0xa7, - 0xd1, 0x43, 0xad, 0x47, 0x7a, 0xa8, 0x6b, 0xbd, 0x96, 0xc7, 0x37, 0x2d, 0xb3, 0x89, 0xfa, 0x93, - 0x58, 0x13, 0x55, 0xeb, 0x1f, 0xf2, 0xf8, 0x2e, 0xea, 0xa7, 0x79, 0x98, 0x0e, 0x98, 0x83, 0x36, - 0xea, 0x4e, 0x64, 0x8d, 0x7f, 0x2f, 0xb6, 0xc6, 0xb3, 0x29, 0x22, 0x2f, 0xac, 0x8f, 0x7a, 0xfe, - 0xfd, 0x0c, 0x7a, 0x02, 0xe3, 0xac, 0x71, 0x72, 0xc3, 0x83, 0xb7, 0x65, 0xc3, 0x03, 0xb7, 0x65, - 0x7e, 0x01, 0x5d, 0x89, 0x20, 0xe1, 0x18, 0x72, 0x46, 0x1b, 0x58, 0x7c, 0xd1, 0x6d, 0xa0, 0xfc, - 0xa5, 0x04, 0xe3, 0xc1, 0x32, 0x9d, 0x42, 0xd3, 0xb6, 0x16, 0x6d, 0xda, 0xae, 0xf4, 0x1d, 0xa2, - 0x19, 0x5d, 0xdb, 0x2f, 0x59, 0x83, 0xef, 0x33, 0xb1, 0x0d, 0xbe, 0xad, 0x34, 0xf7, 0xfa, 0xf8, - 0xfc, 0xfb, 0x4c, 0x02, 0x24, 0xaa, 0xc0, 0x82, 0xae, 0x1b, 0x54, 0x71, 0x73, 0xa5, 0x6b, 0xd6, - 0x72, 0xdf, 0x66, 0x79, 0x1a, 0xab, 0x5b, 0x09, 0xac, 0xbb, 0x3a, 0xb5, 0xba, 0xc1, 0x8a, 0x24, - 0x19, 0x70, 0x8a, 0x01, 0x48, 0x01, 0xb0, 0x04, 0xe6, 0xa6, 0x21, 0x36, 0xf2, 0xb5, 0x3e, 0x72, - 0x1e, 0x13, 0x58, 0x34, 0xf4, 0x1d, 0xb5, 0x1d, 0xa4, 0x1d, 0xec, 0x03, 0xe1, 0x10, 0xe8, 0xdc, - 0x5d, 0x98, 0xcd, 0xb0, 0x16, 0x4d, 0x42, 0x7e, 0x8f, 0x74, 0x5d, 0xb7, 0x61, 0xf6, 0x27, 0x3a, - 0x17, 0xfe, 0x4c, 0x1e, 0x11, 0x5f, 0xb8, 0xef, 0xe4, 0x6e, 0x4b, 0xf2, 0x17, 0x43, 0xe1, 0xd8, - 0xe1, 0x1d, 0xf3, 0x65, 0x28, 0x59, 0xc4, 0xd4, 0xd4, 0xa6, 0x62, 0x8b, 0x46, 0x88, 0x37, 0xbf, - 0x58, 0x8c, 0x61, 0x9f, 0x1a, 0xe9, 0xad, 0x73, 0x2f, 0xb6, 0xb7, 0xce, 0x3f, 0x9f, 0xde, 0xfa, - 0xcf, 0xa1, 0x64, 0x7b, 0x5d, 0x75, 0x81, 0x43, 0x5e, 0x1f, 0x20, 0xbf, 0x8a, 0x86, 0xda, 0x57, - 0xe0, 0xb7, 0xd2, 0x3e, 0x68, 0x5a, 0x13, 0x3d, 0x34, 0x60, 0x13, 0xfd, 0x5c, 0x1b, 0x5f, 0x96, - 0x53, 0x4d, 0xc5, 0xb1, 0x49, 0x8b, 0x27, 0xa2, 0x52, 0x90, 0x53, 0x37, 0xf8, 0x28, 0x16, 0x54, - 0xf4, 0x38, 0x12, 0xb2, 0xa5, 0x93, 0x84, 0xec, 0x78, 0x76, 0xb8, 0xa2, 0x2d, 0x98, 0x35, 0x2d, - 0xa3, 0x6d, 0x11, 0xdb, 0x5e, 0x22, 0x4a, 0x4b, 0x53, 0x75, 0xe2, 0xf9, 0xc7, 0xed, 0x88, 0xce, - 0x1f, 0x1d, 0x56, 0x66, 0x37, 0xd2, 0x59, 0x70, 0x96, 0xac, 0xfc, 0xb4, 0x00, 0x93, 0xf1, 0x0a, - 0x98, 0xd1, 0xa4, 0x4a, 0x27, 0x6a, 0x52, 0xaf, 0x86, 0x36, 0x83, 0xdb, 0xc1, 0xfb, 0xab, 0x9f, - 0xb2, 0x21, 0x16, 0x60, 0x42, 0x64, 0x03, 0x8f, 0x28, 0xda, 0x74, 0x7f, 0xf5, 0xb7, 0xa2, 0x64, - 0x1c, 0xe7, 0x67, 0xad, 0x67, 0xd0, 0x51, 0x7a, 0x20, 0x85, 0x68, 0xeb, 0xb9, 0x10, 0x67, 0xc0, - 0x49, 0x19, 0xb4, 0x0a, 0xd3, 0x8e, 0x9e, 0x84, 0x72, 0xa3, 0xf1, 0xbc, 0x80, 0x9a, 0xde, 0x4a, - 0xb2, 0xe0, 0x34, 0x39, 0xb4, 0x13, 0xe9, 0x46, 0x87, 0x79, 0x86, 0xbd, 0xd1, 0xf7, 0xde, 0xe9, - 0xbb, 0x1d, 0x45, 0x77, 0x60, 0xcc, 0xe2, 0xdf, 0x1d, 0x9e, 0xc1, 0x6e, 0xef, 0xfe, 0x92, 0x10, - 0x1b, 0xc3, 0x61, 0x22, 0x8e, 0xf2, 0xa6, 0xb4, 0xdb, 0xa5, 0x7e, 0xdb, 0x6d, 0xf9, 0xff, 0xa5, - 0x70, 0x11, 0xf2, 0x5b, 0xe0, 0x5e, 0xa7, 0x4c, 0x09, 0x89, 0x50, 0x77, 0x64, 0xa4, 0x77, 0xbf, - 0xb7, 0x06, 0xea, 0x7e, 0x83, 0xe2, 0xd9, 0xbb, 0xfd, 0xfd, 0x5c, 0x82, 0x99, 0x7b, 0x8d, 0xfb, - 0x96, 0xe1, 0x98, 0x9e, 0x39, 0xeb, 0xa6, 0xeb, 0xd7, 0xb7, 0xa1, 0x60, 0x39, 0x9a, 0x37, 0x8f, - 0xd7, 0xbc, 0x79, 0x60, 0x47, 0x63, 0xf3, 0x98, 0x8e, 0x49, 0xb9, 0x93, 0x60, 0x02, 0x68, 0x0d, - 0x86, 0x2d, 0x45, 0x6f, 0x13, 0xaf, 0xac, 0x5e, 0xea, 0x61, 0xfd, 0xf2, 0x12, 0x66, 0xec, 0xa1, - 0xe6, 0x8d, 0x4b, 0x63, 0x81, 0x22, 0xff, 0xbd, 0x04, 0x13, 0x0f, 0x36, 0x37, 0x37, 0x96, 0x75, - 0xbe, 0xa3, 0xf9, 0x79, 0xfa, 0x45, 0x28, 0x98, 0x0a, 0xdd, 0x8d, 0x57, 0x7a, 0x46, 0xc3, 0x9c, - 0x82, 0x3e, 0x80, 0x22, 0xcb, 0x24, 0x44, 0x6f, 0xf5, 0xd9, 0x6a, 0x0b, 0xf8, 0xba, 0x2b, 0x14, - 0x74, 0x88, 0x62, 0x00, 0x7b, 0x70, 0xf2, 0x1e, 0x9c, 0x0b, 0x99, 0xc3, 0xfc, 0xc1, 0x8f, 0x81, - 0x51, 0x03, 0x86, 0x98, 0x66, 0xef, 0x94, 0xb7, 0xd7, 0x61, 0x66, 0x6c, 0x4a, 0x41, 0xa7, 0xc3, - 0x7e, 0xd9, 0xd8, 0xc5, 0x92, 0x57, 0x61, 0x8c, 0x5f, 0x22, 0x18, 0x16, 0xe5, 0x6e, 0x41, 0x17, - 0x20, 0xdf, 0x51, 0x75, 0x51, 0x67, 0x47, 0x85, 0x4c, 0x9e, 0xd5, 0x08, 0x36, 0xce, 0xc9, 0xca, - 0x81, 0xc8, 0x3c, 0x01, 0x59, 0x39, 0xc0, 0x6c, 0x5c, 0xbe, 0x0f, 0x45, 0xe1, 0xee, 0x30, 0x50, - 0xfe, 0x78, 0xa0, 0x7c, 0x0a, 0xd0, 0x3a, 0x14, 0x97, 0x37, 0xea, 0x9a, 0xe1, 0x76, 0x5d, 0x4d, - 0xb5, 0x65, 0xc5, 0xd7, 0x62, 0x71, 0x79, 0x09, 0x63, 0x4e, 0x41, 0x32, 0x0c, 0x93, 0x83, 0x26, - 0x31, 0x29, 0x8f, 0x88, 0x91, 0x3a, 0xb0, 0x55, 0xbe, 0xcb, 0x47, 0xb0, 0xa0, 0xc8, 0xff, 0x90, - 0x83, 0xa2, 0x70, 0xc7, 0x29, 0x7c, 0x85, 0xad, 0x44, 0xbe, 0xc2, 0x5e, 0xef, 0x2f, 0x34, 0x32, - 0x3f, 0xc1, 0x36, 0x63, 0x9f, 0x60, 0x57, 0xfb, 0xc4, 0x3b, 0xfe, 0xfb, 0xeb, 0x7f, 0x24, 0x18, - 0x8f, 0x06, 0x25, 0xba, 0x09, 0xa3, 0xac, 0xe0, 0xa8, 0x4d, 0xb2, 0x16, 0xf4, 0xb9, 0xfe, 0x21, - 0x4c, 0x23, 0x20, 0xe1, 0x30, 0x1f, 0x6a, 0xfb, 0x62, 0x2c, 0x8e, 0xc4, 0xa4, 0xb3, 0x5d, 0xea, - 0x50, 0x55, 0xab, 0xba, 0x17, 0x63, 0xd5, 0x65, 0x9d, 0xae, 0x5b, 0x0d, 0x6a, 0xa9, 0x7a, 0x3b, - 0xa1, 0x88, 0x07, 0x65, 0x18, 0x59, 0xfe, 0x3f, 0x09, 0x46, 0x85, 0xc9, 0xa7, 0xf0, 0x55, 0xf1, - 0xc7, 0xd1, 0xaf, 0x8a, 0x4b, 0x7d, 0x6e, 0xf0, 0xf4, 0x4f, 0x8a, 0xff, 0x08, 0x4c, 0x67, 0x5b, - 0x9a, 0x45, 0xf5, 0xae, 0x61, 0xd3, 0x78, 0x54, 0xb3, 0xcd, 0x88, 0x39, 0x05, 0x39, 0x30, 0xa9, - 0xc6, 0x72, 0x80, 0x70, 0x6d, 0xad, 0x3f, 0x4b, 0x7c, 0xb1, 0x7a, 0x59, 0xc0, 0x4f, 0xc6, 0x29, - 0x38, 0xa1, 0x42, 0x26, 0x90, 0xe0, 0x42, 0x0f, 0xa1, 0xb0, 0x4b, 0xa9, 0x99, 0x72, 0x5e, 0xdd, - 0x23, 0xf3, 0x04, 0x26, 0x94, 0xf8, 0xec, 0x36, 0x37, 0x37, 0x30, 0x87, 0x92, 0x7f, 0x15, 0xf8, - 0xa3, 0xe1, 0xc6, 0xb8, 0x9f, 0x4f, 0xa5, 0x93, 0xe4, 0xd3, 0xd1, 0xb4, 0x5c, 0x8a, 0x1e, 0x40, - 0x9e, 0x6a, 0xfd, 0x7e, 0x16, 0x0a, 0xc4, 0xcd, 0x95, 0x46, 0x90, 0x90, 0x36, 0x57, 0x1a, 0x98, - 0x41, 0xa0, 0x75, 0x18, 0x62, 0xd5, 0x87, 0x6d, 0xc1, 0x7c, 0xff, 0x5b, 0x9a, 0xcd, 0x3f, 0x08, - 0x08, 0xf6, 0xcb, 0xc6, 0x2e, 0x8e, 0xfc, 0x09, 0x8c, 0x45, 0xf6, 0x29, 0xfa, 0x18, 0xce, 0x6a, - 0x86, 0xd2, 0xaa, 0x2b, 0x9a, 0xa2, 0x37, 0x89, 0x77, 0x39, 0x70, 0x29, 0xed, 0x0b, 0x63, 0x25, - 0xc4, 0x27, 0x76, 0xb9, 0x7f, 0x9d, 0x1a, 0xa6, 0xe1, 0x08, 0xa2, 0xac, 0x00, 0x04, 0x73, 0x44, - 0x15, 0x18, 0x62, 0x71, 0xe6, 0xd6, 0x93, 0x91, 0xfa, 0x08, 0xb3, 0x90, 0x85, 0x9f, 0x8d, 0xdd, - 0x71, 0x74, 0x03, 0xc0, 0x26, 0x4d, 0x8b, 0x50, 0x9e, 0x0c, 0x72, 0xd1, 0x4b, 0xe5, 0x86, 0x4f, - 0xc1, 0x21, 0x2e, 0xf9, 0x47, 0x12, 0x8c, 0xad, 0x11, 0xfa, 0xa9, 0x61, 0xed, 0x6d, 0xf0, 0xc7, - 0x00, 0xa7, 0x90, 0x6c, 0x71, 0x24, 0xd9, 0xbe, 0xd1, 0x63, 0x65, 0x22, 0xd6, 0x65, 0xa5, 0x5c, - 0xf9, 0x4b, 0x09, 0x66, 0x23, 0x9c, 0x77, 0x83, 0xad, 0xbb, 0x05, 0x43, 0xa6, 0x61, 0x51, 0xaf, - 0x10, 0x0f, 0xa4, 0x90, 0xa5, 0xb1, 0x50, 0x29, 0x66, 0x30, 0xd8, 0x45, 0x43, 0x2b, 0x90, 0xa3, - 0x86, 0x08, 0xd5, 0xc1, 0x30, 0x09, 0xb1, 0xea, 0x20, 0x30, 0x73, 0x9b, 0x06, 0xce, 0x51, 0x83, - 0x2d, 0x44, 0x39, 0xc2, 0x15, 0x4e, 0x3e, 0x2f, 0x68, 0x06, 0x18, 0x0a, 0x3b, 0x96, 0xd1, 0x39, - 0xf1, 0x1c, 0xfc, 0x85, 0xb8, 0x67, 0x19, 0x1d, 0xcc, 0xb1, 0xe4, 0xaf, 0x24, 0x98, 0x8a, 0x70, - 0x9e, 0x42, 0xe2, 0x7f, 0x18, 0x4d, 0xfc, 0x57, 0x07, 0x99, 0x48, 0x46, 0xfa, 0xff, 0x2a, 0x17, - 0x9b, 0x06, 0x9b, 0x30, 0xda, 0x81, 0x51, 0xd3, 0x68, 0x35, 0x9e, 0xc3, 0x75, 0xe0, 0x04, 0xab, - 0x9b, 0x1b, 0x01, 0x16, 0x0e, 0x03, 0xa3, 0x03, 0x98, 0xd2, 0x95, 0x0e, 0xb1, 0x4d, 0xa5, 0x49, - 0x1a, 0xcf, 0xe1, 0x80, 0xe4, 0x25, 0x7e, 0xdf, 0x10, 0x47, 0xc4, 0x49, 0x25, 0x68, 0x15, 0x8a, - 0xaa, 0xc9, 0xfb, 0x38, 0xd1, 0xbb, 0xf4, 0xac, 0xa2, 0x6e, 0xd7, 0xe7, 0xe6, 0x73, 0xf1, 0x03, - 0x7b, 0x18, 0xf2, 0x7f, 0xc6, 0xa3, 0x81, 0xc5, 0x1f, 0xba, 0x0f, 0x25, 0xfe, 0xac, 0xa6, 0x69, - 0x68, 0xde, 0xcd, 0x00, 0x5b, 0xd9, 0x0d, 0x31, 0xf6, 0xec, 0xb0, 0x72, 0x3e, 0xe5, 0xd0, 0xd7, - 0x23, 0x63, 0x5f, 0x18, 0xad, 0x41, 0xc1, 0xfc, 0x21, 0x1d, 0x0c, 0x2f, 0x72, 0xbc, 0x6d, 0xe1, - 0x38, 0xf2, 0x5f, 0xe7, 0x63, 0xe6, 0xf2, 0x52, 0xf7, 0xe4, 0xb9, 0xad, 0xba, 0xdf, 0x31, 0x65, - 0xae, 0xfc, 0x36, 0x14, 0x45, 0x85, 0x17, 0xc1, 0xfc, 0xf6, 0x20, 0xc1, 0x1c, 0xae, 0x62, 0xfe, - 0x07, 0x8b, 0x37, 0xe8, 0x01, 0xa3, 0x8f, 0x60, 0x98, 0xb8, 0x2a, 0xdc, 0xda, 0x78, 0x6b, 0x10, - 0x15, 0x41, 0x5e, 0x0d, 0x1a, 0x55, 0x31, 0x26, 0x50, 0xd1, 0x7b, 0xcc, 0x5f, 0x8c, 0x97, 0x7d, - 0x04, 0xda, 0xe5, 0x02, 0x2f, 0x57, 0x17, 0xdc, 0x69, 0xfb, 0xc3, 0xcf, 0x0e, 0x2b, 0x10, 0xfc, - 0xc4, 0x61, 0x09, 0xf9, 0x27, 0x12, 0x4c, 0x71, 0x0f, 0x35, 0x1d, 0x4b, 0xa5, 0xdd, 0x53, 0x2b, - 0x4c, 0x8f, 0x22, 0x85, 0xe9, 0xad, 0x1e, 0x6e, 0x49, 0x58, 0x98, 0x59, 0x9c, 0xbe, 0x96, 0xe0, - 0xa5, 0x04, 0xf7, 0x29, 0xe4, 0xc5, 0xad, 0x68, 0x5e, 0x7c, 0x63, 0xd0, 0x09, 0x65, 0xbd, 0x91, - 0x18, 0x4b, 0x99, 0x0e, 0xdf, 0x29, 0x37, 0x00, 0x4c, 0x4b, 0xdd, 0x57, 0x35, 0xd2, 0x16, 0x97, - 0xe0, 0xa5, 0xd0, 0xb3, 0x36, 0x9f, 0x82, 0x43, 0x5c, 0xc8, 0x86, 0x99, 0x16, 0xd9, 0x51, 0x1c, - 0x8d, 0x2e, 0xb4, 0x5a, 0x8b, 0x8a, 0xa9, 0x6c, 0xab, 0x9a, 0x4a, 0x55, 0x71, 0x5c, 0x30, 0x52, - 0xbf, 0xe3, 0x5e, 0x4e, 0xa7, 0x71, 0x3c, 0x3b, 0xac, 0x5c, 0x48, 0xbb, 0x1d, 0xf2, 0x58, 0xba, - 0x38, 0x03, 0x1a, 0x75, 0xa1, 0x6c, 0x91, 0x4f, 0x1c, 0xd5, 0x22, 0xad, 0x25, 0xcb, 0x30, 0x23, - 0x6a, 0xf3, 0x5c, 0xed, 0x1f, 0x1e, 0x1d, 0x56, 0xca, 0x38, 0x83, 0xa7, 0xb7, 0xe2, 0x4c, 0x78, - 0xf4, 0x04, 0xa6, 0x15, 0xf7, 0x35, 0x60, 0x44, 0xab, 0xbb, 0x4b, 0x6e, 0x1f, 0x1d, 0x56, 0xa6, - 0x17, 0x92, 0xe4, 0xde, 0x0a, 0xd3, 0x40, 0x51, 0x0d, 0x8a, 0xfb, 0xfc, 0xad, 0xa2, 0x5d, 0x1e, - 0xe2, 0xf8, 0xac, 0x10, 0x14, 0xdd, 0xe7, 0x8b, 0x0c, 0x73, 0xf8, 0x5e, 0x83, 0xef, 0x3e, 0x8f, - 0x8b, 0x7d, 0x50, 0xb2, 0x5e, 0x52, 0xec, 0x78, 0x7e, 0x62, 0x5c, 0x0a, 0xb2, 0xd6, 0x83, 0x80, - 0x84, 0xc3, 0x7c, 0xe8, 0x31, 0x8c, 0xec, 0x8a, 0x53, 0x09, 0xbb, 0x5c, 0xec, 0xab, 0x08, 0x47, - 0x4e, 0x31, 0xea, 0x53, 0x42, 0xc5, 0x88, 0x37, 0x6c, 0xe3, 0x00, 0x11, 0x5d, 0x81, 0x22, 0xff, - 0xb1, 0xbc, 0xc4, 0x8f, 0xe3, 0x4a, 0x41, 0x6e, 0x7b, 0xe0, 0x0e, 0x63, 0x8f, 0xee, 0xb1, 0x2e, - 0x6f, 0x2c, 0xf2, 0x63, 0xe1, 0x18, 0xeb, 0xf2, 0xc6, 0x22, 0xf6, 0xe8, 0xe8, 0x63, 0x28, 0xda, - 0x64, 0x45, 0xd5, 0x9d, 0x83, 0x32, 0xf4, 0x75, 0xa9, 0xdc, 0xb8, 0xcb, 0xb9, 0x63, 0x07, 0x63, - 0x81, 0x06, 0x41, 0xc7, 0x1e, 0x2c, 0xda, 0x85, 0x11, 0xcb, 0xd1, 0x17, 0xec, 0x2d, 0x9b, 0x58, - 0xe5, 0x51, 0xae, 0xa3, 0x57, 0x3a, 0xc7, 0x1e, 0x7f, 0x5c, 0x8b, 0xef, 0x21, 0x9f, 0x03, 0x07, - 0xe0, 0xe8, 0xef, 0x24, 0x40, 0xb6, 0x63, 0x9a, 0x1a, 0xe9, 0x10, 0x9d, 0x2a, 0x1a, 0x3f, 0x8b, - 0xb3, 0xcb, 0x67, 0xb9, 0xce, 0x3f, 0xea, 0x35, 0xaf, 0x84, 0x60, 0x5c, 0xb9, 0x7f, 0xe8, 0x9d, - 0x64, 0xc5, 0x29, 0x7a, 0x99, 0x6b, 0x77, 0x6c, 0xfe, 0x77, 0x79, 0xac, 0x2f, 0xd7, 0xa6, 0x9f, - 0x39, 0x06, 0xae, 0x15, 0x74, 0xec, 0xc1, 0xa2, 0x47, 0x30, 0x63, 0x11, 0xa5, 0xb5, 0xae, 0x6b, - 0x5d, 0x6c, 0x18, 0xf4, 0x9e, 0xaa, 0x11, 0xbb, 0x6b, 0x53, 0xd2, 0x29, 0x8f, 0xf3, 0x65, 0xf7, - 0xdf, 0x7e, 0xe0, 0x54, 0x2e, 0x9c, 0x21, 0x8d, 0x3a, 0x50, 0xf1, 0x52, 0x06, 0xdb, 0x4f, 0x7e, - 0xce, 0xba, 0x6b, 0x37, 0x15, 0xcd, 0xbd, 0x07, 0x98, 0xe0, 0x0a, 0x5e, 0x3b, 0x3a, 0xac, 0x54, - 0x96, 0x8e, 0x67, 0xc5, 0xbd, 0xb0, 0xd0, 0x07, 0x50, 0x56, 0xb2, 0xf4, 0x4c, 0x72, 0x3d, 0xaf, - 0xb0, 0x3c, 0x94, 0xa9, 0x20, 0x53, 0x1a, 0x51, 0x98, 0x54, 0xa2, 0x8f, 0x8e, 0xed, 0xf2, 0x54, - 0x5f, 0x07, 0x91, 0xb1, 0xb7, 0xca, 0xc1, 0x61, 0x44, 0x8c, 0x60, 0xe3, 0x84, 0x06, 0xf4, 0x17, - 0x80, 0x94, 0xf8, 0x3b, 0x69, 0xbb, 0x8c, 0xfa, 0x2a, 0x3f, 0x89, 0x07, 0xd6, 0x41, 0xd8, 0x25, - 0x48, 0x36, 0x4e, 0xd1, 0xc3, 0x1f, 0x6f, 0x88, 0xa3, 0xfc, 0xd3, 0x79, 0x00, 0x3b, 0xd8, 0xe3, - 0x8d, 0xc0, 0xb4, 0xe7, 0xf6, 0x78, 0x23, 0x04, 0x79, 0xfc, 0xe1, 0xe1, 0x2f, 0x72, 0x30, 0x1d, - 0x30, 0xf7, 0xfd, 0x78, 0x23, 0x45, 0xe4, 0x77, 0x8f, 0x60, 0x7b, 0x3f, 0x82, 0xfd, 0x52, 0x82, - 0xf1, 0xc0, 0x75, 0xbf, 0x79, 0x0f, 0x2a, 0x02, 0xdb, 0x32, 0x5a, 0xbc, 0xff, 0xce, 0x85, 0x27, - 0xf0, 0x5b, 0x7f, 0xab, 0xff, 0xc3, 0x5f, 0xae, 0xca, 0x5f, 0xe7, 0x61, 0x32, 0xbe, 0x1b, 0x23, - 0x97, 0xbf, 0x52, 0xcf, 0xcb, 0xdf, 0x0d, 0x38, 0xb7, 0xe3, 0x68, 0x5a, 0x97, 0xbb, 0x21, 0x74, - 0x03, 0xec, 0x5e, 0xde, 0xbc, 0x22, 0x24, 0xcf, 0xdd, 0x4b, 0xe1, 0xc1, 0xa9, 0x92, 0x19, 0x17, - 0xd9, 0xf9, 0x13, 0x5d, 0x64, 0x27, 0xee, 0x55, 0x0b, 0x03, 0xdc, 0xab, 0xa6, 0x5e, 0x4a, 0x0f, - 0x9d, 0xe0, 0x52, 0xfa, 0x24, 0xb7, 0xc8, 0x29, 0x49, 0xac, 0xe7, 0xa3, 0xc6, 0x57, 0x60, 0x4e, - 0x88, 0x51, 0x7e, 0xc1, 0xab, 0x53, 0xcb, 0xd0, 0x34, 0x62, 0x2d, 0x39, 0x9d, 0x4e, 0x57, 0x7e, - 0x17, 0xc6, 0xa3, 0x4f, 0x17, 0xdc, 0x95, 0x76, 0x5f, 0x4f, 0x88, 0x2b, 0xb4, 0xd0, 0x4a, 0xbb, - 0xe3, 0xd8, 0xe7, 0x90, 0xff, 0x46, 0x82, 0x99, 0xf4, 0x27, 0x8a, 0x48, 0x83, 0xf1, 0x8e, 0x72, - 0x10, 0x7e, 0x36, 0x2a, 0x9d, 0xf0, 0x70, 0x83, 0xdf, 0x59, 0xaf, 0x46, 0xb0, 0x70, 0x0c, 0x5b, - 0xfe, 0x5e, 0x82, 0xd9, 0x8c, 0xdb, 0xe2, 0xd3, 0xb5, 0x04, 0x7d, 0x08, 0xa5, 0x8e, 0x72, 0xd0, - 0x70, 0xac, 0x36, 0x39, 0xf1, 0x71, 0x0e, 0xcf, 0x18, 0xab, 0x02, 0x05, 0xfb, 0x78, 0xf2, 0xe7, - 0x12, 0x94, 0xb3, 0x1a, 0x6b, 0x74, 0x33, 0x72, 0xaf, 0xfd, 0x6a, 0xec, 0x5e, 0x7b, 0x2a, 0x21, - 0xf7, 0x82, 0x6e, 0xb5, 0xff, 0x4b, 0x82, 0x99, 0xf4, 0x0f, 0x0c, 0xf4, 0x66, 0xc4, 0xc2, 0x4a, - 0xcc, 0xc2, 0x89, 0x98, 0x94, 0xb0, 0xef, 0x23, 0x18, 0x17, 0x9f, 0x21, 0x02, 0x46, 0x78, 0x55, - 0x4e, 0xcb, 0x95, 0x02, 0xc2, 0x6b, 0xbb, 0xf9, 0x7a, 0x45, 0xc7, 0x70, 0x0c, 0x4d, 0xfe, 0xdb, - 0x1c, 0x0c, 0x35, 0x9a, 0x8a, 0x46, 0x4e, 0xa1, 0xcd, 0x7a, 0x3f, 0xd2, 0x66, 0xf5, 0xfa, 0x17, - 0x0f, 0x6e, 0x55, 0x66, 0x87, 0x85, 0x63, 0x1d, 0xd6, 0xeb, 0x7d, 0xa1, 0x1d, 0xdf, 0x5c, 0xfd, - 0x01, 0x8c, 0xf8, 0x4a, 0x07, 0xcb, 0xf9, 0xf2, 0xbf, 0xe7, 0x60, 0x34, 0xa4, 0x62, 0xc0, 0x8a, - 0xb1, 0x13, 0xa9, 0xb4, 0xfd, 0xfc, 0x63, 0x5d, 0x48, 0x57, 0xd5, 0xab, 0xad, 0xee, 0x13, 0xc5, - 0xe0, 0x51, 0x5a, 0xb2, 0xe4, 0xbe, 0x0b, 0xe3, 0x94, 0xff, 0xe3, 0x99, 0x7f, 0x08, 0x9a, 0xe7, - 0xb1, 0xe8, 0x3f, 0x6c, 0xdd, 0x8c, 0x50, 0x71, 0x8c, 0x7b, 0xee, 0x0e, 0x8c, 0x45, 0x94, 0x0d, - 0xf4, 0xc2, 0xf0, 0x7f, 0x25, 0x78, 0xb5, 0xe7, 0x27, 0x2a, 0xaa, 0x47, 0x36, 0x49, 0x35, 0xb6, - 0x49, 0xe6, 0xb3, 0x01, 0x5e, 0xdc, 0x4b, 0x95, 0xfa, 0xb5, 0xa7, 0xdf, 0xcd, 0x9f, 0xf9, 0xe6, - 0xbb, 0xf9, 0x33, 0xdf, 0x7e, 0x37, 0x7f, 0xe6, 0xaf, 0x8e, 0xe6, 0xa5, 0xa7, 0x47, 0xf3, 0xd2, - 0x37, 0x47, 0xf3, 0xd2, 0xb7, 0x47, 0xf3, 0xd2, 0xcf, 0x8e, 0xe6, 0xa5, 0x7f, 0xfc, 0x7e, 0xfe, - 0xcc, 0x87, 0x45, 0x01, 0xf7, 0xeb, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb1, 0xb3, 0xc8, 0xe2, 0x54, - 0x3c, 0x00, 0x00, + // 3637 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5b, 0xcb, 0x6f, 0x1c, 0x47, + 0x73, 0xd7, 0xec, 0x2e, 0xb9, 0xcb, 0xa2, 0xf8, 0x6a, 0xd2, 0xe4, 0x7e, 0x94, 0xc5, 0xd5, 0x37, + 0x06, 0x14, 0xc9, 0x91, 0x76, 0x2d, 0xd9, 0xd2, 0xa7, 0x58, 0x88, 0x6d, 0x2e, 0x29, 0x4a, 0x74, + 0xf8, 0x52, 0x2f, 0xa9, 0x38, 0x46, 0xe4, 0x78, 0xb8, 0xdb, 0x5c, 0x8e, 0x38, 0x3b, 0x33, 0x9e, + 0xe9, 0xa1, 0xb9, 0x40, 0x10, 0xe4, 0x10, 0x04, 0x08, 0x90, 0x20, 0xc9, 0xc1, 0x79, 0xdc, 0xe2, + 0x4b, 0x4e, 0x09, 0x92, 0x5b, 0x72, 0x30, 0x0c, 0x04, 0x70, 0x00, 0x21, 0x70, 0x00, 0xdf, 0xe2, + 0x13, 0x11, 0xd3, 0xa7, 0x20, 0xff, 0x40, 0xa0, 0x43, 0x10, 0x74, 0x4f, 0xcf, 0x7b, 0x86, 0xbb, + 0x4b, 0x4b, 0x44, 0x10, 0xe4, 0xc6, 0xed, 0xaa, 0xfa, 0x55, 0x75, 0x75, 0x75, 0x55, 0x4d, 0x77, + 0x13, 0x56, 0x0e, 0xee, 0xd9, 0x55, 0xd5, 0xa8, 0x1d, 0x38, 0xbb, 0xc4, 0xd2, 0x09, 0x25, 0x76, + 0xed, 0x90, 0xe8, 0x2d, 0xc3, 0xaa, 0x09, 0x82, 0x62, 0xaa, 0x35, 0x72, 0x44, 0x89, 0x6e, 0xab, + 0x86, 0x6e, 0xd7, 0x0e, 0x6f, 0xed, 0x12, 0xaa, 0xdc, 0xaa, 0xb5, 0x89, 0x4e, 0x2c, 0x85, 0x92, + 0x56, 0xd5, 0xb4, 0x0c, 0x6a, 0xa0, 0xcb, 0x2e, 0x7b, 0x55, 0x31, 0xd5, 0x6a, 0xc0, 0x5e, 0x15, + 0xec, 0xf3, 0x37, 0xdb, 0x2a, 0xdd, 0x77, 0x76, 0xab, 0x4d, 0xa3, 0x53, 0x6b, 0x1b, 0x6d, 0xa3, + 0xc6, 0xa5, 0x76, 0x9d, 0x3d, 0xfe, 0x8b, 0xff, 0xe0, 0x7f, 0xb9, 0x68, 0xf3, 0x72, 0x48, 0x79, + 0xd3, 0xb0, 0x48, 0xed, 0x30, 0xa1, 0x71, 0xfe, 0x7a, 0x88, 0xc7, 0x34, 0x34, 0xb5, 0xd9, 0xcd, + 0x32, 0x6e, 0xfe, 0x9d, 0x80, 0xb5, 0xa3, 0x34, 0xf7, 0x55, 0x9d, 0x58, 0xdd, 0x9a, 0x79, 0xd0, + 0xe6, 0xb2, 0x16, 0xb1, 0x0d, 0xc7, 0x6a, 0x92, 0x81, 0xa4, 0xec, 0x5a, 0x87, 0x50, 0x25, 0xcd, + 0xac, 0x5a, 0x96, 0x94, 0xe5, 0xe8, 0x54, 0xed, 0x24, 0xd5, 0xdc, 0xed, 0x25, 0x60, 0x37, 0xf7, + 0x49, 0x47, 0x49, 0xc8, 0xbd, 0x9d, 0x25, 0xe7, 0x50, 0x55, 0xab, 0xa9, 0x3a, 0xb5, 0xa9, 0x15, + 0x17, 0x92, 0xef, 0xc3, 0xd4, 0xa2, 0xa6, 0x19, 0x9f, 0x93, 0xd6, 0x8a, 0x46, 0x8e, 0x9e, 0x18, + 0x9a, 0xd3, 0x21, 0xe8, 0x2a, 0x0c, 0xb7, 0x2c, 0xf5, 0x90, 0x58, 0x65, 0xe9, 0x8a, 0x74, 0x6d, + 0xa4, 0x3e, 0xfe, 0xfc, 0xb8, 0x72, 0xe1, 0xe4, 0xb8, 0x32, 0xbc, 0xcc, 0x47, 0xb1, 0xa0, 0xca, + 0x36, 0x4c, 0x08, 0xe1, 0x47, 0x86, 0x4d, 0xb7, 0x14, 0xba, 0x8f, 0x6e, 0x03, 0x98, 0x0a, 0xdd, + 0xdf, 0xb2, 0xc8, 0x9e, 0x7a, 0x24, 0xc4, 0x91, 0x10, 0x87, 0x2d, 0x9f, 0x82, 0x43, 0x5c, 0xe8, + 0x06, 0x94, 0x2c, 0xa2, 0xb4, 0x36, 0x75, 0xad, 0x5b, 0xce, 0x5d, 0x91, 0xae, 0x95, 0xea, 0x93, + 0x42, 0xa2, 0x84, 0xc5, 0x38, 0xf6, 0x39, 0xe4, 0xbf, 0x94, 0xe0, 0x67, 0x4b, 0x8e, 0x4d, 0x8d, + 0xce, 0x3a, 0xa1, 0x96, 0xda, 0x5c, 0x72, 0x2c, 0x8b, 0xe8, 0xb4, 0x41, 0x15, 0xea, 0xd8, 0xe8, + 0x0a, 0x14, 0x74, 0xa5, 0x43, 0x84, 0xe6, 0x8b, 0x02, 0xa7, 0xb0, 0xa1, 0x74, 0x08, 0xe6, 0x14, + 0xf4, 0x31, 0x0c, 0x1d, 0x2a, 0x9a, 0x43, 0xb8, 0xaa, 0xd1, 0xdb, 0xd5, 0x6a, 0x10, 0xa8, 0xbe, + 0xdb, 0xaa, 0xe6, 0x41, 0x9b, 0x47, 0xae, 0x17, 0x0b, 0xd5, 0xc7, 0x8e, 0xa2, 0x53, 0x95, 0x76, + 0xeb, 0x33, 0x02, 0xf2, 0xa2, 0xd0, 0xfb, 0x84, 0x61, 0x61, 0x17, 0x52, 0xfe, 0x1d, 0xb8, 0x9c, + 0x69, 0xda, 0x9a, 0x6a, 0x53, 0xf4, 0x14, 0x86, 0x54, 0x4a, 0x3a, 0x76, 0x59, 0xba, 0x92, 0xbf, + 0x36, 0x7a, 0xfb, 0x5e, 0xf5, 0xd4, 0x5d, 0x52, 0xcd, 0x04, 0xab, 0x8f, 0x09, 0x33, 0x86, 0x56, + 0x19, 0x1c, 0x76, 0x51, 0xe5, 0x3f, 0x95, 0x00, 0x85, 0x65, 0xb6, 0x15, 0xab, 0x4d, 0x68, 0x1f, + 0x4e, 0xf9, 0x8d, 0x9f, 0xe6, 0x94, 0x69, 0x01, 0x39, 0xea, 0x2a, 0x8c, 0xf8, 0xc4, 0x84, 0xd9, + 0xa4, 0x49, 0xdc, 0x19, 0x4f, 0xa2, 0xce, 0xb8, 0x35, 0x80, 0x33, 0x5c, 0x94, 0x0c, 0x2f, 0x7c, + 0x91, 0x83, 0x91, 0x65, 0x85, 0x74, 0x0c, 0xbd, 0x41, 0x28, 0xfa, 0x14, 0x4a, 0x6c, 0x6b, 0xb6, + 0x14, 0xaa, 0x70, 0x07, 0x8c, 0xde, 0x7e, 0xeb, 0xb4, 0xd9, 0xd9, 0x55, 0xc6, 0x5d, 0x3d, 0xbc, + 0x55, 0xdd, 0xdc, 0x7d, 0x46, 0x9a, 0x74, 0x9d, 0x50, 0x25, 0x88, 0xe0, 0x60, 0x0c, 0xfb, 0xa8, + 0x68, 0x03, 0x0a, 0xb6, 0x49, 0x9a, 0xc2, 0x77, 0x37, 0x7a, 0x4c, 0xc3, 0xb7, 0xac, 0x61, 0x92, + 0x66, 0xb0, 0x18, 0xec, 0x17, 0xe6, 0x38, 0xe8, 0x09, 0x0c, 0xdb, 0x7c, 0x95, 0xcb, 0xf9, 0xc4, + 0x6a, 0x9c, 0x8e, 0xe8, 0xc6, 0x86, 0xbf, 0x5d, 0xdd, 0xdf, 0x58, 0xa0, 0xc9, 0xff, 0x91, 0x03, + 0xe4, 0xf3, 0x2e, 0x19, 0x7a, 0x4b, 0xa5, 0xaa, 0xa1, 0xa3, 0x77, 0xa1, 0x40, 0xbb, 0xa6, 0x17, + 0x1d, 0x57, 0x3d, 0x83, 0xb6, 0xbb, 0x26, 0x79, 0x71, 0x5c, 0x99, 0x4d, 0x4a, 0x30, 0x0a, 0xe6, + 0x32, 0x68, 0xcd, 0x37, 0x35, 0xc7, 0xa5, 0xdf, 0x89, 0xaa, 0x7e, 0x71, 0x5c, 0x49, 0xc9, 0xdc, + 0x55, 0x1f, 0x29, 0x6a, 0x20, 0x3a, 0x04, 0xa4, 0x29, 0x36, 0xdd, 0xb6, 0x14, 0xdd, 0x76, 0x35, + 0xa9, 0x1d, 0x22, 0x9c, 0xf0, 0x66, 0x7f, 0x8b, 0xc6, 0x24, 0xea, 0xf3, 0xc2, 0x0a, 0xb4, 0x96, + 0x40, 0xc3, 0x29, 0x1a, 0x58, 0xbe, 0xb3, 0x88, 0x62, 0x1b, 0x7a, 0xb9, 0x10, 0xcd, 0x77, 0x98, + 0x8f, 0x62, 0x41, 0x45, 0xd7, 0xa1, 0xd8, 0x21, 0xb6, 0xad, 0xb4, 0x49, 0x79, 0x88, 0x33, 0x4e, + 0x08, 0xc6, 0xe2, 0xba, 0x3b, 0x8c, 0x3d, 0xba, 0xfc, 0x95, 0x04, 0x63, 0xbe, 0xe7, 0x78, 0xb4, + 0xff, 0x66, 0x22, 0x0e, 0xab, 0xfd, 0x4d, 0x89, 0x49, 0xf3, 0x28, 0xf4, 0xb3, 0xa2, 0x37, 0x12, + 0x8a, 0xc1, 0x75, 0x6f, 0x2f, 0xe5, 0xf8, 0x5e, 0xba, 0xd6, 0x6f, 0xc8, 0x64, 0x6c, 0xa1, 0x3f, + 0x2b, 0x84, 0xcc, 0x67, 0xa1, 0x89, 0x9e, 0x42, 0xc9, 0x26, 0x1a, 0x69, 0x52, 0xc3, 0x12, 0xe6, + 0xbf, 0xdd, 0xa7, 0xf9, 0xca, 0x2e, 0xd1, 0x1a, 0x42, 0xb4, 0x7e, 0x91, 0xd9, 0xef, 0xfd, 0xc2, + 0x3e, 0x24, 0x7a, 0x0c, 0x25, 0x4a, 0x3a, 0xa6, 0xa6, 0x50, 0x2f, 0x07, 0xbd, 0x11, 0x9e, 0x02, + 0x8b, 0x1c, 0x06, 0xb6, 0x65, 0xb4, 0xb6, 0x05, 0x1b, 0xdf, 0x3e, 0xbe, 0x4b, 0xbc, 0x51, 0xec, + 0xc3, 0xa0, 0x43, 0x18, 0x77, 0xcc, 0x16, 0xe3, 0xa4, 0xac, 0xe2, 0xb5, 0xbb, 0x22, 0x92, 0xee, + 0xf6, 0xeb, 0x9b, 0x9d, 0x88, 0x74, 0x7d, 0x56, 0xe8, 0x1a, 0x8f, 0x8e, 0xe3, 0x98, 0x16, 0xb4, + 0x08, 0x13, 0x1d, 0x55, 0x67, 0x95, 0xab, 0xdb, 0x20, 0x4d, 0x43, 0x6f, 0xd9, 0x3c, 0xac, 0x86, + 0xea, 0x73, 0x02, 0x60, 0x62, 0x3d, 0x4a, 0xc6, 0x71, 0x7e, 0xf4, 0x21, 0x20, 0x6f, 0x1a, 0x0f, + 0xdd, 0x82, 0xad, 0x1a, 0x3a, 0x8f, 0xb9, 0x7c, 0x10, 0xdc, 0xdb, 0x09, 0x0e, 0x9c, 0x22, 0x85, + 0xd6, 0x60, 0xc6, 0x22, 0x87, 0x2a, 0x9b, 0xe3, 0x23, 0xd5, 0xa6, 0x86, 0xd5, 0x5d, 0x53, 0x3b, + 0x2a, 0x2d, 0x0f, 0x73, 0x9b, 0xca, 0x27, 0xc7, 0x95, 0x19, 0x9c, 0x42, 0xc7, 0xa9, 0x52, 0xf2, + 0x9f, 0x0f, 0xc3, 0x44, 0x2c, 0xdf, 0xa0, 0x27, 0x30, 0xdb, 0x74, 0x8b, 0xd3, 0x86, 0xd3, 0xd9, + 0x25, 0x56, 0xa3, 0xb9, 0x4f, 0x5a, 0x8e, 0x46, 0x5a, 0x3c, 0x50, 0x86, 0xea, 0x0b, 0xc2, 0xe2, + 0xd9, 0xa5, 0x54, 0x2e, 0x9c, 0x21, 0xcd, 0xbc, 0xa0, 0xf3, 0xa1, 0x75, 0xd5, 0xb6, 0x7d, 0xcc, + 0x1c, 0xc7, 0xf4, 0xbd, 0xb0, 0x91, 0xe0, 0xc0, 0x29, 0x52, 0xcc, 0xc6, 0x16, 0xb1, 0x55, 0x8b, + 0xb4, 0xe2, 0x36, 0xe6, 0xa3, 0x36, 0x2e, 0xa7, 0x72, 0xe1, 0x0c, 0x69, 0x74, 0x07, 0x46, 0x5d, + 0x6d, 0x7c, 0xfd, 0xc4, 0x42, 0xfb, 0xe5, 0x70, 0x23, 0x20, 0xe1, 0x30, 0x1f, 0x9b, 0x9a, 0xb1, + 0x6b, 0x13, 0xeb, 0x90, 0xb4, 0xb2, 0x17, 0x78, 0x33, 0xc1, 0x81, 0x53, 0xa4, 0xd8, 0xd4, 0xdc, + 0x08, 0x4c, 0x4c, 0x6d, 0x38, 0x3a, 0xb5, 0x9d, 0x54, 0x2e, 0x9c, 0x21, 0xcd, 0xe2, 0xd8, 0x35, + 0x79, 0xf1, 0x50, 0x51, 0x35, 0x65, 0x57, 0x23, 0xe5, 0x62, 0x34, 0x8e, 0x37, 0xa2, 0x64, 0x1c, + 0xe7, 0x47, 0x0f, 0x61, 0xca, 0x1d, 0xda, 0xd1, 0x15, 0x1f, 0xa4, 0xc4, 0x41, 0x7e, 0x26, 0x40, + 0xa6, 0x36, 0xe2, 0x0c, 0x38, 0x29, 0x83, 0xde, 0x85, 0xf1, 0xa6, 0xa1, 0x69, 0x3c, 0x1e, 0x97, + 0x0c, 0x47, 0xa7, 0xe5, 0x11, 0x8e, 0x82, 0xd8, 0x7e, 0x5c, 0x8a, 0x50, 0x70, 0x8c, 0x13, 0x11, + 0x80, 0xa6, 0x57, 0x70, 0xec, 0x32, 0xf4, 0xd5, 0x6b, 0x24, 0x8b, 0x5e, 0xd0, 0x03, 0xf8, 0x43, + 0x36, 0x0e, 0x01, 0xcb, 0xff, 0x22, 0xc1, 0x5c, 0x46, 0xea, 0x40, 0xef, 0x47, 0x4a, 0xec, 0x2f, + 0xc7, 0x4a, 0xec, 0xa5, 0x0c, 0xb1, 0x50, 0x9d, 0xd5, 0x61, 0xcc, 0x62, 0xb3, 0xd2, 0xdb, 0x2e, + 0x8b, 0xc8, 0x91, 0x77, 0x7a, 0x4c, 0x03, 0x87, 0x65, 0x82, 0x9c, 0x3f, 0x75, 0x72, 0x5c, 0x19, + 0x8b, 0xd0, 0x70, 0x14, 0x5e, 0xfe, 0x8b, 0x1c, 0xc0, 0x32, 0x31, 0x35, 0xa3, 0xdb, 0x21, 0xfa, + 0x79, 0xf4, 0x50, 0x9b, 0x91, 0x1e, 0xea, 0x66, 0xaf, 0xe5, 0xf1, 0x4d, 0xcb, 0x6c, 0xa2, 0x7e, + 0x3d, 0xd6, 0x44, 0xd5, 0xfa, 0x87, 0x3c, 0xbd, 0x8b, 0xfa, 0xb7, 0x3c, 0x4c, 0x07, 0xcc, 0x41, + 0x1b, 0x75, 0x3f, 0xb2, 0xc6, 0xbf, 0x14, 0x5b, 0xe3, 0xb9, 0x14, 0x91, 0x57, 0xd6, 0x47, 0xbd, + 0xfc, 0x7e, 0x06, 0x3d, 0x83, 0x71, 0xd6, 0x38, 0xb9, 0xe1, 0xc1, 0xdb, 0xb2, 0xe1, 0x81, 0xdb, + 0x32, 0xbf, 0x80, 0xae, 0x45, 0x90, 0x70, 0x0c, 0x39, 0xa3, 0x0d, 0x2c, 0xbe, 0xea, 0x36, 0x50, + 0xfe, 0x5a, 0x82, 0xf1, 0x60, 0x99, 0xce, 0xa1, 0x69, 0xdb, 0x88, 0x36, 0x6d, 0xd7, 0xfb, 0x0e, + 0xd1, 0x8c, 0xae, 0xed, 0xbf, 0x58, 0x83, 0xef, 0x33, 0xb1, 0x0d, 0xbe, 0xab, 0x34, 0x0f, 0xfa, + 0xf8, 0xfc, 0xfb, 0x42, 0x02, 0x24, 0xaa, 0xc0, 0xa2, 0xae, 0x1b, 0x54, 0x71, 0x73, 0xa5, 0x6b, + 0xd6, 0x6a, 0xdf, 0x66, 0x79, 0x1a, 0xab, 0x3b, 0x09, 0xac, 0x07, 0x3a, 0xb5, 0xba, 0xc1, 0x8a, + 0x24, 0x19, 0x70, 0x8a, 0x01, 0x48, 0x01, 0xb0, 0x04, 0xe6, 0xb6, 0x21, 0x36, 0xf2, 0xcd, 0x3e, + 0x72, 0x1e, 0x13, 0x58, 0x32, 0xf4, 0x3d, 0xb5, 0x1d, 0xa4, 0x1d, 0xec, 0x03, 0xe1, 0x10, 0xe8, + 0xfc, 0x03, 0x98, 0xcb, 0xb0, 0x16, 0x4d, 0x42, 0xfe, 0x80, 0x74, 0x5d, 0xb7, 0x61, 0xf6, 0x27, + 0x9a, 0x09, 0x7f, 0x26, 0x8f, 0x88, 0x2f, 0xdc, 0x77, 0x73, 0xf7, 0x24, 0xf9, 0xab, 0xa1, 0x70, + 0xec, 0xf0, 0x8e, 0xf9, 0x1a, 0x94, 0x2c, 0x62, 0x6a, 0x6a, 0x53, 0xb1, 0x45, 0x23, 0x74, 0xd1, + 0x3d, 0xd2, 0x70, 0xc7, 0xb0, 0x4f, 0x8d, 0xf4, 0xd6, 0xb9, 0x57, 0xdb, 0x5b, 0xe7, 0x5f, 0x4e, + 0x6f, 0xfd, 0x5b, 0x50, 0xb2, 0xbd, 0xae, 0xba, 0xc0, 0x21, 0x6f, 0x0d, 0x90, 0x5f, 0x45, 0x43, + 0xed, 0x2b, 0xf0, 0x5b, 0x69, 0x1f, 0x34, 0xad, 0x89, 0x1e, 0x1a, 0xb0, 0x89, 0x7e, 0xa9, 0x8d, + 0x2f, 0xcb, 0xa9, 0xa6, 0xe2, 0xd8, 0xa4, 0xc5, 0x13, 0x51, 0x29, 0xc8, 0xa9, 0x5b, 0x7c, 0x14, + 0x0b, 0x2a, 0x7a, 0x1a, 0x09, 0xd9, 0xd2, 0x59, 0x42, 0x76, 0x3c, 0x3b, 0x5c, 0xd1, 0x0e, 0xcc, + 0x99, 0x96, 0xd1, 0xb6, 0x88, 0x6d, 0x2f, 0x13, 0xa5, 0xa5, 0xa9, 0x3a, 0xf1, 0xfc, 0xe3, 0x76, + 0x44, 0x97, 0x4e, 0x8e, 0x2b, 0x73, 0x5b, 0xe9, 0x2c, 0x38, 0x4b, 0x56, 0x7e, 0x5e, 0x80, 0xc9, + 0x78, 0x05, 0xcc, 0x68, 0x52, 0xa5, 0x33, 0x35, 0xa9, 0x37, 0x42, 0x9b, 0xc1, 0xed, 0xe0, 0x43, + 0x67, 0x7c, 0x89, 0x0d, 0xb1, 0x08, 0x13, 0x22, 0x1b, 0x78, 0x44, 0xd1, 0xa6, 0xfb, 0xab, 0xbf, + 0x13, 0x25, 0xe3, 0x38, 0x3f, 0x6b, 0x3d, 0x83, 0x8e, 0xd2, 0x03, 0x29, 0x44, 0x5b, 0xcf, 0xc5, + 0x38, 0x03, 0x4e, 0xca, 0xa0, 0x75, 0x98, 0x76, 0xf4, 0x24, 0x94, 0x1b, 0x8d, 0x97, 0x04, 0xd4, + 0xf4, 0x4e, 0x92, 0x05, 0xa7, 0xc9, 0xa1, 0xbd, 0x48, 0x37, 0x3a, 0xcc, 0x33, 0xec, 0xed, 0xbe, + 0xf7, 0x4e, 0xdf, 0xed, 0x28, 0xba, 0x0f, 0x63, 0x16, 0xff, 0xee, 0xf0, 0x0c, 0x76, 0x7b, 0xf7, + 0xd7, 0x84, 0xd8, 0x18, 0x0e, 0x13, 0x71, 0x94, 0x37, 0xa5, 0xdd, 0x2e, 0xf5, 0xdb, 0x6e, 0xcb, + 0xff, 0x24, 0x85, 0x8b, 0x90, 0xdf, 0x02, 0xf7, 0x3a, 0x65, 0x4a, 0x48, 0x84, 0xba, 0x23, 0x23, + 0xbd, 0xfb, 0xbd, 0x3b, 0x50, 0xf7, 0x1b, 0x14, 0xcf, 0xde, 0xed, 0xef, 0x97, 0x12, 0xcc, 0xae, + 0x34, 0x1e, 0x5a, 0x86, 0x63, 0x7a, 0xe6, 0x6c, 0x9a, 0xae, 0x5f, 0x7f, 0x01, 0x05, 0xcb, 0xd1, + 0xbc, 0x79, 0xbc, 0xe1, 0xcd, 0x03, 0x3b, 0x1a, 0x9b, 0xc7, 0x74, 0x4c, 0xca, 0x9d, 0x04, 0x13, + 0x40, 0x1b, 0x30, 0x6c, 0x29, 0x7a, 0x9b, 0x78, 0x65, 0xf5, 0x6a, 0x0f, 0xeb, 0x57, 0x97, 0x31, + 0x63, 0x0f, 0x35, 0x6f, 0x5c, 0x1a, 0x0b, 0x14, 0xf9, 0x8f, 0x24, 0x98, 0x78, 0xb4, 0xbd, 0xbd, + 0xb5, 0xaa, 0xf3, 0x1d, 0xcd, 0x4f, 0xdf, 0xaf, 0x40, 0xc1, 0x54, 0xe8, 0x7e, 0xbc, 0xd2, 0x33, + 0x1a, 0xe6, 0x14, 0xf4, 0x11, 0x14, 0x59, 0x26, 0x21, 0x7a, 0xab, 0xcf, 0x56, 0x5b, 0xc0, 0xd7, + 0x5d, 0xa1, 0xa0, 0x43, 0x14, 0x03, 0xd8, 0x83, 0x93, 0x0f, 0x60, 0x26, 0x64, 0x0e, 0xf3, 0x07, + 0x3f, 0x06, 0x46, 0x0d, 0x18, 0x62, 0x9a, 0xbd, 0x53, 0xde, 0x5e, 0x87, 0x99, 0xb1, 0x29, 0x05, + 0x9d, 0x0e, 0xfb, 0x65, 0x63, 0x17, 0x4b, 0x5e, 0x87, 0x31, 0x7e, 0xe5, 0x60, 0x58, 0x94, 0xbb, + 0x05, 0x5d, 0x86, 0x7c, 0x47, 0xd5, 0x45, 0x9d, 0x1d, 0x15, 0x32, 0x79, 0x56, 0x23, 0xd8, 0x38, + 0x27, 0x2b, 0x47, 0x22, 0xf3, 0x04, 0x64, 0xe5, 0x08, 0xb3, 0x71, 0xf9, 0x21, 0x14, 0x85, 0xbb, + 0xc3, 0x40, 0xf9, 0xd3, 0x81, 0xf2, 0x29, 0x40, 0x9b, 0x50, 0x5c, 0xdd, 0xaa, 0x6b, 0x86, 0xdb, + 0x75, 0x35, 0xd5, 0x96, 0x15, 0x5f, 0x8b, 0xa5, 0xd5, 0x65, 0x8c, 0x39, 0x05, 0xc9, 0x30, 0x4c, + 0x8e, 0x9a, 0xc4, 0xa4, 0x3c, 0x22, 0x46, 0xea, 0xc0, 0x56, 0xf9, 0x01, 0x1f, 0xc1, 0x82, 0x22, + 0xff, 0x71, 0x0e, 0x8a, 0xc2, 0x1d, 0xe7, 0xf0, 0x15, 0xb6, 0x16, 0xf9, 0x0a, 0x7b, 0xb3, 0xbf, + 0xd0, 0xc8, 0xfc, 0x04, 0xdb, 0x8e, 0x7d, 0x82, 0xdd, 0xe8, 0x13, 0xef, 0xf4, 0xef, 0xaf, 0xbf, + 0x97, 0x60, 0x3c, 0x1a, 0x94, 0xe8, 0x0e, 0x8c, 0xb2, 0x82, 0xa3, 0x36, 0xc9, 0x46, 0xd0, 0xe7, + 0xfa, 0x87, 0x30, 0x8d, 0x80, 0x84, 0xc3, 0x7c, 0xa8, 0xed, 0x8b, 0xb1, 0x38, 0x12, 0x93, 0xce, + 0x76, 0xa9, 0x43, 0x55, 0xad, 0xea, 0x5e, 0xa3, 0x55, 0x57, 0x75, 0xba, 0x69, 0x35, 0xa8, 0xa5, + 0xea, 0xed, 0x84, 0x22, 0x1e, 0x94, 0x61, 0x64, 0xf9, 0x1f, 0x25, 0x18, 0x15, 0x26, 0x9f, 0xc3, + 0x57, 0xc5, 0xaf, 0x45, 0xbf, 0x2a, 0xae, 0xf6, 0xb9, 0xc1, 0xd3, 0x3f, 0x29, 0xfe, 0x3a, 0x30, + 0x9d, 0x6d, 0x69, 0x16, 0xd5, 0xfb, 0x86, 0x4d, 0xe3, 0x51, 0xcd, 0x36, 0x23, 0xe6, 0x14, 0xe4, + 0xc0, 0xa4, 0x1a, 0xcb, 0x01, 0xc2, 0xb5, 0xb5, 0xfe, 0x2c, 0xf1, 0xc5, 0xea, 0x65, 0x01, 0x3f, + 0x19, 0xa7, 0xe0, 0x84, 0x0a, 0x99, 0x40, 0x82, 0x0b, 0x3d, 0x86, 0xc2, 0x3e, 0xa5, 0x66, 0xca, + 0x79, 0x75, 0x8f, 0xcc, 0x13, 0x98, 0x50, 0xe2, 0xb3, 0xdb, 0xde, 0xde, 0xc2, 0x1c, 0x4a, 0xfe, + 0xef, 0xc0, 0x1f, 0x0d, 0x37, 0xc6, 0xfd, 0x7c, 0x2a, 0x9d, 0x25, 0x9f, 0x8e, 0xa6, 0xe5, 0x52, + 0xf4, 0x08, 0xf2, 0x54, 0xeb, 0xf7, 0xb3, 0x50, 0x20, 0x6e, 0xaf, 0x35, 0x82, 0x84, 0xb4, 0xbd, + 0xd6, 0xc0, 0x0c, 0x02, 0x6d, 0xc2, 0x10, 0xab, 0x3e, 0x6c, 0x0b, 0xe6, 0xfb, 0xdf, 0xd2, 0x6c, + 0xfe, 0x41, 0x40, 0xb0, 0x5f, 0x36, 0x76, 0x71, 0xe4, 0xcf, 0x60, 0x2c, 0xb2, 0x4f, 0xd1, 0xa7, + 0x70, 0x51, 0x33, 0x94, 0x56, 0x5d, 0xd1, 0x14, 0xbd, 0x49, 0xbc, 0xcb, 0x81, 0xab, 0x69, 0x5f, + 0x18, 0x6b, 0x21, 0x3e, 0xb1, 0xcb, 0xfd, 0xeb, 0xd4, 0x30, 0x0d, 0x47, 0x10, 0x65, 0x05, 0x20, + 0x98, 0x23, 0xaa, 0xc0, 0x10, 0x8b, 0x33, 0xb7, 0x9e, 0x8c, 0xd4, 0x47, 0x98, 0x85, 0x2c, 0xfc, + 0x6c, 0xec, 0x8e, 0xa3, 0xdb, 0x00, 0x36, 0x69, 0x5a, 0x84, 0xf2, 0x64, 0x90, 0x8b, 0x5e, 0x41, + 0x37, 0x7c, 0x0a, 0x0e, 0x71, 0xc9, 0xff, 0x2c, 0xc1, 0xd8, 0x06, 0xa1, 0x9f, 0x1b, 0xd6, 0xc1, + 0x16, 0x7f, 0x3a, 0x70, 0x0e, 0xc9, 0x16, 0x47, 0x92, 0xed, 0x5b, 0x3d, 0x56, 0x26, 0x62, 0x5d, + 0x56, 0xca, 0x95, 0xbf, 0x96, 0x60, 0x2e, 0xc2, 0xf9, 0x20, 0xd8, 0xba, 0x3b, 0x30, 0x64, 0x1a, + 0x16, 0xf5, 0x0a, 0xf1, 0x40, 0x0a, 0x59, 0x1a, 0x0b, 0x95, 0x62, 0x06, 0x83, 0x5d, 0x34, 0xb4, + 0x06, 0x39, 0x6a, 0x88, 0x50, 0x1d, 0x0c, 0x93, 0x10, 0xab, 0x0e, 0x02, 0x33, 0xb7, 0x6d, 0xe0, + 0x1c, 0x35, 0xd8, 0x42, 0x94, 0x23, 0x5c, 0xe1, 0xe4, 0xf3, 0x8a, 0x66, 0x80, 0xa1, 0xb0, 0x67, + 0x19, 0x9d, 0x33, 0xcf, 0xc1, 0x5f, 0x88, 0x15, 0xcb, 0xe8, 0x60, 0x8e, 0x25, 0x7f, 0x23, 0xc1, + 0x54, 0x84, 0xf3, 0x1c, 0x12, 0xff, 0xe3, 0x68, 0xe2, 0xbf, 0x31, 0xc8, 0x44, 0x32, 0xd2, 0xff, + 0x37, 0xb9, 0xd8, 0x34, 0xd8, 0x84, 0xd1, 0x1e, 0x8c, 0x9a, 0x46, 0xab, 0xf1, 0x12, 0xae, 0x03, + 0x27, 0x58, 0xdd, 0xdc, 0x0a, 0xb0, 0x70, 0x18, 0x18, 0x1d, 0xc1, 0x94, 0xae, 0x74, 0x88, 0x6d, + 0x2a, 0x4d, 0xd2, 0x78, 0x09, 0x07, 0x24, 0xaf, 0xf1, 0xfb, 0x86, 0x38, 0x22, 0x4e, 0x2a, 0x41, + 0xeb, 0x50, 0x54, 0x4d, 0xde, 0xc7, 0x89, 0xde, 0xa5, 0x67, 0x15, 0x75, 0xbb, 0x3e, 0x37, 0x9f, + 0x8b, 0x1f, 0xd8, 0xc3, 0x90, 0xff, 0x26, 0x1e, 0x0d, 0x2c, 0xfe, 0xd0, 0x43, 0x28, 0xf1, 0x47, + 0x38, 0x4d, 0x43, 0xf3, 0x6e, 0x06, 0xd8, 0xca, 0x6e, 0x89, 0xb1, 0x17, 0xc7, 0x95, 0x4b, 0x29, + 0x87, 0xbe, 0x1e, 0x19, 0xfb, 0xc2, 0x68, 0x03, 0x0a, 0xe6, 0x4f, 0xe9, 0x60, 0x78, 0x91, 0xe3, + 0x6d, 0x0b, 0xc7, 0x91, 0x7f, 0x2f, 0x1f, 0x33, 0x97, 0x97, 0xba, 0x67, 0x2f, 0x6d, 0xd5, 0xfd, + 0x8e, 0x29, 0x73, 0xe5, 0x77, 0xa1, 0x28, 0x2a, 0xbc, 0x08, 0xe6, 0x5f, 0x0c, 0x12, 0xcc, 0xe1, + 0x2a, 0xe6, 0x7f, 0xb0, 0x78, 0x83, 0x1e, 0x30, 0xfa, 0x04, 0x86, 0x89, 0xab, 0xc2, 0xad, 0x8d, + 0x77, 0x07, 0x51, 0x11, 0xe4, 0xd5, 0xa0, 0x51, 0x15, 0x63, 0x02, 0x15, 0xbd, 0xcf, 0xfc, 0xc5, + 0x78, 0xd9, 0x47, 0xa0, 0x5d, 0x2e, 0xf0, 0x72, 0x75, 0xd9, 0x9d, 0xb6, 0x3f, 0xfc, 0xe2, 0xb8, + 0x02, 0xc1, 0x4f, 0x1c, 0x96, 0x90, 0xff, 0x55, 0x82, 0x29, 0xee, 0xa1, 0xa6, 0x63, 0xa9, 0xb4, + 0x7b, 0x6e, 0x85, 0xe9, 0x49, 0xa4, 0x30, 0xbd, 0xd3, 0xc3, 0x2d, 0x09, 0x0b, 0x33, 0x8b, 0xd3, + 0xb7, 0x12, 0xbc, 0x96, 0xe0, 0x3e, 0x87, 0xbc, 0xb8, 0x13, 0xcd, 0x8b, 0x6f, 0x0d, 0x3a, 0xa1, + 0xac, 0xd6, 0x78, 0x3c, 0x65, 0x3a, 0x7c, 0xa7, 0xdc, 0x06, 0x30, 0x2d, 0xf5, 0x50, 0xd5, 0x48, + 0x5b, 0x5c, 0x82, 0x97, 0x42, 0x8f, 0xe0, 0x7c, 0x0a, 0x0e, 0x71, 0x21, 0x1b, 0x66, 0x5b, 0x64, + 0x4f, 0x71, 0x34, 0xba, 0xd8, 0x6a, 0x2d, 0x29, 0xa6, 0xb2, 0xab, 0x6a, 0x2a, 0x55, 0xc5, 0x71, + 0xc1, 0x48, 0xfd, 0xbe, 0x7b, 0x39, 0x9d, 0xc6, 0xf1, 0xe2, 0xb8, 0x72, 0x39, 0xed, 0x76, 0xc8, + 0x63, 0xe9, 0xe2, 0x0c, 0x68, 0xd4, 0x85, 0xb2, 0x45, 0x3e, 0x73, 0x54, 0x8b, 0xb4, 0x96, 0x2d, + 0xc3, 0x8c, 0xa8, 0xcd, 0x73, 0xb5, 0xbf, 0x7a, 0x72, 0x5c, 0x29, 0xe3, 0x0c, 0x9e, 0xde, 0x8a, + 0x33, 0xe1, 0xd1, 0x33, 0x98, 0x56, 0xdc, 0xb7, 0x83, 0x11, 0xad, 0xee, 0x2e, 0xb9, 0x77, 0x72, + 0x5c, 0x99, 0x5e, 0x4c, 0x92, 0x7b, 0x2b, 0x4c, 0x03, 0x45, 0x35, 0x28, 0x1e, 0xf2, 0x97, 0x8d, + 0x76, 0x79, 0x88, 0xe3, 0xb3, 0x42, 0x50, 0x74, 0x1f, 0x3b, 0x32, 0xcc, 0xe1, 0x95, 0x06, 0xdf, + 0x7d, 0x1e, 0x17, 0xfb, 0xa0, 0x64, 0xbd, 0xa4, 0xd8, 0xf1, 0xfc, 0xc4, 0xb8, 0x14, 0x64, 0xad, + 0x47, 0x01, 0x09, 0x87, 0xf9, 0xd0, 0x53, 0x18, 0xd9, 0x17, 0xa7, 0x12, 0x76, 0xb9, 0xd8, 0x57, + 0x11, 0x8e, 0x9c, 0x62, 0xd4, 0xa7, 0x84, 0x8a, 0x11, 0x6f, 0xd8, 0xc6, 0x01, 0x22, 0xba, 0x0e, + 0x45, 0xfe, 0x63, 0x75, 0x99, 0x1f, 0xc7, 0x95, 0x82, 0xdc, 0xf6, 0xc8, 0x1d, 0xc6, 0x1e, 0xdd, + 0x63, 0x5d, 0xdd, 0x5a, 0xe2, 0xc7, 0xc2, 0x31, 0xd6, 0xd5, 0xad, 0x25, 0xec, 0xd1, 0xd1, 0xa7, + 0x50, 0xb4, 0xc9, 0x9a, 0xaa, 0x3b, 0x47, 0x65, 0xe8, 0xeb, 0x52, 0xb9, 0xf1, 0x80, 0x73, 0xc7, + 0x0e, 0xc6, 0x02, 0x0d, 0x82, 0x8e, 0x3d, 0x58, 0xb4, 0x0f, 0x23, 0x96, 0xa3, 0x2f, 0xda, 0x3b, + 0x36, 0xb1, 0xca, 0xa3, 0x5c, 0x47, 0xaf, 0x74, 0x8e, 0x3d, 0xfe, 0xb8, 0x16, 0xdf, 0x43, 0x3e, + 0x07, 0x0e, 0xc0, 0xd1, 0x1f, 0x4a, 0x80, 0x6c, 0xc7, 0x34, 0x35, 0xd2, 0x21, 0x3a, 0x55, 0x34, + 0x7e, 0x16, 0x67, 0x97, 0x2f, 0x72, 0x9d, 0x1f, 0xf4, 0x9a, 0x57, 0x42, 0x30, 0xae, 0xdc, 0x3f, + 0xf4, 0x4e, 0xb2, 0xe2, 0x14, 0xbd, 0xcc, 0xb5, 0x7b, 0x36, 0xff, 0xbb, 0x3c, 0xd6, 0x97, 0x6b, + 0xd3, 0xcf, 0x1c, 0x03, 0xd7, 0x0a, 0x3a, 0xf6, 0x60, 0xd1, 0x13, 0x98, 0xf5, 0x1e, 0xc6, 0x62, + 0xc3, 0xa0, 0x2b, 0xaa, 0x46, 0xec, 0xae, 0x4d, 0x49, 0xa7, 0x3c, 0xce, 0x97, 0xdd, 0x7f, 0xfb, + 0x81, 0x53, 0xb9, 0x70, 0x86, 0x34, 0xea, 0x40, 0xc5, 0x4b, 0x19, 0x6c, 0x3f, 0xf9, 0x39, 0xeb, + 0x81, 0xdd, 0x54, 0x34, 0xf7, 0x1e, 0x60, 0x82, 0x2b, 0x78, 0xe3, 0xe4, 0xb8, 0x52, 0x59, 0x3e, + 0x9d, 0x15, 0xf7, 0xc2, 0x42, 0x1f, 0x41, 0x59, 0xc9, 0xd2, 0x33, 0xc9, 0xf5, 0xbc, 0xce, 0xf2, + 0x50, 0xa6, 0x82, 0x4c, 0x69, 0x44, 0x61, 0x52, 0x89, 0x3e, 0x51, 0xb6, 0xcb, 0x53, 0x7d, 0x1d, + 0x44, 0xc6, 0x5e, 0x36, 0x07, 0x87, 0x11, 0x31, 0x82, 0x8d, 0x13, 0x1a, 0xd0, 0x6f, 0x03, 0x52, + 0xe2, 0xaf, 0xaa, 0xed, 0x32, 0xea, 0xab, 0xfc, 0x24, 0x9e, 0x63, 0x07, 0x61, 0x97, 0x20, 0xd9, + 0x38, 0x45, 0x0f, 0x5a, 0x83, 0x19, 0x31, 0xba, 0xa3, 0xdb, 0xca, 0x1e, 0x69, 0x74, 0xed, 0x26, + 0xd5, 0xec, 0xf2, 0x34, 0xcf, 0x7d, 0xfc, 0xe2, 0x6b, 0x31, 0x85, 0x8e, 0x53, 0xa5, 0xd0, 0x07, + 0x30, 0xb9, 0x67, 0x58, 0xbb, 0x6a, 0xab, 0x45, 0x74, 0x0f, 0x69, 0x86, 0x23, 0xcd, 0x30, 0x6f, + 0xac, 0xc4, 0x68, 0x38, 0xc1, 0xcd, 0x1f, 0x93, 0x88, 0xab, 0x85, 0xf3, 0x79, 0x90, 0x3b, 0xd8, + 0x63, 0x92, 0xc0, 0xb4, 0x97, 0xf6, 0x98, 0x24, 0x04, 0x79, 0xfa, 0x61, 0xe6, 0x7f, 0xe6, 0x60, + 0x3a, 0x60, 0xee, 0xfb, 0x31, 0x49, 0x8a, 0xc8, 0xff, 0x3f, 0xca, 0xed, 0xfd, 0x28, 0xf7, 0x6b, + 0x09, 0xc6, 0x03, 0xd7, 0xfd, 0xef, 0x7b, 0xe0, 0x11, 0xd8, 0x96, 0xd1, 0x72, 0xfe, 0x5d, 0x2e, + 0x3c, 0x81, 0xff, 0xf3, 0xaf, 0x0c, 0x7e, 0xfa, 0x4b, 0x5a, 0xf9, 0xdb, 0x3c, 0x4c, 0xc6, 0x77, + 0x63, 0xe4, 0x32, 0x5a, 0xea, 0x79, 0x19, 0xbd, 0x05, 0x33, 0x7b, 0x8e, 0xa6, 0x75, 0xb9, 0x1b, + 0x42, 0x37, 0xd2, 0xee, 0x65, 0xd2, 0xeb, 0x42, 0x72, 0x66, 0x25, 0x85, 0x07, 0xa7, 0x4a, 0x66, + 0x5c, 0xac, 0xe7, 0xcf, 0x74, 0xb1, 0x9e, 0xb8, 0xe7, 0x2d, 0x0c, 0x70, 0xcf, 0x9b, 0x7a, 0x49, + 0x3e, 0x74, 0x86, 0x4b, 0xf2, 0xb3, 0xdc, 0x6a, 0xa7, 0x24, 0xb1, 0x9e, 0x8f, 0x2c, 0x5f, 0x87, + 0x79, 0x21, 0x46, 0xf9, 0x85, 0xb3, 0x4e, 0x2d, 0x43, 0xd3, 0x88, 0xb5, 0xec, 0x74, 0x3a, 0x5d, + 0xf9, 0x3d, 0x18, 0x8f, 0x3e, 0xa5, 0x70, 0x57, 0xda, 0x7d, 0xcd, 0x21, 0xae, 0xf4, 0x42, 0x2b, + 0xed, 0x8e, 0x63, 0x9f, 0x43, 0xfe, 0x7d, 0x09, 0x66, 0xd3, 0x9f, 0x4c, 0x22, 0x0d, 0xc6, 0x3b, + 0xca, 0x51, 0xf8, 0x19, 0xab, 0x74, 0xc6, 0xc3, 0x16, 0x7e, 0x87, 0xbe, 0x1e, 0xc1, 0xc2, 0x31, + 0x6c, 0xf9, 0x47, 0x09, 0xe6, 0x32, 0x6e, 0xaf, 0xcf, 0xd7, 0x12, 0xf4, 0x31, 0x94, 0x3a, 0xca, + 0x51, 0xc3, 0xb1, 0xda, 0xe4, 0xcc, 0xc7, 0x4b, 0x3c, 0x63, 0xac, 0x0b, 0x14, 0xec, 0xe3, 0xc9, + 0x5f, 0x4a, 0x50, 0xce, 0x6a, 0xf4, 0xd1, 0x9d, 0xc8, 0x3d, 0xfb, 0xcf, 0x63, 0xf7, 0xec, 0x53, + 0x09, 0xb9, 0x57, 0x74, 0xcb, 0xfe, 0xb7, 0x12, 0xcc, 0xa6, 0x7f, 0xf0, 0xa0, 0xb7, 0x23, 0x16, + 0x56, 0x62, 0x16, 0x4e, 0xc4, 0xa4, 0x84, 0x7d, 0x9f, 0xc0, 0xb8, 0xf8, 0x2c, 0x12, 0x30, 0xc2, + 0xab, 0x72, 0x5a, 0xae, 0x14, 0x10, 0xde, 0x67, 0x00, 0x5f, 0xaf, 0xe8, 0x18, 0x8e, 0xa1, 0xc9, + 0x7f, 0x90, 0x83, 0xa1, 0x46, 0x53, 0xd1, 0xc8, 0x39, 0xb4, 0x59, 0x1f, 0x46, 0xda, 0xac, 0x5e, + 0xff, 0x72, 0xc2, 0xad, 0xca, 0xec, 0xb0, 0x70, 0xac, 0xc3, 0x7a, 0xb3, 0x2f, 0xb4, 0xd3, 0x9b, + 0xab, 0x5f, 0x81, 0x11, 0x5f, 0xe9, 0x60, 0x39, 0x5f, 0xfe, 0xab, 0x1c, 0x8c, 0x86, 0x54, 0x0c, + 0x58, 0x31, 0xf6, 0x22, 0x95, 0xb6, 0x9f, 0x7f, 0xf4, 0x0b, 0xe9, 0xaa, 0x7a, 0xb5, 0xd5, 0x7d, + 0x32, 0x19, 0x3c, 0x92, 0x4b, 0x96, 0xdc, 0xf7, 0x60, 0x9c, 0xf2, 0x7f, 0x84, 0xf3, 0x0f, 0x65, + 0xf3, 0x3c, 0x16, 0xfd, 0x87, 0xb6, 0xdb, 0x11, 0x2a, 0x8e, 0x71, 0xcf, 0xdf, 0x87, 0xb1, 0x88, + 0xb2, 0x81, 0x5e, 0x3c, 0xfe, 0x83, 0x04, 0x3f, 0xef, 0xf9, 0xc9, 0x8c, 0xea, 0x91, 0x4d, 0x52, + 0x8d, 0x6d, 0x92, 0x85, 0x6c, 0x80, 0x57, 0xf7, 0x72, 0xa6, 0x7e, 0xf3, 0xf9, 0x0f, 0x0b, 0x17, + 0xbe, 0xfb, 0x61, 0xe1, 0xc2, 0xf7, 0x3f, 0x2c, 0x5c, 0xf8, 0xdd, 0x93, 0x05, 0xe9, 0xf9, 0xc9, + 0x82, 0xf4, 0xdd, 0xc9, 0x82, 0xf4, 0xfd, 0xc9, 0x82, 0xf4, 0xef, 0x27, 0x0b, 0xd2, 0x9f, 0xfc, + 0xb8, 0x70, 0xe1, 0xe3, 0xa2, 0x80, 0xfb, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7b, 0xc2, 0x4a, + 0x40, 0x12, 0x3d, 0x00, 0x00, } diff --git a/staging/src/k8s.io/api/extensions/v1beta1/generated.proto b/staging/src/k8s.io/api/extensions/v1beta1/generated.proto index a47c67c0da7..3a87fbe5ec5 100644 --- a/staging/src/k8s.io/api/extensions/v1beta1/generated.proto +++ b/staging/src/k8s.io/api/extensions/v1beta1/generated.proto @@ -51,6 +51,10 @@ message AllowedHostPath { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` optional string pathPrefix = 1; + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + optional bool readOnly = 2; } message CustomMetricCurrentStatus { @@ -878,6 +882,27 @@ message PodSecurityPolicySpec { // is allowed in the "volumes" field. // +optional repeated AllowedFlexVolume allowedFlexVolumes = 18; + + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + repeated string allowedUnsafeSysctls = 19; + + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + repeated string forbiddenSysctls = 20; } // DEPRECATED - This group version of ReplicaSet is deprecated by apps/v1beta2/ReplicaSet. See the release notes for diff --git a/staging/src/k8s.io/api/extensions/v1beta1/types.go b/staging/src/k8s.io/api/extensions/v1beta1/types.go index be405be4f89..3a86ef43a07 100644 --- a/staging/src/k8s.io/api/extensions/v1beta1/types.go +++ b/staging/src/k8s.io/api/extensions/v1beta1/types.go @@ -946,6 +946,25 @@ type PodSecurityPolicySpec struct { // is allowed in the "volumes" field. // +optional AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"` + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + AllowedUnsafeSysctls []string `json:"allowedUnsafeSysctls,omitempty" protobuf:"bytes,19,rep,name=allowedUnsafeSysctls"` + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + ForbiddenSysctls []string `json:"forbiddenSysctls,omitempty" protobuf:"bytes,20,rep,name=forbiddenSysctls"` } // AllowedHostPath defines the host volume conditions that will be enabled by a policy @@ -960,6 +979,10 @@ type AllowedHostPath struct { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` PathPrefix string `json:"pathPrefix,omitempty" protobuf:"bytes,1,rep,name=pathPrefix"` + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,2,opt,name=readOnly"` } // FSType gives strong typing to different file systems that are used by volumes. diff --git a/staging/src/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go index dfe5fba1748..d261b424797 100644 --- a/staging/src/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go @@ -39,6 +39,7 @@ func (AllowedFlexVolume) SwaggerDoc() map[string]string { var map_AllowedHostPath = map[string]string{ "": "AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined. Deprecated: use AllowedHostPath from policy API Group instead.", "pathPrefix": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "readOnly": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.", } func (AllowedHostPath) SwaggerDoc() map[string]string { @@ -478,6 +479,8 @@ var map_PodSecurityPolicySpec = map[string]string{ "allowPrivilegeEscalation": "allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", "allowedHostPaths": "allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.", "allowedFlexVolumes": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field.", + "allowedUnsafeSysctls": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc.", + "forbiddenSysctls": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc.", } func (PodSecurityPolicySpec) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go index a91c9119d70..8ec2b1ff7c6 100644 --- a/staging/src/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go @@ -1204,6 +1204,16 @@ func (in *PodSecurityPolicySpec) DeepCopyInto(out *PodSecurityPolicySpec) { *out = make([]AllowedFlexVolume, len(*in)) copy(*out, *in) } + if in.AllowedUnsafeSysctls != nil { + in, out := &in.AllowedUnsafeSysctls, &out.AllowedUnsafeSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ForbiddenSysctls != nil { + in, out := &in.ForbiddenSysctls, &out.ForbiddenSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/staging/src/k8s.io/api/policy/v1beta1/generated.pb.go b/staging/src/k8s.io/api/policy/v1beta1/generated.pb.go index ab787f27617..505fb0e036f 100644 --- a/staging/src/k8s.io/api/policy/v1beta1/generated.pb.go +++ b/staging/src/k8s.io/api/policy/v1beta1/generated.pb.go @@ -200,6 +200,14 @@ func (m *AllowedHostPath) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.PathPrefix))) i += copy(dAtA[i:], m.PathPrefix) + dAtA[i] = 0x10 + i++ + if m.ReadOnly { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ return i, nil } @@ -794,6 +802,40 @@ func (m *PodSecurityPolicySpec) MarshalTo(dAtA []byte) (int, error) { i += n } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + dAtA[i] = 0x9a + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + dAtA[i] = 0xa2 + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } return i, nil } @@ -937,6 +979,7 @@ func (m *AllowedHostPath) Size() (n int) { _ = l l = len(m.PathPrefix) n += 1 + l + sovGenerated(uint64(l)) + n += 2 return n } @@ -1134,6 +1177,18 @@ func (m *PodSecurityPolicySpec) Size() (n int) { n += 2 + l + sovGenerated(uint64(l)) } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } return n } @@ -1206,6 +1261,7 @@ func (this *AllowedHostPath) String() string { } s := strings.Join([]string{`&AllowedHostPath{`, `PathPrefix:` + fmt.Sprintf("%v", this.PathPrefix) + `,`, + `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, `}`, }, "") return s @@ -1359,6 +1415,8 @@ func (this *PodSecurityPolicySpec) String() string { `AllowPrivilegeEscalation:` + valueToStringGenerated(this.AllowPrivilegeEscalation) + `,`, `AllowedHostPaths:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedHostPaths), "AllowedHostPath", "AllowedHostPath", 1), `&`, ``, 1) + `,`, `AllowedFlexVolumes:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedFlexVolumes), "AllowedFlexVolume", "AllowedFlexVolume", 1), `&`, ``, 1) + `,`, + `AllowedUnsafeSysctls:` + fmt.Sprintf("%v", this.AllowedUnsafeSysctls) + `,`, + `ForbiddenSysctls:` + fmt.Sprintf("%v", this.ForbiddenSysctls) + `,`, `}`, }, "") return s @@ -1541,6 +1599,26 @@ func (m *AllowedHostPath) Unmarshal(dAtA []byte) error { } m.PathPrefix = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ReadOnly = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -3348,6 +3426,64 @@ func (m *PodSecurityPolicySpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedUnsafeSysctls", 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 + } + m.AllowedUnsafeSysctls = append(m.AllowedUnsafeSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 20: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ForbiddenSysctls", 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 + } + m.ForbiddenSysctls = append(m.ForbiddenSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -3811,106 +3947,110 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1605 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4f, 0x6f, 0x1b, 0xb9, - 0x15, 0xf7, 0x58, 0xb6, 0x65, 0xd3, 0xf2, 0x3f, 0xba, 0x76, 0x27, 0x46, 0x23, 0x35, 0x0a, 0x50, - 0xa4, 0x41, 0x33, 0x8a, 0x9d, 0xa4, 0x35, 0x9a, 0xb6, 0xa8, 0xc7, 0xf2, 0xbf, 0x20, 0xae, 0x55, - 0x2a, 0x09, 0xda, 0x22, 0x2d, 0x4a, 0x69, 0x68, 0x89, 0xf1, 0x68, 0x66, 0x4a, 0x72, 0x14, 0xe9, - 0xd6, 0x43, 0x0f, 0x3d, 0xf6, 0x0b, 0xf4, 0x13, 0x14, 0x3d, 0xed, 0x97, 0xf0, 0x02, 0x8b, 0x45, - 0x8e, 0xc1, 0x1e, 0x84, 0x8d, 0x16, 0xfb, 0x25, 0x72, 0x5a, 0x0c, 0xc5, 0x91, 0x34, 0x33, 0x92, - 0x1c, 0x07, 0x48, 0x6e, 0x1a, 0xbe, 0xdf, 0xef, 0xf7, 0x1e, 0x1f, 0xc9, 0xc7, 0x47, 0x01, 0xf3, - 0x62, 0x97, 0x1b, 0xd4, 0x2d, 0x5c, 0xf8, 0x15, 0xc2, 0x1c, 0x22, 0x08, 0x2f, 0x34, 0x89, 0x63, - 0xb9, 0xac, 0xa0, 0x0c, 0xd8, 0xa3, 0x05, 0xcf, 0xb5, 0x69, 0xb5, 0x5d, 0x68, 0x6e, 0x57, 0x88, - 0xc0, 0xdb, 0x85, 0x1a, 0x71, 0x08, 0xc3, 0x82, 0x58, 0x86, 0xc7, 0x5c, 0xe1, 0xc2, 0x1b, 0x3d, - 0xa8, 0x81, 0x3d, 0x6a, 0xf4, 0xa0, 0x86, 0x82, 0x6e, 0xdd, 0xab, 0x51, 0x51, 0xf7, 0x2b, 0x46, - 0xd5, 0x6d, 0x14, 0x6a, 0x6e, 0xcd, 0x2d, 0x48, 0x46, 0xc5, 0x3f, 0x97, 0x5f, 0xf2, 0x43, 0xfe, - 0xea, 0x29, 0x6d, 0xe5, 0x87, 0x9c, 0x56, 0x5d, 0x46, 0x0a, 0xcd, 0x84, 0xb7, 0xad, 0x87, 0x03, - 0x4c, 0x03, 0x57, 0xeb, 0xd4, 0x21, 0xac, 0x5d, 0xf0, 0x2e, 0x6a, 0xc1, 0x00, 0x2f, 0x34, 0x88, - 0xc0, 0xa3, 0x58, 0x85, 0x71, 0x2c, 0xe6, 0x3b, 0x82, 0x36, 0x48, 0x82, 0xf0, 0xcb, 0xab, 0x08, - 0xbc, 0x5a, 0x27, 0x0d, 0x9c, 0xe0, 0x3d, 0x18, 0xc7, 0xf3, 0x05, 0xb5, 0x0b, 0xd4, 0x11, 0x5c, - 0xb0, 0x38, 0x29, 0xff, 0x18, 0xac, 0xed, 0xd9, 0xb6, 0xfb, 0x9a, 0x58, 0x87, 0x36, 0x69, 0xbd, - 0x70, 0x6d, 0xbf, 0x41, 0xe0, 0xcf, 0xc0, 0x9c, 0xc5, 0x68, 0x93, 0x30, 0x5d, 0xfb, 0xa9, 0x76, - 0x67, 0xc1, 0x5c, 0xbe, 0xec, 0xe4, 0xa6, 0xba, 0x9d, 0xdc, 0x5c, 0x51, 0x8e, 0x22, 0x65, 0xcd, - 0x1f, 0x80, 0x15, 0x45, 0x3e, 0x76, 0xb9, 0x28, 0x61, 0x51, 0x87, 0x3b, 0x00, 0x78, 0x58, 0xd4, - 0x4b, 0x8c, 0x9c, 0xd3, 0x96, 0xa2, 0x43, 0x45, 0x07, 0xa5, 0xbe, 0x05, 0x0d, 0xa1, 0xf2, 0xdf, - 0x68, 0x60, 0xfe, 0xa0, 0x49, 0xab, 0x82, 0xba, 0x0e, 0xfc, 0x3b, 0x98, 0x0f, 0x32, 0x69, 0x61, - 0x81, 0x25, 0x7d, 0x71, 0xe7, 0xbe, 0x31, 0x58, 0xe5, 0xfe, 0xc4, 0x0c, 0xef, 0xa2, 0x16, 0x0c, - 0x70, 0x23, 0x40, 0x1b, 0xcd, 0x6d, 0xe3, 0xac, 0xf2, 0x8a, 0x54, 0xc5, 0x29, 0x11, 0x78, 0xe0, - 0x70, 0x30, 0x86, 0xfa, 0xaa, 0xd0, 0x06, 0x4b, 0x16, 0xb1, 0x89, 0x20, 0x67, 0x5e, 0xe0, 0x91, - 0xeb, 0xd3, 0xd2, 0xcd, 0x83, 0x0f, 0x73, 0x53, 0x1c, 0xa6, 0x9a, 0x6b, 0xdd, 0x4e, 0x6e, 0x29, - 0x32, 0x84, 0xa2, 0xe2, 0xf9, 0xff, 0x6a, 0x60, 0xf3, 0xb0, 0x7c, 0xc4, 0x5c, 0xdf, 0x2b, 0x8b, - 0x20, 0xf3, 0xb5, 0xb6, 0x32, 0xc1, 0x5f, 0x81, 0x19, 0xe6, 0xdb, 0x44, 0x65, 0xe9, 0xb6, 0x0a, - 0x7a, 0x06, 0xf9, 0x36, 0x79, 0xdf, 0xc9, 0xad, 0xc7, 0x58, 0xcf, 0xda, 0x1e, 0x41, 0x92, 0x00, - 0x9f, 0x80, 0x39, 0x86, 0x9d, 0x1a, 0x09, 0x42, 0x4f, 0xdd, 0x59, 0xdc, 0xc9, 0x1b, 0x63, 0xcf, - 0x81, 0x71, 0x52, 0x44, 0x01, 0x74, 0xb0, 0x86, 0xf2, 0x93, 0x23, 0xa5, 0x90, 0x3f, 0x05, 0x4b, - 0x72, 0xf1, 0x5c, 0x26, 0xa4, 0x05, 0xde, 0x04, 0xa9, 0x06, 0x75, 0x64, 0x50, 0xb3, 0xe6, 0xa2, - 0x62, 0xa5, 0x4e, 0xa9, 0x83, 0x82, 0x71, 0x69, 0xc6, 0x2d, 0x99, 0xb3, 0x61, 0x33, 0x6e, 0xa1, - 0x60, 0x3c, 0x7f, 0x04, 0xd2, 0xca, 0xe3, 0xb0, 0x50, 0x6a, 0xb2, 0x50, 0x6a, 0x84, 0xd0, 0xff, - 0xa6, 0xc1, 0x7a, 0xc9, 0xb5, 0x8a, 0x94, 0x33, 0x5f, 0xe6, 0xcb, 0xf4, 0xad, 0x1a, 0x11, 0x9f, - 0x61, 0x7f, 0x3c, 0x03, 0x33, 0xdc, 0x23, 0x55, 0xb5, 0x2d, 0x76, 0x26, 0xe4, 0x76, 0x44, 0x7c, - 0x65, 0x8f, 0x54, 0xcd, 0x4c, 0xb8, 0x94, 0xc1, 0x17, 0x92, 0x6a, 0xf0, 0x25, 0x98, 0xe3, 0x02, - 0x0b, 0x9f, 0xeb, 0x29, 0xa9, 0xfb, 0xf0, 0x9a, 0xba, 0x92, 0x3b, 0x58, 0xc5, 0xde, 0x37, 0x52, - 0x9a, 0xf9, 0xaf, 0x34, 0xf0, 0xe3, 0x11, 0xac, 0xa7, 0x94, 0x0b, 0xf8, 0x32, 0x91, 0x31, 0xe3, - 0xc3, 0x32, 0x16, 0xb0, 0x65, 0xbe, 0x56, 0x95, 0xd7, 0xf9, 0x70, 0x64, 0x28, 0x5b, 0x65, 0x30, - 0x4b, 0x05, 0x69, 0x84, 0x5b, 0xd1, 0xb8, 0xde, 0xb4, 0xcc, 0x25, 0x25, 0x3d, 0x7b, 0x12, 0x88, - 0xa0, 0x9e, 0x56, 0xfe, 0xeb, 0xe9, 0x91, 0xd3, 0x09, 0xd2, 0x09, 0xcf, 0x41, 0xa6, 0x41, 0x9d, - 0xbd, 0x26, 0xa6, 0x36, 0xae, 0xa8, 0xd3, 0x33, 0x69, 0x13, 0x04, 0xd5, 0xcf, 0xe8, 0x55, 0x3f, - 0xe3, 0xc4, 0x11, 0x67, 0xac, 0x2c, 0x18, 0x75, 0x6a, 0xe6, 0x6a, 0xb7, 0x93, 0xcb, 0x9c, 0x0e, - 0x29, 0xa1, 0x88, 0x2e, 0xfc, 0x2b, 0x98, 0xe7, 0xc4, 0x26, 0x55, 0xe1, 0xb2, 0xeb, 0x55, 0x88, - 0xa7, 0xb8, 0x42, 0xec, 0xb2, 0xa2, 0x9a, 0x99, 0x20, 0x6f, 0xe1, 0x17, 0xea, 0x4b, 0x42, 0x1b, - 0x2c, 0x37, 0x70, 0xeb, 0xb9, 0x83, 0xfb, 0x13, 0x49, 0x7d, 0xe4, 0x44, 0x60, 0xb7, 0x93, 0x5b, - 0x3e, 0x8d, 0x68, 0xa1, 0x98, 0x76, 0xfe, 0xfb, 0x19, 0x70, 0x63, 0xec, 0xae, 0x82, 0x4f, 0x00, - 0x74, 0x2b, 0x9c, 0xb0, 0x26, 0xb1, 0x8e, 0x7a, 0xf7, 0x03, 0x75, 0xc3, 0x83, 0xbb, 0xa5, 0x16, - 0x08, 0x9e, 0x25, 0x10, 0x68, 0x04, 0x0b, 0xfe, 0x4b, 0x03, 0x4b, 0x56, 0xcf, 0x0d, 0xb1, 0x4a, - 0xae, 0x15, 0x6e, 0x8c, 0xa3, 0x8f, 0xd9, 0xef, 0x46, 0x71, 0x58, 0xe9, 0xc0, 0x11, 0xac, 0x6d, - 0x6e, 0xa8, 0x80, 0x96, 0x22, 0x36, 0x14, 0x75, 0x0a, 0x4f, 0x01, 0xb4, 0xfa, 0x92, 0x5c, 0xdd, - 0x52, 0x32, 0xc5, 0xb3, 0xe6, 0x4d, 0xa5, 0xb0, 0x11, 0xf1, 0x1b, 0x82, 0xd0, 0x08, 0x22, 0xfc, - 0x1d, 0x58, 0xae, 0xfa, 0x8c, 0x11, 0x47, 0x1c, 0x13, 0x6c, 0x8b, 0x7a, 0x5b, 0x9f, 0x91, 0x52, - 0x9b, 0x4a, 0x6a, 0x79, 0x3f, 0x62, 0x45, 0x31, 0x74, 0xc0, 0xb7, 0x08, 0xa7, 0x8c, 0x58, 0x21, - 0x7f, 0x36, 0xca, 0x2f, 0x46, 0xac, 0x28, 0x86, 0x86, 0xbb, 0x20, 0x43, 0x5a, 0x1e, 0xa9, 0x86, - 0x39, 0x9d, 0x93, 0xec, 0x1f, 0x29, 0x76, 0xe6, 0x60, 0xc8, 0x86, 0x22, 0xc8, 0x2d, 0x1b, 0xc0, - 0x64, 0x12, 0xe1, 0x2a, 0x48, 0x5d, 0x90, 0x76, 0xef, 0xe6, 0x41, 0xc1, 0x4f, 0xf8, 0x7b, 0x30, - 0xdb, 0xc4, 0xb6, 0x4f, 0xd4, 0x5e, 0xbf, 0xfb, 0x61, 0x7b, 0xfd, 0x19, 0x6d, 0x10, 0xd4, 0x23, - 0xfe, 0x7a, 0x7a, 0x57, 0xcb, 0x7f, 0xa9, 0x81, 0xb5, 0x92, 0x6b, 0x95, 0x49, 0xd5, 0x67, 0x54, - 0xb4, 0x4b, 0x72, 0x9d, 0x3f, 0x43, 0xcd, 0x46, 0x91, 0x9a, 0x7d, 0x7f, 0xf2, 0x5e, 0x8b, 0x46, - 0x37, 0xae, 0x62, 0xe7, 0x2f, 0x35, 0xb0, 0x91, 0x40, 0x7f, 0x86, 0x8a, 0xfa, 0xc7, 0x68, 0x45, - 0xfd, 0xc5, 0x75, 0x26, 0x33, 0xa6, 0x9e, 0xbe, 0xcf, 0x8c, 0x98, 0x8a, 0xac, 0xa6, 0x41, 0xbf, - 0xc6, 0x68, 0x93, 0xda, 0xa4, 0x46, 0x2c, 0x39, 0x99, 0xf9, 0xa1, 0x7e, 0xad, 0x6f, 0x41, 0x43, - 0x28, 0xc8, 0xc1, 0xa6, 0x45, 0xce, 0xb1, 0x6f, 0x8b, 0x3d, 0xcb, 0xda, 0xc7, 0x1e, 0xae, 0x50, - 0x9b, 0x0a, 0xaa, 0xda, 0x91, 0x05, 0xf3, 0x71, 0xb7, 0x93, 0xdb, 0x2c, 0x8e, 0x44, 0xbc, 0xef, - 0xe4, 0x6e, 0x26, 0x3b, 0x6d, 0xa3, 0x0f, 0x69, 0xa3, 0x31, 0xd2, 0xb0, 0x0d, 0x74, 0x46, 0xfe, - 0xe1, 0x07, 0x87, 0xa2, 0xc8, 0x5c, 0x2f, 0xe2, 0x36, 0x25, 0xdd, 0xfe, 0xb6, 0xdb, 0xc9, 0xe9, - 0x68, 0x0c, 0xe6, 0x6a, 0xc7, 0x63, 0xe5, 0xe1, 0x2b, 0xb0, 0x8e, 0x7b, 0x75, 0x20, 0xe2, 0x75, - 0x46, 0x7a, 0xdd, 0xed, 0x76, 0x72, 0xeb, 0x7b, 0x49, 0xf3, 0xd5, 0x0e, 0x47, 0x89, 0xc2, 0x02, - 0x48, 0x37, 0x65, 0x13, 0xce, 0xf5, 0x59, 0xa9, 0xbf, 0xd1, 0xed, 0xe4, 0xd2, 0xbd, 0xbe, 0x3c, - 0xd0, 0x9c, 0x3b, 0x2c, 0xcb, 0x46, 0x30, 0x44, 0xc1, 0x47, 0x60, 0xb1, 0xee, 0x72, 0xf1, 0x07, - 0x22, 0x5e, 0xbb, 0xec, 0x42, 0x16, 0x86, 0x79, 0x73, 0x5d, 0xad, 0xe0, 0xe2, 0xf1, 0xc0, 0x84, - 0x86, 0x71, 0xf0, 0xcf, 0x60, 0xa1, 0xae, 0xda, 0x3e, 0xae, 0xa7, 0xe5, 0x46, 0xbb, 0x33, 0x61, - 0xa3, 0x45, 0x5a, 0x44, 0x73, 0x4d, 0xc9, 0x2f, 0x84, 0xc3, 0x1c, 0x0d, 0xd4, 0xe0, 0xcf, 0x41, - 0x5a, 0x7e, 0x9c, 0x14, 0xf5, 0x79, 0x19, 0xcd, 0x8a, 0x82, 0xa7, 0x8f, 0x7b, 0xc3, 0x28, 0xb4, - 0x87, 0xd0, 0x93, 0xd2, 0xbe, 0xbe, 0x90, 0x84, 0x9e, 0x94, 0xf6, 0x51, 0x68, 0x87, 0x2f, 0x41, - 0x9a, 0x93, 0xa7, 0xd4, 0xf1, 0x5b, 0x3a, 0x90, 0x47, 0x6e, 0x7b, 0x42, 0xb8, 0xe5, 0x03, 0x89, - 0x8c, 0x35, 0xdc, 0x03, 0x75, 0x65, 0x47, 0xa1, 0x24, 0xb4, 0xc0, 0x02, 0xf3, 0x9d, 0x3d, 0xfe, - 0x9c, 0x13, 0xa6, 0x2f, 0x26, 0x6e, 0xfb, 0xb8, 0x3e, 0x0a, 0xb1, 0x71, 0x0f, 0xfd, 0xcc, 0xf4, - 0x11, 0x68, 0x20, 0x0c, 0xff, 0xad, 0x01, 0xc8, 0x7d, 0xcf, 0xb3, 0x49, 0x83, 0x38, 0x02, 0xdb, - 0xb2, 0xbf, 0xe7, 0x7a, 0x46, 0xfa, 0xfb, 0xcd, 0xa4, 0xf9, 0x24, 0x48, 0x71, 0xc7, 0xfd, 0x6b, - 0x3a, 0x09, 0x45, 0x23, 0x7c, 0x06, 0xe9, 0x3c, 0xe7, 0xf2, 0xb7, 0xbe, 0x74, 0x65, 0x3a, 0x47, - 0xbf, 0x5f, 0x06, 0xe9, 0x54, 0x76, 0x14, 0x4a, 0xc2, 0x17, 0x60, 0x93, 0x11, 0x6c, 0x9d, 0x39, - 0x76, 0x1b, 0xb9, 0xae, 0x38, 0xa4, 0x36, 0xe1, 0x6d, 0x2e, 0x48, 0x43, 0x5f, 0x96, 0xcb, 0x9c, - 0x55, 0xcc, 0x4d, 0x34, 0x12, 0x85, 0xc6, 0xb0, 0x61, 0x03, 0xe4, 0xc2, 0xf2, 0x10, 0x9c, 0x9d, - 0x7e, 0x7d, 0x3a, 0xe0, 0x55, 0x6c, 0xf7, 0xba, 0x96, 0x15, 0xe9, 0xe0, 0x76, 0xb7, 0x93, 0xcb, - 0x15, 0x27, 0x43, 0xd1, 0x55, 0x5a, 0xf0, 0x4f, 0x40, 0xc7, 0xe3, 0xfc, 0xac, 0x4a, 0x3f, 0x3f, - 0x09, 0x6a, 0xce, 0x58, 0x07, 0x63, 0xd9, 0xd0, 0x03, 0xab, 0x38, 0xfa, 0x72, 0xe6, 0xfa, 0x9a, - 0x3c, 0x85, 0x77, 0x27, 0xac, 0x43, 0xec, 0xb1, 0x6d, 0xea, 0x2a, 0x8d, 0xab, 0x31, 0x03, 0x47, - 0x09, 0x75, 0xd8, 0x02, 0x10, 0xc7, 0x1f, 0xfa, 0x5c, 0x87, 0x57, 0x5e, 0x31, 0x89, 0x7f, 0x07, - 0x06, 0x5b, 0x2d, 0x61, 0xe2, 0x68, 0x84, 0x8f, 0xe0, 0x05, 0xac, 0x8f, 0x3b, 0x30, 0xf0, 0x51, - 0xe4, 0x0d, 0x7c, 0x2b, 0xf6, 0x06, 0x5e, 0x4b, 0xf0, 0x3e, 0xc1, 0x0b, 0xf8, 0xff, 0x1a, 0xd8, - 0x1c, 0x5d, 0x30, 0xe0, 0x83, 0x48, 0x74, 0xb9, 0x58, 0x74, 0x2b, 0x31, 0x96, 0x8a, 0xed, 0x6f, - 0x60, 0x59, 0x95, 0x95, 0xe8, 0x1f, 0x0c, 0x91, 0x18, 0x83, 0xfb, 0x20, 0xe8, 0x08, 0x94, 0x44, - 0x78, 0xa4, 0x64, 0x2f, 0x1f, 0x1d, 0x43, 0x31, 0xb5, 0xfc, 0x17, 0x1a, 0xb8, 0x75, 0x65, 0x41, - 0x80, 0x66, 0x24, 0x74, 0x23, 0x16, 0x7a, 0x76, 0xbc, 0xc0, 0xa7, 0xf9, 0x9f, 0xc1, 0xbc, 0x77, - 0xf9, 0x2e, 0x3b, 0xf5, 0xe6, 0x5d, 0x76, 0xea, 0xed, 0xbb, 0xec, 0xd4, 0x3f, 0xbb, 0x59, 0xed, - 0xb2, 0x9b, 0xd5, 0xde, 0x74, 0xb3, 0xda, 0xdb, 0x6e, 0x56, 0xfb, 0xb6, 0x9b, 0xd5, 0xfe, 0xf3, - 0x5d, 0x76, 0xea, 0x2f, 0x69, 0x25, 0xf7, 0x43, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc3, 0x7d, 0x0b, - 0x1d, 0x1e, 0x14, 0x00, 0x00, + // 1679 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4f, 0x6f, 0x23, 0xb7, + 0x15, 0xf7, 0xac, 0x6c, 0x4b, 0xa6, 0x6d, 0xad, 0x4d, 0x7b, 0xdd, 0x89, 0xd1, 0xd5, 0x24, 0x0a, + 0x50, 0x6c, 0x83, 0x64, 0x14, 0x7b, 0x93, 0xd6, 0x68, 0xda, 0x22, 0x1e, 0xcb, 0xff, 0x02, 0xbb, + 0x56, 0xa9, 0xdd, 0xa0, 0x2d, 0xb6, 0x45, 0x29, 0x0d, 0x2d, 0x31, 0x1e, 0xcd, 0x4c, 0x49, 0x8e, + 0x22, 0xdd, 0x7a, 0xe8, 0xa1, 0xe8, 0xa9, 0x5f, 0xa0, 0x9f, 0xa0, 0xe8, 0xa9, 0x5f, 0xc2, 0x05, + 0x8a, 0x22, 0xc7, 0xa0, 0x07, 0xa1, 0xab, 0xa2, 0x5f, 0x22, 0xa7, 0x62, 0x28, 0x8e, 0xa4, 0xf9, + 0x23, 0x79, 0x1d, 0x60, 0xf7, 0xa6, 0xe1, 0xfb, 0xfd, 0x7e, 0xef, 0xf1, 0xf1, 0xf1, 0x91, 0x14, + 0xb0, 0x6e, 0x0e, 0xb8, 0x49, 0xbd, 0xca, 0x4d, 0xd0, 0x20, 0xcc, 0x25, 0x82, 0xf0, 0x4a, 0x97, + 0xb8, 0xb6, 0xc7, 0x2a, 0xca, 0x80, 0x7d, 0x5a, 0xf1, 0x3d, 0x87, 0x36, 0xfb, 0x95, 0xee, 0x5e, + 0x83, 0x08, 0xbc, 0x57, 0x69, 0x11, 0x97, 0x30, 0x2c, 0x88, 0x6d, 0xfa, 0xcc, 0x13, 0x1e, 0x7c, + 0x6b, 0x04, 0x35, 0xb1, 0x4f, 0xcd, 0x11, 0xd4, 0x54, 0xd0, 0xdd, 0x0f, 0x5a, 0x54, 0xb4, 0x83, + 0x86, 0xd9, 0xf4, 0x3a, 0x95, 0x96, 0xd7, 0xf2, 0x2a, 0x92, 0xd1, 0x08, 0xae, 0xe5, 0x97, 0xfc, + 0x90, 0xbf, 0x46, 0x4a, 0xbb, 0xe5, 0x29, 0xa7, 0x4d, 0x8f, 0x91, 0x4a, 0x37, 0xe5, 0x6d, 0xf7, + 0xa3, 0x09, 0xa6, 0x83, 0x9b, 0x6d, 0xea, 0x12, 0xd6, 0xaf, 0xf8, 0x37, 0xad, 0x70, 0x80, 0x57, + 0x3a, 0x44, 0xe0, 0x2c, 0x56, 0x65, 0x16, 0x8b, 0x05, 0xae, 0xa0, 0x1d, 0x92, 0x22, 0xfc, 0xe0, + 0x2e, 0x02, 0x6f, 0xb6, 0x49, 0x07, 0xa7, 0x78, 0x4f, 0x67, 0xf1, 0x02, 0x41, 0x9d, 0x0a, 0x75, + 0x05, 0x17, 0x2c, 0x49, 0x2a, 0x7f, 0x02, 0x36, 0x0f, 0x1d, 0xc7, 0xfb, 0x92, 0xd8, 0x27, 0x0e, + 0xe9, 0x7d, 0xee, 0x39, 0x41, 0x87, 0xc0, 0xef, 0x81, 0x65, 0x9b, 0xd1, 0x2e, 0x61, 0xba, 0xf6, + 0xb6, 0xf6, 0x64, 0xc5, 0x2a, 0xde, 0x0e, 0x8c, 0x85, 0xe1, 0xc0, 0x58, 0xae, 0xca, 0x51, 0xa4, + 0xac, 0x65, 0x0e, 0x1e, 0x2a, 0xf2, 0x99, 0xc7, 0x45, 0x0d, 0x8b, 0x36, 0xdc, 0x07, 0xc0, 0xc7, + 0xa2, 0x5d, 0x63, 0xe4, 0x9a, 0xf6, 0x14, 0x1d, 0x2a, 0x3a, 0xa8, 0x8d, 0x2d, 0x68, 0x0a, 0x05, + 0xdf, 0x07, 0x05, 0x46, 0xb0, 0x7d, 0xe5, 0x3a, 0x7d, 0xfd, 0xc1, 0xdb, 0xda, 0x93, 0x82, 0xb5, + 0xa1, 0x18, 0x05, 0xa4, 0xc6, 0xd1, 0x18, 0x51, 0xfe, 0xb7, 0x06, 0x0a, 0xc7, 0x5d, 0xda, 0x14, + 0xd4, 0x73, 0xe1, 0x6f, 0x41, 0x21, 0xcc, 0xbb, 0x8d, 0x05, 0x96, 0xce, 0x56, 0xf7, 0x3f, 0x34, + 0x27, 0x35, 0x31, 0x4e, 0x83, 0xe9, 0xdf, 0xb4, 0xc2, 0x01, 0x6e, 0x86, 0x68, 0xb3, 0xbb, 0x67, + 0x5e, 0x35, 0xbe, 0x20, 0x4d, 0x71, 0x49, 0x04, 0x9e, 0x84, 0x37, 0x19, 0x43, 0x63, 0x55, 0xe8, + 0x80, 0x75, 0x9b, 0x38, 0x44, 0x90, 0x2b, 0x3f, 0xf4, 0xc8, 0x65, 0x84, 0xab, 0xfb, 0x4f, 0x5f, + 0xcd, 0x4d, 0x75, 0x9a, 0x6a, 0x6d, 0x0e, 0x07, 0xc6, 0x7a, 0x6c, 0x08, 0xc5, 0xc5, 0xcb, 0x7f, + 0xd1, 0xc0, 0xce, 0x49, 0xfd, 0x94, 0x79, 0x81, 0x5f, 0x17, 0xe1, 0x3a, 0xb5, 0xfa, 0xca, 0x04, + 0x7f, 0x08, 0x16, 0x59, 0xe0, 0x10, 0x95, 0xd3, 0x77, 0x55, 0xd0, 0x8b, 0x28, 0x70, 0xc8, 0x37, + 0x03, 0x63, 0x2b, 0xc1, 0x7a, 0xd6, 0xf7, 0x09, 0x92, 0x04, 0xf8, 0x19, 0x58, 0x66, 0xd8, 0x6d, + 0x91, 0x30, 0xf4, 0xdc, 0x93, 0xd5, 0xfd, 0xb2, 0x39, 0x73, 0xd7, 0x98, 0xe7, 0x55, 0x14, 0x42, + 0x27, 0x2b, 0x2e, 0x3f, 0x39, 0x52, 0x0a, 0xe5, 0x4b, 0xb0, 0x2e, 0x97, 0xda, 0x63, 0x42, 0x5a, + 0xe0, 0x63, 0x90, 0xeb, 0x50, 0x57, 0x06, 0xb5, 0x64, 0xad, 0x2a, 0x56, 0xee, 0x92, 0xba, 0x28, + 0x1c, 0x97, 0x66, 0xdc, 0x93, 0x39, 0x9b, 0x36, 0xe3, 0x1e, 0x0a, 0xc7, 0xcb, 0xa7, 0x20, 0xaf, + 0x3c, 0x4e, 0x0b, 0xe5, 0xe6, 0x0b, 0xe5, 0x32, 0x84, 0xfe, 0xfa, 0x00, 0x6c, 0xd5, 0x3c, 0xbb, + 0x4a, 0x39, 0x0b, 0x64, 0xbe, 0xac, 0xc0, 0x6e, 0x11, 0xf1, 0x06, 0xea, 0xe3, 0x19, 0x58, 0xe4, + 0x3e, 0x69, 0xaa, 0xb2, 0xd8, 0x9f, 0x93, 0xdb, 0x8c, 0xf8, 0xea, 0x3e, 0x69, 0x5a, 0x6b, 0xd1, + 0x52, 0x86, 0x5f, 0x48, 0xaa, 0xc1, 0x17, 0x60, 0x99, 0x0b, 0x2c, 0x02, 0xae, 0xe7, 0xa4, 0xee, + 0x47, 0xf7, 0xd4, 0x95, 0xdc, 0xc9, 0x2a, 0x8e, 0xbe, 0x91, 0xd2, 0x2c, 0xff, 0x53, 0x03, 0xdf, + 0xc9, 0x60, 0x5d, 0x50, 0x2e, 0xe0, 0x8b, 0x54, 0xc6, 0xcc, 0x57, 0xcb, 0x58, 0xc8, 0x96, 0xf9, + 0x1a, 0x6f, 0xde, 0x68, 0x64, 0x2a, 0x5b, 0x75, 0xb0, 0x44, 0x05, 0xe9, 0x44, 0xa5, 0x68, 0xde, + 0x6f, 0x5a, 0xd6, 0xba, 0x92, 0x5e, 0x3a, 0x0f, 0x45, 0xd0, 0x48, 0xab, 0xfc, 0xaf, 0x07, 0x99, + 0xd3, 0x09, 0xd3, 0x09, 0xaf, 0xc1, 0x5a, 0x87, 0xba, 0x87, 0x5d, 0x4c, 0x1d, 0xdc, 0x50, 0xbb, + 0x67, 0x5e, 0x11, 0x84, 0xbd, 0xd2, 0x1c, 0xf5, 0x4a, 0xf3, 0xdc, 0x15, 0x57, 0xac, 0x2e, 0x18, + 0x75, 0x5b, 0xd6, 0xc6, 0x70, 0x60, 0xac, 0x5d, 0x4e, 0x29, 0xa1, 0x98, 0x2e, 0xfc, 0x35, 0x28, + 0x70, 0xe2, 0x90, 0xa6, 0xf0, 0xd8, 0xfd, 0x3a, 0xc4, 0x05, 0x6e, 0x10, 0xa7, 0xae, 0xa8, 0xd6, + 0x5a, 0x98, 0xb7, 0xe8, 0x0b, 0x8d, 0x25, 0xa1, 0x03, 0x8a, 0x1d, 0xdc, 0x7b, 0xee, 0xe2, 0xf1, + 0x44, 0x72, 0xdf, 0x72, 0x22, 0x70, 0x38, 0x30, 0x8a, 0x97, 0x31, 0x2d, 0x94, 0xd0, 0x2e, 0xff, + 0x6f, 0x11, 0xbc, 0x35, 0xb3, 0xaa, 0xe0, 0x67, 0x00, 0x7a, 0x0d, 0x4e, 0x58, 0x97, 0xd8, 0xa7, + 0xa3, 0xd3, 0x84, 0x7a, 0xd1, 0xc6, 0xdd, 0x55, 0x0b, 0x04, 0xaf, 0x52, 0x08, 0x94, 0xc1, 0x82, + 0x7f, 0xd0, 0xc0, 0xba, 0x3d, 0x72, 0x43, 0xec, 0x9a, 0x67, 0x47, 0x85, 0x71, 0xfa, 0x6d, 0xea, + 0xdd, 0xac, 0x4e, 0x2b, 0x1d, 0xbb, 0x82, 0xf5, 0xad, 0x47, 0x2a, 0xa0, 0xf5, 0x98, 0x0d, 0xc5, + 0x9d, 0xc2, 0x4b, 0x00, 0xed, 0xb1, 0x24, 0x57, 0x67, 0x9a, 0x4c, 0xf1, 0x92, 0xf5, 0x58, 0x29, + 0x3c, 0x8a, 0xf9, 0x8d, 0x40, 0x28, 0x83, 0x08, 0x7f, 0x0a, 0x8a, 0xcd, 0x80, 0x31, 0xe2, 0x8a, + 0x33, 0x82, 0x1d, 0xd1, 0xee, 0xeb, 0x8b, 0x52, 0x6a, 0x47, 0x49, 0x15, 0x8f, 0x62, 0x56, 0x94, + 0x40, 0x87, 0x7c, 0x9b, 0x70, 0xca, 0x88, 0x1d, 0xf1, 0x97, 0xe2, 0xfc, 0x6a, 0xcc, 0x8a, 0x12, + 0x68, 0x78, 0x00, 0xd6, 0x48, 0xcf, 0x27, 0xcd, 0x28, 0xa7, 0xcb, 0x92, 0xbd, 0xad, 0xd8, 0x6b, + 0xc7, 0x53, 0x36, 0x14, 0x43, 0xee, 0x3a, 0x00, 0xa6, 0x93, 0x08, 0x37, 0x40, 0xee, 0x86, 0xf4, + 0x47, 0x27, 0x0f, 0x0a, 0x7f, 0xc2, 0x4f, 0xc1, 0x52, 0x17, 0x3b, 0x01, 0x51, 0xb5, 0xfe, 0xde, + 0xab, 0xd5, 0xfa, 0x33, 0xda, 0x21, 0x68, 0x44, 0xfc, 0xd1, 0x83, 0x03, 0xad, 0xfc, 0x0f, 0x0d, + 0x6c, 0xd6, 0x3c, 0xbb, 0x4e, 0x9a, 0x01, 0xa3, 0xa2, 0x5f, 0x93, 0xeb, 0xfc, 0x06, 0x7a, 0x36, + 0x8a, 0xf5, 0xec, 0x0f, 0xe7, 0xd7, 0x5a, 0x3c, 0xba, 0x59, 0x1d, 0xbb, 0x7c, 0xab, 0x81, 0x47, + 0x29, 0xf4, 0x1b, 0xe8, 0xa8, 0x3f, 0x8f, 0x77, 0xd4, 0xf7, 0xef, 0x33, 0x99, 0x19, 0xfd, 0xf4, + 0x4f, 0xc5, 0x8c, 0xa9, 0xc8, 0x6e, 0x1a, 0xde, 0xee, 0x18, 0xed, 0x52, 0x87, 0xb4, 0x88, 0x2d, + 0x27, 0x53, 0x98, 0xba, 0xdd, 0x8d, 0x2d, 0x68, 0x0a, 0x05, 0x39, 0xd8, 0xb1, 0xc9, 0x35, 0x0e, + 0x1c, 0x71, 0x68, 0xdb, 0x47, 0xd8, 0xc7, 0x0d, 0xea, 0x50, 0x41, 0xd5, 0x75, 0x64, 0xc5, 0xfa, + 0x64, 0x38, 0x30, 0x76, 0xaa, 0x99, 0x88, 0x6f, 0x06, 0xc6, 0xe3, 0xf4, 0xbd, 0xdc, 0x1c, 0x43, + 0xfa, 0x68, 0x86, 0x34, 0xec, 0x03, 0x9d, 0x91, 0xdf, 0x05, 0xe1, 0xa6, 0xa8, 0x32, 0xcf, 0x8f, + 0xb9, 0xcd, 0x49, 0xb7, 0x3f, 0x19, 0x0e, 0x0c, 0x1d, 0xcd, 0xc0, 0xdc, 0xed, 0x78, 0xa6, 0x3c, + 0xfc, 0x02, 0x6c, 0xe1, 0x51, 0x1f, 0x88, 0x79, 0x5d, 0x94, 0x5e, 0x0f, 0x86, 0x03, 0x63, 0xeb, + 0x30, 0x6d, 0xbe, 0xdb, 0x61, 0x96, 0x28, 0xac, 0x80, 0x7c, 0x57, 0x5e, 0xd9, 0xb9, 0xbe, 0x24, + 0xf5, 0x1f, 0x0d, 0x07, 0x46, 0x7e, 0x74, 0x8b, 0x0f, 0x35, 0x97, 0x4f, 0xea, 0xf2, 0x22, 0x18, + 0xa1, 0xe0, 0xc7, 0x60, 0xb5, 0xed, 0x71, 0xf1, 0x33, 0x22, 0xbe, 0xf4, 0xd8, 0x8d, 0x6c, 0x0c, + 0x05, 0x6b, 0x4b, 0xad, 0xe0, 0xea, 0xd9, 0xc4, 0x84, 0xa6, 0x71, 0xf0, 0x97, 0x60, 0xa5, 0xad, + 0xae, 0x7d, 0x5c, 0xcf, 0xcb, 0x42, 0x7b, 0x32, 0xa7, 0xd0, 0x62, 0x57, 0x44, 0x6b, 0x53, 0xc9, + 0xaf, 0x44, 0xc3, 0x1c, 0x4d, 0xd4, 0xe0, 0xf7, 0x41, 0x5e, 0x7e, 0x9c, 0x57, 0xf5, 0x82, 0x8c, + 0xe6, 0xa1, 0x82, 0xe7, 0xcf, 0x46, 0xc3, 0x28, 0xb2, 0x47, 0xd0, 0xf3, 0xda, 0x91, 0xbe, 0x92, + 0x86, 0x9e, 0xd7, 0x8e, 0x50, 0x64, 0x87, 0x2f, 0x40, 0x9e, 0x93, 0x0b, 0xea, 0x06, 0x3d, 0x1d, + 0xc8, 0x2d, 0xb7, 0x37, 0x27, 0xdc, 0xfa, 0xb1, 0x44, 0x26, 0x2e, 0xdc, 0x13, 0x75, 0x65, 0x47, + 0x91, 0x24, 0xb4, 0xc1, 0x0a, 0x0b, 0xdc, 0x43, 0xfe, 0x9c, 0x13, 0xa6, 0xaf, 0xa6, 0x4e, 0xfb, + 0xa4, 0x3e, 0x8a, 0xb0, 0x49, 0x0f, 0xe3, 0xcc, 0x8c, 0x11, 0x68, 0x22, 0x0c, 0xff, 0xa8, 0x01, + 0xc8, 0x03, 0xdf, 0x77, 0x48, 0x87, 0xb8, 0x02, 0x3b, 0xf2, 0x7e, 0xcf, 0xf5, 0x35, 0xe9, 0xef, + 0xc7, 0xf3, 0xe6, 0x93, 0x22, 0x25, 0x1d, 0x8f, 0x8f, 0xe9, 0x34, 0x14, 0x65, 0xf8, 0x0c, 0xd3, + 0x79, 0xcd, 0xe5, 0x6f, 0x7d, 0xfd, 0xce, 0x74, 0x66, 0xbf, 0x5f, 0x26, 0xe9, 0x54, 0x76, 0x14, + 0x49, 0xc2, 0xcf, 0xc1, 0x4e, 0xf4, 0xba, 0x43, 0x9e, 0x27, 0x4e, 0xa8, 0x43, 0x78, 0x9f, 0x0b, + 0xd2, 0xd1, 0x8b, 0x72, 0x99, 0x4b, 0x8a, 0xb9, 0x83, 0x32, 0x51, 0x68, 0x06, 0x1b, 0x76, 0x80, + 0x11, 0xb5, 0x87, 0x70, 0xef, 0x8c, 0xfb, 0xd3, 0x31, 0x6f, 0x62, 0x67, 0x74, 0x6b, 0x79, 0x28, + 0x1d, 0xbc, 0x3b, 0x1c, 0x18, 0x46, 0x75, 0x3e, 0x14, 0xdd, 0xa5, 0x05, 0x7f, 0x01, 0x74, 0x3c, + 0xcb, 0xcf, 0x86, 0xf4, 0xf3, 0xdd, 0xb0, 0xe7, 0xcc, 0x74, 0x30, 0x93, 0x0d, 0x7d, 0xb0, 0x81, + 0xe3, 0xef, 0x6c, 0xae, 0x6f, 0xca, 0x5d, 0xf8, 0xde, 0x9c, 0x75, 0x48, 0x3c, 0xcd, 0x2d, 0x5d, + 0xa5, 0x71, 0x23, 0x61, 0xe0, 0x28, 0xa5, 0x0e, 0x7b, 0x00, 0xe2, 0xe4, 0xdf, 0x02, 0x5c, 0x87, + 0x77, 0x1e, 0x31, 0xa9, 0xff, 0x12, 0x26, 0xa5, 0x96, 0x32, 0x71, 0x94, 0xe1, 0x03, 0x5e, 0x80, + 0x6d, 0x35, 0xfa, 0xdc, 0xe5, 0xf8, 0x9a, 0xd4, 0xfb, 0xbc, 0x29, 0x1c, 0xae, 0x6f, 0xc9, 0xfe, + 0xa6, 0x0f, 0x07, 0xc6, 0xf6, 0x61, 0x86, 0x1d, 0x65, 0xb2, 0xe0, 0xa7, 0x60, 0xe3, 0xda, 0x63, + 0x0d, 0x6a, 0xdb, 0xc4, 0x8d, 0x94, 0xb6, 0xa5, 0xd2, 0x76, 0x98, 0x89, 0x93, 0x84, 0x0d, 0xa5, + 0xd0, 0xe1, 0x8b, 0x5c, 0x9f, 0xb5, 0x81, 0xe1, 0xc7, 0xb1, 0x37, 0xf9, 0x3b, 0x89, 0x37, 0xf9, + 0x66, 0x8a, 0xf7, 0x1a, 0x5e, 0xe4, 0x7f, 0xd3, 0xc0, 0x4e, 0x76, 0x03, 0x83, 0x4f, 0x63, 0xd1, + 0x19, 0x89, 0xe8, 0x1e, 0x26, 0x58, 0x2a, 0xb6, 0xdf, 0x80, 0xa2, 0x6a, 0x73, 0xf1, 0x3f, 0x3c, + 0x62, 0x31, 0x86, 0xe7, 0x53, 0x78, 0x43, 0x51, 0x12, 0xd1, 0x16, 0x97, 0x6f, 0x8b, 0xf8, 0x18, + 0x4a, 0xa8, 0x95, 0xff, 0xae, 0x81, 0x77, 0xee, 0x6c, 0x50, 0xd0, 0x8a, 0x85, 0x6e, 0x26, 0x42, + 0x2f, 0xcd, 0x16, 0x78, 0x3d, 0xff, 0x7b, 0x58, 0x1f, 0xdc, 0xbe, 0x2c, 0x2d, 0x7c, 0xf5, 0xb2, + 0xb4, 0xf0, 0xf5, 0xcb, 0xd2, 0xc2, 0xef, 0x87, 0x25, 0xed, 0x76, 0x58, 0xd2, 0xbe, 0x1a, 0x96, + 0xb4, 0xaf, 0x87, 0x25, 0xed, 0x3f, 0xc3, 0x92, 0xf6, 0xe7, 0xff, 0x96, 0x16, 0x7e, 0x95, 0x57, + 0x72, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x91, 0xe5, 0x7f, 0xdc, 0x14, 0x00, 0x00, } diff --git a/staging/src/k8s.io/api/policy/v1beta1/generated.proto b/staging/src/k8s.io/api/policy/v1beta1/generated.proto index 290ddc8b54a..1a14d946fcf 100644 --- a/staging/src/k8s.io/api/policy/v1beta1/generated.proto +++ b/staging/src/k8s.io/api/policy/v1beta1/generated.proto @@ -47,6 +47,10 @@ message AllowedHostPath { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` optional string pathPrefix = 1; + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + optional bool readOnly = 2; } // Eviction evicts a pod from its node subject to certain policies and safety constraints. @@ -271,6 +275,27 @@ message PodSecurityPolicySpec { // is allowed in the "volumes" field. // +optional repeated AllowedFlexVolume allowedFlexVolumes = 18; + + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + repeated string allowedUnsafeSysctls = 19; + + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + repeated string forbiddenSysctls = 20; } // RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. diff --git a/staging/src/k8s.io/api/policy/v1beta1/types.go b/staging/src/k8s.io/api/policy/v1beta1/types.go index cd8e02c2122..ba1e4ff314f 100644 --- a/staging/src/k8s.io/api/policy/v1beta1/types.go +++ b/staging/src/k8s.io/api/policy/v1beta1/types.go @@ -201,6 +201,25 @@ type PodSecurityPolicySpec struct { // is allowed in the "volumes" field. // +optional AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"` + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + AllowedUnsafeSysctls []string `json:"allowedUnsafeSysctls,omitempty" protobuf:"bytes,19,rep,name=allowedUnsafeSysctls"` + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + ForbiddenSysctls []string `json:"forbiddenSysctls,omitempty" protobuf:"bytes,20,rep,name=forbiddenSysctls"` } // AllowedHostPath defines the host volume conditions that will be enabled by a policy @@ -214,6 +233,10 @@ type AllowedHostPath struct { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` PathPrefix string `json:"pathPrefix,omitempty" protobuf:"bytes,1,rep,name=pathPrefix"` + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,2,opt,name=readOnly"` } // FSType gives strong typing to different file systems that are used by volumes. diff --git a/staging/src/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go index 56c74dbe7cf..12228764539 100644 --- a/staging/src/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go @@ -39,6 +39,7 @@ func (AllowedFlexVolume) SwaggerDoc() map[string]string { var map_AllowedHostPath = map[string]string{ "": "AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", "pathPrefix": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "readOnly": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.", } func (AllowedHostPath) SwaggerDoc() map[string]string { @@ -168,6 +169,8 @@ var map_PodSecurityPolicySpec = map[string]string{ "allowPrivilegeEscalation": "allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", "allowedHostPaths": "allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.", "allowedFlexVolumes": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field.", + "allowedUnsafeSysctls": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc.", + "forbiddenSysctls": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc.", } func (PodSecurityPolicySpec) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go index 96fd14679fa..1980bd1611c 100644 --- a/staging/src/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go @@ -394,6 +394,16 @@ func (in *PodSecurityPolicySpec) DeepCopyInto(out *PodSecurityPolicySpec) { *out = make([]AllowedFlexVolume, len(*in)) copy(*out, *in) } + if in.AllowedUnsafeSysctls != nil { + in, out := &in.AllowedUnsafeSysctls, &out.AllowedUnsafeSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ForbiddenSysctls != nil { + in, out := &in.ForbiddenSysctls, &out.ForbiddenSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/staging/src/k8s.io/api/storage/v1/generated.pb.go b/staging/src/k8s.io/api/storage/v1/generated.pb.go index 7c6fe0a16fe..b13b03fc73e 100644 --- a/staging/src/k8s.io/api/storage/v1/generated.pb.go +++ b/staging/src/k8s.io/api/storage/v1/generated.pb.go @@ -152,6 +152,18 @@ func (m *StorageClass) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(len(*m.VolumeBindingMode))) i += copy(dAtA[i:], *m.VolumeBindingMode) } + if len(m.AllowedTopologies) > 0 { + for _, msg := range m.AllowedTopologies { + dAtA[i] = 0x42 + 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 } @@ -252,6 +264,12 @@ func (m *StorageClass) Size() (n int) { l = len(*m.VolumeBindingMode) n += 1 + l + sovGenerated(uint64(l)) } + if len(m.AllowedTopologies) > 0 { + for _, e := range m.AllowedTopologies { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -304,6 +322,7 @@ func (this *StorageClass) String() string { `MountOptions:` + fmt.Sprintf("%v", this.MountOptions) + `,`, `AllowVolumeExpansion:` + valueToStringGenerated(this.AllowVolumeExpansion) + `,`, `VolumeBindingMode:` + valueToStringGenerated(this.VolumeBindingMode) + `,`, + `AllowedTopologies:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedTopologies), "TopologySelectorTerm", "k8s_io_api_core_v1.TopologySelectorTerm", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -641,6 +660,37 @@ func (m *StorageClass) Unmarshal(dAtA []byte) error { s := VolumeBindingMode(dAtA[iNdEx:postIndex]) m.VolumeBindingMode = &s iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedTopologies", 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.AllowedTopologies = append(m.AllowedTopologies, k8s_io_api_core_v1.TopologySelectorTerm{}) + if err := m.AllowedTopologies[len(m.AllowedTopologies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -883,44 +933,48 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 623 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x4f, 0x6f, 0xd3, 0x3c, - 0x18, 0x6f, 0xda, 0xb7, 0x2f, 0x9b, 0xbb, 0x89, 0x2e, 0x0c, 0x29, 0xea, 0x21, 0xa9, 0xc6, 0xa5, - 0x9a, 0x84, 0xb3, 0x6e, 0x03, 0x4d, 0x48, 0x20, 0x11, 0x34, 0x09, 0xa4, 0x4d, 0xab, 0x82, 0x34, - 0x21, 0xc4, 0x01, 0x37, 0x7d, 0xc8, 0x4c, 0x13, 0x3b, 0xb2, 0x9d, 0x40, 0x6f, 0x7c, 0x04, 0xce, - 0x7c, 0x14, 0x3e, 0xc1, 0x8e, 0x3b, 0xee, 0x14, 0xb1, 0xf0, 0x2d, 0x76, 0x42, 0x49, 0xca, 0x9a, - 0xad, 0x9d, 0xd8, 0x2d, 0xfe, 0xfd, 0xb3, 0x9f, 0x27, 0x3f, 0xf4, 0x62, 0xbc, 0x27, 0x31, 0xe5, - 0xf6, 0x38, 0x1e, 0x82, 0x60, 0xa0, 0x40, 0xda, 0x09, 0xb0, 0x11, 0x17, 0xf6, 0x94, 0x20, 0x11, - 0xb5, 0xa5, 0xe2, 0x82, 0xf8, 0x60, 0x27, 0x7d, 0xdb, 0x07, 0x06, 0x82, 0x28, 0x18, 0xe1, 0x48, - 0x70, 0xc5, 0xf5, 0x87, 0xa5, 0x0c, 0x93, 0x88, 0xe2, 0xa9, 0x0c, 0x27, 0xfd, 0xce, 0x63, 0x9f, - 0xaa, 0x93, 0x78, 0x88, 0x3d, 0x1e, 0xda, 0x3e, 0xf7, 0xb9, 0x5d, 0xa8, 0x87, 0xf1, 0xa7, 0xe2, - 0x54, 0x1c, 0x8a, 0xaf, 0x32, 0xa5, 0xb3, 0xb9, 0xf0, 0xb2, 0x21, 0x28, 0x32, 0x77, 0x63, 0x67, - 0x77, 0xa6, 0x0d, 0x89, 0x77, 0x42, 0x19, 0x88, 0x89, 0x1d, 0x8d, 0xfd, 0x1c, 0x90, 0x76, 0x08, - 0x8a, 0x2c, 0x78, 0x67, 0xc7, 0xbe, 0xcd, 0x25, 0x62, 0xa6, 0x68, 0x08, 0x73, 0x86, 0xa7, 0xff, - 0x32, 0x48, 0xef, 0x04, 0x42, 0x32, 0xe7, 0xdb, 0xb9, 0xcd, 0x17, 0x2b, 0x1a, 0xd8, 0x94, 0x29, - 0xa9, 0xc4, 0x4d, 0xd3, 0xc6, 0x8f, 0x26, 0x5a, 0x79, 0x5b, 0xce, 0xfd, 0x2a, 0x20, 0x52, 0xea, - 0x1f, 0xd1, 0x52, 0x3e, 0xc9, 0x88, 0x28, 0x62, 0x68, 0x5d, 0xad, 0xd7, 0xda, 0xde, 0xc2, 0xb3, - 0x4d, 0x5f, 0x05, 0xe3, 0x68, 0xec, 0xe7, 0x80, 0xc4, 0xb9, 0x1a, 0x27, 0x7d, 0x7c, 0x34, 0xfc, - 0x0c, 0x9e, 0x3a, 0x04, 0x45, 0x1c, 0xfd, 0x34, 0xb5, 0x6a, 0x59, 0x6a, 0xa1, 0x19, 0xe6, 0x5e, - 0xa5, 0xea, 0x4f, 0x50, 0x2b, 0x12, 0x3c, 0xa1, 0x92, 0x72, 0x06, 0xc2, 0xa8, 0x77, 0xb5, 0xde, - 0xb2, 0xf3, 0x60, 0x6a, 0x69, 0x0d, 0x66, 0x94, 0x5b, 0xd5, 0xe9, 0x3e, 0x42, 0x11, 0x11, 0x24, - 0x04, 0x05, 0x42, 0x1a, 0x8d, 0x6e, 0xa3, 0xd7, 0xda, 0xde, 0xc1, 0x0b, 0x4b, 0x80, 0xab, 0x13, - 0xe1, 0xc1, 0x95, 0x6b, 0x9f, 0x29, 0x31, 0x99, 0xbd, 0x6e, 0x46, 0xb8, 0x95, 0x68, 0x7d, 0x8c, - 0x56, 0x05, 0x78, 0x01, 0xa1, 0xe1, 0x80, 0x07, 0xd4, 0x9b, 0x18, 0xff, 0x15, 0x2f, 0xdc, 0xcf, - 0x52, 0x6b, 0xd5, 0xad, 0x12, 0x97, 0xa9, 0xb5, 0x55, 0xa9, 0x8f, 0xc7, 0x45, 0xde, 0x1d, 0x3c, - 0x00, 0x21, 0xa9, 0x54, 0xc0, 0xd4, 0x31, 0x0f, 0xe2, 0x10, 0xae, 0x79, 0xdc, 0xeb, 0xd9, 0xfa, - 0x2e, 0x5a, 0x09, 0x79, 0xcc, 0xd4, 0x51, 0xa4, 0x28, 0x67, 0xd2, 0x68, 0x76, 0x1b, 0xbd, 0x65, - 0xa7, 0x9d, 0xa5, 0xd6, 0xca, 0x61, 0x05, 0x77, 0xaf, 0xa9, 0xf4, 0x03, 0xb4, 0x4e, 0x82, 0x80, - 0x7f, 0x29, 0x2f, 0xd8, 0xff, 0x1a, 0x11, 0x96, 0x6f, 0xc9, 0xf8, 0xbf, 0xab, 0xf5, 0x96, 0x1c, - 0x23, 0x4b, 0xad, 0xf5, 0x97, 0x0b, 0x78, 0x77, 0xa1, 0x4b, 0x7f, 0x87, 0xd6, 0x92, 0x02, 0x72, - 0x28, 0x1b, 0x51, 0xe6, 0x1f, 0xf2, 0x11, 0x18, 0xf7, 0x8a, 0xa1, 0x37, 0xb3, 0xd4, 0x5a, 0x3b, - 0xbe, 0x49, 0x5e, 0x2e, 0x02, 0xdd, 0xf9, 0x90, 0xce, 0x73, 0x74, 0xff, 0xc6, 0xf6, 0xf5, 0x36, - 0x6a, 0x8c, 0x61, 0x52, 0x54, 0x6b, 0xd9, 0xcd, 0x3f, 0xf5, 0x75, 0xd4, 0x4c, 0x48, 0x10, 0x43, - 0xd9, 0x04, 0xb7, 0x3c, 0x3c, 0xab, 0xef, 0x69, 0x1b, 0x3f, 0x35, 0xd4, 0xae, 0xfe, 0xca, 0x03, - 0x2a, 0x95, 0xfe, 0x61, 0xae, 0xa0, 0xf8, 0x6e, 0x05, 0xcd, 0xdd, 0x45, 0x3d, 0xdb, 0xd3, 0x02, - 0x2c, 0xfd, 0x45, 0x2a, 0xe5, 0x7c, 0x8d, 0x9a, 0x54, 0x41, 0x28, 0x8d, 0x7a, 0x51, 0xb0, 0x47, - 0x77, 0x28, 0x98, 0xb3, 0x3a, 0xcd, 0x6b, 0xbe, 0xc9, 0x9d, 0x6e, 0x19, 0xe0, 0xf4, 0x4e, 0x2f, - 0xcc, 0xda, 0xd9, 0x85, 0x59, 0x3b, 0xbf, 0x30, 0x6b, 0xdf, 0x32, 0x53, 0x3b, 0xcd, 0x4c, 0xed, - 0x2c, 0x33, 0xb5, 0xf3, 0xcc, 0xd4, 0x7e, 0x65, 0xa6, 0xf6, 0xfd, 0xb7, 0x59, 0x7b, 0x5f, 0x4f, - 0xfa, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xee, 0x56, 0xcc, 0xfd, 0x0a, 0x05, 0x00, 0x00, + // 677 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xc1, 0x6e, 0xd3, 0x4a, + 0x14, 0x8d, 0x93, 0x97, 0xbe, 0x74, 0xd2, 0xea, 0x25, 0x7e, 0x45, 0x32, 0x59, 0x38, 0x51, 0xd9, + 0x44, 0x95, 0x18, 0x37, 0x6d, 0x41, 0x15, 0x12, 0x48, 0x35, 0xaa, 0x04, 0x52, 0xab, 0x46, 0x6e, + 0x55, 0x21, 0xc4, 0x82, 0x89, 0x73, 0x71, 0x87, 0xd8, 0x33, 0x66, 0x66, 0x6c, 0xc8, 0x8e, 0x1f, + 0x40, 0xe2, 0x7b, 0xf8, 0x82, 0x2e, 0xbb, 0xec, 0x2a, 0xa2, 0xe6, 0x2f, 0xba, 0x42, 0x76, 0x42, + 0xe3, 0x26, 0xa9, 0xe8, 0x6e, 0xe6, 0xdc, 0x73, 0xce, 0x9d, 0x3b, 0xf7, 0x5e, 0xf4, 0x62, 0xb0, + 0x2b, 0x31, 0xe5, 0xd6, 0x20, 0xea, 0x81, 0x60, 0xa0, 0x40, 0x5a, 0x31, 0xb0, 0x3e, 0x17, 0xd6, + 0x24, 0x40, 0x42, 0x6a, 0x49, 0xc5, 0x05, 0xf1, 0xc0, 0x8a, 0x3b, 0x96, 0x07, 0x0c, 0x04, 0x51, + 0xd0, 0xc7, 0xa1, 0xe0, 0x8a, 0xeb, 0x0f, 0xc6, 0x34, 0x4c, 0x42, 0x8a, 0x27, 0x34, 0x1c, 0x77, + 0x1a, 0x8f, 0x3d, 0xaa, 0xce, 0xa2, 0x1e, 0x76, 0x79, 0x60, 0x79, 0xdc, 0xe3, 0x56, 0xc6, 0xee, + 0x45, 0x1f, 0xb2, 0x5b, 0x76, 0xc9, 0x4e, 0x63, 0x97, 0xc6, 0x7a, 0x2e, 0x99, 0xcb, 0xc5, 0xa2, + 0x4c, 0x8d, 0x8d, 0x85, 0x0f, 0xea, 0x81, 0x22, 0xf3, 0xdc, 0x9d, 0x29, 0x37, 0x20, 0xee, 0x19, + 0x65, 0x20, 0x86, 0x56, 0x38, 0xf0, 0x52, 0x40, 0x5a, 0x01, 0x28, 0xb2, 0x28, 0x83, 0x75, 0x97, + 0x4a, 0x44, 0x4c, 0xd1, 0x00, 0xe6, 0x04, 0x4f, 0xff, 0x26, 0x90, 0xee, 0x19, 0x04, 0x64, 0x4e, + 0xb7, 0x7d, 0x97, 0x2e, 0x52, 0xd4, 0xb7, 0x28, 0x53, 0x52, 0x89, 0x59, 0xd1, 0xfa, 0xb7, 0x25, + 0xb4, 0x72, 0x3c, 0xae, 0xfb, 0xa5, 0x4f, 0xa4, 0xd4, 0xdf, 0xa3, 0x4a, 0x5a, 0x49, 0x9f, 0x28, + 0x62, 0x68, 0x2d, 0xad, 0x5d, 0xdd, 0xda, 0xc4, 0xd3, 0x6e, 0xdc, 0x18, 0xe3, 0x70, 0xe0, 0xa5, + 0x80, 0xc4, 0x29, 0x1b, 0xc7, 0x1d, 0x7c, 0xd4, 0xfb, 0x08, 0xae, 0x3a, 0x04, 0x45, 0x6c, 0xfd, + 0x7c, 0xd4, 0x2c, 0x24, 0xa3, 0x26, 0x9a, 0x62, 0xce, 0x8d, 0xab, 0xfe, 0x04, 0x55, 0x43, 0xc1, + 0x63, 0x2a, 0x29, 0x67, 0x20, 0x8c, 0x62, 0x4b, 0x6b, 0x2f, 0xdb, 0xff, 0x4f, 0x24, 0xd5, 0xee, + 0x34, 0xe4, 0xe4, 0x79, 0xba, 0x87, 0x50, 0x48, 0x04, 0x09, 0x40, 0x81, 0x90, 0x46, 0xa9, 0x55, + 0x6a, 0x57, 0xb7, 0xb6, 0xf1, 0xc2, 0x41, 0xc1, 0xf9, 0x8a, 0x70, 0xf7, 0x46, 0xb5, 0xcf, 0x94, + 0x18, 0x4e, 0x5f, 0x37, 0x0d, 0x38, 0x39, 0x6b, 0x7d, 0x80, 0x56, 0x05, 0xb8, 0x3e, 0xa1, 0x41, + 0x97, 0xfb, 0xd4, 0x1d, 0x1a, 0xff, 0x64, 0x2f, 0xdc, 0x4f, 0x46, 0xcd, 0x55, 0x27, 0x1f, 0xb8, + 0x1e, 0x35, 0x37, 0xe7, 0x47, 0x0c, 0x77, 0x41, 0x48, 0x2a, 0x15, 0x30, 0x75, 0xca, 0xfd, 0x28, + 0x80, 0x5b, 0x1a, 0xe7, 0xb6, 0xb7, 0xbe, 0x83, 0x56, 0x02, 0x1e, 0x31, 0x75, 0x14, 0x2a, 0xca, + 0x99, 0x34, 0xca, 0xad, 0x52, 0x7b, 0xd9, 0xae, 0x25, 0xa3, 0xe6, 0xca, 0x61, 0x0e, 0x77, 0x6e, + 0xb1, 0xf4, 0x03, 0xb4, 0x46, 0x7c, 0x9f, 0x7f, 0x1e, 0x27, 0xd8, 0xff, 0x12, 0x12, 0x96, 0xfe, + 0x92, 0xb1, 0xd4, 0xd2, 0xda, 0x15, 0xdb, 0x48, 0x46, 0xcd, 0xb5, 0xbd, 0x05, 0x71, 0x67, 0xa1, + 0x4a, 0x7f, 0x83, 0xea, 0x71, 0x06, 0xd9, 0x94, 0xf5, 0x29, 0xf3, 0x0e, 0x79, 0x1f, 0x8c, 0x7f, + 0xb3, 0xa2, 0x37, 0x92, 0x51, 0xb3, 0x7e, 0x3a, 0x1b, 0xbc, 0x5e, 0x04, 0x3a, 0xf3, 0x26, 0xfa, + 0x27, 0x54, 0xcf, 0x32, 0x42, 0xff, 0x84, 0x87, 0xdc, 0xe7, 0x1e, 0x05, 0x69, 0x54, 0xb2, 0xd6, + 0xb5, 0xf3, 0xad, 0x4b, 0xbf, 0x2e, 0xed, 0xdb, 0x84, 0x35, 0x3c, 0x06, 0x1f, 0x5c, 0xc5, 0xc5, + 0x09, 0x88, 0xc0, 0x7e, 0x38, 0xe9, 0x57, 0x7d, 0x6f, 0xd6, 0xca, 0x99, 0x77, 0x6f, 0x3c, 0x47, + 0xff, 0xcd, 0x34, 0x5c, 0xaf, 0xa1, 0xd2, 0x00, 0x86, 0xd9, 0x34, 0x2f, 0x3b, 0xe9, 0x51, 0x5f, + 0x43, 0xe5, 0x98, 0xf8, 0x11, 0x8c, 0x87, 0xcf, 0x19, 0x5f, 0x9e, 0x15, 0x77, 0xb5, 0xf5, 0x1f, + 0x1a, 0xaa, 0xe5, 0xa7, 0xe7, 0x80, 0x4a, 0xa5, 0xbf, 0x9b, 0xdb, 0x09, 0x7c, 0xbf, 0x9d, 0x48, + 0xd5, 0xd9, 0x46, 0xd4, 0x26, 0x35, 0x54, 0xfe, 0x20, 0xb9, 0x7d, 0x78, 0x85, 0xca, 0x54, 0x41, + 0x20, 0x8d, 0x62, 0xf6, 0x31, 0x8f, 0xee, 0x31, 0xd3, 0xf6, 0xea, 0xc4, 0xaf, 0xfc, 0x3a, 0x55, + 0x3a, 0x63, 0x03, 0xbb, 0x7d, 0x7e, 0x65, 0x16, 0x2e, 0xae, 0xcc, 0xc2, 0xe5, 0x95, 0x59, 0xf8, + 0x9a, 0x98, 0xda, 0x79, 0x62, 0x6a, 0x17, 0x89, 0xa9, 0x5d, 0x26, 0xa6, 0xf6, 0x33, 0x31, 0xb5, + 0xef, 0xbf, 0xcc, 0xc2, 0xdb, 0x62, 0xdc, 0xf9, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x0e, 0x67, 0x74, + 0x30, 0xa1, 0x05, 0x00, 0x00, } diff --git a/staging/src/k8s.io/api/storage/v1/generated.proto b/staging/src/k8s.io/api/storage/v1/generated.proto index d8a01ee8e4a..cff642211d0 100644 --- a/staging/src/k8s.io/api/storage/v1/generated.proto +++ b/staging/src/k8s.io/api/storage/v1/generated.proto @@ -21,6 +21,7 @@ syntax = 'proto2'; package k8s.io.api.storage.v1; +import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/api/storage/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; @@ -70,6 +71,14 @@ message StorageClass { // the VolumeScheduling feature. // +optional optional string volumeBindingMode = 7; + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + repeated k8s.io.api.core.v1.TopologySelectorTerm allowedTopologies = 8; } // StorageClassList is a collection of storage classes. diff --git a/staging/src/k8s.io/api/storage/v1/types.go b/staging/src/k8s.io/api/storage/v1/types.go index 288d40abb8f..45bfa7681be 100644 --- a/staging/src/k8s.io/api/storage/v1/types.go +++ b/staging/src/k8s.io/api/storage/v1/types.go @@ -66,6 +66,14 @@ type StorageClass struct { // the VolumeScheduling feature. // +optional VolumeBindingMode *VolumeBindingMode `json:"volumeBindingMode,omitempty" protobuf:"bytes,7,opt,name=volumeBindingMode"` + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + AllowedTopologies []v1.TopologySelectorTerm `json:"allowedTopologies,omitempty" protobuf:"bytes,8,rep,name=allowedTopologies"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/staging/src/k8s.io/api/storage/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/storage/v1/types_swagger_doc_generated.go index 220e3bd4cad..1d658704700 100644 --- a/staging/src/k8s.io/api/storage/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/storage/v1/types_swagger_doc_generated.go @@ -36,6 +36,7 @@ var map_StorageClass = map[string]string{ "mountOptions": "Dynamically provisioned PersistentVolumes of this storage class are created with these mountOptions, e.g. [\"ro\", \"soft\"]. Not validated - mount of the PVs will simply fail if one is invalid.", "allowVolumeExpansion": "AllowVolumeExpansion shows whether the storage class allow volume expand", "volumeBindingMode": "VolumeBindingMode indicates how PersistentVolumeClaims should be provisioned and bound. When unset, VolumeBindingImmediate is used. This field is alpha-level and is only honored by servers that enable the VolumeScheduling feature.", + "allowedTopologies": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.", } func (StorageClass) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/storage/v1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/storage/v1/zz_generated.deepcopy.go index b5ee5c1cb02..a1050134c0e 100644 --- a/staging/src/k8s.io/api/storage/v1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/storage/v1/zz_generated.deepcopy.go @@ -69,6 +69,13 @@ func (in *StorageClass) DeepCopyInto(out *StorageClass) { **out = **in } } + if in.AllowedTopologies != nil { + in, out := &in.AllowedTopologies, &out.AllowedTopologies + *out = make([]core_v1.TopologySelectorTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/staging/src/k8s.io/api/storage/v1beta1/generated.pb.go b/staging/src/k8s.io/api/storage/v1beta1/generated.pb.go index 5f4fbe07fc3..058702593ea 100644 --- a/staging/src/k8s.io/api/storage/v1beta1/generated.pb.go +++ b/staging/src/k8s.io/api/storage/v1beta1/generated.pb.go @@ -188,6 +188,18 @@ func (m *StorageClass) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(len(*m.VolumeBindingMode))) i += copy(dAtA[i:], *m.VolumeBindingMode) } + if len(m.AllowedTopologies) > 0 { + for _, msg := range m.AllowedTopologies { + dAtA[i] = 0x42 + 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 } @@ -524,6 +536,12 @@ func (m *StorageClass) Size() (n int) { l = len(*m.VolumeBindingMode) n += 1 + l + sovGenerated(uint64(l)) } + if len(m.AllowedTopologies) > 0 { + for _, e := range m.AllowedTopologies { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -657,6 +675,7 @@ func (this *StorageClass) String() string { `MountOptions:` + fmt.Sprintf("%v", this.MountOptions) + `,`, `AllowVolumeExpansion:` + valueToStringGenerated(this.AllowVolumeExpansion) + `,`, `VolumeBindingMode:` + valueToStringGenerated(this.VolumeBindingMode) + `,`, + `AllowedTopologies:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedTopologies), "TopologySelectorTerm", "k8s_io_api_core_v1.TopologySelectorTerm", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -1073,6 +1092,37 @@ func (m *StorageClass) Unmarshal(dAtA []byte) error { s := VolumeBindingMode(dAtA[iNdEx:postIndex]) m.VolumeBindingMode = &s iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedTopologies", 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.AllowedTopologies = append(m.AllowedTopologies, k8s_io_api_core_v1.TopologySelectorTerm{}) + if err := m.AllowedTopologies[len(m.AllowedTopologies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -2145,67 +2195,69 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 977 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x6f, 0x1b, 0x45, - 0x14, 0xcf, 0xc6, 0xf9, 0x1c, 0x27, 0x34, 0x1d, 0x22, 0xb0, 0x7c, 0x58, 0x47, 0xbe, 0x60, 0xaa, - 0x66, 0xb7, 0x09, 0x05, 0x45, 0x48, 0x1c, 0xb2, 0x25, 0x07, 0x50, 0xdc, 0x86, 0x29, 0xaa, 0x50, - 0xc5, 0x81, 0xc9, 0xee, 0xab, 0x33, 0xd8, 0xfb, 0xa1, 0x99, 0x59, 0xd3, 0xdc, 0x38, 0x71, 0xe6, - 0xc4, 0x95, 0x0b, 0xff, 0x07, 0x47, 0x72, 0x42, 0x3d, 0xf6, 0x64, 0x91, 0xe5, 0xbf, 0x88, 0x38, - 0xa0, 0x99, 0x9d, 0x78, 0xd7, 0x5e, 0x5b, 0x4d, 0x7a, 0xe8, 0x2d, 0xf3, 0xde, 0xfb, 0xfd, 0xde, - 0xd7, 0xef, 0xad, 0x83, 0x1e, 0xf5, 0x0f, 0x84, 0xc3, 0x62, 0xb7, 0x9f, 0x9e, 0x02, 0x8f, 0x40, - 0x82, 0x70, 0x87, 0x10, 0x05, 0x31, 0x77, 0x8d, 0x83, 0x26, 0xcc, 0x15, 0x32, 0xe6, 0xb4, 0x07, - 0xee, 0x70, 0xef, 0x14, 0x24, 0xdd, 0x73, 0x7b, 0x10, 0x01, 0xa7, 0x12, 0x02, 0x27, 0xe1, 0xb1, - 0x8c, 0x71, 0x33, 0x8f, 0x75, 0x68, 0xc2, 0x1c, 0x13, 0xeb, 0x98, 0xd8, 0xe6, 0x6e, 0x8f, 0xc9, - 0xb3, 0xf4, 0xd4, 0xf1, 0xe3, 0xd0, 0xed, 0xc5, 0xbd, 0xd8, 0xd5, 0x90, 0xd3, 0xf4, 0x85, 0x7e, - 0xe9, 0x87, 0xfe, 0x2b, 0xa7, 0x6a, 0xb6, 0x4b, 0x69, 0xfd, 0x98, 0xab, 0x9c, 0xd3, 0xe9, 0x9a, - 0xdd, 0x22, 0x06, 0x5e, 0x4a, 0x88, 0x04, 0x8b, 0x23, 0xb1, 0x4b, 0x13, 0x26, 0x80, 0x0f, 0x81, - 0xbb, 0x49, 0xbf, 0xa7, 0x7c, 0x62, 0x32, 0x60, 0x5e, 0xf5, 0xcd, 0x87, 0x05, 0x5d, 0x48, 0xfd, - 0x33, 0x16, 0x01, 0x3f, 0x2f, 0x38, 0x42, 0x90, 0x74, 0x56, 0x11, 0xee, 0x3c, 0x14, 0x4f, 0x23, - 0xc9, 0x42, 0xa8, 0x00, 0x3e, 0x7b, 0x13, 0x40, 0xf8, 0x67, 0x10, 0xd2, 0x0a, 0xee, 0x93, 0x79, - 0xb8, 0x54, 0xb2, 0x81, 0xcb, 0x22, 0x29, 0x24, 0x9f, 0x06, 0xb5, 0x7f, 0x5f, 0x46, 0x1b, 0x4f, - 0xf3, 0x4d, 0x3c, 0x1a, 0x50, 0x21, 0xf0, 0x0f, 0x68, 0x4d, 0x75, 0x12, 0x50, 0x49, 0x1b, 0xd6, - 0x8e, 0xd5, 0xa9, 0xef, 0x3f, 0x70, 0x8a, 0xad, 0x8d, 0x89, 0x9d, 0xa4, 0xdf, 0x53, 0x06, 0xe1, - 0xa8, 0x68, 0x67, 0xb8, 0xe7, 0x3c, 0x39, 0xfd, 0x11, 0x7c, 0xd9, 0x05, 0x49, 0x3d, 0x7c, 0x31, - 0x6a, 0x2d, 0x64, 0xa3, 0x16, 0x2a, 0x6c, 0x64, 0xcc, 0x8a, 0x3f, 0x45, 0xf5, 0x84, 0xc7, 0x43, - 0xa6, 0x86, 0x0d, 0xbc, 0xb1, 0xb8, 0x63, 0x75, 0xd6, 0xbd, 0xf7, 0x0d, 0xa4, 0x7e, 0x52, 0xb8, - 0x48, 0x39, 0x0e, 0x0f, 0x10, 0x4a, 0x28, 0xa7, 0x21, 0x48, 0xe0, 0xa2, 0x51, 0xdb, 0xa9, 0x75, - 0xea, 0xfb, 0x07, 0xce, 0x7c, 0x41, 0x39, 0xe5, 0xb6, 0x9c, 0x93, 0x31, 0xf4, 0x28, 0x92, 0xfc, - 0xbc, 0x28, 0xb1, 0x70, 0x90, 0x12, 0x3f, 0xee, 0xa3, 0x4d, 0x0e, 0xfe, 0x80, 0xb2, 0xf0, 0x24, - 0x1e, 0x30, 0xff, 0xbc, 0xb1, 0xa4, 0xcb, 0x3c, 0xca, 0x46, 0xad, 0x4d, 0x52, 0x76, 0x5c, 0x8d, - 0x5a, 0x0f, 0xaa, 0x52, 0x74, 0x4e, 0x80, 0x0b, 0x26, 0x24, 0x44, 0xf2, 0x59, 0x3c, 0x48, 0x43, - 0x98, 0xc0, 0x90, 0x49, 0x6e, 0xfc, 0x10, 0x6d, 0x84, 0x71, 0x1a, 0xc9, 0x27, 0x89, 0x54, 0x02, - 0x6c, 0x2c, 0xef, 0xd4, 0x3a, 0xeb, 0xde, 0x56, 0x36, 0x6a, 0x6d, 0x74, 0x4b, 0x76, 0x32, 0x11, - 0x85, 0x8f, 0xd1, 0x36, 0x1d, 0x0c, 0xe2, 0x9f, 0xf2, 0x04, 0x47, 0x2f, 0x13, 0xaa, 0xf5, 0xdb, - 0x58, 0xd9, 0xb1, 0x3a, 0x6b, 0x5e, 0x23, 0x1b, 0xb5, 0xb6, 0x0f, 0x67, 0xf8, 0xc9, 0x4c, 0x14, - 0xfe, 0x0e, 0xdd, 0x1d, 0x6a, 0x93, 0xc7, 0xa2, 0x80, 0x45, 0xbd, 0x6e, 0x1c, 0x40, 0x63, 0x55, - 0x37, 0x7d, 0x2f, 0x1b, 0xb5, 0xee, 0x3e, 0x9b, 0x76, 0x5e, 0xcd, 0x32, 0x92, 0x2a, 0x49, 0xf3, - 0x0b, 0x74, 0x67, 0x6a, 0xfa, 0x78, 0x0b, 0xd5, 0xfa, 0x70, 0xae, 0xf5, 0xb5, 0x4e, 0xd4, 0x9f, - 0x78, 0x1b, 0x2d, 0x0f, 0xe9, 0x20, 0x85, 0x5c, 0x0e, 0x24, 0x7f, 0x7c, 0xbe, 0x78, 0x60, 0xb5, - 0xff, 0xb4, 0xd0, 0x56, 0x79, 0x95, 0xc7, 0x4c, 0x48, 0xfc, 0x7d, 0x45, 0xa5, 0xce, 0xcd, 0x54, - 0xaa, 0xd0, 0x5a, 0xa3, 0x5b, 0x46, 0x00, 0x6b, 0xd7, 0x96, 0x92, 0x42, 0xbb, 0x68, 0x99, 0x49, - 0x08, 0x45, 0x63, 0x51, 0xab, 0xac, 0x73, 0x53, 0x95, 0x79, 0x9b, 0x86, 0x74, 0xf9, 0x2b, 0x05, - 0x27, 0x39, 0x4b, 0xfb, 0x8f, 0x45, 0xb4, 0x95, 0x4f, 0xea, 0x50, 0x4a, 0xea, 0x9f, 0x85, 0x10, - 0xc9, 0x77, 0x70, 0x67, 0x04, 0x2d, 0x89, 0x04, 0x7c, 0x3d, 0xd1, 0x49, 0xf6, 0x4a, 0x13, 0xd3, - 0xd5, 0x3d, 0x4d, 0xc0, 0xf7, 0x36, 0x0c, 0xfb, 0x92, 0x7a, 0x11, 0xcd, 0x85, 0x9f, 0xa3, 0x15, - 0x21, 0xa9, 0x4c, 0xd5, 0x01, 0x2a, 0xd6, 0xfd, 0x5b, 0xb1, 0x6a, 0xa4, 0xf7, 0x9e, 0xe1, 0x5d, - 0xc9, 0xdf, 0xc4, 0x30, 0xb6, 0xff, 0xb2, 0xd0, 0xf6, 0x34, 0xe4, 0x1d, 0x2c, 0xfb, 0x9b, 0xc9, - 0x65, 0xdf, 0xbf, 0x4d, 0x47, 0x73, 0x16, 0xfe, 0x02, 0x7d, 0x50, 0xe9, 0x3d, 0x4e, 0xb9, 0x0f, - 0xea, 0x66, 0x93, 0xa9, 0x2f, 0xc3, 0x63, 0x1a, 0x42, 0x7e, 0x09, 0xf9, 0xcd, 0x9e, 0xcc, 0xf0, - 0x93, 0x99, 0xa8, 0xf6, 0xdf, 0x33, 0x26, 0xa6, 0x96, 0x85, 0xef, 0xa3, 0x35, 0xaa, 0x2d, 0xc0, - 0x0d, 0xf5, 0x78, 0x02, 0x87, 0xc6, 0x4e, 0xc6, 0x11, 0x7a, 0xa9, 0xba, 0x3c, 0x23, 0x95, 0xdb, - 0x2d, 0x55, 0x23, 0x4b, 0x4b, 0xd5, 0x6f, 0x62, 0x18, 0x55, 0x25, 0x51, 0x1c, 0xe4, 0x4d, 0xd6, - 0x26, 0x2b, 0x79, 0x6c, 0xec, 0x64, 0x1c, 0xd1, 0xfe, 0xaf, 0x36, 0x63, 0x72, 0x5a, 0x1d, 0xa5, - 0x96, 0x02, 0xdd, 0xd2, 0x5a, 0xa5, 0xa5, 0x60, 0xdc, 0x52, 0x80, 0x7f, 0xb3, 0x10, 0xa6, 0x63, - 0x8a, 0xee, 0xb5, 0x7a, 0xf2, 0x15, 0x7f, 0x7d, 0x7b, 0xd1, 0x3a, 0x87, 0x15, 0xb2, 0xfc, 0x77, - 0xa4, 0x69, 0x8a, 0xc0, 0xd5, 0x00, 0x32, 0xa3, 0x02, 0xcc, 0x50, 0x3d, 0xb7, 0x1e, 0x71, 0x1e, - 0x73, 0x73, 0x45, 0x1f, 0xbd, 0xb9, 0x20, 0x1d, 0xee, 0xd9, 0xea, 0x17, 0xf2, 0xb0, 0xc0, 0x5f, - 0x8d, 0x5a, 0xf5, 0x92, 0x9f, 0x94, 0xb9, 0x55, 0xaa, 0x00, 0x8a, 0x54, 0x4b, 0x6f, 0x91, 0xea, - 0x4b, 0x98, 0x9f, 0xaa, 0xc4, 0xdd, 0x3c, 0x42, 0x1f, 0xce, 0x19, 0xd0, 0xad, 0x3e, 0xf5, 0xbf, - 0x58, 0xa8, 0x9c, 0x03, 0x1f, 0xa3, 0x25, 0xf5, 0x0f, 0x8f, 0x39, 0xfa, 0x7b, 0x37, 0x3b, 0xfa, - 0x6f, 0x59, 0x08, 0xc5, 0xb7, 0x4b, 0xbd, 0x88, 0x66, 0xc1, 0x1f, 0xa3, 0xd5, 0x10, 0x84, 0xa0, - 0x3d, 0x93, 0xd9, 0xbb, 0x63, 0x82, 0x56, 0xbb, 0xb9, 0x99, 0x5c, 0xfb, 0xbd, 0xdd, 0x8b, 0x4b, - 0x7b, 0xe1, 0xd5, 0xa5, 0xbd, 0xf0, 0xfa, 0xd2, 0x5e, 0xf8, 0x39, 0xb3, 0xad, 0x8b, 0xcc, 0xb6, - 0x5e, 0x65, 0xb6, 0xf5, 0x3a, 0xb3, 0xad, 0x7f, 0x32, 0xdb, 0xfa, 0xf5, 0x5f, 0x7b, 0xe1, 0xf9, - 0xaa, 0x99, 0xdb, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x4b, 0x7f, 0x8a, 0x3b, 0x1c, 0x0b, 0x00, - 0x00, + // 1022 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4d, 0x6f, 0x1b, 0x45, + 0x18, 0xce, 0xc6, 0xf9, 0x70, 0xc6, 0x09, 0x4d, 0x96, 0x08, 0x8c, 0x0f, 0x76, 0xe4, 0x0b, 0xa6, + 0x6a, 0x76, 0x9b, 0x50, 0x50, 0x84, 0xc4, 0xc1, 0x5b, 0x72, 0x00, 0xc5, 0x6d, 0x98, 0x44, 0x15, + 0xaa, 0x38, 0x30, 0xd9, 0x7d, 0xeb, 0x0c, 0xde, 0xdd, 0x59, 0x66, 0xc6, 0xa6, 0xb9, 0x71, 0xe2, + 0x8c, 0x38, 0xf0, 0x0b, 0xf8, 0x1f, 0x1c, 0xc9, 0x09, 0xf5, 0xd8, 0x93, 0x45, 0xcc, 0xbf, 0x88, + 0x38, 0xa0, 0x99, 0x9d, 0x78, 0xd7, 0x5e, 0x9b, 0x36, 0x3d, 0xf4, 0xe6, 0xf7, 0xe3, 0x79, 0xde, + 0xef, 0x59, 0xa3, 0x87, 0xbd, 0x03, 0xe1, 0x50, 0xe6, 0xf6, 0xfa, 0x67, 0xc0, 0x63, 0x90, 0x20, + 0xdc, 0x01, 0xc4, 0x01, 0xe3, 0xae, 0x31, 0x90, 0x84, 0xba, 0x42, 0x32, 0x4e, 0xba, 0xe0, 0x0e, + 0xf6, 0xce, 0x40, 0x92, 0x3d, 0xb7, 0x0b, 0x31, 0x70, 0x22, 0x21, 0x70, 0x12, 0xce, 0x24, 0xb3, + 0x6b, 0xa9, 0xaf, 0x43, 0x12, 0xea, 0x18, 0x5f, 0xc7, 0xf8, 0xd6, 0x76, 0xbb, 0x54, 0x9e, 0xf7, + 0xcf, 0x1c, 0x9f, 0x45, 0x6e, 0x97, 0x75, 0x99, 0xab, 0x21, 0x67, 0xfd, 0x67, 0x5a, 0xd2, 0x82, + 0xfe, 0x95, 0x52, 0xd5, 0x9a, 0xb9, 0xb0, 0x3e, 0xe3, 0x2a, 0xe6, 0x74, 0xb8, 0x5a, 0x27, 0xf3, + 0x81, 0xe7, 0x12, 0x62, 0x41, 0x59, 0x2c, 0x76, 0x49, 0x42, 0x05, 0xf0, 0x01, 0x70, 0x37, 0xe9, + 0x75, 0x95, 0x4d, 0x4c, 0x3a, 0xcc, 0xcb, 0xbe, 0xf6, 0x20, 0xa3, 0x8b, 0x88, 0x7f, 0x4e, 0x63, + 0xe0, 0x17, 0x19, 0x47, 0x04, 0x92, 0xcc, 0x4a, 0xc2, 0x9d, 0x87, 0xe2, 0xfd, 0x58, 0xd2, 0x08, + 0x0a, 0x80, 0x4f, 0x5f, 0x05, 0x10, 0xfe, 0x39, 0x44, 0xa4, 0x80, 0xfb, 0x78, 0x1e, 0xae, 0x2f, + 0x69, 0xe8, 0xd2, 0x58, 0x0a, 0xc9, 0xa7, 0x41, 0xcd, 0x5f, 0x57, 0xd0, 0xfa, 0x49, 0x3a, 0x89, + 0x87, 0x21, 0x11, 0xc2, 0xfe, 0x0e, 0x95, 0x55, 0x25, 0x01, 0x91, 0xa4, 0x6a, 0xed, 0x58, 0xad, + 0xca, 0xfe, 0x7d, 0x27, 0x9b, 0xda, 0x98, 0xd8, 0x49, 0x7a, 0x5d, 0xa5, 0x10, 0x8e, 0xf2, 0x76, + 0x06, 0x7b, 0xce, 0xe3, 0xb3, 0xef, 0xc1, 0x97, 0x1d, 0x90, 0xc4, 0xb3, 0x2f, 0x87, 0x8d, 0x85, + 0xd1, 0xb0, 0x81, 0x32, 0x1d, 0x1e, 0xb3, 0xda, 0x9f, 0xa0, 0x4a, 0xc2, 0xd9, 0x80, 0xaa, 0x66, + 0x03, 0xaf, 0x2e, 0xee, 0x58, 0xad, 0x35, 0xef, 0x5d, 0x03, 0xa9, 0x1c, 0x67, 0x26, 0x9c, 0xf7, + 0xb3, 0x43, 0x84, 0x12, 0xc2, 0x49, 0x04, 0x12, 0xb8, 0xa8, 0x96, 0x76, 0x4a, 0xad, 0xca, 0xfe, + 0x81, 0x33, 0x7f, 0xa1, 0x9c, 0x7c, 0x59, 0xce, 0xf1, 0x18, 0x7a, 0x18, 0x4b, 0x7e, 0x91, 0xa5, + 0x98, 0x19, 0x70, 0x8e, 0xdf, 0xee, 0xa1, 0x0d, 0x0e, 0x7e, 0x48, 0x68, 0x74, 0xcc, 0x42, 0xea, + 0x5f, 0x54, 0x97, 0x74, 0x9a, 0x87, 0xa3, 0x61, 0x63, 0x03, 0xe7, 0x0d, 0xd7, 0xc3, 0xc6, 0xfd, + 0xe2, 0x2a, 0x3a, 0xc7, 0xc0, 0x05, 0x15, 0x12, 0x62, 0xf9, 0x84, 0x85, 0xfd, 0x08, 0x26, 0x30, + 0x78, 0x92, 0xdb, 0x7e, 0x80, 0xd6, 0x23, 0xd6, 0x8f, 0xe5, 0xe3, 0x44, 0xaa, 0x05, 0xac, 0x2e, + 0xef, 0x94, 0x5a, 0x6b, 0xde, 0xe6, 0x68, 0xd8, 0x58, 0xef, 0xe4, 0xf4, 0x78, 0xc2, 0xcb, 0x3e, + 0x42, 0xdb, 0x24, 0x0c, 0xd9, 0x8f, 0x69, 0x80, 0xc3, 0xe7, 0x09, 0xd1, 0xfb, 0x5b, 0x5d, 0xd9, + 0xb1, 0x5a, 0x65, 0xaf, 0x3a, 0x1a, 0x36, 0xb6, 0xdb, 0x33, 0xec, 0x78, 0x26, 0xca, 0xfe, 0x06, + 0x6d, 0x0d, 0xb4, 0xca, 0xa3, 0x71, 0x40, 0xe3, 0x6e, 0x87, 0x05, 0x50, 0x5d, 0xd5, 0x45, 0xdf, + 0x1d, 0x0d, 0x1b, 0x5b, 0x4f, 0xa6, 0x8d, 0xd7, 0xb3, 0x94, 0xb8, 0x48, 0x62, 0xff, 0x80, 0xb6, + 0x74, 0x44, 0x08, 0x4e, 0x59, 0xc2, 0x42, 0xd6, 0xa5, 0x20, 0xaa, 0x65, 0x3d, 0xbf, 0x56, 0x7e, + 0x7e, 0xaa, 0x75, 0x6a, 0x91, 0x8c, 0xd7, 0xc5, 0x09, 0x84, 0xe0, 0x4b, 0xc6, 0x4f, 0x81, 0x47, + 0xde, 0x07, 0x66, 0x5e, 0x5b, 0xed, 0x69, 0x2a, 0x5c, 0x64, 0xaf, 0x7d, 0x8e, 0xee, 0x4c, 0x0d, + 0xdc, 0xde, 0x44, 0xa5, 0x1e, 0x5c, 0xe8, 0x95, 0x5e, 0xc3, 0xea, 0xa7, 0xbd, 0x8d, 0x96, 0x07, + 0x24, 0xec, 0x43, 0xba, 0x81, 0x38, 0x15, 0x3e, 0x5b, 0x3c, 0xb0, 0x9a, 0x7f, 0x58, 0x68, 0x33, + 0xbf, 0x3d, 0x47, 0x54, 0x48, 0xfb, 0xdb, 0xc2, 0x61, 0x38, 0xaf, 0x77, 0x18, 0x0a, 0xad, 0xcf, + 0x62, 0xd3, 0xd4, 0x50, 0xbe, 0xd1, 0xe4, 0x8e, 0xa2, 0x83, 0x96, 0xa9, 0x84, 0x48, 0x54, 0x17, + 0x8b, 0x8d, 0xf9, 0xbf, 0xc5, 0xf6, 0x36, 0x0c, 0xe9, 0xf2, 0x97, 0x0a, 0x8e, 0x53, 0x96, 0xe6, + 0xef, 0x8b, 0x68, 0x33, 0x1d, 0x4e, 0x5b, 0x4a, 0xe2, 0x9f, 0x47, 0x10, 0xcb, 0xb7, 0x70, 0xda, + 0x18, 0x2d, 0x89, 0x04, 0x7c, 0xdd, 0xd1, 0x49, 0xf6, 0x42, 0x11, 0xd3, 0xd9, 0x9d, 0x24, 0xe0, + 0x7b, 0xeb, 0x86, 0x7d, 0x49, 0x49, 0x58, 0x73, 0xd9, 0x4f, 0xd1, 0x8a, 0x90, 0x44, 0xf6, 0xd5, + 0xcd, 0x2b, 0xd6, 0xfd, 0x5b, 0xb1, 0x6a, 0xa4, 0xf7, 0x8e, 0xe1, 0x5d, 0x49, 0x65, 0x6c, 0x18, + 0x9b, 0x7f, 0x5a, 0x68, 0x7b, 0x1a, 0xf2, 0x16, 0x86, 0xfd, 0xf5, 0xe4, 0xb0, 0xef, 0xdd, 0xa6, + 0xa2, 0x39, 0x03, 0x7f, 0x86, 0xde, 0x2b, 0xd4, 0xce, 0xfa, 0xdc, 0x07, 0xf5, 0x4c, 0x24, 0x53, + 0x8f, 0xd1, 0x23, 0x12, 0x41, 0x7a, 0x09, 0xe9, 0x33, 0x71, 0x3c, 0xc3, 0x8e, 0x67, 0xa2, 0x9a, + 0x7f, 0xcd, 0xe8, 0x98, 0x1a, 0x96, 0x7d, 0x0f, 0x95, 0x89, 0xd6, 0x00, 0x37, 0xd4, 0xe3, 0x0e, + 0xb4, 0x8d, 0x1e, 0x8f, 0x3d, 0xf4, 0x50, 0x75, 0x7a, 0x66, 0x55, 0x6e, 0x37, 0x54, 0x8d, 0xcc, + 0x0d, 0x55, 0xcb, 0xd8, 0x30, 0xaa, 0x4c, 0x62, 0x16, 0xa4, 0x45, 0x96, 0x26, 0x33, 0x79, 0x64, + 0xf4, 0x78, 0xec, 0xd1, 0xfc, 0xb7, 0x34, 0xa3, 0x73, 0x7a, 0x3b, 0x72, 0x25, 0x05, 0xba, 0xa4, + 0x72, 0xa1, 0xa4, 0x60, 0x5c, 0x52, 0x60, 0xff, 0x66, 0x21, 0x9b, 0x8c, 0x29, 0x3a, 0x37, 0xdb, + 0x93, 0x8e, 0xf8, 0xab, 0xdb, 0x2f, 0xad, 0xd3, 0x2e, 0x90, 0xa5, 0x9f, 0xae, 0x9a, 0x49, 0xc2, + 0x2e, 0x3a, 0xe0, 0x19, 0x19, 0xd8, 0x14, 0x55, 0x52, 0xed, 0x21, 0xe7, 0x8c, 0x9b, 0x2b, 0xfa, + 0xf0, 0xd5, 0x09, 0x69, 0x77, 0xaf, 0xae, 0x3e, 0xca, 0xed, 0x0c, 0x7f, 0x3d, 0x6c, 0x54, 0x72, + 0x76, 0x9c, 0xe7, 0x56, 0xa1, 0x02, 0xc8, 0x42, 0x2d, 0xbd, 0x41, 0xa8, 0x2f, 0x60, 0x7e, 0xa8, + 0x1c, 0x77, 0xed, 0x10, 0xbd, 0x3f, 0xa7, 0x41, 0xb7, 0x7a, 0xea, 0x7f, 0xb6, 0x50, 0x3e, 0x86, + 0x7d, 0x84, 0x96, 0xd4, 0x7f, 0x2c, 0x73, 0xf4, 0x77, 0x5f, 0xef, 0xe8, 0x4f, 0x69, 0x04, 0xd9, + 0xdb, 0xa5, 0x24, 0xac, 0x59, 0xec, 0x8f, 0xd0, 0x6a, 0x04, 0x42, 0x90, 0xae, 0x89, 0xec, 0xdd, + 0x31, 0x4e, 0xab, 0x9d, 0x54, 0x8d, 0x6f, 0xec, 0xde, 0xee, 0xe5, 0x55, 0x7d, 0xe1, 0xc5, 0x55, + 0x7d, 0xe1, 0xe5, 0x55, 0x7d, 0xe1, 0xa7, 0x51, 0xdd, 0xba, 0x1c, 0xd5, 0xad, 0x17, 0xa3, 0xba, + 0xf5, 0x72, 0x54, 0xb7, 0xfe, 0x1e, 0xd5, 0xad, 0x5f, 0xfe, 0xa9, 0x2f, 0x3c, 0x5d, 0x35, 0x7d, + 0xfb, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xa9, 0x81, 0xd5, 0x8f, 0x0b, 0x00, 0x00, } diff --git a/staging/src/k8s.io/api/storage/v1beta1/generated.proto b/staging/src/k8s.io/api/storage/v1beta1/generated.proto index 31548fc740e..32032b1a327 100644 --- a/staging/src/k8s.io/api/storage/v1beta1/generated.proto +++ b/staging/src/k8s.io/api/storage/v1beta1/generated.proto @@ -71,6 +71,14 @@ message StorageClass { // the VolumeScheduling feature. // +optional optional string volumeBindingMode = 7; + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + repeated k8s.io.api.core.v1.TopologySelectorTerm allowedTopologies = 8; } // StorageClassList is a collection of storage classes. diff --git a/staging/src/k8s.io/api/storage/v1beta1/types.go b/staging/src/k8s.io/api/storage/v1beta1/types.go index 99c9e4594d8..7ec1e908f47 100644 --- a/staging/src/k8s.io/api/storage/v1beta1/types.go +++ b/staging/src/k8s.io/api/storage/v1beta1/types.go @@ -66,6 +66,14 @@ type StorageClass struct { // the VolumeScheduling feature. // +optional VolumeBindingMode *VolumeBindingMode `json:"volumeBindingMode,omitempty" protobuf:"bytes,7,opt,name=volumeBindingMode"` + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + AllowedTopologies []v1.TopologySelectorTerm `json:"allowedTopologies,omitempty" protobuf:"bytes,8,rep,name=allowedTopologies"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/staging/src/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go index 138586956ac..423e7f271b4 100644 --- a/staging/src/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go @@ -36,6 +36,7 @@ var map_StorageClass = map[string]string{ "mountOptions": "Dynamically provisioned PersistentVolumes of this storage class are created with these mountOptions, e.g. [\"ro\", \"soft\"]. Not validated - mount of the PVs will simply fail if one is invalid.", "allowVolumeExpansion": "AllowVolumeExpansion shows whether the storage class allow volume expand", "volumeBindingMode": "VolumeBindingMode indicates how PersistentVolumeClaims should be provisioned and bound. When unset, VolumeBindingImmediate is used. This field is alpha-level and is only honored by servers that enable the VolumeScheduling feature.", + "allowedTopologies": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.", } func (StorageClass) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go index fa6c55d4404..7c7c8fde5d1 100644 --- a/staging/src/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go @@ -69,6 +69,13 @@ func (in *StorageClass) DeepCopyInto(out *StorageClass) { **out = **in } } + if in.AllowedTopologies != nil { + in, out := &in.AllowedTopologies, &out.AllowedTopologies + *out = make([]v1.TopologySelectorTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/staging/src/k8s.io/apiextensions-apiserver/BUILD b/staging/src/k8s.io/apiextensions-apiserver/BUILD index 8092fcb8216..31d0de0ae36 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/BUILD +++ b/staging/src/k8s.io/apiextensions-apiserver/BUILD @@ -44,6 +44,7 @@ filegroup( "//staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver/pkg/cmd/server:all-srcs", + "//staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver/pkg/controller/finalizer:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver/pkg/features:all-srcs", diff --git a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json index fba71ace596..a3ac798fa6b 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json @@ -436,35 +436,35 @@ }, { "ImportPath": "github.com/golang/protobuf/jsonpb", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/protoc-gen-go/descriptor", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/struct", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -532,7 +532,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "2ddf6d758266fcb080a4f9e054b9f292c85e6798" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/mailru/easyjson/buffer", @@ -1910,6 +1910,10 @@ "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" @@ -2010,6 +2014,10 @@ "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" @@ -2028,23 +2036,23 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/equality", @@ -2078,6 +2086,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/api/validation", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -2266,6 +2278,10 @@ "ImportPath": "k8s.io/client-go/dynamic", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/scheme", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/rest", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/apiextensions-apiserver/OWNERS b/staging/src/k8s.io/apiextensions-apiserver/OWNERS index e0cd3186f02..d9cb557fc7b 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/OWNERS +++ b/staging/src/k8s.io/apiextensions-apiserver/OWNERS @@ -2,6 +2,7 @@ reviewers: - deads2k - sttts - enisoc +- mbohlool approvers: - deads2k - lavalamp diff --git a/staging/src/k8s.io/apiextensions-apiserver/SECURITY_CONTACTS b/staging/src/k8s.io/apiextensions-apiserver/SECURITY_CONTACTS new file mode 100644 index 00000000000..0648a8ebff7 --- /dev/null +++ b/staging/src/k8s.io/apiextensions-apiserver/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# 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/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/BUILD b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/BUILD index a6e5ed9df8c..983bb2bbcb6 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/BUILD +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/BUILD @@ -12,6 +12,7 @@ go_library( deps = [ "//vendor/github.com/google/gofuzz:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go index 0fe919ab64e..ff8cc033469 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go @@ -23,9 +23,12 @@ import ( "github.com/google/gofuzz" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" ) +var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() + // Funcs returns the fuzzer functions for the apiextensions apis. func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ @@ -53,6 +56,11 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { } else if len(obj.Versions) != 0 { obj.Version = obj.Versions[0].Name } + if len(obj.AdditionalPrinterColumns) == 0 { + obj.AdditionalPrinterColumns = []apiextensions.CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"}, + } + } }, func(obj *apiextensions.CustomResourceDefinition, c fuzz.Continue) { c.FuzzNoCustom(obj) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go index debe74a5b0c..6fc75154fac 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go @@ -49,6 +49,8 @@ type CustomResourceDefinitionSpec struct { // major version, then minor version. An example sorted list of versions: // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. Versions []CustomResourceDefinitionVersion + // AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column. + AdditionalPrinterColumns []CustomResourceColumnDefinition } type CustomResourceDefinitionVersion struct { @@ -61,6 +63,28 @@ type CustomResourceDefinitionVersion struct { Storage bool } +// CustomResourceColumnDefinition specifies a column for server side printing. +type CustomResourceColumnDefinition struct { + // name is a human readable name for the column. + Name string + // type is an OpenAPI type definition for this column. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Type string + // format is an optional OpenAPI type definition for this column. The 'name' format is applied + // to the primary identifier column to assist in clients identifying column is the resource name. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Format string + // description is a human readable description of this column. + Description string + // priority is an integer defining the relative importance of this column compared to others. Lower + // numbers are considered higher priority. Columns that may be omitted in limited space scenarios + // should be given a higher priority. + Priority int32 + + // JSONPath is a simple JSON path, i.e. without array notation. + JSONPath string +} + // CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition type CustomResourceDefinitionNames struct { // Plural is the plural name of the resource to serve. It must match the name of the CustomResourceDefinition-registration diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go index 1984e229778..e3235e8702c 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go @@ -19,9 +19,12 @@ package v1beta1 import ( "strings" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) +var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() + func addDefaultingFuncs(scheme *runtime.Scheme) error { scheme.AddTypeDefaultingFunc(&CustomResourceDefinition{}, func(obj interface{}) { SetDefaults_CustomResourceDefinition(obj.(*CustomResourceDefinition)) }) // TODO figure out why I can't seem to get my defaulter generated @@ -63,4 +66,9 @@ func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec) if len(obj.Version) == 0 && len(obj.Versions) != 0 { obj.Version = obj.Versions[0].Name } + if len(obj.AdditionalPrinterColumns) == 0 { + obj.AdditionalPrinterColumns = []CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"}, + } + } } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go index b5a8c0e0002..8e30403c8e3 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go @@ -25,6 +25,7 @@ limitations under the License. k8s.io/kubernetes/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto It has these top-level messages: + CustomResourceColumnDefinition CustomResourceDefinition CustomResourceDefinitionCondition CustomResourceDefinitionList @@ -67,99 +68,106 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +func (m *CustomResourceColumnDefinition) Reset() { *m = CustomResourceColumnDefinition{} } +func (*CustomResourceColumnDefinition) ProtoMessage() {} +func (*CustomResourceColumnDefinition) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{0} +} + func (m *CustomResourceDefinition) Reset() { *m = CustomResourceDefinition{} } func (*CustomResourceDefinition) ProtoMessage() {} func (*CustomResourceDefinition) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{0} + return fileDescriptorGenerated, []int{1} } func (m *CustomResourceDefinitionCondition) Reset() { *m = CustomResourceDefinitionCondition{} } func (*CustomResourceDefinitionCondition) ProtoMessage() {} func (*CustomResourceDefinitionCondition) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{1} + return fileDescriptorGenerated, []int{2} } func (m *CustomResourceDefinitionList) Reset() { *m = CustomResourceDefinitionList{} } func (*CustomResourceDefinitionList) ProtoMessage() {} func (*CustomResourceDefinitionList) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{2} + return fileDescriptorGenerated, []int{3} } func (m *CustomResourceDefinitionNames) Reset() { *m = CustomResourceDefinitionNames{} } func (*CustomResourceDefinitionNames) ProtoMessage() {} func (*CustomResourceDefinitionNames) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{3} + return fileDescriptorGenerated, []int{4} } func (m *CustomResourceDefinitionSpec) Reset() { *m = CustomResourceDefinitionSpec{} } func (*CustomResourceDefinitionSpec) ProtoMessage() {} func (*CustomResourceDefinitionSpec) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{4} + return fileDescriptorGenerated, []int{5} } func (m *CustomResourceDefinitionStatus) Reset() { *m = CustomResourceDefinitionStatus{} } func (*CustomResourceDefinitionStatus) ProtoMessage() {} func (*CustomResourceDefinitionStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{5} + return fileDescriptorGenerated, []int{6} } func (m *CustomResourceDefinitionVersion) Reset() { *m = CustomResourceDefinitionVersion{} } func (*CustomResourceDefinitionVersion) ProtoMessage() {} func (*CustomResourceDefinitionVersion) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{6} + return fileDescriptorGenerated, []int{7} } func (m *CustomResourceSubresourceScale) Reset() { *m = CustomResourceSubresourceScale{} } func (*CustomResourceSubresourceScale) ProtoMessage() {} func (*CustomResourceSubresourceScale) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{7} + return fileDescriptorGenerated, []int{8} } func (m *CustomResourceSubresourceStatus) Reset() { *m = CustomResourceSubresourceStatus{} } func (*CustomResourceSubresourceStatus) ProtoMessage() {} func (*CustomResourceSubresourceStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{8} + return fileDescriptorGenerated, []int{9} } func (m *CustomResourceSubresources) Reset() { *m = CustomResourceSubresources{} } func (*CustomResourceSubresources) ProtoMessage() {} func (*CustomResourceSubresources) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{9} + return fileDescriptorGenerated, []int{10} } func (m *CustomResourceValidation) Reset() { *m = CustomResourceValidation{} } func (*CustomResourceValidation) ProtoMessage() {} func (*CustomResourceValidation) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{10} + return fileDescriptorGenerated, []int{11} } func (m *ExternalDocumentation) Reset() { *m = ExternalDocumentation{} } func (*ExternalDocumentation) ProtoMessage() {} -func (*ExternalDocumentation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } +func (*ExternalDocumentation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } func (m *JSON) Reset() { *m = JSON{} } func (*JSON) ProtoMessage() {} -func (*JSON) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } +func (*JSON) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } func (m *JSONSchemaProps) Reset() { *m = JSONSchemaProps{} } func (*JSONSchemaProps) ProtoMessage() {} -func (*JSONSchemaProps) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } +func (*JSONSchemaProps) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } func (m *JSONSchemaPropsOrArray) Reset() { *m = JSONSchemaPropsOrArray{} } func (*JSONSchemaPropsOrArray) ProtoMessage() {} -func (*JSONSchemaPropsOrArray) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } +func (*JSONSchemaPropsOrArray) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } func (m *JSONSchemaPropsOrBool) Reset() { *m = JSONSchemaPropsOrBool{} } func (*JSONSchemaPropsOrBool) ProtoMessage() {} -func (*JSONSchemaPropsOrBool) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } +func (*JSONSchemaPropsOrBool) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } func (m *JSONSchemaPropsOrStringArray) Reset() { *m = JSONSchemaPropsOrStringArray{} } func (*JSONSchemaPropsOrStringArray) ProtoMessage() {} func (*JSONSchemaPropsOrStringArray) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{16} + return fileDescriptorGenerated, []int{17} } func init() { + proto.RegisterType((*CustomResourceColumnDefinition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition") proto.RegisterType((*CustomResourceDefinition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition") proto.RegisterType((*CustomResourceDefinitionCondition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition") proto.RegisterType((*CustomResourceDefinitionList)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionList") @@ -178,6 +186,47 @@ func init() { proto.RegisterType((*JSONSchemaPropsOrBool)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool") proto.RegisterType((*JSONSchemaPropsOrStringArray)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray") } +func (m *CustomResourceColumnDefinition) 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 *CustomResourceColumnDefinition) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Type))) + i += copy(dAtA[i:], m.Type) + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Format))) + i += copy(dAtA[i:], m.Format) + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Description))) + i += copy(dAtA[i:], m.Description) + dAtA[i] = 0x28 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Priority)) + dAtA[i] = 0x32 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.JSONPath))) + i += copy(dAtA[i:], m.JSONPath) + return i, nil +} + func (m *CustomResourceDefinition) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -431,6 +480,18 @@ func (m *CustomResourceDefinitionSpec) MarshalTo(dAtA []byte) (int, error) { i += n } } + if len(m.AdditionalPrinterColumns) > 0 { + for _, msg := range m.AdditionalPrinterColumns { + dAtA[i] = 0x42 + 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 } @@ -1257,6 +1318,23 @@ func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return offset + 1 } +func (m *CustomResourceColumnDefinition) Size() (n int) { + var l int + _ = l + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Type) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Format) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Description) + n += 1 + l + sovGenerated(uint64(l)) + n += 1 + sovGenerated(uint64(m.Priority)) + l = len(m.JSONPath) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *CustomResourceDefinition) Size() (n int) { var l int _ = l @@ -1350,6 +1428,12 @@ func (m *CustomResourceDefinitionSpec) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + if len(m.AdditionalPrinterColumns) > 0 { + for _, e := range m.AdditionalPrinterColumns { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -1651,6 +1735,21 @@ func sovGenerated(x uint64) (n int) { func sozGenerated(x uint64) (n int) { return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (this *CustomResourceColumnDefinition) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CustomResourceColumnDefinition{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Type:` + fmt.Sprintf("%v", this.Type) + `,`, + `Format:` + fmt.Sprintf("%v", this.Format) + `,`, + `Description:` + fmt.Sprintf("%v", this.Description) + `,`, + `Priority:` + fmt.Sprintf("%v", this.Priority) + `,`, + `JSONPath:` + fmt.Sprintf("%v", this.JSONPath) + `,`, + `}`, + }, "") + return s +} func (this *CustomResourceDefinition) String() string { if this == nil { return "nil" @@ -1715,6 +1814,7 @@ func (this *CustomResourceDefinitionSpec) String() string { `Validation:` + strings.Replace(fmt.Sprintf("%v", this.Validation), "CustomResourceValidation", "CustomResourceValidation", 1) + `,`, `Subresources:` + strings.Replace(fmt.Sprintf("%v", this.Subresources), "CustomResourceSubresources", "CustomResourceSubresources", 1) + `,`, `Versions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Versions), "CustomResourceDefinitionVersion", "CustomResourceDefinitionVersion", 1), `&`, ``, 1) + `,`, + `AdditionalPrinterColumns:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AdditionalPrinterColumns), "CustomResourceColumnDefinition", "CustomResourceColumnDefinition", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -1932,6 +2032,220 @@ func valueToStringGenerated(v interface{}) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("*%v", pv) } +func (m *CustomResourceColumnDefinition) 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: CustomResourceColumnDefinition: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CustomResourceColumnDefinition: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", 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 + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", 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 + } + m.Type = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Format", 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 + } + m.Format = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", 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 + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) + } + m.Priority = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Priority |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field JSONPath", 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 + } + m.JSONPath = string(dAtA[iNdEx:postIndex]) + 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 *CustomResourceDefinition) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -2846,6 +3160,37 @@ func (m *CustomResourceDefinitionSpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AdditionalPrinterColumns", 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.AdditionalPrinterColumns = append(m.AdditionalPrinterColumns, CustomResourceColumnDefinition{}) + if err := m.AdditionalPrinterColumns[len(m.AdditionalPrinterColumns)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -5529,143 +5874,150 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2200 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xcd, 0x6f, 0x1c, 0x49, - 0x15, 0x77, 0xcf, 0x78, 0xfc, 0x51, 0xb6, 0x63, 0xbb, 0x12, 0x87, 0x8e, 0x49, 0x66, 0xec, 0x59, - 0x76, 0x65, 0x60, 0x33, 0x43, 0xf6, 0x83, 0x5d, 0x56, 0xe2, 0xe0, 0xb1, 0x0d, 0xca, 0x62, 0xc7, - 0x56, 0x4d, 0x12, 0x04, 0xfb, 0x59, 0xee, 0xae, 0x19, 0x77, 0xdc, 0x5f, 0xe9, 0xaa, 0x9e, 0xd8, - 0x12, 0x20, 0x3e, 0xb4, 0x42, 0x42, 0xc0, 0x22, 0x88, 0x90, 0x90, 0xb8, 0x80, 0xc4, 0x05, 0x21, - 0x38, 0xc0, 0x91, 0x3f, 0x20, 0xc7, 0x95, 0xb8, 0xec, 0x69, 0x44, 0x86, 0x7f, 0x01, 0x09, 0xc9, - 0x27, 0x54, 0x1f, 0x5d, 0xdd, 0x3d, 0xe3, 0xd9, 0x44, 0xda, 0x99, 0xcd, 0xcd, 0xfd, 0xde, 0xab, - 0xf7, 0xfb, 0xd5, 0xab, 0x57, 0xaf, 0xde, 0x1b, 0x83, 0xd6, 0xf1, 0xeb, 0xb4, 0xe6, 0x04, 0xf5, - 0xe3, 0xf8, 0x90, 0x44, 0x3e, 0x61, 0x84, 0xd6, 0x3b, 0xc4, 0xb7, 0x83, 0xa8, 0xae, 0x14, 0x38, - 0x74, 0xc8, 0x09, 0x23, 0x3e, 0x75, 0x02, 0x9f, 0x5e, 0xc7, 0xa1, 0x43, 0x49, 0xd4, 0x21, 0x51, - 0x3d, 0x3c, 0x6e, 0x73, 0x1d, 0xcd, 0x1b, 0xd4, 0x3b, 0x37, 0x0e, 0x09, 0xc3, 0x37, 0xea, 0x6d, - 0xe2, 0x93, 0x08, 0x33, 0x62, 0xd7, 0xc2, 0x28, 0x60, 0x01, 0xfc, 0xba, 0x74, 0x57, 0xcb, 0x59, - 0xbf, 0xa7, 0xdd, 0xd5, 0xc2, 0xe3, 0x36, 0xd7, 0xd1, 0xbc, 0x41, 0x4d, 0xb9, 0x5b, 0xbd, 0xde, - 0x76, 0xd8, 0x51, 0x7c, 0x58, 0xb3, 0x02, 0xaf, 0xde, 0x0e, 0xda, 0x41, 0x5d, 0x78, 0x3d, 0x8c, - 0x5b, 0xe2, 0x4b, 0x7c, 0x88, 0xbf, 0x24, 0xda, 0xea, 0x2b, 0x29, 0x79, 0x0f, 0x5b, 0x47, 0x8e, - 0x4f, 0xa2, 0xd3, 0x94, 0xb1, 0x47, 0x18, 0xae, 0x77, 0x06, 0x38, 0xae, 0xd6, 0x87, 0xad, 0x8a, - 0x62, 0x9f, 0x39, 0x1e, 0x19, 0x58, 0xf0, 0xd5, 0x27, 0x2d, 0xa0, 0xd6, 0x11, 0xf1, 0xf0, 0xc0, - 0xba, 0x97, 0x87, 0xad, 0x8b, 0x99, 0xe3, 0xd6, 0x1d, 0x9f, 0x51, 0x16, 0xf5, 0x2f, 0xaa, 0xfe, - 0xa4, 0x08, 0xcc, 0xad, 0x98, 0xb2, 0xc0, 0x43, 0x84, 0x06, 0x71, 0x64, 0x91, 0x6d, 0xd2, 0x72, - 0x7c, 0x87, 0x39, 0x81, 0x0f, 0xdf, 0x07, 0x33, 0x7c, 0x57, 0x36, 0x66, 0xd8, 0x34, 0xd6, 0x8c, - 0x8d, 0xb9, 0x97, 0xbe, 0x52, 0x4b, 0x23, 0xae, 0x41, 0xd2, 0x30, 0x73, 0xeb, 0x5a, 0xe7, 0x46, - 0x6d, 0xff, 0xf0, 0x1e, 0xb1, 0xd8, 0x1e, 0x61, 0xb8, 0x01, 0x1f, 0x75, 0x2b, 0x13, 0xbd, 0x6e, - 0x05, 0xa4, 0x32, 0xa4, 0xbd, 0xc2, 0xef, 0x83, 0x49, 0x1a, 0x12, 0xcb, 0x2c, 0x08, 0xef, 0x6f, - 0xd5, 0x3e, 0xd5, 0x79, 0xd6, 0x86, 0x6d, 0xa4, 0x19, 0x12, 0xab, 0x31, 0xaf, 0x88, 0x4c, 0xf2, - 0x2f, 0x24, 0x60, 0xe1, 0x07, 0x06, 0x98, 0xa2, 0x0c, 0xb3, 0x98, 0x9a, 0x45, 0xc1, 0xe0, 0x9d, - 0x71, 0x31, 0x10, 0x20, 0x8d, 0x0b, 0x8a, 0xc3, 0x94, 0xfc, 0x46, 0x0a, 0xbc, 0xfa, 0xdf, 0x02, - 0x58, 0x1f, 0xb6, 0x74, 0x2b, 0xf0, 0x6d, 0x79, 0x1c, 0x37, 0xc1, 0x24, 0x3b, 0x0d, 0x89, 0x38, - 0x8a, 0xd9, 0xc6, 0xab, 0xc9, 0x7e, 0x6e, 0x9f, 0x86, 0xe4, 0xac, 0x5b, 0x79, 0xfe, 0x89, 0x0e, - 0xb8, 0x21, 0x12, 0x2e, 0xe0, 0xd7, 0xf4, 0xbe, 0x0b, 0xc2, 0xd9, 0x7a, 0x9e, 0xd8, 0x59, 0xb7, - 0xb2, 0xa8, 0x97, 0xe5, 0xb9, 0xc2, 0x0e, 0x80, 0x2e, 0xa6, 0xec, 0x76, 0x84, 0x7d, 0x2a, 0xdd, - 0x3a, 0x1e, 0x51, 0xe1, 0xfb, 0xd2, 0xd3, 0xa5, 0x07, 0x5f, 0xd1, 0x58, 0x55, 0x90, 0x70, 0x77, - 0xc0, 0x1b, 0x3a, 0x07, 0x01, 0xbe, 0x00, 0xa6, 0x22, 0x82, 0x69, 0xe0, 0x9b, 0x93, 0x82, 0xb2, - 0x8e, 0x25, 0x12, 0x52, 0xa4, 0xb4, 0xf0, 0x8b, 0x60, 0xda, 0x23, 0x94, 0xe2, 0x36, 0x31, 0x4b, - 0xc2, 0x70, 0x51, 0x19, 0x4e, 0xef, 0x49, 0x31, 0x4a, 0xf4, 0xd5, 0x33, 0x03, 0x5c, 0x1d, 0x16, - 0xb5, 0x5d, 0x87, 0x32, 0xf8, 0xf6, 0xc0, 0x05, 0xa8, 0x3d, 0xdd, 0x0e, 0xf9, 0x6a, 0x91, 0xfe, - 0x4b, 0x0a, 0x7c, 0x26, 0x91, 0x64, 0x92, 0xff, 0x7b, 0xa0, 0xe4, 0x30, 0xe2, 0xf1, 0x33, 0x28, - 0x6e, 0xcc, 0xbd, 0xf4, 0xed, 0x31, 0xe5, 0x5e, 0x63, 0x41, 0x71, 0x28, 0xdd, 0xe4, 0x68, 0x48, - 0x82, 0x56, 0xff, 0x54, 0x00, 0xd7, 0x86, 0x2d, 0xb9, 0x85, 0x3d, 0x42, 0x79, 0xc4, 0x43, 0x37, - 0x8e, 0xb0, 0xab, 0x32, 0x4e, 0x47, 0xfc, 0x40, 0x48, 0x91, 0xd2, 0xc2, 0x17, 0xc1, 0x0c, 0x75, - 0xfc, 0x76, 0xec, 0xe2, 0x48, 0xa5, 0x93, 0xde, 0x75, 0x53, 0xc9, 0x91, 0xb6, 0x80, 0x35, 0x00, - 0xe8, 0x51, 0x10, 0x31, 0x81, 0x61, 0x16, 0xd7, 0x8a, 0xdc, 0x33, 0x2f, 0x10, 0x4d, 0x2d, 0x45, - 0x19, 0x0b, 0xb8, 0x06, 0x26, 0x8f, 0x1d, 0xdf, 0x56, 0xa7, 0xae, 0x6f, 0xf1, 0xb7, 0x1c, 0xdf, - 0x46, 0x42, 0xc3, 0xf1, 0x5d, 0x87, 0x32, 0x2e, 0x51, 0x47, 0x9e, 0x8b, 0xba, 0xb0, 0xd4, 0x16, - 0x1c, 0xdf, 0xc2, 0x8c, 0xb4, 0x83, 0xc8, 0x21, 0xd4, 0x9c, 0x4a, 0xf1, 0xb7, 0xb4, 0x14, 0x65, - 0x2c, 0xaa, 0xff, 0x2a, 0x0d, 0x4f, 0x12, 0x5e, 0x4a, 0xe0, 0x73, 0xa0, 0xd4, 0x8e, 0x82, 0x38, - 0x54, 0x51, 0xd2, 0xd1, 0xfe, 0x26, 0x17, 0x22, 0xa9, 0xe3, 0x59, 0xd9, 0x21, 0x11, 0x3f, 0x30, - 0x15, 0x22, 0x9d, 0x95, 0x77, 0xa5, 0x18, 0x25, 0x7a, 0xf8, 0x23, 0x03, 0x94, 0x7c, 0x15, 0x1c, - 0x9e, 0x72, 0x6f, 0x8f, 0x29, 0x2f, 0x44, 0x78, 0x53, 0xba, 0x32, 0xf2, 0x12, 0x19, 0xbe, 0x02, - 0x4a, 0xd4, 0x0a, 0x42, 0xa2, 0xa2, 0x5e, 0x4e, 0x8c, 0x9a, 0x5c, 0x78, 0xd6, 0xad, 0x2c, 0x24, - 0xee, 0x84, 0x00, 0x49, 0x63, 0xf8, 0x53, 0x03, 0x80, 0x0e, 0x76, 0x1d, 0x1b, 0x73, 0xff, 0xe2, - 0x2c, 0x46, 0x9d, 0xd6, 0x77, 0xb5, 0x7b, 0x79, 0x68, 0xe9, 0x37, 0xca, 0x40, 0xc3, 0x0f, 0x0d, - 0x30, 0x4f, 0xe3, 0xc3, 0x48, 0xad, 0xe2, 0xe7, 0xcc, 0xb9, 0x7c, 0x67, 0xa4, 0x5c, 0x9a, 0x19, - 0x80, 0xc6, 0x52, 0xaf, 0x5b, 0x99, 0xcf, 0x4a, 0x50, 0x8e, 0x00, 0xfc, 0xb9, 0x01, 0x66, 0xd4, - 0x09, 0x53, 0x73, 0x5a, 0x5c, 0xf8, 0x77, 0xc7, 0x74, 0xb0, 0x2a, 0xa3, 0xd2, 0x5b, 0xa0, 0x04, - 0x14, 0x69, 0x06, 0xd5, 0x0f, 0x8b, 0xa0, 0xfc, 0xc9, 0x8f, 0x15, 0x7c, 0x68, 0x00, 0x60, 0x25, - 0x8f, 0x00, 0x35, 0x0d, 0xc1, 0xf9, 0xfd, 0x31, 0x71, 0xd6, 0xaf, 0x4d, 0xda, 0x30, 0x68, 0x11, - 0xbf, 0x8f, 0xfa, 0x6f, 0xf8, 0x3b, 0x03, 0x2c, 0x60, 0xcb, 0x22, 0x21, 0x23, 0xb6, 0xac, 0x21, - 0x85, 0xcf, 0xe0, 0x9a, 0xac, 0x28, 0x56, 0x0b, 0x9b, 0x59, 0x68, 0x94, 0x67, 0x02, 0xdf, 0x00, - 0x17, 0x28, 0x0b, 0x22, 0x62, 0x27, 0x11, 0x57, 0xf5, 0x0d, 0xf6, 0xba, 0x95, 0x0b, 0xcd, 0x9c, - 0x06, 0xf5, 0x59, 0x56, 0x7f, 0x6b, 0x80, 0xca, 0x13, 0x4e, 0x94, 0xd7, 0x42, 0x7e, 0x3f, 0x55, - 0xa5, 0xd1, 0xb5, 0x90, 0x83, 0x23, 0xa1, 0xe1, 0x35, 0x5b, 0x6c, 0xd7, 0x16, 0x51, 0x99, 0xc9, - 0x74, 0x1c, 0x42, 0x8a, 0x94, 0x96, 0xd7, 0x23, 0x8e, 0xcf, 0x5f, 0xc9, 0xa2, 0x30, 0xd4, 0xf5, - 0xa8, 0x29, 0xc5, 0x28, 0xd1, 0x57, 0xff, 0x67, 0xf4, 0xa7, 0x4a, 0x26, 0xcd, 0x9b, 0x16, 0x76, - 0x09, 0xdc, 0x06, 0x4b, 0xbc, 0x9f, 0x42, 0x24, 0x74, 0x1d, 0x0b, 0xd3, 0x03, 0xcc, 0x8e, 0x14, - 0x47, 0x53, 0xb9, 0x5d, 0x6a, 0xf6, 0xe9, 0xd1, 0xc0, 0x0a, 0xf8, 0x26, 0x80, 0xb2, 0xc7, 0xc8, - 0xf9, 0x91, 0xe5, 0x52, 0x77, 0x0b, 0xcd, 0x01, 0x0b, 0x74, 0xce, 0x2a, 0xb8, 0x05, 0x96, 0x5d, - 0x7c, 0x48, 0xdc, 0x26, 0x71, 0x89, 0xc5, 0x82, 0x48, 0xb8, 0x2a, 0x0a, 0x57, 0x2b, 0xbd, 0x6e, - 0x65, 0x79, 0xb7, 0x5f, 0x89, 0x06, 0xed, 0xab, 0xeb, 0xfd, 0x27, 0x92, 0xdd, 0xb8, 0xec, 0xdc, - 0xfe, 0x50, 0x00, 0xab, 0xc3, 0xab, 0x02, 0xfc, 0x71, 0xda, 0x60, 0xca, 0xfe, 0xe1, 0xdd, 0x71, - 0x55, 0x20, 0xd5, 0x61, 0x82, 0xc1, 0xee, 0x12, 0xfe, 0x80, 0x17, 0x73, 0xec, 0x12, 0x75, 0x51, - 0xde, 0x19, 0x1b, 0x05, 0x0e, 0xd2, 0x98, 0x95, 0xef, 0x04, 0x76, 0xc5, 0xb3, 0x80, 0x5d, 0x52, - 0xfd, 0xb3, 0xd1, 0x3f, 0x63, 0xa4, 0x55, 0x1b, 0xfe, 0xc2, 0x00, 0x8b, 0x41, 0x48, 0xfc, 0xcd, - 0x83, 0x9b, 0x77, 0x5f, 0x6e, 0x8a, 0xc9, 0x46, 0x85, 0xea, 0xd6, 0xa7, 0xe4, 0xf9, 0x66, 0x73, - 0xff, 0x96, 0x74, 0x78, 0x10, 0x05, 0x21, 0x6d, 0x5c, 0xec, 0x75, 0x2b, 0x8b, 0xfb, 0x79, 0x28, - 0xd4, 0x8f, 0x5d, 0xf5, 0xc0, 0xca, 0xce, 0x09, 0x23, 0x91, 0x8f, 0xdd, 0xed, 0xc0, 0x8a, 0x3d, - 0xe2, 0x33, 0x49, 0xf4, 0x55, 0x30, 0x67, 0x13, 0x6a, 0x45, 0x4e, 0x28, 0x1e, 0x37, 0x99, 0xde, - 0x17, 0x55, 0x5a, 0xce, 0x6d, 0xa7, 0x2a, 0x94, 0xb5, 0x83, 0xd7, 0x40, 0x31, 0x8e, 0x5c, 0x95, - 0xc5, 0x73, 0xca, 0xbc, 0x78, 0x07, 0xed, 0x22, 0x2e, 0xaf, 0xae, 0x83, 0x49, 0xce, 0x13, 0x5e, - 0x01, 0xc5, 0x08, 0x3f, 0x10, 0x5e, 0xe7, 0x1b, 0xd3, 0xdc, 0x04, 0xe1, 0x07, 0x88, 0xcb, 0xaa, - 0x7f, 0xb9, 0x0a, 0x16, 0xfb, 0xf6, 0x02, 0x57, 0x41, 0xc1, 0xb1, 0x15, 0x07, 0xa0, 0x9c, 0x16, - 0x6e, 0x6e, 0xa3, 0x82, 0x63, 0xc3, 0xd7, 0xc0, 0x94, 0x9c, 0x10, 0x15, 0x68, 0x45, 0x97, 0x00, - 0x21, 0xe5, 0xaf, 0x77, 0xea, 0x8e, 0x13, 0x51, 0xe6, 0x82, 0x03, 0x69, 0xa9, 0x5b, 0x22, 0x39, - 0x90, 0x16, 0xe2, 0xb2, 0xfe, 0xcd, 0x4f, 0x3e, 0xe5, 0xe6, 0xd7, 0xd4, 0xc4, 0x52, 0xca, 0xd7, - 0xab, 0xcc, 0x20, 0xf2, 0x02, 0x98, 0x6a, 0x05, 0x91, 0x87, 0x99, 0x78, 0xa1, 0x33, 0x3d, 0xe6, - 0x37, 0x84, 0x14, 0x29, 0x2d, 0x6f, 0xb2, 0x98, 0xc3, 0x5c, 0x62, 0x4e, 0xe7, 0x9b, 0xac, 0xdb, - 0x5c, 0x88, 0xa4, 0x0e, 0xde, 0x03, 0xd3, 0x36, 0x69, 0xe1, 0xd8, 0x65, 0xe6, 0x8c, 0x48, 0xa1, - 0xad, 0x11, 0xa4, 0x50, 0x63, 0x8e, 0x57, 0xc5, 0x6d, 0xe9, 0x17, 0x25, 0x00, 0xf0, 0x79, 0x30, - 0xed, 0xe1, 0x13, 0xc7, 0x8b, 0x3d, 0x73, 0x76, 0xcd, 0xd8, 0x30, 0xa4, 0xd9, 0x9e, 0x14, 0xa1, - 0x44, 0xc7, 0x2b, 0x23, 0x39, 0xb1, 0xdc, 0x98, 0x3a, 0x1d, 0xa2, 0x94, 0x26, 0x10, 0x05, 0x57, - 0x57, 0xc6, 0x9d, 0x3e, 0x3d, 0x1a, 0x58, 0x21, 0xc0, 0x1c, 0x5f, 0x2c, 0x9e, 0xcb, 0x80, 0x49, - 0x11, 0x4a, 0x74, 0x79, 0x30, 0x65, 0x3f, 0x3f, 0x0c, 0x4c, 0x2d, 0x1e, 0x58, 0x01, 0xbf, 0x0c, - 0x66, 0x3d, 0x7c, 0xb2, 0x4b, 0xfc, 0x36, 0x3b, 0x32, 0x17, 0xd6, 0x8c, 0x8d, 0x62, 0x63, 0xa1, - 0xd7, 0xad, 0xcc, 0xee, 0x25, 0x42, 0x94, 0xea, 0x85, 0xb1, 0xe3, 0x2b, 0xe3, 0x0b, 0x19, 0xe3, - 0x44, 0x88, 0x52, 0x3d, 0x7f, 0x74, 0x42, 0xcc, 0xf8, 0xe5, 0x32, 0x17, 0xf3, 0x4d, 0xf0, 0x81, - 0x14, 0xa3, 0x44, 0x0f, 0x37, 0xc0, 0x8c, 0x87, 0x4f, 0xc4, 0xc0, 0x62, 0x2e, 0x09, 0xb7, 0xf3, - 0xbc, 0x93, 0xd9, 0x53, 0x32, 0xa4, 0xb5, 0xc2, 0xd2, 0xf1, 0xa5, 0xe5, 0x72, 0xc6, 0x52, 0xc9, - 0x90, 0xd6, 0xf2, 0x24, 0x8e, 0x7d, 0xe7, 0x7e, 0x4c, 0xa4, 0x31, 0x14, 0x91, 0xd1, 0x49, 0x7c, - 0x27, 0x55, 0xa1, 0xac, 0x1d, 0x1f, 0x18, 0xbc, 0xd8, 0x65, 0x4e, 0xe8, 0x92, 0xfd, 0x96, 0x79, - 0x51, 0xc4, 0x5f, 0xf4, 0x9e, 0x7b, 0x5a, 0x8a, 0x32, 0x16, 0x90, 0x80, 0x49, 0xe2, 0xc7, 0x9e, - 0x79, 0x49, 0x34, 0x4c, 0x23, 0x49, 0x41, 0x7d, 0x73, 0x76, 0xfc, 0xd8, 0x43, 0xc2, 0x3d, 0x7c, - 0x0d, 0x2c, 0x78, 0xf8, 0x84, 0x97, 0x03, 0x12, 0x31, 0x3e, 0xca, 0xac, 0x88, 0xcd, 0x2f, 0xf3, - 0x26, 0x65, 0x2f, 0xab, 0x40, 0x79, 0x3b, 0xb1, 0xd0, 0xf1, 0x33, 0x0b, 0x2f, 0x67, 0x16, 0x66, - 0x15, 0x28, 0x6f, 0xc7, 0x23, 0x1d, 0x91, 0xfb, 0xb1, 0x13, 0x11, 0xdb, 0xfc, 0x9c, 0xe8, 0x6b, - 0x44, 0xa4, 0x91, 0x92, 0x21, 0xad, 0x85, 0x9d, 0x64, 0xb2, 0x35, 0xc5, 0x35, 0xbc, 0x33, 0xda, - 0x4a, 0xbe, 0x1f, 0x6d, 0x46, 0x11, 0x3e, 0x95, 0x2f, 0x4d, 0x76, 0xa6, 0x85, 0x14, 0x94, 0xb0, - 0xeb, 0xee, 0xb7, 0xcc, 0x2b, 0x22, 0xf6, 0xa3, 0x7e, 0x41, 0x74, 0xd5, 0xd9, 0xe4, 0x20, 0x48, - 0x62, 0x71, 0xd0, 0xc0, 0xe7, 0xa9, 0xb1, 0x3a, 0x5e, 0xd0, 0x7d, 0x0e, 0x82, 0x24, 0x96, 0xd8, - 0xa9, 0x7f, 0xba, 0xdf, 0x32, 0x3f, 0x3f, 0xe6, 0x9d, 0x72, 0x10, 0x24, 0xb1, 0xa0, 0x03, 0x8a, - 0x7e, 0xc0, 0xcc, 0xab, 0x63, 0x79, 0x9e, 0xc5, 0x83, 0x73, 0x2b, 0x60, 0x88, 0x63, 0xc0, 0x5f, - 0x1b, 0x00, 0x84, 0x69, 0x8a, 0x5e, 0x1b, 0xc9, 0xc0, 0xd4, 0x07, 0x59, 0x4b, 0x73, 0x7b, 0xc7, - 0x67, 0xd1, 0x69, 0x3a, 0x7a, 0x64, 0xee, 0x40, 0x86, 0x05, 0xfc, 0xa3, 0x01, 0x2e, 0x61, 0x5b, - 0x0e, 0x22, 0xd8, 0xcd, 0xdc, 0xa0, 0xb2, 0x88, 0xc8, 0xed, 0x51, 0xa7, 0x79, 0x23, 0x08, 0xdc, - 0x86, 0xd9, 0xeb, 0x56, 0x2e, 0x6d, 0x9e, 0x83, 0x8a, 0xce, 0xe5, 0x02, 0xff, 0x6a, 0x80, 0x65, - 0x55, 0x45, 0x33, 0x0c, 0x2b, 0x22, 0x80, 0x64, 0xd4, 0x01, 0xec, 0xc7, 0x91, 0x71, 0xbc, 0xa2, - 0xe2, 0xb8, 0x3c, 0xa0, 0x47, 0x83, 0xd4, 0xe0, 0x3f, 0x0c, 0x30, 0x6f, 0x93, 0x90, 0xf8, 0x36, - 0xf1, 0x2d, 0xce, 0x75, 0x6d, 0x24, 0x93, 0x66, 0x3f, 0xd7, 0xed, 0x0c, 0x84, 0xa4, 0x59, 0x53, - 0x34, 0xe7, 0xb3, 0xaa, 0xb3, 0x6e, 0xe5, 0x72, 0xba, 0x34, 0xab, 0x41, 0x39, 0x96, 0xf0, 0x37, - 0x06, 0x58, 0x4c, 0x0f, 0x40, 0x3e, 0x29, 0xeb, 0x63, 0xcc, 0x03, 0xd1, 0xbe, 0x6e, 0xe6, 0x01, - 0x51, 0x3f, 0x03, 0xf8, 0x37, 0x83, 0x77, 0x6a, 0xc9, 0xdc, 0x48, 0xcd, 0xaa, 0x88, 0xe5, 0x7b, - 0x23, 0x8f, 0xa5, 0x46, 0x90, 0xa1, 0x7c, 0x31, 0x6d, 0x05, 0xb5, 0xe6, 0xac, 0x5b, 0x59, 0xc9, - 0x46, 0x52, 0x2b, 0x50, 0x96, 0x21, 0xfc, 0x99, 0x01, 0xe6, 0x49, 0xda, 0x71, 0x53, 0xf3, 0xb9, - 0x91, 0x04, 0xf1, 0xdc, 0x26, 0x5e, 0xfe, 0x4a, 0x93, 0x51, 0x51, 0x94, 0xc3, 0xe6, 0x1d, 0x24, - 0x39, 0xc1, 0x5e, 0xe8, 0x12, 0xf3, 0x0b, 0x23, 0xee, 0x20, 0x77, 0xa4, 0x5f, 0x94, 0x00, 0xac, - 0xf2, 0xc9, 0xa7, 0xef, 0xe6, 0xc0, 0x25, 0x50, 0x3c, 0x26, 0xa7, 0xb2, 0xb1, 0x47, 0xfc, 0x4f, - 0x68, 0x83, 0x52, 0x07, 0xbb, 0x71, 0x32, 0xbc, 0x8d, 0xb8, 0xea, 0x22, 0xe9, 0xfc, 0x8d, 0xc2, - 0xeb, 0xc6, 0xea, 0x43, 0x03, 0x5c, 0x3e, 0xff, 0x42, 0x3f, 0x53, 0x5a, 0xbf, 0x37, 0xc0, 0xf2, - 0xc0, 0xdd, 0x3d, 0x87, 0xd1, 0xfd, 0x3c, 0xa3, 0xb7, 0x46, 0x7d, 0x09, 0x9b, 0x2c, 0x72, 0xfc, - 0xb6, 0xe8, 0x3c, 0xb2, 0xf4, 0x7e, 0x69, 0x80, 0xa5, 0xfe, 0xeb, 0xf0, 0x2c, 0xe3, 0x55, 0x7d, - 0x58, 0x00, 0x97, 0xcf, 0x6f, 0x98, 0x60, 0xa4, 0x27, 0xc3, 0xf1, 0x4c, 0xd8, 0x20, 0x9d, 0x32, - 0xf5, 0x50, 0xf9, 0x81, 0x01, 0xe6, 0xee, 0x69, 0xbb, 0xe4, 0x7f, 0x1d, 0x23, 0x9f, 0xed, 0x93, - 0xfa, 0x93, 0x2a, 0x28, 0xca, 0xe2, 0x56, 0xff, 0x6e, 0x80, 0x95, 0x73, 0x0b, 0x2b, 0x1f, 0x41, - 0xb1, 0xeb, 0x06, 0x0f, 0xe4, 0x4f, 0x34, 0x99, 0x9f, 0xcc, 0x36, 0x85, 0x14, 0x29, 0x6d, 0x26, - 0x7a, 0x85, 0xcf, 0x2a, 0x7a, 0xd5, 0x7f, 0x1a, 0xe0, 0xea, 0x27, 0x65, 0xe2, 0x33, 0x39, 0xd2, - 0x0d, 0x30, 0xa3, 0x9a, 0xa2, 0x53, 0x71, 0x9c, 0x6a, 0x0e, 0x50, 0x45, 0xe3, 0x14, 0x69, 0x6d, - 0xe3, 0xfa, 0xa3, 0xc7, 0xe5, 0x89, 0x8f, 0x1e, 0x97, 0x27, 0x3e, 0x7e, 0x5c, 0x9e, 0xf8, 0x61, - 0xaf, 0x6c, 0x3c, 0xea, 0x95, 0x8d, 0x8f, 0x7a, 0x65, 0xe3, 0xe3, 0x5e, 0xd9, 0xf8, 0x77, 0xaf, - 0x6c, 0xfc, 0xea, 0x3f, 0xe5, 0x89, 0xef, 0x4e, 0x2b, 0xf0, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, - 0x8c, 0x3a, 0x89, 0x32, 0x37, 0x20, 0x00, 0x00, + // 2306 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x6f, 0x5b, 0x49, + 0x15, 0xef, 0xb5, 0xe3, 0xc4, 0x19, 0x27, 0x4d, 0x32, 0x6d, 0xca, 0x6d, 0x68, 0xed, 0xd4, 0x65, + 0x57, 0x01, 0xb6, 0x36, 0xed, 0xee, 0xb2, 0xcb, 0x4a, 0x3c, 0xc4, 0x49, 0x41, 0x5d, 0x9a, 0x26, + 0x1a, 0xb7, 0x45, 0xb0, 0x9f, 0x13, 0x7b, 0xe2, 0xdc, 0xe6, 0x7e, 0x75, 0x66, 0xae, 0x9b, 0x48, + 0x80, 0xf8, 0xd0, 0x0a, 0x09, 0x01, 0x0b, 0x6c, 0x85, 0x84, 0xc4, 0x0b, 0x48, 0xbc, 0x20, 0x04, + 0x0f, 0xf0, 0x06, 0x7f, 0x40, 0x1f, 0xf7, 0x71, 0x9f, 0x2c, 0x6a, 0xfe, 0x05, 0x24, 0xa4, 0x3c, + 0xa1, 0xf9, 0xb8, 0x73, 0xef, 0xb5, 0xe3, 0x6d, 0xb5, 0x6b, 0x6f, 0xdf, 0x7c, 0xcf, 0x39, 0x73, + 0x7e, 0xbf, 0x39, 0x73, 0xe6, 0xcc, 0x39, 0x09, 0xd8, 0x3b, 0x78, 0x95, 0xd5, 0x9c, 0xa0, 0x7e, + 0x10, 0xed, 0x12, 0xea, 0x13, 0x4e, 0x58, 0xbd, 0x4b, 0xfc, 0x76, 0x40, 0xeb, 0x5a, 0x81, 0x43, + 0x87, 0x1c, 0x72, 0xe2, 0x33, 0x27, 0xf0, 0xd9, 0x15, 0x1c, 0x3a, 0x8c, 0xd0, 0x2e, 0xa1, 0xf5, + 0xf0, 0xa0, 0x23, 0x74, 0x2c, 0x6b, 0x50, 0xef, 0x5e, 0xdd, 0x25, 0x1c, 0x5f, 0xad, 0x77, 0x88, + 0x4f, 0x28, 0xe6, 0xa4, 0x5d, 0x0b, 0x69, 0xc0, 0x03, 0xf8, 0x75, 0xe5, 0xae, 0x96, 0xb1, 0x7e, + 0xc7, 0xb8, 0xab, 0x85, 0x07, 0x1d, 0xa1, 0x63, 0x59, 0x83, 0x9a, 0x76, 0xb7, 0x72, 0xa5, 0xe3, + 0xf0, 0xfd, 0x68, 0xb7, 0xd6, 0x0a, 0xbc, 0x7a, 0x27, 0xe8, 0x04, 0x75, 0xe9, 0x75, 0x37, 0xda, + 0x93, 0x5f, 0xf2, 0x43, 0xfe, 0x52, 0x68, 0x2b, 0x2f, 0x25, 0xe4, 0x3d, 0xdc, 0xda, 0x77, 0x7c, + 0x42, 0x8f, 0x12, 0xc6, 0x1e, 0xe1, 0xb8, 0xde, 0x1d, 0xe2, 0xb8, 0x52, 0x1f, 0xb5, 0x8a, 0x46, + 0x3e, 0x77, 0x3c, 0x32, 0xb4, 0xe0, 0xab, 0x4f, 0x5a, 0xc0, 0x5a, 0xfb, 0xc4, 0xc3, 0x43, 0xeb, + 0x5e, 0x1c, 0xb5, 0x2e, 0xe2, 0x8e, 0x5b, 0x77, 0x7c, 0xce, 0x38, 0x1d, 0x5c, 0x54, 0xfd, 0x20, + 0x07, 0xca, 0x1b, 0x11, 0xe3, 0x81, 0x87, 0x08, 0x0b, 0x22, 0xda, 0x22, 0x1b, 0x81, 0x1b, 0x79, + 0xfe, 0x26, 0xd9, 0x73, 0x7c, 0x87, 0x3b, 0x81, 0x0f, 0x57, 0xc1, 0x94, 0x8f, 0x3d, 0x62, 0x5b, + 0xab, 0xd6, 0xda, 0x6c, 0x63, 0xee, 0x51, 0xaf, 0x72, 0xaa, 0xdf, 0xab, 0x4c, 0xdd, 0xc2, 0x1e, + 0x41, 0x52, 0x23, 0x2c, 0xf8, 0x51, 0x48, 0xec, 0x5c, 0xd6, 0xe2, 0xf6, 0x51, 0x48, 0x90, 0xd4, + 0xc0, 0xe7, 0xc1, 0xf4, 0x5e, 0x40, 0x3d, 0xcc, 0xed, 0xbc, 0xb4, 0x39, 0xad, 0x6d, 0xa6, 0xbf, + 0x21, 0xa5, 0x48, 0x6b, 0xe1, 0xcb, 0xa0, 0xd4, 0x26, 0xac, 0x45, 0x9d, 0x50, 0x40, 0xdb, 0x53, + 0xd2, 0xf8, 0x8c, 0x36, 0x2e, 0x6d, 0x26, 0x2a, 0x94, 0xb6, 0x83, 0x2f, 0x80, 0x62, 0x48, 0x9d, + 0x80, 0x3a, 0xfc, 0xc8, 0x2e, 0xac, 0x5a, 0x6b, 0x85, 0xc6, 0xa2, 0x5e, 0x53, 0xdc, 0xd1, 0x72, + 0x64, 0x2c, 0xe0, 0x2a, 0x28, 0xbe, 0xde, 0xdc, 0xbe, 0xb5, 0x83, 0xf9, 0xbe, 0x3d, 0x2d, 0x11, + 0xa6, 0x84, 0x35, 0x2a, 0xde, 0xd3, 0xd2, 0xea, 0x4f, 0xf2, 0xc0, 0xce, 0x46, 0x25, 0x15, 0x8f, + 0x77, 0x41, 0x51, 0x9c, 0x75, 0x1b, 0x73, 0x2c, 0x63, 0x52, 0xba, 0xf6, 0x95, 0x5a, 0x92, 0x87, + 0x26, 0xf4, 0x49, 0xf2, 0x09, 0xeb, 0x5a, 0xf7, 0x6a, 0x6d, 0x7b, 0xf7, 0x1e, 0x69, 0xf1, 0x2d, + 0xc2, 0x71, 0x03, 0x6a, 0x7a, 0x20, 0x91, 0x21, 0xe3, 0x15, 0x7e, 0x1f, 0x4c, 0xb1, 0x90, 0xb4, + 0x64, 0x3c, 0x4b, 0xd7, 0xde, 0xa8, 0x7d, 0xaa, 0x2c, 0xaf, 0x8d, 0xda, 0x48, 0x33, 0x24, 0xad, + 0xe4, 0xb0, 0xc4, 0x17, 0x92, 0xb0, 0xf0, 0x3d, 0x0b, 0x4c, 0x33, 0x8e, 0x79, 0xc4, 0xe4, 0x69, + 0x95, 0xae, 0xbd, 0x35, 0x29, 0x06, 0x12, 0x24, 0x49, 0x06, 0xf5, 0x8d, 0x34, 0x78, 0xf5, 0xbf, + 0x39, 0x70, 0x69, 0xd4, 0xd2, 0x8d, 0xc0, 0x6f, 0xab, 0xe3, 0xb8, 0xa1, 0x93, 0x4f, 0xa5, 0xe7, + 0xcb, 0xe9, 0xe4, 0x3b, 0xee, 0x55, 0x9e, 0x7b, 0xa2, 0x83, 0x54, 0x96, 0x7e, 0xcd, 0xec, 0x5b, + 0x65, 0xf2, 0xa5, 0x2c, 0xb1, 0xe3, 0x5e, 0x65, 0xc1, 0x2c, 0xcb, 0x72, 0x85, 0x5d, 0x00, 0x5d, + 0xcc, 0xf8, 0x6d, 0x8a, 0x7d, 0xa6, 0xdc, 0x3a, 0x1e, 0xd1, 0xe1, 0xfb, 0xd2, 0xd3, 0xa5, 0x87, + 0x58, 0xd1, 0x58, 0xd1, 0x90, 0xf0, 0xe6, 0x90, 0x37, 0x74, 0x02, 0x82, 0xb8, 0x58, 0x94, 0x60, + 0x66, 0xee, 0x8a, 0x89, 0x25, 0x92, 0x52, 0xa4, 0xb5, 0xf0, 0x8b, 0x60, 0xc6, 0x23, 0x8c, 0xe1, + 0x0e, 0x91, 0x17, 0x64, 0xb6, 0xb1, 0xa0, 0x0d, 0x67, 0xb6, 0x94, 0x18, 0xc5, 0xfa, 0xea, 0xb1, + 0x05, 0x2e, 0x8c, 0x8a, 0xda, 0x4d, 0x87, 0x71, 0xf8, 0xe6, 0xd0, 0x05, 0xa8, 0x3d, 0xdd, 0x0e, + 0xc5, 0x6a, 0x99, 0xfe, 0xe6, 0x76, 0xc6, 0x92, 0x54, 0xf2, 0x7f, 0x0f, 0x14, 0x1c, 0x4e, 0x3c, + 0x71, 0x06, 0xf9, 0xb5, 0xd2, 0xb5, 0x6f, 0x4f, 0x28, 0xf7, 0x1a, 0xf3, 0x9a, 0x43, 0xe1, 0x86, + 0x40, 0x43, 0x0a, 0xb4, 0xfa, 0xa7, 0x1c, 0xb8, 0x38, 0x6a, 0x89, 0xa8, 0x78, 0x4c, 0x44, 0x3c, + 0x74, 0x23, 0x8a, 0x5d, 0x9d, 0x71, 0x26, 0xe2, 0x3b, 0x52, 0x8a, 0xb4, 0x56, 0xd4, 0x24, 0xe6, + 0xf8, 0x9d, 0xc8, 0xc5, 0x54, 0xa7, 0x93, 0xd9, 0x75, 0x53, 0xcb, 0x91, 0xb1, 0x80, 0x35, 0x00, + 0xd8, 0x7e, 0x40, 0xb9, 0xc4, 0xb0, 0xf3, 0xab, 0x79, 0xe1, 0x59, 0x14, 0x88, 0xa6, 0x91, 0xa2, + 0x94, 0x85, 0x28, 0xb9, 0x07, 0x8e, 0xdf, 0xd6, 0xa7, 0x6e, 0x6e, 0xf1, 0xb7, 0x1c, 0xbf, 0x8d, + 0xa4, 0x46, 0xe0, 0xbb, 0x0e, 0xe3, 0x42, 0xa2, 0x8f, 0x3c, 0x13, 0x75, 0x69, 0x69, 0x2c, 0x04, + 0x7e, 0x0b, 0x73, 0xd2, 0x09, 0xa8, 0x43, 0x98, 0x3d, 0x9d, 0xe0, 0x6f, 0x18, 0x29, 0x4a, 0x59, + 0x54, 0x7f, 0x3d, 0x33, 0x3a, 0x49, 0x44, 0x29, 0x81, 0x97, 0x41, 0xa1, 0x43, 0x83, 0x28, 0xd4, + 0x51, 0x32, 0xd1, 0xfe, 0xa6, 0x10, 0x22, 0xa5, 0x13, 0x59, 0xd9, 0x25, 0x54, 0x1c, 0x98, 0x0e, + 0x91, 0xc9, 0xca, 0xbb, 0x4a, 0x8c, 0x62, 0x3d, 0xfc, 0x91, 0x05, 0x0a, 0xbe, 0x0e, 0x8e, 0x48, + 0xb9, 0x37, 0x27, 0x94, 0x17, 0x32, 0xbc, 0x09, 0x5d, 0x15, 0x79, 0x85, 0x0c, 0x5f, 0x02, 0x05, + 0xd6, 0x0a, 0x42, 0xa2, 0xa3, 0x5e, 0x8e, 0x8d, 0x9a, 0x42, 0x78, 0xdc, 0xab, 0xcc, 0xc7, 0xee, + 0xa4, 0x00, 0x29, 0x63, 0xf8, 0x53, 0x0b, 0x80, 0x2e, 0x76, 0x9d, 0x36, 0x96, 0x6f, 0x5a, 0x41, + 0xd2, 0x1f, 0x6f, 0x5a, 0xdf, 0x35, 0xee, 0xd5, 0xa1, 0x25, 0xdf, 0x28, 0x05, 0x0d, 0xdf, 0xb7, + 0xc0, 0x1c, 0x8b, 0x76, 0xa9, 0x5e, 0xc5, 0xe4, 0xeb, 0x57, 0xba, 0xf6, 0x9d, 0xb1, 0x72, 0x69, + 0xa6, 0x00, 0x1a, 0x8b, 0xfd, 0x5e, 0x65, 0x2e, 0x2d, 0x41, 0x19, 0x02, 0xf0, 0xe7, 0x16, 0x28, + 0xea, 0x13, 0x66, 0xf6, 0x8c, 0xbc, 0xf0, 0x6f, 0x4f, 0xe8, 0x60, 0x75, 0x46, 0x25, 0xb7, 0x40, + 0x0b, 0x18, 0x32, 0x0c, 0xe0, 0x3f, 0x2d, 0x60, 0xe3, 0xb6, 0x2a, 0xf0, 0xd8, 0xdd, 0xa1, 0x8e, + 0xcf, 0x09, 0x55, 0x0d, 0x11, 0xb3, 0x8b, 0x92, 0xde, 0x78, 0xdf, 0xc2, 0xc1, 0x66, 0xab, 0xb1, + 0xaa, 0xd9, 0xd9, 0xeb, 0x23, 0x68, 0xa0, 0x91, 0x04, 0xab, 0xef, 0xe7, 0x07, 0x7b, 0xb9, 0xc1, + 0xa7, 0x16, 0x3e, 0xb4, 0x00, 0x68, 0xc5, 0x4f, 0x18, 0xb3, 0x2d, 0xb9, 0xa5, 0x77, 0x27, 0x14, + 0x71, 0xf3, 0x56, 0x26, 0xed, 0x8e, 0x11, 0x89, 0x6a, 0x62, 0x7e, 0xc3, 0xdf, 0x59, 0x60, 0x1e, + 0xb7, 0x5a, 0x24, 0xe4, 0xa4, 0xad, 0x2a, 0x60, 0xee, 0x33, 0xb8, 0xe4, 0xcb, 0x9a, 0xd5, 0xfc, + 0x7a, 0x1a, 0x1a, 0x65, 0x99, 0xc0, 0xd7, 0xc0, 0x69, 0xc6, 0x03, 0x4a, 0xda, 0x71, 0xbe, 0xe8, + 0xea, 0x0c, 0xfb, 0xbd, 0xca, 0xe9, 0x66, 0x46, 0x83, 0x06, 0x2c, 0xab, 0xbf, 0xb5, 0x40, 0xe5, + 0x09, 0xf9, 0xf8, 0x14, 0xed, 0xf5, 0xf3, 0x60, 0x5a, 0x6e, 0xb7, 0x2d, 0xa3, 0x52, 0x4c, 0xf5, + 0x4b, 0x52, 0x8a, 0xb4, 0x56, 0x54, 0x53, 0x81, 0x2f, 0xde, 0xf8, 0xbc, 0x34, 0x34, 0xd5, 0xb4, + 0xa9, 0xc4, 0x28, 0xd6, 0x57, 0xff, 0x67, 0x0d, 0xa6, 0x4a, 0xea, 0x92, 0x36, 0x5b, 0xd8, 0x25, + 0x70, 0x13, 0x2c, 0x8a, 0x6e, 0x10, 0x91, 0xd0, 0x75, 0x5a, 0x98, 0xc9, 0x6e, 0x59, 0x71, 0xb4, + 0xb5, 0xdb, 0xc5, 0xe6, 0x80, 0x1e, 0x0d, 0xad, 0x80, 0xaf, 0x03, 0xa8, 0x3a, 0xa4, 0x8c, 0x1f, + 0x55, 0xec, 0x4d, 0xaf, 0xd3, 0x1c, 0xb2, 0x40, 0x27, 0xac, 0x82, 0x1b, 0x60, 0xc9, 0xc5, 0xbb, + 0xc4, 0x6d, 0x12, 0x97, 0xb4, 0x78, 0x40, 0xa5, 0x2b, 0x35, 0x4f, 0x2c, 0xf7, 0x7b, 0x95, 0xa5, + 0x9b, 0x83, 0x4a, 0x34, 0x6c, 0x5f, 0xbd, 0x34, 0x78, 0x22, 0xe9, 0x8d, 0xab, 0xbe, 0xf3, 0x0f, + 0x39, 0xb0, 0x32, 0xba, 0xa6, 0xc1, 0x1f, 0x27, 0xed, 0xb1, 0xea, 0x7e, 0xde, 0x9e, 0x54, 0xfd, + 0xd4, 0xfd, 0x31, 0x18, 0xee, 0x8d, 0xe1, 0x0f, 0xc4, 0x53, 0x84, 0x5d, 0xa2, 0x2f, 0xca, 0x5b, + 0x13, 0xa3, 0x20, 0x40, 0x1a, 0xb3, 0xea, 0x95, 0xc3, 0xae, 0x7c, 0xd4, 0xb0, 0x4b, 0xaa, 0x7f, + 0xb6, 0x06, 0x27, 0xa4, 0xe4, 0xcd, 0x81, 0xbf, 0xb0, 0xc0, 0x42, 0x10, 0x12, 0x7f, 0x7d, 0xe7, + 0xc6, 0xdd, 0x17, 0x9b, 0x72, 0x5a, 0xd5, 0xa1, 0xba, 0xf5, 0x29, 0x79, 0x8a, 0xb9, 0x4d, 0x39, + 0xdc, 0xa1, 0x41, 0xc8, 0x1a, 0x67, 0xfa, 0xbd, 0xca, 0xc2, 0x76, 0x16, 0x0a, 0x0d, 0x62, 0x57, + 0x3d, 0xb0, 0x7c, 0xfd, 0x90, 0x13, 0xea, 0x63, 0x77, 0x33, 0x68, 0x45, 0x1e, 0xf1, 0xb9, 0x22, + 0x3a, 0x30, 0x6e, 0x5a, 0x4f, 0x39, 0x6e, 0x5e, 0x04, 0xf9, 0x88, 0xba, 0x3a, 0x8b, 0x4b, 0xda, + 0x3c, 0x7f, 0x07, 0xdd, 0x44, 0x42, 0x5e, 0xbd, 0x04, 0xa6, 0x04, 0x4f, 0x78, 0x1e, 0xe4, 0x29, + 0x7e, 0x20, 0xbd, 0xce, 0x35, 0x66, 0x84, 0x09, 0xc2, 0x0f, 0x90, 0x90, 0x55, 0xff, 0x72, 0x01, + 0x2c, 0x0c, 0xec, 0x05, 0xae, 0x80, 0x9c, 0xd3, 0xd6, 0x1c, 0x80, 0x76, 0x9a, 0xbb, 0xb1, 0x89, + 0x72, 0x4e, 0x1b, 0xbe, 0x02, 0xa6, 0xd5, 0xd4, 0xaf, 0x41, 0x2b, 0xa6, 0x04, 0x48, 0xa9, 0xe8, + 0x3d, 0x12, 0x77, 0x82, 0x88, 0x36, 0x97, 0x1c, 0xc8, 0x9e, 0xbe, 0x25, 0x8a, 0x03, 0xd9, 0x43, + 0x42, 0xf6, 0x49, 0x67, 0xed, 0x78, 0xd8, 0x2f, 0x3c, 0xc5, 0xb0, 0x3f, 0xfd, 0xb1, 0xc3, 0xfe, + 0x65, 0x50, 0xe0, 0x0e, 0x77, 0x89, 0x3d, 0x93, 0x6d, 0x11, 0x6f, 0x0b, 0x21, 0x52, 0x3a, 0x78, + 0x0f, 0xcc, 0xb4, 0xc9, 0x1e, 0x8e, 0x5c, 0x6e, 0x17, 0x65, 0x0a, 0x6d, 0x8c, 0x21, 0x85, 0x1a, + 0x25, 0x51, 0x15, 0x37, 0x95, 0x5f, 0x14, 0x03, 0xc0, 0xe7, 0xc0, 0x8c, 0x87, 0x0f, 0x1d, 0x2f, + 0xf2, 0xec, 0xd9, 0x55, 0x6b, 0xcd, 0x52, 0x66, 0x5b, 0x4a, 0x84, 0x62, 0x9d, 0xa8, 0x8c, 0xe4, + 0xb0, 0xe5, 0x46, 0xcc, 0xe9, 0x12, 0xad, 0xb4, 0x81, 0x2c, 0xb8, 0xa6, 0x32, 0x5e, 0x1f, 0xd0, + 0xa3, 0xa1, 0x15, 0x12, 0xcc, 0xf1, 0xe5, 0xe2, 0x52, 0x0a, 0x4c, 0x89, 0x50, 0xac, 0xcb, 0x82, + 0x69, 0xfb, 0xb9, 0x51, 0x60, 0x7a, 0xf1, 0xd0, 0x0a, 0xf8, 0x65, 0x30, 0xeb, 0xe1, 0xc3, 0x9b, + 0xc4, 0xef, 0xf0, 0x7d, 0x7b, 0x7e, 0xd5, 0x5a, 0xcb, 0x37, 0xe6, 0xfb, 0xbd, 0xca, 0xec, 0x56, + 0x2c, 0x44, 0x89, 0x5e, 0x1a, 0x3b, 0xbe, 0x36, 0x3e, 0x9d, 0x32, 0x8e, 0x85, 0x28, 0xd1, 0x8b, + 0x47, 0x27, 0xc4, 0x5c, 0x5c, 0x2e, 0x7b, 0x21, 0xdb, 0xc2, 0xef, 0x28, 0x31, 0x8a, 0xf5, 0x70, + 0x0d, 0x14, 0x3d, 0x7c, 0x28, 0xc7, 0x2d, 0x7b, 0x51, 0xba, 0x9d, 0x13, 0x7d, 0xd8, 0x96, 0x96, + 0x21, 0xa3, 0x95, 0x96, 0x8e, 0xaf, 0x2c, 0x97, 0x52, 0x96, 0x5a, 0x86, 0x8c, 0x56, 0x24, 0x71, + 0xe4, 0x3b, 0xf7, 0x23, 0xa2, 0x8c, 0xa1, 0x8c, 0x8c, 0x49, 0xe2, 0x3b, 0x89, 0x0a, 0xa5, 0xed, + 0xc4, 0xb8, 0xe3, 0x45, 0x2e, 0x77, 0x42, 0x97, 0x6c, 0xef, 0xd9, 0x67, 0x64, 0xfc, 0x65, 0xe7, + 0xbc, 0x65, 0xa4, 0x28, 0x65, 0x01, 0x09, 0x98, 0x22, 0x7e, 0xe4, 0xd9, 0x67, 0x65, 0xc3, 0x34, + 0x96, 0x14, 0x34, 0x37, 0xe7, 0xba, 0x1f, 0x79, 0x48, 0xba, 0x87, 0xaf, 0x80, 0x79, 0x0f, 0x1f, + 0x8a, 0x72, 0x40, 0x28, 0x17, 0x83, 0xd8, 0xb2, 0xdc, 0xfc, 0x92, 0x68, 0x52, 0xb6, 0xd2, 0x0a, + 0x94, 0xb5, 0x93, 0x0b, 0x1d, 0x3f, 0xb5, 0xf0, 0x5c, 0x6a, 0x61, 0x5a, 0x81, 0xb2, 0x76, 0x22, + 0xd2, 0x94, 0xdc, 0x8f, 0x1c, 0x4a, 0xda, 0xf6, 0xe7, 0x64, 0x5f, 0x23, 0x23, 0x8d, 0xb4, 0x0c, + 0x19, 0x2d, 0xec, 0xc6, 0x73, 0xb9, 0x2d, 0xaf, 0xe1, 0x9d, 0xf1, 0x56, 0xf2, 0x6d, 0xba, 0x4e, + 0x29, 0x3e, 0x52, 0x2f, 0x4d, 0x7a, 0x22, 0x87, 0x0c, 0x14, 0xb0, 0xeb, 0x6e, 0xef, 0xd9, 0xe7, + 0x65, 0xec, 0xc7, 0xfd, 0x82, 0x98, 0xaa, 0xb3, 0x2e, 0x40, 0x90, 0xc2, 0x12, 0xa0, 0x81, 0x2f, + 0x52, 0x63, 0x65, 0xb2, 0xa0, 0xdb, 0x02, 0x04, 0x29, 0x2c, 0xb9, 0x53, 0xff, 0x68, 0x7b, 0xcf, + 0xfe, 0xfc, 0x84, 0x77, 0x2a, 0x40, 0x90, 0xc2, 0x82, 0x0e, 0xc8, 0xfb, 0x01, 0xb7, 0x2f, 0x4c, + 0xe4, 0x79, 0x96, 0x0f, 0xce, 0xad, 0x80, 0x23, 0x81, 0x01, 0x7f, 0x63, 0x01, 0x10, 0x26, 0x29, + 0x7a, 0x71, 0x2c, 0xe3, 0xde, 0x00, 0x64, 0x2d, 0xc9, 0xed, 0xeb, 0x3e, 0xa7, 0x47, 0xc9, 0xe8, + 0x91, 0xba, 0x03, 0x29, 0x16, 0xf0, 0x8f, 0x16, 0x38, 0x9b, 0x9e, 0xa8, 0x0c, 0xbd, 0xb2, 0x8c, + 0xc8, 0xed, 0x71, 0xa7, 0x79, 0x23, 0x08, 0xdc, 0x86, 0xdd, 0xef, 0x55, 0xce, 0xae, 0x9f, 0x80, + 0x8a, 0x4e, 0xe4, 0x02, 0xff, 0x6a, 0x81, 0x25, 0x5d, 0x45, 0x53, 0x0c, 0x2b, 0x32, 0x80, 0x64, + 0xdc, 0x01, 0x1c, 0xc4, 0x51, 0x71, 0x3c, 0xaf, 0xe3, 0xb8, 0x34, 0xa4, 0x47, 0xc3, 0xd4, 0xe0, + 0x3f, 0x2c, 0x30, 0xd7, 0x26, 0x21, 0xf1, 0xdb, 0xc4, 0x6f, 0x09, 0xae, 0xab, 0x63, 0x99, 0x34, + 0x07, 0xb9, 0x6e, 0xa6, 0x20, 0x14, 0xcd, 0x9a, 0xa6, 0x39, 0x97, 0x56, 0x1d, 0xf7, 0x2a, 0xe7, + 0x92, 0xa5, 0x69, 0x0d, 0xca, 0xb0, 0x84, 0x1f, 0x58, 0x60, 0x21, 0x39, 0x00, 0xf5, 0xa4, 0x5c, + 0x9a, 0x60, 0x1e, 0xc8, 0xf6, 0x75, 0x3d, 0x0b, 0x88, 0x06, 0x19, 0xc0, 0xbf, 0x59, 0xa2, 0x53, + 0x8b, 0xe7, 0x46, 0x66, 0x57, 0x65, 0x2c, 0xdf, 0x19, 0x7b, 0x2c, 0x0d, 0x82, 0x0a, 0xe5, 0x0b, + 0x49, 0x2b, 0x68, 0x34, 0xc7, 0xbd, 0xca, 0x72, 0x3a, 0x92, 0x46, 0x81, 0xd2, 0x0c, 0xe1, 0xcf, + 0x2c, 0x30, 0x47, 0x92, 0x8e, 0x9b, 0xd9, 0x97, 0xc7, 0x12, 0xc4, 0x13, 0x9b, 0x78, 0xf5, 0x37, + 0xa6, 0x94, 0x8a, 0xa1, 0x0c, 0xb6, 0xe8, 0x20, 0xc9, 0x21, 0xf6, 0x42, 0x97, 0xd8, 0x5f, 0x18, + 0x73, 0x07, 0x79, 0x5d, 0xf9, 0x45, 0x31, 0xc0, 0x8a, 0x98, 0x7c, 0x06, 0x6e, 0x0e, 0x5c, 0x04, + 0xf9, 0x03, 0x72, 0xa4, 0x1a, 0x7b, 0x24, 0x7e, 0xc2, 0x36, 0x28, 0x74, 0xb1, 0x1b, 0xc5, 0xc3, + 0xdb, 0x98, 0xab, 0x2e, 0x52, 0xce, 0x5f, 0xcb, 0xbd, 0x6a, 0xad, 0x3c, 0xb4, 0xc0, 0xb9, 0x93, + 0x2f, 0xf4, 0x33, 0xa5, 0xf5, 0x7b, 0x0b, 0x2c, 0x0d, 0xdd, 0xdd, 0x13, 0x18, 0xdd, 0xcf, 0x32, + 0x7a, 0x63, 0xdc, 0x97, 0xb0, 0xc9, 0xa9, 0xe3, 0x77, 0x64, 0xe7, 0x91, 0xa6, 0xf7, 0x4b, 0x0b, + 0x2c, 0x0e, 0x5e, 0x87, 0x67, 0x19, 0xaf, 0xea, 0xc3, 0x1c, 0x38, 0x77, 0x72, 0xc3, 0x04, 0xa9, + 0x99, 0x0c, 0x27, 0x33, 0x61, 0x83, 0x64, 0xca, 0x34, 0x43, 0xe5, 0x7b, 0x16, 0x28, 0xdd, 0x33, + 0x76, 0xf1, 0x7f, 0x6a, 0xc6, 0x3e, 0xdb, 0xc7, 0xf5, 0x27, 0x51, 0x30, 0x94, 0xc6, 0xad, 0xfe, + 0xdd, 0x02, 0xcb, 0x27, 0x16, 0x56, 0x31, 0x82, 0x62, 0xd7, 0x0d, 0x1e, 0xa8, 0x3f, 0xd1, 0xa4, + 0xfe, 0x64, 0xb6, 0x2e, 0xa5, 0x48, 0x6b, 0x53, 0xd1, 0xcb, 0x7d, 0x56, 0xd1, 0xab, 0xfe, 0xcb, + 0x02, 0x17, 0x3e, 0x2e, 0x13, 0x9f, 0xc9, 0x91, 0xae, 0x81, 0xa2, 0x6e, 0x8a, 0x8e, 0xe4, 0x71, + 0xea, 0x39, 0x40, 0x17, 0x0d, 0xf9, 0xdf, 0x73, 0xf5, 0xab, 0x71, 0xe5, 0xd1, 0xe3, 0xf2, 0xa9, + 0x0f, 0x1f, 0x97, 0x4f, 0x7d, 0xf4, 0xb8, 0x7c, 0xea, 0x87, 0xfd, 0xb2, 0xf5, 0xa8, 0x5f, 0xb6, + 0x3e, 0xec, 0x97, 0xad, 0x8f, 0xfa, 0x65, 0xeb, 0xdf, 0xfd, 0xb2, 0xf5, 0xab, 0xff, 0x94, 0x4f, + 0x7d, 0x77, 0x46, 0x83, 0xff, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x9e, 0x11, 0xe8, 0x41, 0x0b, 0x22, + 0x00, 0x00, } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto index 0d494317838..2a75484ffd9 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto @@ -29,6 +29,32 @@ import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; +// CustomResourceColumnDefinition specifies a column for server side printing. +message CustomResourceColumnDefinition { + // name is a human readable name for the column. + optional string name = 1; + + // type is an OpenAPI type definition for this column. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + optional string type = 2; + + // format is an optional OpenAPI type definition for this column. The 'name' format is applied + // to the primary identifier column to assist in clients identifying column is the resource name. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + optional string format = 3; + + // description is a human readable description of this column. + optional string description = 4; + + // priority is an integer defining the relative importance of this column compared to others. Lower + // numbers are considered higher priority. Columns that may be omitted in limited space scenarios + // should be given a higher priority. + optional int32 priority = 5; + + // JSONPath is a simple JSON path, i.e. with array notation. + optional string JSONPath = 6; +} + // CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format // <.spec.name>.<.spec.group>. message CustomResourceDefinition { @@ -132,6 +158,9 @@ message CustomResourceDefinitionSpec { // major version, then minor version. An example sorted list of versions: // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. repeated CustomResourceDefinitionVersion versions = 7; + + // AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column. + repeated CustomResourceColumnDefinition additionalPrinterColumns = 8; } // CustomResourceDefinitionStatus indicates the state of the CustomResourceDefinition diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go index 9d8d1cd80d1..2080cc8217e 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go @@ -52,6 +52,8 @@ type CustomResourceDefinitionSpec struct { // major version, then minor version. An example sorted list of versions: // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. Versions []CustomResourceDefinitionVersion `json:"versions,omitempty" protobuf:"bytes,7,rep,name=versions"` + // AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column. + AdditionalPrinterColumns []CustomResourceColumnDefinition `json:"additionalPrinterColumns,omitempty" protobuf:"bytes,8,rep,name=additionalPrinterColumns"` } type CustomResourceDefinitionVersion struct { @@ -64,6 +66,28 @@ type CustomResourceDefinitionVersion struct { Storage bool `json:"storage" protobuf:"varint,3,opt,name=storage"` } +// CustomResourceColumnDefinition specifies a column for server side printing. +type CustomResourceColumnDefinition struct { + // name is a human readable name for the column. + Name string `json:"name" protobuf:"bytes,1,opt,name=name"` + // type is an OpenAPI type definition for this column. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Type string `json:"type" protobuf:"bytes,2,opt,name=type"` + // format is an optional OpenAPI type definition for this column. The 'name' format is applied + // to the primary identifier column to assist in clients identifying column is the resource name. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Format string `json:"format,omitempty" protobuf:"bytes,3,opt,name=format"` + // description is a human readable description of this column. + Description string `json:"description,omitempty" protobuf:"bytes,4,opt,name=description"` + // priority is an integer defining the relative importance of this column compared to others. Lower + // numbers are considered higher priority. Columns that may be omitted in limited space scenarios + // should be given a higher priority. + Priority int32 `json:"priority,omitempty" protobuf:"bytes,5,opt,name=priority"` + + // JSONPath is a simple JSON path, i.e. with array notation. + JSONPath string `json:"JSONPath" protobuf:"bytes,6,opt,name=JSONPath"` +} + // CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition type CustomResourceDefinitionNames struct { // Plural is the plural name of the resource to serve. It must match the name of the CustomResourceDefinition-registration diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go index db2340e7333..bcb2527c81b 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go @@ -36,6 +36,8 @@ func init() { // Public to allow building arbitrary schemes. func RegisterConversions(scheme *runtime.Scheme) error { return scheme.AddGeneratedConversionFuncs( + Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition, + Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition, Convert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition, Convert_apiextensions_CustomResourceDefinition_To_v1beta1_CustomResourceDefinition, Convert_v1beta1_CustomResourceDefinitionCondition_To_apiextensions_CustomResourceDefinitionCondition, @@ -73,6 +75,36 @@ func RegisterConversions(scheme *runtime.Scheme) error { ) } +func autoConvert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in *CustomResourceColumnDefinition, out *apiextensions.CustomResourceColumnDefinition, s conversion.Scope) error { + out.Name = in.Name + out.Type = in.Type + out.Format = in.Format + out.Description = in.Description + out.Priority = in.Priority + out.JSONPath = in.JSONPath + return nil +} + +// Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition is an autogenerated conversion function. +func Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in *CustomResourceColumnDefinition, out *apiextensions.CustomResourceColumnDefinition, s conversion.Scope) error { + return autoConvert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in, out, s) +} + +func autoConvert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in *apiextensions.CustomResourceColumnDefinition, out *CustomResourceColumnDefinition, s conversion.Scope) error { + out.Name = in.Name + out.Type = in.Type + out.Format = in.Format + out.Description = in.Description + out.Priority = in.Priority + out.JSONPath = in.JSONPath + return nil +} + +// Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition is an autogenerated conversion function. +func Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in *apiextensions.CustomResourceColumnDefinition, out *CustomResourceColumnDefinition, s conversion.Scope) error { + return autoConvert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in, out, s) +} + func autoConvert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition(in *CustomResourceDefinition, out *apiextensions.CustomResourceDefinition, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(&in.Spec, &out.Spec, s); err != nil { @@ -223,6 +255,7 @@ func autoConvert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomRes } out.Subresources = (*apiextensions.CustomResourceSubresources)(unsafe.Pointer(in.Subresources)) out.Versions = *(*[]apiextensions.CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions)) + out.AdditionalPrinterColumns = *(*[]apiextensions.CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns)) return nil } @@ -249,6 +282,7 @@ func autoConvert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomRes } out.Subresources = (*CustomResourceSubresources)(unsafe.Pointer(in.Subresources)) out.Versions = *(*[]CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions)) + out.AdditionalPrinterColumns = *(*[]CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns)) return nil } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go index c990055d03a..d2c1cebf232 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go @@ -24,6 +24,22 @@ 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 *CustomResourceColumnDefinition) DeepCopyInto(out *CustomResourceColumnDefinition) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceColumnDefinition. +func (in *CustomResourceColumnDefinition) DeepCopy() *CustomResourceColumnDefinition { + if in == nil { + return nil + } + out := new(CustomResourceColumnDefinition) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) { *out = *in @@ -155,6 +171,11 @@ func (in *CustomResourceDefinitionSpec) DeepCopyInto(out *CustomResourceDefiniti *out = make([]CustomResourceDefinitionVersion, len(*in)) copy(*out, *in) } + if in.AdditionalPrinterColumns != nil { + in, out := &in.AdditionalPrinterColumns, &out.AdditionalPrinterColumns + *out = make([]CustomResourceColumnDefinition, len(*in)) + copy(*out, *in) + } return } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/BUILD b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/BUILD index b641b609370..c43365fe032 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/BUILD +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/BUILD @@ -15,6 +15,7 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/validation:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/features:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", 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 eb9acc79e8e..1179226dd75 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 @@ -22,6 +22,7 @@ import ( "strings" genericvalidation "k8s.io/apimachinery/pkg/api/validation" + "k8s.io/apimachinery/pkg/util/sets" validationutil "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -31,6 +32,11 @@ import ( apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features" ) +var ( + printerColumnDatatypes = sets.NewString("integer", "number", "string", "boolean", "date") + customResourceColumnDefinitionFormats = sets.NewString("int32", "int64", "float", "double", "byte", "date", "date-time", "password") +) + // ValidateCustomResourceDefinition statically validates func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinition) field.ErrorList { nameValidationFn := func(name string, prefix bool) []string { @@ -175,6 +181,12 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi allErrs = append(allErrs, field.Forbidden(fldPath.Child("subresources"), "disabled by feature-gate CustomResourceSubresources")) } + for i := range spec.AdditionalPrinterColumns { + if errs := ValidateCustomResourceColumnDefinition(&spec.AdditionalPrinterColumns[i], fldPath.Child("columns").Index(i)); len(errs) > 0 { + allErrs = append(allErrs, errs...) + } + } + return allErrs } @@ -238,6 +250,33 @@ func ValidateCustomResourceDefinitionNames(names *apiextensions.CustomResourceDe return allErrs } +// ValidateCustomResourceColumnDefinition statically validates a printer column. +func ValidateCustomResourceColumnDefinition(col *apiextensions.CustomResourceColumnDefinition, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if len(col.Name) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("header"), "")) + } + + if len(col.Type) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("type"), fmt.Sprintf("must be one of %s", strings.Join(printerColumnDatatypes.List(), ",")))) + } else if !printerColumnDatatypes.Has(col.Type) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), col.Type, fmt.Sprintf("must be one of %s", strings.Join(printerColumnDatatypes.List(), ",")))) + } + + if len(col.Format) > 0 && !customResourceColumnDefinitionFormats.Has(col.Format) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("format"), col.Format, fmt.Sprintf("must be one of %s", strings.Join(customResourceColumnDefinitionFormats.List(), ",")))) + } + + if len(col.JSONPath) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("path"), "")) + } else if errs := validateSimpleJSONPath(col.JSONPath, fldPath.Child("path")); len(errs) > 0 { + allErrs = append(allErrs, errs...) + } + + return allErrs +} + // specStandardValidator applies validations for different OpenAPI specification versions. type specStandardValidator interface { validate(spec *apiextensions.JSONSchemaProps, fldPath *field.Path) field.ErrorList @@ -252,7 +291,7 @@ func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiext } if schema := customResourceValidation.OpenAPIV3Schema; schema != nil { - // if subresources are enabled, only "properties" and "required" is allowed inside the root schema + // if subresources are enabled, only "properties", "required" and "description" are allowed inside the root schema if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && statusSubresourceEnabled { v := reflect.ValueOf(schema).Elem() for i := 0; i < v.NumField(); i++ { @@ -261,8 +300,8 @@ func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiext continue } - if name := v.Type().Field(i).Name; name != "Properties" && name != "Required" { - allErrs = append(allErrs, field.Invalid(fldPath.Child("openAPIV3Schema"), *schema, fmt.Sprintf(`must only have "properties" or "required" at the root if the status subresource is enabled`))) + if name := v.Type().Field(i).Name; name != "Properties" && name != "Required" && name != "Description" { + allErrs = append(allErrs, field.Invalid(fldPath.Child("openAPIV3Schema"), *schema, fmt.Sprintf(`must only have "properties", "required" or "description" at the root if the status subresource is enabled`))) break } } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go index 6bc545c0fd8..68dc8aaede5 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go @@ -849,14 +849,15 @@ func TestValidateCustomResourceDefinitionValidation(t *testing.T) { wantError: true, }, { - name: "properties and required with status", + name: "properties, required and description with status", input: apiextensions.CustomResourceValidation{ OpenAPIV3Schema: &apiextensions.JSONSchemaProps{ Properties: map[string]apiextensions.JSONSchemaProps{ "spec": {}, "status": {}, }, - Required: []string{"spec", "status"}, + Required: []string{"spec", "status"}, + Description: "This is a description", }, }, statusEnabled: true, diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go index 9284bbc81c4..145b3c5d715 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go @@ -24,6 +24,22 @@ 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 *CustomResourceColumnDefinition) DeepCopyInto(out *CustomResourceColumnDefinition) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceColumnDefinition. +func (in *CustomResourceColumnDefinition) DeepCopy() *CustomResourceColumnDefinition { + if in == nil { + return nil + } + out := new(CustomResourceColumnDefinition) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) { *out = *in @@ -155,6 +171,11 @@ func (in *CustomResourceDefinitionSpec) DeepCopyInto(out *CustomResourceDefiniti *out = make([]CustomResourceDefinitionVersion, len(*in)) copy(*out, *in) } + if in.AdditionalPrinterColumns != nil { + in, out := &in.AdditionalPrinterColumns, &out.AdditionalPrinterColumns + *out = make([]CustomResourceColumnDefinition, len(*in)) + copy(*out, *in) + } return } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/BUILD b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/BUILD index 4d5e2a73ec0..e405af28e56 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/BUILD +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/BUILD @@ -15,6 +15,7 @@ go_library( "customresource_handler.go", ], importpath = "k8s.io/apiextensions-apiserver/pkg/apiserver", + visibility = ["//visibility:public"], deps = [ "//vendor/github.com/go-openapi/spec:go_default_library", "//vendor/github.com/go-openapi/strfmt:go_default_library", @@ -32,6 +33,7 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/controller/establish:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/controller/finalizer:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/controller/status:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/features:go_default_library", @@ -74,6 +76,30 @@ go_library( ], ) +go_test( + name = "go_default_test", + srcs = [ + "customresource_handler_test.go", + "jsonpath_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", + ], +) + filegroup( name = "package-srcs", srcs = glob(["**"]), @@ -89,14 +115,5 @@ filegroup( "//staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation:all-srcs", ], tags = ["automanaged"], -) - -go_test( - name = "go_default_test", - srcs = ["customresource_handler_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", - "//vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion:go_default_library", - ], + visibility = ["//visibility:public"], ) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go index f2c73601135..f1fc89ba96c 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go @@ -37,11 +37,11 @@ import ( "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset" internalinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion" + "k8s.io/apiextensions-apiserver/pkg/controller/establish" "k8s.io/apiextensions-apiserver/pkg/controller/finalizer" "k8s.io/apiextensions-apiserver/pkg/controller/status" "k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition" - // make sure the generated client works _ "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" _ "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions" _ "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion" @@ -74,6 +74,10 @@ func init() { type ExtraConfig struct { CRDRESTOptionsGetter genericregistry.RESTOptionsGetter + + // MasterCount is used to detect whether cluster is HA, and if it is + // the CRD Establishing will be hold by 5 seconds. + MasterCount int } type Config struct { @@ -162,6 +166,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) discovery: map[string]*discovery.APIGroupHandler{}, delegate: delegateHandler, } + establishingController := establish.NewEstablishingController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), crdClient.Apiextensions()) crdHandler := NewCustomResourceDefinitionHandler( versionDiscoveryHandler, groupDiscoveryHandler, @@ -169,6 +174,8 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) delegateHandler, c.ExtraConfig.CRDRESTOptionsGetter, c.GenericConfig.AdmissionControl, + establishingController, + c.ExtraConfig.MasterCount, ) s.GenericAPIServer.Handler.NonGoRestfulMux.Handle("/apis", crdHandler) s.GenericAPIServer.Handler.NonGoRestfulMux.HandlePrefix("/apis/", crdHandler) @@ -188,6 +195,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) s.GenericAPIServer.AddPostStartHook("start-apiextensions-controllers", func(context genericapiserver.PostStartHookContext) error { go crdController.Run(context.StopCh) go namingController.Run(context.StopCh) + go establishingController.Run(context.StopCh) go finalizingController.Run(5, context.StopCh) return nil }) 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 20231bdf866..7be3711dc17 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 @@ -62,6 +62,7 @@ import ( apiservervalidation "k8s.io/apiextensions-apiserver/pkg/apiserver/validation" informers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion" listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion" + "k8s.io/apiextensions-apiserver/pkg/controller/establish" "k8s.io/apiextensions-apiserver/pkg/controller/finalizer" apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features" "k8s.io/apiextensions-apiserver/pkg/registry/customresource" @@ -86,6 +87,12 @@ type crdHandler struct { delegate http.Handler restOptionsGetter generic.RESTOptionsGetter admission admission.Interface + + establishingController *establish.EstablishingController + + // MasterCount is used to implement sleep to improve + // CRD establishing process for HA clusters. + masterCount int } // crdInfo stores enough information to serve the storage for the custom resource @@ -120,7 +127,9 @@ func NewCustomResourceDefinitionHandler( crdInformer informers.CustomResourceDefinitionInformer, delegate http.Handler, restOptionsGetter generic.RESTOptionsGetter, - admission admission.Interface) *crdHandler { + admission admission.Interface, + establishingController *establish.EstablishingController, + masterCount int) *crdHandler { ret := &crdHandler{ versionDiscoveryHandler: versionDiscoveryHandler, groupDiscoveryHandler: groupDiscoveryHandler, @@ -129,6 +138,8 @@ func NewCustomResourceDefinitionHandler( delegate: delegate, restOptionsGetter: restOptionsGetter, admission: admission, + establishingController: establishingController, + masterCount: masterCount, } crdInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: ret.updateCustomResourceDefinition, @@ -181,7 +192,12 @@ func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { r.delegate.ServeHTTP(w, req) return } - if !apiextensions.IsCRDConditionTrue(crd, apiextensions.Established) { + // There is a small chance that a CRD is being served because NamesAccepted condition is true, + // but it becomes "unserved" because another names update leads to a conflict + // and EstablishingController wasn't fast enough to put the CRD into the Established condition. + // We accept this as the problem is small and self-healing. + if !apiextensions.IsCRDConditionTrue(crd, apiextensions.NamesAccepted) && + !apiextensions.IsCRDConditionTrue(crd, apiextensions.Established) { r.delegate.ServeHTTP(w, req) return } @@ -299,6 +315,19 @@ func (r *crdHandler) updateCustomResourceDefinition(oldObj, newObj interface{}) r.customStorageLock.Lock() defer r.customStorageLock.Unlock() + // Add CRD to the establishing controller queue. + // For HA clusters, we want to prevent race conditions when changing status to Established, + // so we want to be sure that CRD is Installing at least for 5 seconds before Establishing it. + // TODO: find a real HA safe checkpointing mechanism instead of an arbitrary wait. + if !apiextensions.IsCRDConditionTrue(newCRD, apiextensions.Established) && + apiextensions.IsCRDConditionTrue(newCRD, apiextensions.NamesAccepted) { + if r.masterCount > 1 { + r.establishingController.QueueCRD(newCRD.Name, 5*time.Second) + } else { + r.establishingController.QueueCRD(newCRD.Name, 0) + } + } + storageMap := r.customStorage.Load().(crdStorageMap) oldInfo, found := storageMap[newCRD.UID] if !found { @@ -370,6 +399,8 @@ func (r *crdHandler) GetCustomResourceListerCollectionDeleter(crd *apiextensions return info.storages[info.storageVersion].CustomResource, nil } +var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() + func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResourceDefinition) (*crdInfo, error) { storageMap := r.customStorage.Load().(crdStorageMap) if ret, ok := storageMap[crd.UID]; ok { @@ -439,8 +470,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource scaleSpec = crd.Spec.Subresources.Scale } - // TODO: identify how to pass printer specification from the CRD - table, err := tableconvertor.New(nil) + table, err := tableconvertor.New(crd.Spec.AdditionalPrinterColumns) if err != nil { glog.V(2).Infof("The CRD for %v has an invalid printer specification, falling back to default printing: %v", kind, err) } @@ -580,7 +610,8 @@ func (s unstructuredNegotiatedSerializer) EncoderForVersion(encoder runtime.Enco } func (s unstructuredNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { - return versioning.NewDefaultingCodecForScheme(Scheme, nil, decoder, nil, gv) + d := schemaCoercingDecoder{delegate: decoder, validator: unstructuredSchemaCoercer{}} + return versioning.NewDefaultingCodecForScheme(Scheme, nil, d, nil, gv) } type UnstructuredObjectTyper struct { @@ -674,7 +705,179 @@ type crdConversionRESTOptionsGetter struct { func (t crdConversionRESTOptionsGetter) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) { ret, err := t.RESTOptionsGetter.GetRESTOptions(resource) if err == nil { - ret.StorageConfig.Codec = versioning.NewCodec(ret.StorageConfig.Codec, ret.StorageConfig.Codec, t.converter, &unstructuredCreator{}, discovery.NewUnstructuredObjectTyper(), &unstructuredDefaulter{delegate: Scheme}, t.encoderVersion, t.decoderVersion) + d := schemaCoercingDecoder{delegate: ret.StorageConfig.Codec, validator: unstructuredSchemaCoercer{ + // drop invalid fields while decoding old CRs (before we had any ObjectMeta validation) + dropInvalidMetadata: true, + }} + c := schemaCoercingConverter{delegate: t.converter, validator: unstructuredSchemaCoercer{}} + ret.StorageConfig.Codec = versioning.NewCodec(ret.StorageConfig.Codec, d, c, &unstructuredCreator{}, discovery.NewUnstructuredObjectTyper(), &unstructuredDefaulter{delegate: Scheme}, t.encoderVersion, t.decoderVersion) } return ret, err } + +// schemaCoercingDecoder calls the delegate decoder, and then applies the Unstructured schema validator +// to coerce the schema. +type schemaCoercingDecoder struct { + delegate runtime.Decoder + validator unstructuredSchemaCoercer +} + +var _ runtime.Decoder = schemaCoercingDecoder{} + +func (d schemaCoercingDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { + obj, gvk, err := d.delegate.Decode(data, defaults, into) + if err != nil { + return nil, gvk, err + } + if u, ok := obj.(*unstructured.Unstructured); ok { + if err := d.validator.apply(u); err != nil { + return nil, gvk, err + } + } + + return obj, gvk, nil +} + +// schemaCoercingConverter calls the delegate converter and applies the Unstructured validator to +// coerce the schema. +type schemaCoercingConverter struct { + delegate runtime.ObjectConvertor + validator unstructuredSchemaCoercer +} + +var _ runtime.ObjectConvertor = schemaCoercingConverter{} + +func (v schemaCoercingConverter) Convert(in, out, context interface{}) error { + if err := v.delegate.Convert(in, out, context); err != nil { + return err + } + + if u, ok := out.(*unstructured.Unstructured); ok { + if err := v.validator.apply(u); err != nil { + return err + } + } + + return nil +} + +func (v schemaCoercingConverter) ConvertToVersion(in runtime.Object, gv runtime.GroupVersioner) (runtime.Object, error) { + out, err := v.delegate.ConvertToVersion(in, gv) + if err != nil { + return nil, err + } + + if u, ok := out.(*unstructured.Unstructured); ok { + if err := v.validator.apply(u); err != nil { + return nil, err + } + } + + return out, nil +} + +func (v schemaCoercingConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { + return v.ConvertFieldLabel(version, kind, label, value) +} + +// unstructuredSchemaCoercer does the validation for Unstructured that json.Unmarshal +// does for native types. This includes: +// - validating and pruning ObjectMeta (here with optional error instead of pruning) +// - TODO: application of an OpenAPI validator (against the whole object or a top-level field of it). +// - TODO: optionally application of post-validation algorithms like defaulting and/or OpenAPI based pruning. +type unstructuredSchemaCoercer struct { + dropInvalidMetadata bool +} + +func (v *unstructuredSchemaCoercer) apply(u *unstructured.Unstructured) error { + // save implicit meta fields that don't have to be specified in the validation spec + kind, foundKind, err := unstructured.NestedString(u.UnstructuredContent(), "kind") + if err != nil { + return err + } + apiVersion, foundApiVersion, err := unstructured.NestedString(u.UnstructuredContent(), "apiVersion") + if err != nil { + return err + } + objectMeta, foundObjectMeta, err := getObjectMeta(u, v.dropInvalidMetadata) + if err != nil { + return err + } + + // restore meta fields, starting clean + if foundKind { + u.SetKind(kind) + } + if foundApiVersion { + u.SetAPIVersion(apiVersion) + } + if foundObjectMeta { + if err := setObjectMeta(u, objectMeta); err != nil { + return err + } + } + + return nil +} + +var encodingjson = json.CaseSensitiveJsonIterator() + +func getObjectMeta(u *unstructured.Unstructured, dropMalformedFields bool) (*metav1.ObjectMeta, bool, error) { + metadata, found := u.UnstructuredContent()["metadata"] + if !found { + return nil, false, nil + } + + // round-trip through JSON first, hoping that unmarshaling just works + objectMeta := &metav1.ObjectMeta{} + metadataBytes, err := encodingjson.Marshal(metadata) + if err != nil { + return nil, false, err + } + if err = encodingjson.Unmarshal(metadataBytes, objectMeta); err == nil { + // if successful, return + return objectMeta, true, nil + } + if !dropMalformedFields { + // if we're not trying to drop malformed fields, return the error + return nil, true, err + } + + metadataMap, ok := metadata.(map[string]interface{}) + if !ok { + return nil, false, fmt.Errorf("invalid metadata: expected object, got %T", metadata) + } + + // Go field by field accumulating into the metadata object. + // This takes advantage of the fact that you can repeatedly unmarshal individual fields into a single struct, + // each iteration preserving the old key-values. + accumulatedObjectMeta := &metav1.ObjectMeta{} + testObjectMeta := &metav1.ObjectMeta{} + for k, v := range metadataMap { + // serialize a single field + if singleFieldBytes, err := encodingjson.Marshal(map[string]interface{}{k: v}); err == nil { + // do a test unmarshal + if encodingjson.Unmarshal(singleFieldBytes, testObjectMeta) == nil { + // if that succeeds, unmarshal for real + encodingjson.Unmarshal(singleFieldBytes, accumulatedObjectMeta) + } + } + } + + return accumulatedObjectMeta, true, nil +} + +func setObjectMeta(u *unstructured.Unstructured, objectMeta *metav1.ObjectMeta) error { + if objectMeta == nil { + unstructured.RemoveNestedField(u.UnstructuredContent(), "metadata") + return nil + } + + metadata, err := runtime.DefaultUnstructuredConverter.ToUnstructured(objectMeta) + if err != nil { + return err + } + + u.UnstructuredContent()["metadata"] = metadata + return nil +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go index c275e93b12c..a6d6e23a123 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go @@ -17,10 +17,23 @@ limitations under the License. package apiserver import ( + "math/rand" + "reflect" "testing" + corev1 "k8s.io/api/core/v1" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" - conversion "k8s.io/apiextensions-apiserver/pkg/apiserver/conversion" + "k8s.io/apiextensions-apiserver/pkg/apiserver/conversion" + "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/api/testing/fuzzer" + metafuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/runtime/serializer/json" + "k8s.io/apimachinery/pkg/util/diff" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" ) func TestConvertFieldLabel(t *testing.T) { @@ -94,3 +107,202 @@ func TestConvertFieldLabel(t *testing.T) { }) } } + +func TestRoundtripObjectMeta(t *testing.T) { + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + codec := json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false) + seed := rand.Int63() + fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(seed), codecs) + + N := 1000 + for i := 0; i < N; i++ { + u := &unstructured.Unstructured{Object: map[string]interface{}{}} + original := &metav1.ObjectMeta{} + fuzzer.Fuzz(original) + if err := setObjectMeta(u, original); err != nil { + t.Fatalf("unexpected error setting ObjectMeta: %v", err) + } + o, _, err := getObjectMeta(u, false) + if err != nil { + t.Fatalf("unexpected error getting the Objectmeta: %v", err) + } + + if !equality.Semantic.DeepEqual(original, o) { + t.Errorf("diff: %v\nCodec: %#v", diff.ObjectReflectDiff(original, o), codec) + } + } +} + +// TestMalformedObjectMetaFields sets a number of different random values and types for all +// metadata fields. If json.Unmarshal accepts them, compare that getObjectMeta +// gives the same result. Otherwise, drop malformed fields. +func TestMalformedObjectMetaFields(t *testing.T) { + fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(rand.Int63()), serializer.NewCodecFactory(runtime.NewScheme())) + spuriousValues := func() []interface{} { + return []interface{}{ + // primitives + nil, + int64(1), + float64(1.5), + true, + "a", + // well-formed complex values + []interface{}{"a", "b"}, + map[string]interface{}{"a": "1", "b": "2"}, + []interface{}{int64(1), int64(2)}, + []interface{}{float64(1.5), float64(2.5)}, + // known things json decoding tolerates + map[string]interface{}{"a": "1", "b": nil}, + // malformed things + map[string]interface{}{"a": "1", "b": []interface{}{"nested"}}, + []interface{}{"a", int64(1), float64(1.5), true, []interface{}{"nested"}}, + } + } + N := 100 + for i := 0; i < N; i++ { + fuzzedObjectMeta := &metav1.ObjectMeta{} + fuzzer.Fuzz(fuzzedObjectMeta) + goodMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy()) + if err != nil { + t.Fatal(err) + } + for _, pth := range jsonPaths(nil, goodMetaMap) { + for _, v := range spuriousValues() { + // skip values of same type, because they can only cause decoding errors further insides + orig, err := JsonPathValue(goodMetaMap, pth, 0) + if err != nil { + t.Fatalf("unexpected to not find something at %v: %v", pth, err) + } + if reflect.TypeOf(v) == reflect.TypeOf(orig) { + continue + } + + // make a spurious map + spuriousMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy()) + if err != nil { + t.Fatal(err) + } + if err := SetJsonPath(spuriousMetaMap, pth, 0, v); err != nil { + t.Fatal(err) + } + + // See if it can unmarshal to object meta + spuriousJSON, err := encodingjson.Marshal(spuriousMetaMap) + if err != nil { + t.Fatalf("error on %v=%#v: %v", pth, v, err) + } + expectedObjectMeta := &metav1.ObjectMeta{} + if err := encodingjson.Unmarshal(spuriousJSON, expectedObjectMeta); err != nil { + // if standard json unmarshal would fail decoding this field, drop the field entirely + truncatedMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy()) + if err != nil { + t.Fatal(err) + } + + // we expect this logic for the different fields: + switch { + default: + // delete complete top-level field by default + DeleteJsonPath(truncatedMetaMap, pth[:1], 0) + } + + truncatedJSON, err := encodingjson.Marshal(truncatedMetaMap) + if err != nil { + t.Fatalf("error on %v=%#v: %v", pth, v, err) + } + expectedObjectMeta = &metav1.ObjectMeta{} + if err := encodingjson.Unmarshal(truncatedJSON, expectedObjectMeta); err != nil { + t.Fatalf("error on %v=%#v: %v", pth, v, err) + } + } + + // make sure dropInvalidTypedFields+getObjectMeta matches what we expect + u := &unstructured.Unstructured{Object: map[string]interface{}{"metadata": spuriousMetaMap}} + actualObjectMeta, _, err := getObjectMeta(u, true) + if err != nil { + t.Errorf("got unexpected error after dropping invalid typed fields on %v=%#v: %v", pth, v, err) + continue + } + + if !equality.Semantic.DeepEqual(expectedObjectMeta, actualObjectMeta) { + t.Errorf("%v=%#v, diff: %v\n", pth, v, diff.ObjectReflectDiff(expectedObjectMeta, actualObjectMeta)) + t.Errorf("expectedObjectMeta %#v", expectedObjectMeta) + } + } + } + } +} + +func TestGetObjectMetaNils(t *testing.T) { + u := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "kind": "Pod", + "apiVersion": "v1", + "metadata": map[string]interface{}{ + "generateName": nil, + "labels": map[string]interface{}{ + "foo": nil, + }, + }, + }, + } + + o, _, err := getObjectMeta(u, true) + if err != nil { + t.Fatal(err) + } + if o.GenerateName != "" { + t.Errorf("expected null json value to be read as \"\" string, but got: %q", o.GenerateName) + } + if got, expected := o.Labels, map[string]string{"foo": ""}; !reflect.DeepEqual(got, expected) { + t.Errorf("unexpected labels, expected=%#v, got=%#v", expected, got) + } + + // double check this what the kube JSON decode is doing + bs, _ := encodingjson.Marshal(u.UnstructuredContent()) + kubeObj, _, err := clientgoscheme.Codecs.UniversalDecoder(corev1.SchemeGroupVersion).Decode(bs, nil, nil) + if err != nil { + t.Fatal(err) + } + pod, ok := kubeObj.(*corev1.Pod) + if !ok { + t.Fatalf("expected v1 Pod, got: %T", pod) + } + if got, expected := o.GenerateName, pod.ObjectMeta.GenerateName; got != expected { + t.Errorf("expected generatedName to be %q, got %q", expected, got) + } + if got, expected := o.Labels, pod.ObjectMeta.Labels; !reflect.DeepEqual(got, expected) { + t.Errorf("expected labels to be %v, got %v", expected, got) + } +} + +func TestGetObjectMeta(t *testing.T) { + for i := 0; i < 100; i++ { + u := &unstructured.Unstructured{Object: map[string]interface{}{ + "metadata": map[string]interface{}{ + "name": "good", + "Name": "bad1", + "nAme": "bad2", + "naMe": "bad3", + "namE": "bad4", + + "namespace": "good", + "Namespace": "bad1", + "nAmespace": "bad2", + "naMespace": "bad3", + "namEspace": "bad4", + + "creationTimestamp": "a", + }, + }} + + meta, _, err := getObjectMeta(u, true) + if err != nil { + t.Fatal(err) + } + if meta.Name != "good" || meta.Namespace != "good" { + t.Fatalf("got %#v", meta) + } + } +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/jsonpath_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/jsonpath_test.go new file mode 100644 index 00000000000..8d9bb24f877 --- /dev/null +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/jsonpath_test.go @@ -0,0 +1,235 @@ +/* +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 ( + "bytes" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" +) + +type ( + jsonPathNode struct { + index *int + field string + } + JsonPath []jsonPathNode +) + +func (p JsonPath) String() string { + var buf bytes.Buffer + for _, n := range p { + if n.index == nil { + buf.WriteString("." + n.field) + } else { + buf.WriteString(fmt.Sprintf("[%d]", *n.index)) + } + } + return buf.String() +} + +func jsonPaths(base JsonPath, j map[string]interface{}) []JsonPath { + res := make([]JsonPath, 0, len(j)) + for k, old := range j { + kPth := append(append([]jsonPathNode(nil), base...), jsonPathNode{field: k}) + res = append(res, kPth) + + switch old := old.(type) { + case map[string]interface{}: + res = append(res, jsonPaths(kPth, old)...) + case []interface{}: + res = append(res, jsonIterSlice(kPth, old)...) + } + } + return res +} + +func jsonIterSlice(base JsonPath, j []interface{}) []JsonPath { + res := make([]JsonPath, 0, len(j)) + for i, old := range j { + index := i + iPth := append(append([]jsonPathNode(nil), base...), jsonPathNode{index: &index}) + res = append(res, iPth) + + switch old := old.(type) { + case map[string]interface{}: + res = append(res, jsonPaths(iPth, old)...) + case []interface{}: + res = append(res, jsonIterSlice(iPth, old)...) + } + } + return res +} + +func JsonPathValue(j map[string]interface{}, pth JsonPath, base int) (interface{}, error) { + if len(pth) == base { + return nil, fmt.Errorf("empty json path is invalid for object") + } + if pth[base].index != nil { + return nil, fmt.Errorf("index json path is invalid for object") + } + field, ok := j[pth[base].field] + if !ok || len(pth) == base+1 { + if len(pth) > base+1 { + return nil, fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth) + } + return j[pth[base].field], nil + } + switch field := field.(type) { + case map[string]interface{}: + return JsonPathValue(field, pth, base+1) + case []interface{}: + return jsonPathValueSlice(field, pth, base+1) + default: + return nil, fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1]) + } +} + +func jsonPathValueSlice(j []interface{}, pth JsonPath, base int) (interface{}, error) { + if len(pth) == base { + return nil, fmt.Errorf("empty json path %q is invalid for object", pth) + } + if pth[base].index == nil { + return nil, fmt.Errorf("field json path %q is invalid for object", pth[:base+1]) + } + if *pth[base].index >= len(j) { + return nil, fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j)) + } + if len(pth) == base+1 { + return j[*pth[base].index], nil + } + switch item := j[*pth[base].index].(type) { + case map[string]interface{}: + return JsonPathValue(item, pth, base+1) + case []interface{}: + return jsonPathValueSlice(item, pth, base+1) + default: + return nil, fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1]) + } +} + +func SetJsonPath(j map[string]interface{}, pth JsonPath, base int, value interface{}) error { + if len(pth) == base { + return fmt.Errorf("empty json path is invalid for object") + } + if pth[base].index != nil { + return fmt.Errorf("index json path is invalid for object") + } + field, ok := j[pth[base].field] + if !ok || len(pth) == base+1 { + if len(pth) > base+1 { + return fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth) + } + j[pth[base].field] = runtime.DeepCopyJSONValue(value) + return nil + } + switch field := field.(type) { + case map[string]interface{}: + return SetJsonPath(field, pth, base+1, value) + case []interface{}: + return setJsonPathSlice(field, pth, base+1, value) + default: + return fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1]) + } +} + +func setJsonPathSlice(j []interface{}, pth JsonPath, base int, value interface{}) error { + if len(pth) == base { + return fmt.Errorf("empty json path %q is invalid for object", pth) + } + if pth[base].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth[:base+1]) + } + if *pth[base].index >= len(j) { + return fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j)) + } + if len(pth) == base+1 { + j[*pth[base].index] = runtime.DeepCopyJSONValue(value) + return nil + } + switch item := j[*pth[base].index].(type) { + case map[string]interface{}: + return SetJsonPath(item, pth, base+1, value) + case []interface{}: + return setJsonPathSlice(item, pth, base+1, value) + default: + return fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1]) + } +} + +func DeleteJsonPath(j map[string]interface{}, pth JsonPath, base int) error { + if len(pth) == base { + return fmt.Errorf("empty json path is invalid for object") + } + if pth[base].index != nil { + return fmt.Errorf("index json path is invalid for object") + } + field, ok := j[pth[base].field] + if !ok || len(pth) == base+1 { + if len(pth) > base+1 { + return fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth) + } + delete(j, pth[base].field) + return nil + } + switch field := field.(type) { + case map[string]interface{}: + return DeleteJsonPath(field, pth, base+1) + case []interface{}: + if len(pth) == base+2 { + if pth[base+1].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth) + } + j[pth[base].field] = append(field[:*pth[base+1].index], field[*pth[base+1].index+1:]...) + return nil + } + return deleteJsonPathSlice(field, pth, base+1) + default: + return fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1]) + } +} + +func deleteJsonPathSlice(j []interface{}, pth JsonPath, base int) error { + if len(pth) == base { + return fmt.Errorf("empty json path %q is invalid for object", pth) + } + if pth[base].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth[:base+1]) + } + if *pth[base].index >= len(j) { + return fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j)) + } + if len(pth) == base+1 { + return fmt.Errorf("cannot delete item at index %q in-place", pth[:base]) + } + switch item := j[*pth[base].index].(type) { + case map[string]interface{}: + return DeleteJsonPath(item, pth, base+1) + case []interface{}: + if len(pth) == base+2 { + if pth[base+1].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth) + } + j[*pth[base].index] = append(item[:*pth[base+1].index], item[*pth[base+1].index+1:]) + return nil + } + return deleteJsonPathSlice(item, pth, base+1) + default: + return fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1]) + } +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish/BUILD b/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish/BUILD new file mode 100644 index 00000000000..fa3e5dfa1bb --- /dev/null +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish/BUILD @@ -0,0 +1,34 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["establishing_controller.go"], + importpath = "k8s.io/apiextensions-apiserver/pkg/controller/establish", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", + "//vendor/k8s.io/client-go/util/workqueue: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/apiextensions-apiserver/pkg/controller/establish/establishing_controller.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish/establishing_controller.go new file mode 100644 index 00000000000..5c2ebbcaad8 --- /dev/null +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish/establishing_controller.go @@ -0,0 +1,142 @@ +/* +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 establish + +import ( + "fmt" + "time" + + "github.com/golang/glog" + apierrors "k8s.io/apimachinery/pkg/api/errors" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + client "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion" + informers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion" + listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion" +) + +// EstablishingController controls how and when CRD is established. +type EstablishingController struct { + crdClient client.CustomResourceDefinitionsGetter + crdLister listers.CustomResourceDefinitionLister + crdSynced cache.InformerSynced + + // To allow injection for testing. + syncFn func(key string) error + + queue workqueue.RateLimitingInterface +} + +// NewEstablishingController creates new EstablishingController. +func NewEstablishingController(crdInformer informers.CustomResourceDefinitionInformer, + crdClient client.CustomResourceDefinitionsGetter) *EstablishingController { + ec := &EstablishingController{ + crdClient: crdClient, + crdLister: crdInformer.Lister(), + crdSynced: crdInformer.Informer().HasSynced, + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "crdEstablishing"), + } + + ec.syncFn = ec.sync + + return ec +} + +// QueueCRD adds CRD into the establishing queue. +func (ec *EstablishingController) QueueCRD(key string, timeout time.Duration) { + ec.queue.AddAfter(key, timeout) +} + +// Run starts the EstablishingController. +func (ec *EstablishingController) Run(stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer ec.queue.ShutDown() + + glog.Infof("Starting EstablishingController") + defer glog.Infof("Shutting down EstablishingController") + + if !cache.WaitForCacheSync(stopCh, ec.crdSynced) { + return + } + + // only start one worker thread since its a slow moving API + go wait.Until(ec.runWorker, time.Second, stopCh) + + <-stopCh +} + +func (ec *EstablishingController) runWorker() { + for ec.processNextWorkItem() { + } +} + +// processNextWorkItem deals with one key off the queue. +// It returns false when it's time to quit. +func (ec *EstablishingController) processNextWorkItem() bool { + key, quit := ec.queue.Get() + if quit { + return false + } + defer ec.queue.Done(key) + + err := ec.syncFn(key.(string)) + if err == nil { + return true + } + + utilruntime.HandleError(fmt.Errorf("%v failed with: %v", key, err)) + ec.queue.AddRateLimited(key) + + return true +} + +// sync is used to turn CRDs into the Established state. +func (ec *EstablishingController) sync(key string) error { + cachedCRD, err := ec.crdLister.Get(key) + if apierrors.IsNotFound(err) { + return nil + } + if err != nil { + return err + } + + if !apiextensions.IsCRDConditionTrue(cachedCRD, apiextensions.NamesAccepted) || + apiextensions.IsCRDConditionTrue(cachedCRD, apiextensions.Established) { + return nil + } + + crd := cachedCRD.DeepCopy() + establishedCondition := apiextensions.CustomResourceDefinitionCondition{ + Type: apiextensions.Established, + Status: apiextensions.ConditionTrue, + Reason: "InitialNamesAccepted", + Message: "the initial names have been accepted", + } + apiextensions.SetCRDCondition(crd, establishedCondition) + + // Update server with new CRD condition. + _, err = ec.crdClient.CustomResourceDefinitions().UpdateStatus(crd) + if err != nil { + return err + } + + return nil +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/BUILD b/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/BUILD index c408cf4874e..0489e9fccd7 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/BUILD +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/BUILD @@ -28,6 +28,7 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go index 16016e493a5..f00def4b124 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go @@ -24,6 +24,7 @@ import ( "github.com/golang/glog" + "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -191,7 +192,10 @@ func (c *NamingConditionController) calculateNamesAndConditions(in *apiextension namesAcceptedCondition.Message = "no conflicts found" } - // set EstablishedCondition to true if all names are accepted. Never set it back to false. + // set EstablishedCondition initially to false, then set it to true in establishing controller. + // The Establishing Controller will see the NamesAccepted condition when it arrives through the shared informer. + // At that time the API endpoint handler will serve the endpoint, avoiding a race + // which we had if we set Established to true here. establishedCondition := apiextensions.CustomResourceDefinitionCondition{ Type: apiextensions.Established, Status: apiextensions.ConditionFalse, @@ -204,8 +208,8 @@ func (c *NamingConditionController) calculateNamesAndConditions(in *apiextension if establishedCondition.Status != apiextensions.ConditionTrue && namesAcceptedCondition.Status == apiextensions.ConditionTrue { establishedCondition = apiextensions.CustomResourceDefinitionCondition{ Type: apiextensions.Established, - Status: apiextensions.ConditionTrue, - Reason: "InitialNamesAccepted", + Status: apiextensions.ConditionFalse, + Reason: "Installing", Message: "the initial names have been accepted", } } @@ -238,12 +242,16 @@ func (c *NamingConditionController) sync(key string) error { return err } + // Skip checking names if Spec and Status names are same. + if equality.Semantic.DeepEqual(inCustomResourceDefinition.Spec.Names, inCustomResourceDefinition.Status.AcceptedNames) { + return nil + } + acceptedNames, namingCondition, establishedCondition := c.calculateNamesAndConditions(inCustomResourceDefinition) // nothing to do if accepted names and NamesAccepted condition didn't change if reflect.DeepEqual(inCustomResourceDefinition.Status.AcceptedNames, acceptedNames) && - apiextensions.IsCRDConditionEquivalent(&namingCondition, apiextensions.FindCRDCondition(inCustomResourceDefinition, apiextensions.NamesAccepted)) && - apiextensions.IsCRDConditionEquivalent(&establishedCondition, apiextensions.FindCRDCondition(inCustomResourceDefinition, apiextensions.Established)) { + apiextensions.IsCRDConditionEquivalent(&namingCondition, apiextensions.FindCRDCondition(inCustomResourceDefinition, apiextensions.NamesAccepted)) { return nil } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go index 615c5dd85ff..717e5288484 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go @@ -95,19 +95,17 @@ var acceptedCondition = apiextensions.CustomResourceDefinitionCondition{ Message: "no conflicts found", } -func nameConflictCondition(reason, message string) apiextensions.CustomResourceDefinitionCondition { - return apiextensions.CustomResourceDefinitionCondition{ - Type: apiextensions.NamesAccepted, - Status: apiextensions.ConditionFalse, - Reason: reason, - Message: message, - } +var notAcceptedCondition = apiextensions.CustomResourceDefinitionCondition{ + Type: apiextensions.NamesAccepted, + Status: apiextensions.ConditionFalse, + Reason: "NotAccepted", + Message: "not all names are accepted", } -var establishedCondition = apiextensions.CustomResourceDefinitionCondition{ +var installingCondition = apiextensions.CustomResourceDefinitionCondition{ Type: apiextensions.Established, - Status: apiextensions.ConditionTrue, - Reason: "InitialNamesAccepted", + Status: apiextensions.ConditionFalse, + Reason: "Installing", Message: "the initial names have been accepted", } @@ -118,6 +116,15 @@ var notEstablishedCondition = apiextensions.CustomResourceDefinitionCondition{ Message: "not all names are accepted", } +func nameConflictCondition(reason, message string) apiextensions.CustomResourceDefinitionCondition { + return apiextensions.CustomResourceDefinitionCondition{ + Type: apiextensions.NamesAccepted, + Status: apiextensions.ConditionFalse, + Reason: reason, + Message: message, + } +} + func TestSync(t *testing.T) { tests := []struct { name string @@ -136,7 +143,7 @@ func TestSync(t *testing.T) { Plural: "alfa", }, expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "different groups", @@ -146,7 +153,7 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "conflict plural to singular", @@ -206,7 +213,7 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "merge on conflicts", @@ -248,7 +255,7 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "no conflicts on self, remove shortname", @@ -264,44 +271,44 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { - name: "established before with true condition", - in: newCRD("alfa.bravo.com").Condition(establishedCondition).NewOrDie(), + name: "installing before with true condition", + in: newCRD("alfa.bravo.com").Condition(acceptedCondition).NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{}, expectedNames: apiextensions.CustomResourceDefinitionNames{ Plural: "alfa", }, expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { - name: "not established before with false condition", - in: newCRD("alfa.bravo.com").Condition(notEstablishedCondition).NewOrDie(), + name: "not installing before with false condition", + in: newCRD("alfa.bravo.com").Condition(notAcceptedCondition).NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{}, expectedNames: apiextensions.CustomResourceDefinitionNames{ Plural: "alfa", }, expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { - name: "conflicting, established before with true condition", + name: "conflicting, installing before with true condition", in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"). - Condition(establishedCondition). + Condition(acceptedCondition). NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{ newCRD("india.bravo.com").StatusNames("india", "alfa", "", "").NewOrDie(), }, expectedNames: names("", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: nameConflictCondition("PluralConflict", `"alfa" is already in use`), - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: notEstablishedCondition, }, { - name: "conflicting, not established before with false condition", + name: "conflicting, not installing before with false condition", in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"). - Condition(notEstablishedCondition). + Condition(notAcceptedCondition). NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{ newCRD("india.bravo.com").StatusNames("india", "alfa", "", "").NewOrDie(), @@ -322,7 +329,7 @@ func TestSync(t *testing.T) { crdLister: listers.NewCustomResourceDefinitionLister(crdIndexer), crdMutationCache: cache.NewIntegerResourceVersionMutationCache(crdIndexer, crdIndexer, 60*time.Second, false), } - actualNames, actualNameConflictCondition, actualEstablishedCondition := c.calculateNamesAndConditions(tc.in) + actualNames, actualNameConflictCondition, establishedCondition := c.calculateNamesAndConditions(tc.in) if e, a := tc.expectedNames, actualNames; !reflect.DeepEqual(e, a) { t.Errorf("%v expected %v, got %#v", tc.name, e, a) @@ -330,7 +337,7 @@ func TestSync(t *testing.T) { if e, a := tc.expectedNameConflictCondition, actualNameConflictCondition; !apiextensions.IsCRDConditionEquivalent(&e, &a) { t.Errorf("%v expected %v, got %v", tc.name, e, a) } - if e, a := tc.expectedEstablishedCondition, actualEstablishedCondition; !apiextensions.IsCRDConditionEquivalent(&e, &a) { + if e, a := tc.expectedEstablishedCondition, establishedCondition; !apiextensions.IsCRDConditionEquivalent(&e, &a) { t.Errorf("%v expected %v, got %v", tc.name, e, a) } } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/BUILD b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/BUILD index bbef70ca780..cebbd87bfa4 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/BUILD +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/BUILD @@ -71,8 +71,10 @@ go_test( "//vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go index e82ff07e568..d9e8fd97cbd 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go @@ -23,6 +23,7 @@ import ( autoscalingv1 "k8s.io/api/autoscaling/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -106,6 +107,59 @@ func newREST(resource schema.GroupResource, listKind schema.GroupVersionKind, st // Implement CategoriesProvider var _ rest.CategoriesProvider = &REST{} +// List returns a list of items matching labels and field according to the store's PredicateFunc. +func (e *REST) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { + l, err := e.Store.List(ctx, options) + if err != nil { + return nil, err + } + + // Shallow copy ObjectMeta in returned list for each item. Native types have `Items []Item` fields and therefore + // implicitly shallow copy ObjectMeta. The generic store sets the self-link for each item. So this is necessary + // to avoid mutation of the objects from the cache. + if ul, ok := l.(*unstructured.UnstructuredList); ok { + for i := range ul.Items { + shallowCopyObjectMeta(&ul.Items[i]) + } + } + + return l, nil +} + +func (r *REST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { + o, err := r.Store.Get(ctx, name, options) + if err != nil { + return nil, err + } + if u, ok := o.(*unstructured.Unstructured); ok { + shallowCopyObjectMeta(u) + } + return o, nil +} + +func shallowCopyObjectMeta(u runtime.Unstructured) { + obj := shallowMapDeepCopy(u.UnstructuredContent()) + if metadata, ok := obj["metadata"]; ok { + if metadata, ok := metadata.(map[string]interface{}); ok { + obj["metadata"] = shallowMapDeepCopy(metadata) + u.SetUnstructuredContent(obj) + } + } +} + +func shallowMapDeepCopy(in map[string]interface{}) map[string]interface{} { + if in == nil { + return nil + } + + out := make(map[string]interface{}, len(in)) + for k, v := range in { + out[k] = v + } + + return out +} + // Categories implements the CategoriesProvider interface. Returns a list of categories a resource is part of. func (r *REST) Categories() []string { return r.categories diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go index 9a2c8320505..15a242e4493 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go @@ -21,12 +21,15 @@ import ( "reflect" "strings" "testing" + "time" autoscalingv1 "k8s.io/api/autoscaling/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" + metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion" 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/runtime/schema" "k8s.io/apimachinery/pkg/util/diff" @@ -72,8 +75,19 @@ func newStorage(t *testing.T) (customresource.CustomResourceStorage, *etcdtestin status := &apiextensions.CustomResourceSubresourceStatus{} - // TODO: identify how to pass printer specification from the CRD - table, _ := tableconvertor.New(nil) + headers := []apiextensions.CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"}, + {Name: "Replicas", Type: "integer", JSONPath: ".spec.replicas"}, + {Name: "Missing", Type: "string", JSONPath: ".spec.missing"}, + {Name: "Invalid", Type: "integer", JSONPath: ".spec.string"}, + {Name: "String", Type: "string", JSONPath: ".spec.string"}, + {Name: "StringFloat64", Type: "string", JSONPath: ".spec.float64"}, + {Name: "StringInt64", Type: "string", JSONPath: ".spec.replicas"}, + {Name: "StringBool", Type: "string", JSONPath: ".spec.bool"}, + {Name: "Float64", Type: "number", JSONPath: ".spec.float64"}, + {Name: "Bool", Type: "boolean", JSONPath: ".spec.bool"}, + } + table, _ := tableconvertor.New(headers) storage := customresource.NewStorage( schema.GroupResource{Group: "mygroup.example.com", Resource: "noxus"}, @@ -112,11 +126,18 @@ func validNewCustomResource() *unstructured.Unstructured { "apiVersion": "mygroup.example.com/v1beta1", "kind": "Noxu", "metadata": map[string]interface{}{ - "namespace": "default", - "name": "foo", + "namespace": "default", + "name": "foo", + "creationTimestamp": time.Now().Add(-time.Hour*12 - 30*time.Minute).UTC().Format(time.RFC3339), }, "spec": map[string]interface{}{ - "replicas": int64(7), + "replicas": int64(7), + "string": "string", + "float64": float64(3.1415926), + "bool": true, + "stringList": []interface{}{"foo", "bar"}, + "mixedList": []interface{}{"foo", int64(42)}, + "nonPrimitiveList": []interface{}{"foo", []interface{}{int64(1), int64(2)}}, }, }, } @@ -225,6 +246,77 @@ func TestCategories(t *testing.T) { } } +func TestColumns(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.CustomResource.Store.DestroyFunc() + + ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault) + key := "/noxus/" + metav1.NamespaceDefault + "/foo" + validCustomResource := validNewCustomResource() + if err := storage.CustomResource.Storage.Create(ctx, key, validCustomResource, nil, 0); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + gottenList, err := storage.CustomResource.List(ctx, &metainternal.ListOptions{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + tbl, err := storage.CustomResource.ConvertToTable(ctx, gottenList, &metav1beta1.TableOptions{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expectedColumns := []struct { + Name, Type string + }{ + {"Name", "string"}, + {"Age", "date"}, + {"Replicas", "integer"}, + {"Missing", "string"}, + {"Invalid", "integer"}, + {"String", "string"}, + {"StringFloat64", "string"}, + {"StringInt64", "string"}, + {"StringBool", "string"}, + {"Float64", "number"}, + {"Bool", "boolean"}, + } + if len(tbl.ColumnDefinitions) != len(expectedColumns) { + t.Fatalf("got %d columns, expected %d. Got: %+v", len(tbl.ColumnDefinitions), len(expectedColumns), tbl.ColumnDefinitions) + } + for i, d := range tbl.ColumnDefinitions { + if d.Name != expectedColumns[i].Name { + t.Errorf("got column %d name %q, expected %q", i, d.Name, expectedColumns[i].Name) + } + if d.Type != expectedColumns[i].Type { + t.Errorf("got column %d type %q, expected %q", i, d.Type, expectedColumns[i].Type) + } + } + + expectedRows := [][]interface{}{ + { + "foo", + "12h", + int64(7), + nil, + nil, + "string", + "3.1415926", + "7", + "true", + float64(3.1415926), + true, + }, + } + for i, r := range tbl.Rows { + if !reflect.DeepEqual(r.Cells, expectedRows[i]) { + t.Errorf("got row %d with cells %#v, expected %#v", i, r.Cells, expectedRows[i]) + } + } +} + func TestStatusUpdate(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/BUILD b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/BUILD index c9c5e70b772..9f8a352d3d9 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/BUILD +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/BUILD @@ -1,4 +1,4 @@ -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", @@ -6,7 +6,7 @@ go_library( importpath = "k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/go-openapi/spec:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta/table:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -30,3 +30,9 @@ filegroup( tags = ["automanaged"], visibility = ["//visibility:public"], ) + +go_test( + name = "go_default_test", + srcs = ["tableconvertor_test.go"], + embed = [":go_default_library"], +) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go index 8dbc0e77265..e1bed809d99 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go @@ -19,11 +19,11 @@ package tableconvertor import ( "bytes" "context" + "encoding/json" "fmt" - "strings" - - "github.com/go-openapi/spec" + "reflect" + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "k8s.io/apimachinery/pkg/api/meta" metatable "k8s.io/apimachinery/pkg/api/meta/table" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -33,56 +33,46 @@ import ( "k8s.io/client-go/util/jsonpath" ) -const printColumnsKey = "x-kubernetes-print-columns" - var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() -// New creates a new table convertor for the provided OpenAPI schema. If the printer definition cannot be parsed, +// New creates a new table convertor for the provided CRD column definition. If the printer definition cannot be parsed, // error will be returned along with a default table convertor. -func New(extensions spec.Extensions) (rest.TableConvertor, error) { +func New(crdColumns []apiextensions.CustomResourceColumnDefinition) (rest.TableConvertor, error) { headers := []metav1beta1.TableColumnDefinition{ {Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]}, - {Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"]}, } c := &convertor{ headers: headers, } - format, ok := extensions.GetString(printColumnsKey) - if !ok { - return c, nil - } - // "x-kubernetes-print-columns": "custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion" - parts := strings.SplitN(format, "=", 2) - if len(parts) != 2 || parts[0] != "custom-columns" { - return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns', only support 'custom-columns=NAME=JSONPATH[,NAME=JSONPATH]'") - } - columnSpecs := strings.Split(parts[1], ",") - var columns []*jsonpath.JSONPath - for _, spec := range columnSpecs { - parts := strings.SplitN(spec, ":", 2) - if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 { - return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns', must specify NAME=JSONPATH: %s", spec) - } - path := jsonpath.New(parts[0]) - if err := path.Parse(parts[1]); err != nil { - return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns': %v", spec) + + for _, col := range crdColumns { + path := jsonpath.New(col.Name) + if err := path.Parse(fmt.Sprintf("{%s}", col.JSONPath)); err != nil { + return c, fmt.Errorf("unrecognized column definition %q", col.JSONPath) } path.AllowMissingKeys(true) - columns = append(columns, path) - headers = append(headers, metav1beta1.TableColumnDefinition{ - Name: parts[0], - Type: "string", - Description: fmt.Sprintf("Custom resource definition column from OpenAPI (in JSONPath format): %s", parts[1]), + + desc := fmt.Sprintf("Custom resource definition column (in JSONPath format): %s", col.JSONPath) + if len(col.Description) > 0 { + desc = col.Description + } + + c.additionalColumns = append(c.additionalColumns, path) + c.headers = append(c.headers, metav1beta1.TableColumnDefinition{ + Name: col.Name, + Type: col.Type, + Format: col.Format, + Description: desc, + Priority: col.Priority, }) } - c.columns = columns - c.headers = headers + return c, nil } type convertor struct { - headers []metav1beta1.TableColumnDefinition - columns []*jsonpath.JSONPath + headers []metav1beta1.TableColumnDefinition + additionalColumns []*jsonpath.JSONPath } func (c *convertor) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { @@ -103,18 +93,80 @@ func (c *convertor) ConvertToTable(ctx context.Context, obj runtime.Object, tabl var err error buf := &bytes.Buffer{} table.Rows, err = metatable.MetaToTableRow(obj, func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error) { - cells := make([]interface{}, 2, 2+len(c.columns)) + cells := make([]interface{}, 1, 1+len(c.additionalColumns)) cells[0] = name - cells[1] = age - for _, column := range c.columns { - if err := column.Execute(buf, obj); err != nil { + customHeaders := c.headers[1:] + for i, column := range c.additionalColumns { + results, err := column.FindResults(obj.(runtime.Unstructured).UnstructuredContent()) + if err != nil || len(results) == 0 || len(results[0]) == 0 { cells = append(cells, nil) continue } - cells = append(cells, buf.String()) - buf.Reset() + + // as we only support simple JSON path, we can assume to have only one result (or none, filtered out above) + value := results[0][0].Interface() + if customHeaders[i].Type == "string" { + if err := column.PrintResults(buf, []reflect.Value{reflect.ValueOf(value)}); err == nil { + cells = append(cells, buf.String()) + buf.Reset() + } else { + cells = append(cells, nil) + } + } else { + cells = append(cells, cellForJSONValue(customHeaders[i].Type, value)) + } } return cells, nil }) return table, err } + +func cellForJSONValue(headerType string, value interface{}) interface{} { + if value == nil { + return nil + } + + switch headerType { + case "integer": + switch typed := value.(type) { + case int64: + return typed + case float64: + return int64(typed) + case json.Number: + if i64, err := typed.Int64(); err == nil { + return i64 + } + } + case "number": + switch typed := value.(type) { + case int64: + return float64(typed) + case float64: + return typed + case json.Number: + if f, err := typed.Float64(); err == nil { + return f + } + } + case "boolean": + if b, ok := value.(bool); ok { + return b + } + case "string": + if s, ok := value.(string); ok { + return s + } + case "date": + if typed, ok := value.(string); ok { + var timestamp metav1.Time + err := timestamp.UnmarshalQueryParameter(typed) + if err != nil { + return "" + } + return metatable.ConvertToHumanReadableDateType(timestamp) + } + } + + return nil +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go new file mode 100644 index 00000000000..179aabb8ab7 --- /dev/null +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_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 tableconvertor + +import ( + "fmt" + "reflect" + "testing" + "time" +) + +func Test_cellForJSONValue(t *testing.T) { + tests := []struct { + headerType string + value interface{} + want interface{} + }{ + {"integer", int64(42), int64(42)}, + {"integer", float64(3.14), int64(3)}, + {"integer", true, nil}, + {"integer", "foo", nil}, + + {"number", int64(42), float64(42)}, + {"number", float64(3.14), float64(3.14)}, + {"number", true, nil}, + {"number", "foo", nil}, + + {"boolean", int64(42), nil}, + {"boolean", float64(3.14), nil}, + {"boolean", true, true}, + {"boolean", "foo", nil}, + + {"string", int64(42), nil}, + {"string", float64(3.14), nil}, + {"string", true, nil}, + {"string", "foo", "foo"}, + + {"date", int64(42), nil}, + {"date", float64(3.14), nil}, + {"date", true, nil}, + {"date", time.Now().Add(-time.Hour*12 - 30*time.Minute).UTC().Format(time.RFC3339), "12h"}, + {"date", time.Now().Add(+time.Hour*12 + 30*time.Minute).UTC().Format(time.RFC3339), ""}, + {"date", "", ""}, + + {"unknown", "foo", nil}, + } + for _, tt := range tests { + t.Run(fmt.Sprintf("%#v of type %s", tt.value, tt.headerType), func(t *testing.T) { + if got := cellForJSONValue(tt.headerType, tt.value); !reflect.DeepEqual(got, tt.want) { + t.Errorf("cellForJSONValue() = %#v, want %#v", got, tt.want) + } + }) + } +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/BUILD b/staging/src/k8s.io/apiextensions-apiserver/test/integration/BUILD index 6c5adbefbb4..e2a418f158c 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/BUILD +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/BUILD @@ -11,8 +11,10 @@ go_test( srcs = [ "basic_test.go", "finalization_test.go", + "objectmeta_test.go", "registration_test.go", "subresources_test.go", + "table_test.go", "validation_test.go", "versioning_test.go", "yaml_test.go", @@ -21,6 +23,7 @@ go_test( tags = ["integration"], deps = [ "//vendor/github.com/coreos/etcd/clientv3:go_default_library", + "//vendor/github.com/coreos/etcd/pkg/transport:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/k8s.io/api/autoscaling/v1:go_default_library", @@ -32,12 +35,17 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go index 73585b42c42..a53c4ca94a2 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go @@ -226,7 +226,7 @@ func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta t.Fatal(err) } if e, a := createdObjectMeta.GetUID(), deletedObjectMeta.GetUID(); e != a { - t.Errorf("expected %v, got %v", e, a) + t.Errorf("expected equal UID for (expected) %v, and (actual) %v", createdNoxuInstance, watchEvent.Object) } case <-time.After(5 * time.Second): 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 new file mode 100644 index 00000000000..50f656bf120 --- /dev/null +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go @@ -0,0 +1,166 @@ +/* +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 integration + +import ( + "path" + "reflect" + "strings" + "testing" + + "github.com/coreos/etcd/clientv3" + "github.com/coreos/etcd/pkg/transport" + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + "k8s.io/apiextensions-apiserver/test/integration/testserver" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/json" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/client-go/dynamic" +) + +func TestPostInvalidObjectMeta(t *testing.T) { + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + noxuResourceClient := newNamespacedCustomResourceClient("default", dynamicClient, noxuDefinition) + + obj := testserver.NewNoxuInstance("default", "foo") + unstructured.SetNestedField(obj.UnstructuredContent(), int64(42), "metadata", "unknown") + unstructured.SetNestedField(obj.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "labels") + _, err = instantiateCustomResource(t, obj, noxuResourceClient, noxuDefinition) + if err == nil { + t.Fatalf("unexpected non-error, expected invalid labels to be rejected: %v", err) + } + if status, ok := err.(errors.APIStatus); !ok { + t.Fatalf("expected APIStatus error, but got: %#v", err) + } else if !errors.IsBadRequest(err) { + t.Fatalf("expected BadRequst error, but got: %v", errors.ReasonForError(err)) + } else if !strings.Contains(status.Status().Message, "cannot be handled") { + t.Fatalf("expected 'cannot be handled' error message, got: %v", status.Status().Message) + } + + unstructured.SetNestedField(obj.UnstructuredContent(), map[string]interface{}{"bar": "abc"}, "metadata", "labels") + obj, err = instantiateCustomResource(t, obj, noxuResourceClient, noxuDefinition) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if unknown, found, err := unstructured.NestedInt64(obj.UnstructuredContent(), "metadata", "unknown"); err != nil { + t.Errorf("unexpected error getting metadata.unknown: %v", err) + } else if found { + t.Errorf("unexpected metadata.unknown=%#v: expected this to be pruned", unknown) + } +} + +func TestInvalidObjectMetaInStorage(t *testing.T) { + serverConfig, err := testserver.DefaultServerConfig() + if err != nil { + t.Fatal(err) + } + + stopCh, config, err := testserver.StartServer(serverConfig) + defer close(stopCh) + if err != nil { + t.Fatal(err) + } + + apiExtensionClient, err := clientset.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + restOptions, err := serverConfig.GenericConfig.RESTOptionsGetter.GetRESTOptions(schema.GroupResource{Group: noxuDefinition.Spec.Group, Resource: noxuDefinition.Spec.Names.Plural}) + if err != nil { + t.Fatal(err) + } + tlsInfo := transport.TLSInfo{ + CertFile: restOptions.StorageConfig.CertFile, + KeyFile: restOptions.StorageConfig.KeyFile, + CAFile: restOptions.StorageConfig.CAFile, + } + tlsConfig, err := tlsInfo.ClientConfig() + if err != nil { + t.Fatal(err) + } + etcdConfig := clientv3.Config{ + Endpoints: restOptions.StorageConfig.ServerList, + TLS: tlsConfig, + } + etcdclient, err := clientv3.New(etcdConfig) + if err != nil { + t.Fatal(err) + } + + t.Logf("Creating object with invalid labels manually in etcd") + + original := testserver.NewNoxuInstance("default", "foo") + unstructured.SetNestedField(original.UnstructuredContent(), int64(42), "metadata", "unknown") + unstructured.SetNestedField(original.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "labels") + + ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault) + key := path.Join("/", restOptions.StorageConfig.Prefix, noxuDefinition.Spec.Group, "noxus/default/foo") + val, _ := json.Marshal(original.UnstructuredContent()) + if _, err := etcdclient.Put(ctx, key, string(val)); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + t.Logf("Checking that ObjectMeta is pruned from unknown fields") + + noxuResourceClient := newNamespacedCustomResourceClient("default", dynamicClient, noxuDefinition) + obj, err := noxuResourceClient.Get("foo", metav1.GetOptions{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if unknown, found, err := unstructured.NestedFieldNoCopy(obj.UnstructuredContent(), "metadata", "unknown"); err != nil { + t.Errorf("unexpected error: %v", err) + } else if found { + t.Errorf("unexpected to find metadata.unknown=%#v", unknown) + } + + t.Logf("Checking that ObjectMeta is pruned from invalid typed fields") + + if labels, found, err := unstructured.NestedStringMap(obj.UnstructuredContent(), "metadata", "labels"); err != nil { + t.Errorf("unexpected error: %v", err) + } else if found && !reflect.DeepEqual(labels, map[string]string{"bar": "abc"}) { + t.Errorf("unexpected to find metadata.lables=%#v", labels) + } +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go index da40416a338..bce63a4a5ab 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go @@ -359,9 +359,10 @@ func TestValidationSchema(t *testing.T) { }, }, }, - Required: []string{"spec"}, + Required: []string{"spec"}, + Description: "This is a description at the root of the schema", } - noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatalf("unable to created crd %v: %v", noxuDefinition.Name, err) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/table_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/table_test.go new file mode 100644 index 00000000000..0c3ac609a9c --- /dev/null +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/table_test.go @@ -0,0 +1,185 @@ +/* +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 integration + +import ( + "fmt" + "testing" + + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + 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/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/rest" + + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/test/integration/testserver" +) + +func newTableCRD() *apiextensionsv1beta1.CustomResourceDefinition { + return &apiextensionsv1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "tables.mygroup.example.com"}, + Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Version: "v1beta1", + Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Plural: "tables", + Singular: "table", + Kind: "Table", + ListKind: "TablemList", + }, + Scope: apiextensionsv1beta1.ClusterScoped, + AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"}, + {Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"}, + {Name: "Beta", Type: "integer", Description: "the beta field", Format: "int64", Priority: 42, JSONPath: ".spec.beta"}, + {Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values", JSONPath: ".spec.gamma"}, + }, + }, + } +} + +func newTableInstance(name string) *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "mygroup.example.com/v1beta1", + "kind": "Table", + "metadata": map[string]interface{}{ + "name": name, + }, + "spec": map[string]interface{}{ + "alpha": "foo_123", + "beta": 10, + "gamma": "bar", + "delta": "hello", + }, + }, + } +} + +func TestTableGet(t *testing.T) { + stopCh, config, err := testserver.StartDefaultServer() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + apiExtensionClient, err := clientset.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + crd := newTableCRD() + crd, err = testserver.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(crd.Name, metav1.GetOptions{}) + if err != nil { + t.Fatal(err) + } + t.Logf("table crd created: %#v", crd) + + crClient := newNamespacedCustomResourceClient("", dynamicClient, crd) + foo, err := crClient.Create(newTableInstance("foo")) + if err != nil { + t.Fatalf("unable to create noxu instance: %v", err) + } + t.Logf("foo created: %#v", foo.UnstructuredContent()) + + gv := schema.GroupVersion{Group: crd.Spec.Group, Version: crd.Spec.Version} + gvk := gv.WithKind(crd.Spec.Names.Kind) + + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + parameterCodec := runtime.NewParameterCodec(scheme) + metav1.AddToGroupVersion(scheme, gv) + scheme.AddKnownTypes(gv, &metav1beta1.Table{}, &metav1beta1.TableOptions{}) + scheme.AddKnownTypes(metav1beta1.SchemeGroupVersion, &metav1beta1.Table{}, &metav1beta1.TableOptions{}) + + crConfig := *config + crConfig.GroupVersion = &gv + crConfig.APIPath = "/apis" + crConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: codecs} + crRestClient, err := rest.RESTClientFor(&crConfig) + if err != nil { + t.Fatal(err) + } + + ret, err := crRestClient.Get(). + Resource(crd.Spec.Names.Plural). + SetHeader("Accept", fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", metav1beta1.SchemeGroupVersion.Version, metav1beta1.GroupName)). + VersionedParams(&metav1beta1.TableOptions{}, parameterCodec). + Do(). + Get() + if err != nil { + t.Fatalf("failed to list %v resources: %v", gvk, err) + } + + tbl, ok := ret.(*metav1beta1.Table) + if !ok { + t.Fatalf("expected metav1beta1.Table, got %T", ret) + } + t.Logf("%v table list: %#v", gvk, tbl) + + if got, expected := len(tbl.ColumnDefinitions), 5; got != expected { + t.Errorf("expected %d headers, got %d", expected, got) + } else { + alpha := metav1beta1.TableColumnDefinition{Name: "Alpha", Type: "string", Format: "", Description: "Custom resource definition column (in JSONPath format): .spec.alpha", Priority: 0} + if got, expected := tbl.ColumnDefinitions[2], alpha; got != expected { + t.Errorf("expected column definition %#v, got %#v", expected, got) + } + + beta := metav1beta1.TableColumnDefinition{Name: "Beta", Type: "integer", Format: "int64", Description: "the beta field", Priority: 42} + if got, expected := tbl.ColumnDefinitions[3], beta; got != expected { + t.Errorf("expected column definition %#v, got %#v", expected, got) + } + + gamma := metav1beta1.TableColumnDefinition{Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values"} + if got, expected := tbl.ColumnDefinitions[4], gamma; got != expected { + t.Errorf("expected column definition %#v, got %#v", expected, got) + } + } + if got, expected := len(tbl.Rows), 1; got != expected { + t.Errorf("expected %d rows, got %d", expected, got) + } else if got, expected := len(tbl.Rows[0].Cells), 5; got != expected { + t.Errorf("expected %d cells, got %d", expected, got) + } else { + if got, expected := tbl.Rows[0].Cells[0], "foo"; got != expected { + t.Errorf("expected cell[0] to equal %q, got %q", expected, got) + } + if got, expected := tbl.Rows[0].Cells[2], "foo_123"; got != expected { + t.Errorf("expected cell[2] to equal %q, got %q", expected, got) + } + if got, expected := tbl.Rows[0].Cells[3], int64(10); got != expected { + t.Errorf("expected cell[3] to equal %#v, got %#v", expected, got) + } + if got, expected := tbl.Rows[0].Cells[4], interface{}(nil); got != expected { + t.Errorf("expected cell[3] to equal %#v although the type does not match the column, got %#v", expected, got) + } + } +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/BUILD b/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/BUILD index 6ea1e1ec92b..3e55438bdc4 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/BUILD +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/BUILD @@ -19,7 +19,6 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go index b5c24fe1a12..f341b002f77 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go @@ -23,7 +23,6 @@ import ( apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" @@ -191,6 +190,35 @@ func NewCurletInstance(namespace, name string) *unstructured.Unstructured { } } +func servedVersions(crd *apiextensionsv1beta1.CustomResourceDefinition) []string { + if len(crd.Spec.Versions) == 0 { + return []string{crd.Spec.Version} + } + var versions []string + for _, v := range crd.Spec.Versions { + if v.Served { + versions = append(versions, v.Name) + } + } + return versions +} + +func existsInDiscovery(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface, version string) (bool, error) { + groupResource, err := apiExtensionsClient.Discovery().ServerResourcesForGroupVersion(crd.Spec.Group + "/" + version) + if err != nil { + if errors.IsNotFound(err) { + return false, nil + } + return false, err + } + for _, g := range groupResource.APIResources { + if g.Name == crd.Spec.Names.Plural { + return true, nil + } + } + return false, nil +} + // CreateNewCustomResourceDefinitionWatchUnsafe creates the CRD and makes sure // the apiextension apiserver has installed the CRD. But it's not safe to watch // the created CR. Please call CreateNewCustomResourceDefinition if you need to @@ -201,19 +229,15 @@ func CreateNewCustomResourceDefinitionWatchUnsafe(crd *apiextensionsv1beta1.Cust return nil, err } - // wait until the resource appears in discovery - err = wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { - resourceList, err := apiExtensionsClient.Discovery().ServerResourcesForGroupVersion(crd.Spec.Group + "/" + crd.Spec.Version) + // wait until all resources appears in discovery + for _, version := range servedVersions(crd) { + err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { + return existsInDiscovery(crd, apiExtensionsClient, version) + }) if err != nil { - return false, nil + return nil, err } - for _, resource := range resourceList.APIResources { - if resource.Name == crd.Spec.Names.Plural { - return true, nil - } - } - return false, nil - }) + } return crd, err } @@ -234,48 +258,35 @@ func CreateNewCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceD // For this test, we'll actually cycle, "list/watch/create/delete" until we get an RV from list that observes the create and not an error. // This way all the tests that are checking for watches don't have to worry about RV too old problems because crazy things *could* happen // before like the created RV could be too old to watch. - var primingErr error - wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { - primingErr = checkForWatchCachePrimed(crd, dynamicClientSet) - if primingErr == nil { - return true, nil + for _, version := range servedVersions(crd) { + err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { + return isWatchCachePrimed(crd, dynamicClientSet, version) + }) + if err != nil { + return nil, err } - return false, nil - }) - if primingErr != nil { - return nil, primingErr } - return crd, nil } -func checkForWatchCachePrimed(crd *apiextensionsv1beta1.CustomResourceDefinition, dynamicClientSet dynamic.Interface) error { +// isWatchCachePrimed returns true if the watch is primed for an specified version of CRD watch +func isWatchCachePrimed(crd *apiextensionsv1beta1.CustomResourceDefinition, dynamicClientSet dynamic.Interface, version string) (bool, error) { ns := "" if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped { ns = "aval" } - gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural} + gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: version, Resource: crd.Spec.Names.Plural} var resourceClient dynamic.ResourceInterface if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped { resourceClient = dynamicClientSet.Resource(gvr).Namespace(ns) } else { resourceClient = dynamicClientSet.Resource(gvr) } - - initialList, err := resourceClient.List(metav1.ListOptions{}) - if err != nil { - return err - } - initialListListMeta, err := meta.ListAccessor(initialList) - if err != nil { - return err - } - instanceName := "setup-instance" instance := &unstructured.Unstructured{ Object: map[string]interface{}{ - "apiVersion": crd.Spec.Group + "/" + crd.Spec.Version, + "apiVersion": crd.Spec.Group + "/" + version, "kind": crd.Spec.Names.Kind, "metadata": map[string]interface{}{ "namespace": ns, @@ -289,29 +300,32 @@ func checkForWatchCachePrimed(crd *apiextensionsv1beta1.CustomResourceDefinition "spec": map[string]interface{}{}, }, } - if _, err := resourceClient.Create(instance); err != nil { - return err - } - // we created something, clean it up - defer func() { - resourceClient.Delete(instanceName, nil) - }() - - noxuWatch, err := resourceClient.Watch(metav1.ListOptions{ResourceVersion: initialListListMeta.GetResourceVersion()}) + createdInstance, err := resourceClient.Create(instance) if err != nil { - return err + return false, err + } + err = resourceClient.Delete(createdInstance.GetName(), nil) + if err != nil { + return false, err + } + + noxuWatch, err := resourceClient.Watch(metav1.ListOptions{ResourceVersion: createdInstance.GetResourceVersion()}) + if err != nil { + return false, err } defer noxuWatch.Stop() select { case watchEvent := <-noxuWatch.ResultChan(): - if watch.Added == watchEvent.Type { - return nil + if watch.Error == watchEvent.Type { + return false, nil } - return fmt.Errorf("expected add, but got %#v", watchEvent) - + if watch.Deleted != watchEvent.Type { + return false, fmt.Errorf("expected DELETE, but got %#v", watchEvent) + } + return true, nil case <-time.After(5 * time.Second): - return fmt.Errorf("gave up waiting for watch event") + return false, fmt.Errorf("gave up waiting for watch event") } } @@ -319,23 +333,16 @@ func DeleteCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefi if err := apiExtensionsClient.Apiextensions().CustomResourceDefinitions().Delete(crd.Name, nil); err != nil { return err } - err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { - groupResource, err := apiExtensionsClient.Discovery().ServerResourcesForGroupVersion(crd.Spec.Group + "/" + crd.Spec.Version) + for _, version := range servedVersions(crd) { + err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { + exists, err := existsInDiscovery(crd, apiExtensionsClient, version) + return !exists, err + }) if err != nil { - if errors.IsNotFound(err) { - return true, nil - - } - return false, err + return err } - for _, g := range groupResource.APIResources { - if g.Name == crd.Spec.Names.Plural { - return false, nil - } - } - return true, nil - }) - return err + } + return nil } func CreateNewScaleClient(crd *apiextensionsv1beta1.CustomResourceDefinition, config *rest.Config) (scale.ScalesGetter, error) { diff --git a/staging/src/k8s.io/apimachinery/Godeps/Godeps.json b/staging/src/k8s.io/apimachinery/Godeps/Godeps.json index 2de98ffda14..3d8943ae9ee 100644 --- a/staging/src/k8s.io/apimachinery/Godeps/Godeps.json +++ b/staging/src/k8s.io/apimachinery/Godeps/Godeps.json @@ -48,23 +48,23 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/gofuzz", @@ -92,7 +92,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "2ddf6d758266fcb080a4f9e054b9f292c85e6798" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/modern-go/concurrent", @@ -180,7 +180,7 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" } ] } diff --git a/staging/src/k8s.io/apimachinery/SECURITY_CONTACTS b/staging/src/k8s.io/apimachinery/SECURITY_CONTACTS new file mode 100644 index 00000000000..0648a8ebff7 --- /dev/null +++ b/staging/src/k8s.io/apimachinery/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# 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/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/staging/src/k8s.io/apimachinery/pkg/api/meta/table/table.go b/staging/src/k8s.io/apimachinery/pkg/api/meta/table/table.go index a0097a4e26d..2144a77cb19 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/meta/table/table.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/meta/table/table.go @@ -53,7 +53,7 @@ func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1. row := metav1beta1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells, err = rowFn(obj, m, m.GetName(), translateTimestamp(m.GetCreationTimestamp())) + row.Cells, err = rowFn(obj, m, m.GetName(), ConvertToHumanReadableDateType(m.GetCreationTimestamp())) if err != nil { return nil, err } @@ -61,9 +61,9 @@ func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1. return rows, nil } -// translateTimestamp returns the elapsed time since timestamp in +// ConvertToHumanReadableDateType returns the elapsed time since timestamp in // human-readable approximation. -func translateTimestamp(timestamp metav1.Time) string { +func ConvertToHumanReadableDateType(timestamp metav1.Time) string { if timestamp.IsZero() { return "" } diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go index 3d49a5d5cf4..3a28f743118 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go @@ -181,16 +181,45 @@ func v1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} { j.Kind = "" }, func(j *metav1.ObjectMeta, c fuzz.Continue) { - j.Name = c.RandString() + c.FuzzNoCustom(j) + j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10) - j.SelfLink = c.RandString() j.UID = types.UID(c.RandString()) - j.GenerateName = c.RandString() var sec, nsec int64 c.Fuzz(&sec) c.Fuzz(&nsec) j.CreationTimestamp = metav1.Unix(sec, nsec).Rfc3339Copy() + + if j.DeletionTimestamp != nil { + c.Fuzz(&sec) + c.Fuzz(&nsec) + t := metav1.Unix(sec, nsec).Rfc3339Copy() + j.DeletionTimestamp = &t + } + + if len(j.Labels) == 0 { + j.Labels = nil + } else { + delete(j.Labels, "") + } + if len(j.Annotations) == 0 { + j.Annotations = nil + } else { + delete(j.Annotations, "") + } + if len(j.OwnerReferences) == 0 { + j.OwnerReferences = nil + } + if len(j.Finalizers) == 0 { + j.Finalizers = nil + } + }, + func(j *metav1.Initializers, c fuzz.Continue) { + c.FuzzNoCustom(j) + if len(j.Pending) == 0 { + j.Pending = nil + } }, func(j *metav1.ListMeta, c fuzz.Continue) { j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10) diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/BUILD b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/BUILD index 186db1871e4..b4f04f884f1 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/BUILD +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/BUILD @@ -21,9 +21,9 @@ go_test( embed = [":go_default_library"], deps = [ "//vendor/github.com/ghodss/yaml:go_default_library", - "//vendor/github.com/json-iterator/go:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", ], ) 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 1f7f07e81d0..ab62ff424cb 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 @@ -21,7 +21,7 @@ import ( "reflect" "testing" - jsoniter "github.com/json-iterator/go" + k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json" ) type GroupVersionHolder struct { @@ -47,7 +47,8 @@ func TestGroupVersionUnmarshalJSON(t *testing.T) { t.Errorf("JSON codec failed to unmarshal input '%s': expected %+v, got %+v", c.input, c.expect, result.GV) } // test the json-iterator codec - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(c.input, &result); err != nil { + iter := k8s_json.CaseSensitiveJsonIterator() + if err := iter.Unmarshal(c.input, &result); err != nil { t.Errorf("json-iterator codec failed to unmarshal input '%v': %v", c.input, err) } if !reflect.DeepEqual(result.GV, c.expect) { diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go index 116f7505a42..ed5f20c4057 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go @@ -21,7 +21,7 @@ import ( "reflect" "testing" - jsoniter "github.com/json-iterator/go" + k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json" ) func TestVerbsUgorjiMarshalJSON(t *testing.T) { @@ -45,7 +45,7 @@ func TestVerbsUgorjiMarshalJSON(t *testing.T) { } } -func TestVerbsUgorjiUnmarshalJSON(t *testing.T) { +func TestVerbsUJsonIterUnmarshalJSON(t *testing.T) { cases := []struct { input string result APIResource @@ -56,9 +56,10 @@ func TestVerbsUgorjiUnmarshalJSON(t *testing.T) { {`{"verbs":["delete"]}`, APIResource{Verbs: Verbs([]string{"delete"})}}, } + iter := k8s_json.CaseSensitiveJsonIterator() for i, c := range cases { var result APIResource - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(c.input), &result); err != nil { + if err := iter.Unmarshal([]byte(c.input), &result); err != nil { t.Errorf("[%d] Failed to unmarshal input '%v': %v", i, c.input, err) } if !reflect.DeepEqual(result, c.result) { diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go index 7b7c47d827d..344c533e13e 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go @@ -66,8 +66,8 @@ type TableColumnDefinition struct { // TableRow is an individual row in a table. // +protobuf=false type TableRow struct { - // cells will be as wide as headers and may contain strings, numbers, booleans, simple maps, or lists, or - // null. See the type field of the column definition for a more detailed description. + // cells will be as wide as headers and may contain strings, numbers (float64 or int64), booleans, simple + // maps, or lists, or null. See the type field of the column definition for a more detailed description. Cells []interface{} `json:"cells"` // conditions describe additional status of a row that are relevant for a human user. // +optional diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go index 235c2039d3e..7394535d9d9 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go @@ -80,7 +80,7 @@ func (TableOptions) SwaggerDoc() map[string]string { var map_TableRow = map[string]string{ "": "TableRow is an individual row in a table.", - "cells": "cells will be as wide as headers and may contain strings, numbers, booleans, simple maps, or lists, or null. See the type field of the column definition for a more detailed description.", + "cells": "cells will be as wide as headers and may contain strings, numbers (float64 or int64), booleans, simple maps, or lists, or null. See the type field of the column definition for a more detailed description.", "conditions": "conditions describe additional status of a row that are relevant for a human user.", "object": "This field contains the requested additional information about each object based on the includeObject policy when requesting the Table. If \"None\", this field is empty, if \"Object\" this will be the default serialization of the object for the current API version, and if \"Metadata\" (the default) will contain the object metadata. Check the returned kind and apiVersion of the object before parsing.", } diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go b/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go index cfe819e0a28..ba48e6146ed 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go @@ -174,13 +174,16 @@ type ObjectVersioner interface { // ObjectConvertor converts an object to a different version. type ObjectConvertor interface { - // Convert attempts to convert one object into another, or returns an error. This method does - // not guarantee the in object is not mutated. The context argument will be passed to - // all nested conversions. + // Convert attempts to convert one object into another, or returns an error. This + // method does not mutate the in object, but the in and out object might share data structures, + // i.e. the out object cannot be mutated without mutating the in object as well. + // The context argument will be passed to all nested conversions. Convert(in, out, context interface{}) error // ConvertToVersion takes the provided object and converts it the provided version. This - // method does not guarantee that the in object is not mutated. This method is similar to - // Convert() but handles specific details of choosing the correct output version. + // method does not mutate the in object, but the in and out object might share data structures, + // i.e. the out object cannot be mutated without mutating the in object as well. + // This method is similar to Convert() but handles specific details of choosing the correct + // output version. ConvertToVersion(in Object, gv GroupVersioner) (out Object, err error) ConvertFieldLabel(version, kind, label, value string) (string, string, error) } diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go index f7738d116cd..068d3f708e3 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go @@ -93,6 +93,20 @@ func init() { jsoniter.RegisterTypeDecoderFunc("interface {}", decodeNumberAsInt64IfPossible) } +// CaseSensitiveJsonIterator returns a jsoniterator API that's configured to be +// case-sensitive when unmarshalling, and otherwise compatible with +// the encoding/json standard library. +func CaseSensitiveJsonIterator() jsoniter.API { + return jsoniter.Config{ + EscapeHTML: true, + SortMapKeys: true, + ValidateJsonRawMessage: true, + CaseSensitive: true, + }.Froze() +} + +var caseSensitiveJsonIterator = CaseSensitiveJsonIterator() + // gvkWithDefaults returns group kind and version defaulting from provided default func gvkWithDefaults(actual, defaultGVK schema.GroupVersionKind) schema.GroupVersionKind { if len(actual.Kind) == 0 { @@ -157,7 +171,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i types, _, err := s.typer.ObjectKinds(into) switch { case runtime.IsNotRegisteredError(err), isUnstructured: - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(data, into); err != nil { + if err := caseSensitiveJsonIterator.Unmarshal(data, into); err != nil { return nil, actual, err } return into, actual, nil @@ -181,7 +195,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i return nil, actual, err } - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(data, obj); err != nil { + if err := caseSensitiveJsonIterator.Unmarshal(data, obj); err != nil { return nil, actual, err } return obj, actual, nil @@ -190,7 +204,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i // Encode serializes the provided object to the given writer. func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error { if s.yaml { - json, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(obj) + json, err := caseSensitiveJsonIterator.Marshal(obj) if err != nil { return err } @@ -203,7 +217,7 @@ func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error { } if s.pretty { - data, err := jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent(obj, "", " ") + data, err := caseSensitiveJsonIterator.MarshalIndent(obj, "", " ") if err != nil { return err } diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go index c8ae5550c52..b3d629a063c 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go @@ -30,10 +30,31 @@ import ( type testDecodable struct { Other string - Value int `json:"value"` + Value int `json:"value"` + Spec DecodableSpec `json:"spec"` gvk schema.GroupVersionKind } +// DecodableSpec has 15 fields. json-iterator treats struct with more than 10 +// fields differently from struct that has less than 10 fields. +type DecodableSpec struct { + A int `json:"A"` + B int `json:"B"` + C int `json:"C"` + D int `json:"D"` + E int `json:"E"` + F int `json:"F"` + G int `json:"G"` + H int `json:"h"` + I int `json:"i"` + J int `json:"j"` + K int `json:"k"` + L int `json:"l"` + M int `json:"m"` + N int `json:"n"` + O int `json:"o"` +} + func (d *testDecodable) GetObjectKind() schema.ObjectKind { return d } func (d *testDecodable) SetGroupVersionKind(gvk schema.GroupVersionKind) { d.gvk = gvk } func (d *testDecodable) GroupVersionKind() schema.GroupVersionKind { return d.gvk } @@ -221,6 +242,28 @@ func TestDecode(t *testing.T) { }, }, }, + // Unmarshalling is case-sensitive + { + // "VaLue" should have been "value" + data: []byte(`{"kind":"Test","apiVersion":"other/blah","VaLue":1,"Other":"test"}`), + into: &testDecodable{}, + typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})}, + expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, + expectedObject: &testDecodable{ + Other: "test", + }, + }, + // Unmarshalling is case-sensitive for big struct. + { + // "b" should have been "B", "I" should have been "i" + data: []byte(`{"kind":"Test","apiVersion":"other/blah","spec": {"A": 1, "b": 2, "h": 3, "I": 4}}`), + into: &testDecodable{}, + typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})}, + expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, + expectedObject: &testDecodable{ + Spec: DecodableSpec{A: 1, H: 3}, + }, + }, } for i, test := range testCases { 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 0997de8065d..a25e9246541 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/wait/wait.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/wait/wait.go @@ -284,12 +284,32 @@ func PollImmediateInfinite(interval time.Duration, condition ConditionFunc) erro // PollUntil tries a condition func until it returns true, an error or stopCh is // closed. // -// PolUntil always waits interval before the first run of 'condition'. +// PollUntil always waits interval before the first run of 'condition'. // 'condition' will always be invoked at least once. func PollUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error { return WaitFor(poller(interval, 0), condition, stopCh) } +// PollImmediateUntil tries a condition func until it returns true, an error or stopCh is closed. +// +// PollImmediateUntil runs the 'condition' before waiting for the interval. +// 'condition' will always be invoked at least once. +func PollImmediateUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error { + done, err := condition() + if err != nil { + return err + } + if done { + return nil + } + select { + case <-stopCh: + return ErrWaitTimeout + default: + return PollUntil(interval, condition, stopCh) + } +} + // WaitFunc creates a channel that receives an item every time a test // should be executed and is closed when the last test should be invoked. type WaitFunc func(done <-chan struct{}) <-chan struct{} diff --git a/staging/src/k8s.io/apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiserver/Godeps/Godeps.json index 0bdf0001024..1746ca31ad7 100644 --- a/staging/src/k8s.io/apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiserver/Godeps/Godeps.json @@ -412,35 +412,35 @@ }, { "ImportPath": "github.com/golang/protobuf/jsonpb", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/protoc-gen-go/descriptor", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/struct", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -504,7 +504,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "2ddf6d758266fcb080a4f9e054b9f292c85e6798" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/mailru/easyjson/buffer", @@ -1674,6 +1674,10 @@ "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" @@ -1738,6 +1742,10 @@ "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" @@ -1756,23 +1764,23 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/client-go/discovery", diff --git a/staging/src/k8s.io/apiserver/SECURITY_CONTACTS b/staging/src/k8s.io/apiserver/SECURITY_CONTACTS new file mode 100644 index 00000000000..0648a8ebff7 --- /dev/null +++ b/staging/src/k8s.io/apiserver/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# 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/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/staging/src/k8s.io/apiserver/pkg/admission/BUILD b/staging/src/k8s.io/apiserver/pkg/admission/BUILD index f409c9a3690..dd4f2564110 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/admission/BUILD @@ -9,6 +9,8 @@ load( go_test( name = "go_default_test", srcs = [ + "attributes_test.go", + "audit_test.go", "chain_test.go", "config_test.go", "errors_test.go", @@ -16,12 +18,15 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", ], ) @@ -29,6 +34,7 @@ go_library( name = "go_default_library", srcs = [ "attributes.go", + "audit.go", "chain.go", "config.go", "decorator.go", @@ -48,8 +54,11 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", + "//vendor/k8s.io/apiserver/pkg/audit:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/admission/attributes.go b/staging/src/k8s.io/apiserver/pkg/admission/attributes.go index 406235dd03c..7272e888bcf 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/attributes.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/attributes.go @@ -17,8 +17,13 @@ limitations under the License. package admission import ( + "fmt" + "strings" + "sync" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apiserver/pkg/authentication/user" ) @@ -32,6 +37,11 @@ type attributesRecord struct { object runtime.Object oldObject runtime.Object userInfo user.Info + + // other elements are always accessed in single goroutine. + // But ValidatingAdmissionWebhook add annotations concurrently. + annotations map[string]string + annotationsLock sync.RWMutex } func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind schema.GroupVersionKind, namespace, name string, resource schema.GroupVersionResource, subresource string, operation Operation, userInfo user.Info) Attributes { @@ -83,3 +93,48 @@ func (record *attributesRecord) GetOldObject() runtime.Object { func (record *attributesRecord) GetUserInfo() user.Info { return record.userInfo } + +// getAnnotations implements privateAnnotationsGetter.It's a private method used +// by WithAudit decorator. +func (record *attributesRecord) getAnnotations() map[string]string { + record.annotationsLock.RLock() + defer record.annotationsLock.RUnlock() + + if record.annotations == nil { + return nil + } + cp := make(map[string]string, len(record.annotations)) + for key, value := range record.annotations { + cp[key] = value + } + return cp +} + +func (record *attributesRecord) AddAnnotation(key, value string) error { + if err := checkKeyFormat(key); err != nil { + return err + } + + record.annotationsLock.Lock() + defer record.annotationsLock.Unlock() + + if record.annotations == nil { + record.annotations = make(map[string]string) + } + if v, ok := record.annotations[key]; ok && v != value { + return fmt.Errorf("admission annotations are not allowd to be overwritten, key:%q, old value: %q, new value:%q", key, record.annotations[key], value) + } + record.annotations[key] = value + return nil +} + +func checkKeyFormat(key string) error { + parts := strings.Split(key, "/") + if len(parts) != 2 { + return fmt.Errorf("annotation key has invalid format, the right format is a DNS subdomain prefix and '/' and key name. (e.g. 'podsecuritypolicy.admission.k8s.io/admit-policy')") + } + if msgs := validation.IsQualifiedName(key); len(msgs) != 0 { + return fmt.Errorf("annotation key has invalid format %s. A qualified name like 'podsecuritypolicy.admission.k8s.io/admit-policy' is required.", strings.Join(msgs, ",")) + } + return nil +} diff --git a/staging/src/k8s.io/apiserver/pkg/admission/attributes_test.go b/staging/src/k8s.io/apiserver/pkg/admission/attributes_test.go new file mode 100644 index 00000000000..d54780d9998 --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/admission/attributes_test.go @@ -0,0 +1,64 @@ +/* +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 admission + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAddAnnotation(t *testing.T) { + attr := &attributesRecord{} + + // test AddAnnotation + attr.AddAnnotation("podsecuritypolicy.admission.k8s.io/validate-policy", "privileged") + attr.AddAnnotation("podsecuritypolicy.admission.k8s.io/admit-policy", "privileged") + annotations := attr.getAnnotations() + assert.Equal(t, annotations["podsecuritypolicy.admission.k8s.io/validate-policy"], "privileged") + + // test overwrite + assert.Error(t, attr.AddAnnotation("podsecuritypolicy.admission.k8s.io/validate-policy", "privileged-overwrite"), + "admission annotations should not be allowd to be overwritten") + annotations = attr.getAnnotations() + assert.Equal(t, annotations["podsecuritypolicy.admission.k8s.io/validate-policy"], "privileged", "admission annotations should not be overwritten") + + // test invalid plugin names + var testCases map[string]string = map[string]string{ + "invalid dns subdomain": "INVALID-DNS-Subdomain/policy", + "no plugin name": "policy", + "no key name": "podsecuritypolicy.admission.k8s.io", + "empty key": "", + } + for name, invalidKey := range testCases { + err := attr.AddAnnotation(invalidKey, "value-foo") + assert.Error(t, err) + annotations = attr.getAnnotations() + assert.Equal(t, annotations[invalidKey], "", name+": invalid pluginName is not allowed ") + } + + // test all saved annotations + assert.Equal( + t, + annotations, + map[string]string{ + "podsecuritypolicy.admission.k8s.io/validate-policy": "privileged", + "podsecuritypolicy.admission.k8s.io/admit-policy": "privileged", + }, + "unexpected final annotations", + ) +} diff --git a/staging/src/k8s.io/apiserver/pkg/admission/audit.go b/staging/src/k8s.io/apiserver/pkg/admission/audit.go new file mode 100644 index 00000000000..13d86b33b96 --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/admission/audit.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 admission + +import ( + "fmt" + + auditinternal "k8s.io/apiserver/pkg/apis/audit" + "k8s.io/apiserver/pkg/audit" +) + +// auditHandler logs annotations set by other admission handlers +type auditHandler struct { + Interface + ae *auditinternal.Event +} + +var _ Interface = &auditHandler{} +var _ MutationInterface = &auditHandler{} +var _ ValidationInterface = &auditHandler{} + +// WithAudit is a decorator for a admission phase. It saves annotations +// of attribute into the audit event. Attributes passed to the Admit and +// Validate function must be instance of privateAnnotationsGetter or +// AnnotationsGetter, otherwise an error is returned. +func WithAudit(i Interface, ae *auditinternal.Event) Interface { + if i == nil { + return i + } + return &auditHandler{i, ae} +} + +func (handler auditHandler) Admit(a Attributes) error { + if !handler.Interface.Handles(a.GetOperation()) { + return nil + } + if err := ensureAnnotationGetter(a); err != nil { + return err + } + var err error + if mutator, ok := handler.Interface.(MutationInterface); ok { + err = mutator.Admit(a) + handler.logAnnotations(a) + } + return err +} + +func (handler auditHandler) Validate(a Attributes) error { + if !handler.Interface.Handles(a.GetOperation()) { + return nil + } + if err := ensureAnnotationGetter(a); err != nil { + return err + } + var err error + if validator, ok := handler.Interface.(ValidationInterface); ok { + err = validator.Validate(a) + handler.logAnnotations(a) + } + return err +} + +func ensureAnnotationGetter(a Attributes) error { + _, okPrivate := a.(privateAnnotationsGetter) + _, okPublic := a.(AnnotationsGetter) + if okPrivate || okPublic { + return nil + } + return fmt.Errorf("attributes must be an instance of privateAnnotationsGetter or AnnotationsGetter") +} + +func (handler auditHandler) logAnnotations(a Attributes) { + switch a := a.(type) { + case privateAnnotationsGetter: + audit.LogAnnotations(handler.ae, a.getAnnotations()) + case AnnotationsGetter: + audit.LogAnnotations(handler.ae, a.GetAnnotations()) + default: + // this will never happen, because we have already checked it in ensureAnnotationGetter + } +} diff --git a/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go b/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go new file mode 100644 index 00000000000..31f3b5881cf --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go @@ -0,0 +1,173 @@ +/* +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 admission + +import ( + "fmt" + "testing" + + "k8s.io/apimachinery/pkg/runtime/schema" + auditinternal "k8s.io/apiserver/pkg/apis/audit" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// fakeHandler implements Interface +type fakeHandler struct { + // return value of Admit() + admit error + // annotations add to attributesRecord during Admit() phase + admitAnnotations map[string]string + // return value of Validate() + validate error + // annotations add to attributesRecord during Validate() phase + validateAnnotations map[string]string + // return value of Handles() + handles bool +} + +var _ Interface = &fakeHandler{} +var _ MutationInterface = &fakeHandler{} +var _ ValidationInterface = &fakeHandler{} + +func (h fakeHandler) Admit(a Attributes) error { + for k, v := range h.admitAnnotations { + a.AddAnnotation(k, v) + } + return h.admit +} + +func (h fakeHandler) Validate(a Attributes) error { + for k, v := range h.validateAnnotations { + a.AddAnnotation(k, v) + } + return h.validate +} + +func (h fakeHandler) Handles(o Operation) bool { + return h.handles +} + +func attributes() Attributes { + return NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", "", nil) +} + +func TestWithAudit(t *testing.T) { + var testCases = map[string]struct { + admit error + admitAnnotations map[string]string + validate error + validateAnnotations map[string]string + handles bool + }{ + "not handle": { + nil, + nil, + nil, + nil, + false, + }, + "allow": { + nil, + nil, + nil, + nil, + true, + }, + "allow with annotations": { + nil, + map[string]string{ + "plugin.example.com/foo": "bar", + }, + nil, + nil, + true, + }, + "allow with annotations overwrite": { + nil, + map[string]string{ + "plugin.example.com/foo": "bar", + }, + nil, + map[string]string{ + "plugin.example.com/foo": "bar", + }, + true, + }, + "forbidden error": { + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + nil, + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + nil, + true, + }, + "forbidden error with annotations": { + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + nil, + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + map[string]string{ + "plugin.example.com/foo": "bar", + }, + true, + }, + "forbidden error with annotations overwrite": { + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + map[string]string{ + "plugin.example.com/foo": "bar", + }, + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + map[string]string{ + "plugin.example.com/foo": "bar", + }, + true, + }, + } + for tcName, tc := range testCases { + var handler Interface = fakeHandler{tc.admit, tc.admitAnnotations, tc.validate, tc.validateAnnotations, tc.handles} + ae := &auditinternal.Event{Level: auditinternal.LevelMetadata} + auditHandler := WithAudit(handler, ae) + a := attributes() + + assert.Equal(t, handler.Handles(Create), auditHandler.Handles(Create), tcName+": WithAudit decorator should not effect the return value") + + mutator, ok := handler.(MutationInterface) + require.True(t, ok) + auditMutator, ok := auditHandler.(MutationInterface) + require.True(t, ok) + assert.Equal(t, mutator.Admit(a), auditMutator.Admit(a), tcName+": WithAudit decorator should not effect the return value") + + validator, ok := handler.(ValidationInterface) + require.True(t, ok) + auditValidator, ok := auditHandler.(ValidationInterface) + require.True(t, ok) + assert.Equal(t, validator.Validate(a), auditValidator.Validate(a), tcName+": WithAudit decorator should not effect the return value") + + annotations := make(map[string]string, len(tc.admitAnnotations)+len(tc.validateAnnotations)) + for k, v := range tc.admitAnnotations { + annotations[k] = v + } + for k, v := range tc.validateAnnotations { + annotations[k] = v + } + if len(annotations) == 0 { + assert.Nil(t, ae.Annotations, tcName+": unexptected annotations set in audit event") + } else { + assert.Equal(t, annotations, ae.Annotations, tcName+": unexptected annotations set in audit event") + } + } +} diff --git a/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go b/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go index 76d3864e275..68ef558da4c 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go @@ -49,6 +49,23 @@ type Attributes interface { GetKind() schema.GroupVersionKind // GetUserInfo is information about the requesting user GetUserInfo() user.Info + + // AddAnnotation sets annotation according to key-value pair. The key should be qualified, e.g., podsecuritypolicy.admission.k8s.io/admit-policy, where + // "podsecuritypolicy" is the name of the plugin, "admission.k8s.io" is the name of the organization, "admit-policy" is the key name. + // An error is returned if the format of key is invalid. When trying to overwrite annotation with a new value, an error is returned. + // Both ValidationInterface and MutationInterface are allowed to add Annotations. + AddAnnotation(key, value string) error +} + +// privateAnnotationsGetter is a private interface which allows users to get annotations from Attributes. +type privateAnnotationsGetter interface { + getAnnotations() map[string]string +} + +// AnnotationsGetter allows users to get annotations from Attributes. An alternate Attribute should implement +// this interface. +type AnnotationsGetter interface { + GetAnnotations() map[string]string } // Interface is an abstract, pluggable interface for Admission Control decisions. diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD index 96cf3fcba0b..460ecab2ae5 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD @@ -15,6 +15,7 @@ go_library( "//vendor/k8s.io/api/admission/v1beta1:go_default_library", "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go index d10f1935cd8..adfe9f37f3e 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go @@ -29,6 +29,7 @@ import ( admissionv1beta1 "k8s.io/api/admission/v1beta1" "k8s.io/api/admissionregistration/v1beta1" apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" admissionmetrics "k8s.io/apiserver/pkg/admission/metrics" @@ -113,11 +114,24 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta if err != nil { return apierrors.NewInternalError(err) } + + var newVersionedObject runtime.Object + if _, ok := attr.VersionedObject.(*unstructured.Unstructured); ok { + // Custom Resources don't have corresponding Go struct's. + // They are represented as Unstructured. + newVersionedObject = &unstructured.Unstructured{} + } else { + newVersionedObject, err = a.plugin.scheme.New(attr.GetKind()) + if err != nil { + return apierrors.NewInternalError(err) + } + } // TODO: if we have multiple mutating webhooks, we can remember the json // instead of encoding and decoding for each one. - if _, _, err := a.plugin.jsonSerializer.Decode(patchedJS, nil, attr.VersionedObject); err != nil { + if _, _, err := a.plugin.jsonSerializer.Decode(patchedJS, nil, newVersionedObject); err != nil { return apierrors.NewInternalError(err) } + attr.VersionedObject = newVersionedObject a.plugin.scheme.Default(attr.VersionedObject) return nil } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go index 82c4e397271..b60a62f3bd9 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go @@ -18,13 +18,16 @@ package mutating import ( "net/url" + "reflect" "strings" "testing" "k8s.io/api/admission/v1beta1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/admission" webhooktesting "k8s.io/apiserver/pkg/admission/plugin/webhook/testing" ) @@ -69,10 +72,22 @@ func TestAdmit(t *testing.T) { continue } - err = wh.Admit(webhooktesting.NewAttribute(ns)) + var attr admission.Attributes + if tt.IsCRD { + attr = webhooktesting.NewAttributeUnstructured(ns, tt.AdditionalLabels) + } else { + attr = webhooktesting.NewAttribute(ns, tt.AdditionalLabels) + } + + err = wh.Admit(attr) if tt.ExpectAllow != (err == nil) { t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) } + if tt.ExpectLabels != nil { + if !reflect.DeepEqual(tt.ExpectLabels, attr.GetObject().(metav1.Object).GetLabels()) { + t.Errorf("%s: expected labels '%v', but got '%v'", tt.Name, tt.ExpectLabels, attr.GetObject().(metav1.Object).GetLabels()) + } + } // ErrWebhookRejected is not an error for our purposes if tt.ErrorContains != "" { if err == nil || !strings.Contains(err.Error(), tt.ErrorContains) { @@ -127,7 +142,7 @@ func TestAdmitCachedClient(t *testing.T) { continue } - err = wh.Admit(webhooktesting.NewAttribute(ns)) + err = wh.Admit(webhooktesting.NewAttribute(ns, nil)) if tt.ExpectAllow != (err == nil) { t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/BUILD b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/BUILD index 46650326fea..fcb3ce0967c 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/BUILD @@ -15,7 +15,9 @@ go_library( "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go index eb74a58f247..96d696788ad 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go @@ -22,7 +22,9 @@ import ( registrationv1beta1 "k8s.io/api/admissionregistration/v1beta1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts" "k8s.io/apiserver/pkg/authentication/user" @@ -74,36 +76,57 @@ func NewFakeDataSource(name string, webhooks []registrationv1beta1.Webhook, muta return client, informerFactory } -// NewAttribute returns static admission Attributes for testing. -func NewAttribute(namespace string) admission.Attributes { - // Set up a test object for the call - kind := corev1.SchemeGroupVersion.WithKind("Pod") - name := "my-pod" - object := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "pod.name": name, - }, - Name: name, - Namespace: namespace, - }, - TypeMeta: metav1.TypeMeta{ - APIVersion: "v1", - Kind: "Pod", - }, +func newAttributesRecord(object metav1.Object, oldObject metav1.Object, kind schema.GroupVersionKind, namespace string, name string, resource string, labels map[string]string) admission.Attributes { + object.SetName(name) + object.SetNamespace(namespace) + objectLabels := map[string]string{resource + ".name": name} + for k, v := range labels { + objectLabels[k] = v } - oldObject := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace}, - } - operation := admission.Update - resource := corev1.Resource("pods").WithVersion("v1") + object.SetLabels(objectLabels) + + oldObject.SetName(name) + oldObject.SetNamespace(namespace) + + gvr := kind.GroupVersion().WithResource(resource) subResource := "" userInfo := user.DefaultInfo{ Name: "webhook-test", UID: "webhook-test", } - return admission.NewAttributesRecord(&object, &oldObject, kind, namespace, name, resource, subResource, operation, &userInfo) + return admission.NewAttributesRecord(object.(runtime.Object), oldObject.(runtime.Object), kind, namespace, name, gvr, subResource, admission.Update, &userInfo) +} + +// NewAttribute returns static admission Attributes for testing. +func NewAttribute(namespace string, labels map[string]string) admission.Attributes { + // Set up a test object for the call + object := corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Pod", + }, + } + oldObject := corev1.Pod{} + kind := corev1.SchemeGroupVersion.WithKind("Pod") + name := "my-pod" + + return newAttributesRecord(&object, &oldObject, kind, namespace, name, "pod", labels) +} + +// NewAttributeUnstructured returns static admission Attributes for testing with custom resources. +func NewAttributeUnstructured(namespace string, labels map[string]string) admission.Attributes { + // Set up a test object for the call + object := unstructured.Unstructured{} + object.SetKind("TestCRD") + object.SetAPIVersion("custom.resource/v1") + oldObject := unstructured.Unstructured{} + oldObject.SetKind("TestCRD") + oldObject.SetAPIVersion("custom.resource/v1") + kind := object.GroupVersionKind() + name := "my-test-crd" + + return newAttributesRecord(&object, &oldObject, kind, namespace, name, "crd", labels) } type urlConfigGenerator struct { @@ -122,11 +145,14 @@ func (c urlConfigGenerator) ccfgURL(urlPath string) registrationv1beta1.WebhookC // Test is a webhook test case. type Test struct { - Name string - Webhooks []registrationv1beta1.Webhook - Path string - ExpectAllow bool - ErrorContains string + Name string + Webhooks []registrationv1beta1.Webhook + Path string + IsCRD bool + AdditionalLabels map[string]string + ExpectLabels map[string]string + ExpectAllow bool + ErrorContains string } // NewTestCases returns test cases with a given base url. @@ -158,6 +184,64 @@ func NewTestCases(url *url.URL) []Test { }}, ExpectAllow: true, }, + { + Name: "match & remove label", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "removeLabel", + ClientConfig: ccfgSVC("removeLabel"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ExpectAllow: true, + AdditionalLabels: map[string]string{"remove": "me"}, + ExpectLabels: map[string]string{"pod.name": "my-pod"}, + }, + { + Name: "match & add label", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "addLabel", + ClientConfig: ccfgSVC("addLabel"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ExpectAllow: true, + ExpectLabels: map[string]string{"pod.name": "my-pod", "added": "test"}, + }, + { + Name: "match CRD & add label", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "addLabel", + ClientConfig: ccfgSVC("addLabel"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + IsCRD: true, + ExpectAllow: true, + ExpectLabels: map[string]string{"crd.name": "my-test-crd", "added": "test"}, + }, + { + Name: "match CRD & remove label", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "removeLabel", + ClientConfig: ccfgSVC("removeLabel"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + IsCRD: true, + ExpectAllow: true, + AdditionalLabels: map[string]string{"remove": "me"}, + ExpectLabels: map[string]string{"crd.name": "my-test-crd"}, + }, + { + Name: "match & invalid mutation", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "invalidMutation", + ClientConfig: ccfgSVC("invalidMutation"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ErrorContains: "invalid character", + }, { Name: "match & disallow", Webhooks: []registrationv1beta1.Webhook{{ diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/webhook_server.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/webhook_server.go index 1736b467312..a8bb1ac823c 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/webhook_server.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/webhook_server.go @@ -85,6 +85,36 @@ func webhookHandler(w http.ResponseWriter, r *http.Request) { Allowed: true, }, }) + case "/removeLabel": + w.Header().Set("Content-Type", "application/json") + pt := v1beta1.PatchTypeJSONPatch + json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ + Response: &v1beta1.AdmissionResponse{ + Allowed: true, + PatchType: &pt, + Patch: []byte(`[{"op": "remove", "path": "/metadata/labels/remove"}]`), + }, + }) + case "/addLabel": + w.Header().Set("Content-Type", "application/json") + pt := v1beta1.PatchTypeJSONPatch + json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ + Response: &v1beta1.AdmissionResponse{ + Allowed: true, + PatchType: &pt, + Patch: []byte(`[{"op": "add", "path": "/metadata/labels/added", "value": "test"}]`), + }, + }) + case "/invalidMutation": + w.Header().Set("Content-Type", "application/json") + pt := v1beta1.PatchTypeJSONPatch + json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ + Response: &v1beta1.AdmissionResponse{ + Allowed: true, + PatchType: &pt, + Patch: []byte(`[{"op": "add", "CORRUPTED_KEY":}]`), + }, + }) case "/nilResponse": w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{}) diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go index 65832d0a239..1cc031c577b 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go @@ -75,7 +75,7 @@ func TestValidate(t *testing.T) { continue } - err = wh.Validate(webhooktesting.NewAttribute(ns)) + err = wh.Validate(webhooktesting.NewAttribute(ns, nil)) if tt.ExpectAllow != (err == nil) { t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) } @@ -133,7 +133,7 @@ func TestValidateCachedClient(t *testing.T) { continue } - err = wh.Validate(webhooktesting.NewAttribute(ns)) + err = wh.Validate(webhooktesting.NewAttribute(ns, nil)) if tt.ExpectAllow != (err == nil) { t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) } 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 8fe5a1cbb78..54276007826 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go @@ -97,6 +97,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, admit admission.Inte trace.Step("Conversion done") ae := request.AuditEventFrom(ctx) + admit = admission.WithAudit(admit, ae) audit.LogRequestObject(ae, obj, scope.Resource, scope.Subresource, scope.Serializer) userInfo, _ := request.UserFrom(ctx) 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 9da5d43e1b7..03576d72a61 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go @@ -56,6 +56,8 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco } ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) + ae := request.AuditEventFrom(ctx) + admit = admission.WithAudit(admit, ae) options := &metav1.DeleteOptions{} if allowsOptions { @@ -188,6 +190,8 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) + ae := request.AuditEventFrom(ctx) + admit = admission.WithAudit(admit, ae) if admit != nil && admit.Handles(admission.Delete) { userInfo, _ := request.UserFrom(ctx) 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 e94d453204b..0801dcef636 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go @@ -89,6 +89,8 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface } ae := request.AuditEventFrom(ctx) + admit = admission.WithAudit(admit, ae) + audit.LogRequestPatch(ae, patchJS) trace.Step("Recorded the audit event") 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 e37a8ea4786..99673077b2b 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 @@ -61,7 +61,7 @@ func ErrorToAPIStatus(err error) *metav1.Status { // by REST storage - these typically indicate programmer // error by not using pkg/api/errors, or unexpected failure // cases. - runtime.HandleError(fmt.Errorf("apiserver received an error that is not an metav1.Status: %v", err)) + runtime.HandleError(fmt.Errorf("apiserver received an error that is not an metav1.Status: %#+v", err)) return &metav1.Status{ TypeMeta: metav1.TypeMeta{ Kind: "Status", 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 942e53483ff..d42c0194dd6 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go @@ -103,6 +103,9 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi } ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) + ae := request.AuditEventFrom(ctx) + admit = admission.WithAudit(admit, ae) + opts, subpath, subpathKey := connecter.NewConnectOptions() if err := getRequestOptions(req, scope, opts, subpath, subpathKey, isSubresource); err != nil { err = errors.NewBadRequest(err.Error()) 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 4b10cf12bd8..de242771db9 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go @@ -86,6 +86,7 @@ func UpdateResource(r rest.Updater, scope RequestScope, admit admission.Interfac ae := request.AuditEventFrom(ctx) audit.LogRequestObject(ae, obj, scope.Resource, scope.Subresource, scope.Serializer) + admit = admission.WithAudit(admit, ae) if err := checkName(obj, name, namespace, scope.Namer); err != nil { scope.err(err, w, req) diff --git a/staging/src/k8s.io/apiserver/pkg/registry/rest/resttest/resttest.go b/staging/src/k8s.io/apiserver/pkg/registry/rest/resttest/resttest.go index 64d792a607a..647b9401b1e 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/rest/resttest/resttest.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/rest/resttest/resttest.go @@ -1320,7 +1320,7 @@ func (t *Tester) testListTableConversion(obj runtime.Object, assignFn AssignFunc t.Errorf("column %d has no name", j) } switch column.Type { - case "string", "date", "integer": + case "string", "date", "integer", "number", "boolean": default: t.Errorf("column %d has unexpected type: %q", j, column.Type) } @@ -1342,13 +1342,14 @@ func (t *Tester) testListTableConversion(obj runtime.Object, assignFn AssignFunc } for i, row := range table.Rows { if len(row.Cells) != len(table.ColumnDefinitions) { - t.Errorf("row %d did not have the correct number of cells: %d in %v", i, len(table.ColumnDefinitions), row.Cells) + t.Errorf("row %d did not have the correct number of cells: %d in %v, expected %d", i, len(row.Cells), row.Cells, len(table.ColumnDefinitions)) } for j, cell := range row.Cells { // do not add to this test without discussion - may break clients switch cell.(type) { case float64, int64, int32, int, string, bool: case []interface{}: + case nil: default: t.Errorf("row %d, cell %d has an unrecognized type, only JSON serialization safe types are allowed: %T ", i, j, cell) } diff --git a/staging/src/k8s.io/apiserver/pkg/server/config.go b/staging/src/k8s.io/apiserver/pkg/server/config.go index 75a2b5dcc56..41ae90af689 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/config.go +++ b/staging/src/k8s.io/apiserver/pkg/server/config.go @@ -65,6 +65,7 @@ import ( openapicommon "k8s.io/kube-openapi/pkg/common" // install apis + "github.com/golang/glog" _ "k8s.io/apiserver/pkg/apis/apiserver/install" ) @@ -574,6 +575,16 @@ func installAPI(s *GenericAPIServer, c *Config) { if c.EnableContentionProfiling { goruntime.SetBlockProfileRate(1) } + // so far, only logging related endpoints are considered valid to add for these debug flags. + routes.DebugFlags{}.Install(s.Handler.NonGoRestfulMux, "v", routes.StringFlagPutHandler( + routes.StringFlagSetterFunc(func(val string) (string, error) { + var level glog.Level + if err := level.Set(val); err != nil { + return "", fmt.Errorf("failed set glog.logging.verbosity %s: %v", val, err) + } + return "successfully set glog.logging.verbosity to " + val, nil + }), + )) } if c.EnableMetrics { if c.EnableProfiling { @@ -582,6 +593,7 @@ func installAPI(s *GenericAPIServer, c *Config) { routes.DefaultMetrics{}.Install(s.Handler.NonGoRestfulMux) } } + routes.Version{Version: c.Version}.Install(s.Handler.GoRestfulContainer) if c.EnableDiscovery { diff --git a/staging/src/k8s.io/apiserver/pkg/server/config_selfclient.go b/staging/src/k8s.io/apiserver/pkg/server/config_selfclient.go index bf09161c9fc..eb11dc701b2 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/config_selfclient.go +++ b/staging/src/k8s.io/apiserver/pkg/server/config_selfclient.go @@ -63,6 +63,8 @@ func LoopbackHostPort(bindAddress string) (string, string, error) { return "", "", fmt.Errorf("invalid server bind address: %q", bindAddress) } + isIPv6 := net.ParseIP(host).To4() == nil + // Value is expected to be an IP or DNS name, not "0.0.0.0". if host == "0.0.0.0" || host == "::" { host = "localhost" @@ -72,7 +74,7 @@ func LoopbackHostPort(bindAddress string) (string, string, error) { addrs, err := net.InterfaceAddrs() if err == nil { for _, address := range addrs { - if ipnet, ok := address.(*net.IPNet); ok && ipnet.IP.IsLoopback() { + if ipnet, ok := address.(*net.IPNet); ok && ipnet.IP.IsLoopback() && isIPv6 == (ipnet.IP.To4() == nil) { host = ipnet.IP.String() break } diff --git a/staging/src/k8s.io/apiserver/pkg/server/config_selfclient_test.go b/staging/src/k8s.io/apiserver/pkg/server/config_selfclient_test.go index fcf126b232b..9374403ff9d 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/config_selfclient_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/config_selfclient_test.go @@ -59,9 +59,10 @@ func TestLoopbackHostPort(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if ip := net.ParseIP(host); ip == nil || !ip.IsLoopback() { - t.Fatalf("expected host to be loopback, got %q", host) + if ip := net.ParseIP(host); ip == nil || !ip.IsLoopback() || ip.To4() != nil { + t.Fatalf("expected IPv6 host to be loopback, got %q", host) } + if port != "443" { t.Fatalf("expected 443 as port, got %q", port) } 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 56905c36277..78700c33a88 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go +++ b/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go @@ -167,7 +167,7 @@ func WithMaxInFlightLimit( metrics.DroppedRequests.WithLabelValues(metrics.ReadOnlyKind).Inc() } // at this point we're about to return a 429, BUT not all actors should be rate limited. A system:master is so powerful - // that he should always get an answer. It's a super-admin or a loopback connection. + // that they should always get an answer. It's a super-admin or a loopback connection. if currUser, ok := apirequest.UserFrom(ctx); ok { for _, group := range currUser.GetGroups() { if group == user.SystemPrivilegedGroup { diff --git a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go index 8439d8cf75a..00a9f87fe3e 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go @@ -423,6 +423,7 @@ func TestNotRestRoutesHaveAuth(t *testing.T) { {"/"}, {"/swagger-ui/"}, {"/debug/pprof/"}, + {"/debug/flags/"}, {"/version"}, } { resp := httptest.NewRecorder() diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/serving.go b/staging/src/k8s.io/apiserver/pkg/server/options/serving.go index 27536571382..5d21da26179 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/serving.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/serving.go @@ -22,6 +22,7 @@ import ( "net" "path" "strconv" + "strings" "github.com/golang/glog" "github.com/spf13/pflag" @@ -134,14 +135,16 @@ func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&s.ServerCert.CertKey.KeyFile, "tls-private-key-file", s.ServerCert.CertKey.KeyFile, "File containing the default x509 private key matching --tls-cert-file.") + tlsCipherPossibleValues := utilflag.TLSCipherPossibleValues() fs.StringSliceVar(&s.CipherSuites, "tls-cipher-suites", s.CipherSuites, "Comma-separated list of cipher suites for the server. "+ - "Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). "+ - "If omitted, the default Go cipher suites will be used") + "If omitted, the default Go cipher suites will be use. "+ + "Possible values: "+strings.Join(tlsCipherPossibleValues, ",")) + tlsPossibleVersions := utilflag.TLSPossibleVersions() fs.StringVar(&s.MinTLSVersion, "tls-min-version", s.MinTLSVersion, "Minimum TLS version supported. "+ - "Value must match version names from https://golang.org/pkg/crypto/tls/#pkg-constants.") + "Possible values: "+strings.Join(tlsPossibleVersions, ", ")) fs.Var(utilflag.NewNamedCertKeyArray(&s.SNICertKeys), "tls-sni-cert-key", ""+ "A pair of x509 certificate and private key file paths, optionally suffixed with a list of "+ diff --git a/staging/src/k8s.io/apiserver/pkg/server/routes/BUILD b/staging/src/k8s.io/apiserver/pkg/server/routes/BUILD index e7ffd916bfd..9dd38395648 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/routes/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/server/routes/BUILD @@ -9,6 +9,7 @@ go_library( name = "go_default_library", srcs = [ "doc.go", + "flags.go", "index.go", "metrics.go", "openapi.go", diff --git a/staging/src/k8s.io/apiserver/pkg/server/routes/flags.go b/staging/src/k8s.io/apiserver/pkg/server/routes/flags.go new file mode 100644 index 00000000000..d40f11499b3 --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/server/routes/flags.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 routes + +import ( + "fmt" + "html/template" + "io/ioutil" + "net/http" + "path" + "sync" + + "github.com/golang/glog" + + "k8s.io/apiserver/pkg/server/mux" +) + +var ( + lock = &sync.RWMutex{} + registeredFlags = map[string]debugFlag{} +) + +// DebugFlags adds handlers for flags under /debug/flags. +type DebugFlags struct { +} + +// Install registers the APIServer's flags handler. +func (f DebugFlags) Install(c *mux.PathRecorderMux, flag string, handler func(http.ResponseWriter, *http.Request)) { + c.UnlistedHandle("/debug/flags", http.HandlerFunc(f.Index)) + c.UnlistedHandlePrefix("/debug/flags/", http.HandlerFunc(f.Index)) + + url := path.Join("/debug/flags", flag) + c.UnlistedHandleFunc(url, handler) + + f.addFlag(flag) +} + +// Index responds with the `/debug/flags` request. +// For example, "/debug/flags/v" serves the "--v" flag. +// Index responds to a request for "/debug/flags/" with an HTML page +// listing the available flags. +func (f DebugFlags) Index(w http.ResponseWriter, r *http.Request) { + lock.RLock() + defer lock.RUnlock() + if err := indexTmpl.Execute(w, registeredFlags); err != nil { + glog.Error(err) + } +} + +var indexTmpl = template.Must(template.New("index").Parse(` + +/debug/flags/ + + +/debug/flags/
+
+flags:
+ +{{range .}} +{{.Flag}}
+{{end}} +
+
+full flags configurable
+ + +`)) + +type debugFlag struct { + Flag string +} + +func (f DebugFlags) addFlag(flag string) { + lock.Lock() + defer lock.Unlock() + registeredFlags[flag] = debugFlag{flag} +} + +// StringFlagSetterFunc is a func used for setting string type flag. +type StringFlagSetterFunc func(string) (string, error) + +// StringFlagPutHandler wraps an http Handler to set string type flag. +func StringFlagPutHandler(setter StringFlagSetterFunc) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + switch { + case req.Method == "PUT": + body, err := ioutil.ReadAll(req.Body) + if err != nil { + writePlainText(http.StatusBadRequest, "error reading request body: "+err.Error(), w) + return + } + defer req.Body.Close() + response, err := setter(string(body)) + if err != nil { + writePlainText(http.StatusBadRequest, err.Error(), w) + return + } + writePlainText(http.StatusOK, response, w) + return + default: + writePlainText(http.StatusNotAcceptable, "unsupported http method", w) + return + } + }) +} + +// writePlainText renders a simple string response. +func writePlainText(statusCode int, text string, w http.ResponseWriter) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(statusCode) + fmt.Fprintln(w, text) +} diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go index cb87f27b574..4d4f35676ac 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go @@ -149,14 +149,41 @@ func TestCBCKeyRotation(t *testing.T) { } } -func BenchmarkGCMRead_16_1024(b *testing.B) { benchmarkGCMRead(b, 16, 1024, false) } -func BenchmarkGCMRead_32_1024(b *testing.B) { benchmarkGCMRead(b, 32, 1024, false) } -func BenchmarkGCMRead_32_16384(b *testing.B) { benchmarkGCMRead(b, 32, 16384, false) } -func BenchmarkGCMRead_32_16384_Stale(b *testing.B) { benchmarkGCMRead(b, 32, 16384, true) } +func BenchmarkGCMRead(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + expectStale bool + }{ + {keyLength: 16, valueLength: 1024, expectStale: false}, + {keyLength: 32, valueLength: 1024, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: true}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength/%vExpectStale", t.keyLength, t.valueLength, t.expectStale) + b.Run(name, func(b *testing.B) { + benchmarkGCMRead(b, t.keyLength, t.valueLength, t.expectStale) + }) + } +} -func BenchmarkGCMWrite_16_1024(b *testing.B) { benchmarkGCMWrite(b, 16, 1024) } -func BenchmarkGCMWrite_32_1024(b *testing.B) { benchmarkGCMWrite(b, 32, 1024) } -func BenchmarkGCMWrite_32_16384(b *testing.B) { benchmarkGCMWrite(b, 32, 16384) } +func BenchmarkGCMWrite(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + }{ + {keyLength: 16, valueLength: 1024}, + {keyLength: 32, valueLength: 1024}, + {keyLength: 32, valueLength: 16384}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength", t.keyLength, t.valueLength) + b.Run(name, func(b *testing.B) { + benchmarkGCMWrite(b, t.keyLength, t.valueLength) + }) + } +} func benchmarkGCMRead(b *testing.B, keyLength int, valueLength int, expectStale bool) { block1, err := aes.NewCipher(bytes.Repeat([]byte("a"), keyLength)) @@ -227,12 +254,39 @@ func benchmarkGCMWrite(b *testing.B, keyLength int, valueLength int) { b.StopTimer() } -func BenchmarkCBCRead_32_1024(b *testing.B) { benchmarkCBCRead(b, 32, 1024, false) } -func BenchmarkCBCRead_32_16384(b *testing.B) { benchmarkCBCRead(b, 32, 16384, false) } -func BenchmarkCBCRead_32_16384_Stale(b *testing.B) { benchmarkCBCRead(b, 32, 16384, true) } +func BenchmarkCBCRead(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + expectStale bool + }{ + {keyLength: 32, valueLength: 1024, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: true}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength/%vExpectStale", t.keyLength, t.valueLength, t.expectStale) + b.Run(name, func(b *testing.B) { + benchmarkCBCRead(b, t.keyLength, t.valueLength, t.expectStale) + }) + } +} -func BenchmarkCBCWrite_32_1024(b *testing.B) { benchmarkCBCWrite(b, 32, 1024) } -func BenchmarkCBCWrite_32_16384(b *testing.B) { benchmarkCBCWrite(b, 32, 16384) } +func BenchmarkCBCWrite(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + }{ + {keyLength: 32, valueLength: 1024}, + {keyLength: 32, valueLength: 16384}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength", t.keyLength, t.valueLength) + b.Run(name, func(b *testing.B) { + benchmarkCBCWrite(b, t.keyLength, t.valueLength) + }) + } +} func benchmarkCBCRead(b *testing.B, keyLength int, valueLength int, expectStale bool) { block1, err := aes.NewCipher(bytes.Repeat([]byte("a"), keyLength)) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go index e3038c9d9ac..e5a8989d974 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go @@ -24,6 +24,7 @@ import ( "encoding/base64" "encoding/binary" "fmt" + "time" "k8s.io/apiserver/pkg/storage/value" @@ -33,6 +34,10 @@ import ( // defaultCacheSize is the number of decrypted DEKs which would be cached by the transformer. const defaultCacheSize = 1000 +func init() { + value.RegisterMetrics() +} + // Service allows encrypting and decrypting data using an external Key Management Service. type Service interface { // Decrypt a given bytearray to obtain the original data as bytes. @@ -85,6 +90,7 @@ func (t *envelopeTransformer) TransformFromStorage(data []byte, context value.Co // Look up the decrypted DEK from cache or Envelope. transformer := t.getTransformer(encKey) if transformer == nil { + value.RecordCacheMiss() key, err := t.envelopeService.Decrypt(encKey) if err != nil { return nil, false, fmt.Errorf("error while decrypting key: %q", err) @@ -156,10 +162,12 @@ func (t *envelopeTransformer) getTransformer(encKey []byte) value.Transformer { } // generateKey generates a random key using system randomness. -func generateKey(length int) ([]byte, error) { - key := make([]byte, length) - _, err := rand.Read(key) - if err != nil { +func generateKey(length int) (key []byte, err error) { + defer func(start time.Time) { + value.RecordDataKeyGeneration(start, err) + }(time.Now()) + key = make([]byte, length) + if _, err = rand.Read(key); err != nil { return nil, err } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go index 1dd42bd4da3..b19ccc3061f 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go @@ -77,12 +77,39 @@ func TestSecretboxKeyRotation(t *testing.T) { } } -func BenchmarkSecretboxRead_32_1024(b *testing.B) { benchmarkSecretboxRead(b, 32, 1024, false) } -func BenchmarkSecretboxRead_32_16384(b *testing.B) { benchmarkSecretboxRead(b, 32, 16384, false) } -func BenchmarkSecretboxRead_32_16384_Stale(b *testing.B) { benchmarkSecretboxRead(b, 32, 16384, true) } +func BenchmarkSecretboxRead(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + expectStale bool + }{ + {keyLength: 32, valueLength: 1024, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: true}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength/%vExpectStale", t.keyLength, t.valueLength, t.expectStale) + b.Run(name, func(b *testing.B) { + benchmarkSecretboxRead(b, t.keyLength, t.valueLength, t.expectStale) + }) + } +} -func BenchmarkSecretboxWrite_32_1024(b *testing.B) { benchmarkSecretboxWrite(b, 32, 1024) } -func BenchmarkSecretboxWrite_32_16384(b *testing.B) { benchmarkSecretboxWrite(b, 32, 16384) } +func BenchmarkSecretboxWrite(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + }{ + {keyLength: 32, valueLength: 1024}, + {keyLength: 32, valueLength: 16384}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength", t.keyLength, t.valueLength) + b.Run(name, func(b *testing.B) { + benchmarkSecretboxWrite(b, t.keyLength, t.valueLength) + }) + } +} func benchmarkSecretboxRead(b *testing.B, keyLength int, valueLength int, expectStale bool) { p := value.NewPrefixTransformers(nil, diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/metrics.go b/staging/src/k8s.io/apiserver/pkg/storage/value/metrics.go index 0425cd2302e..1fe31678214 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/metrics.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/metrics.go @@ -23,11 +23,16 @@ import ( "github.com/prometheus/client_golang/prometheus" ) +const ( + namespace = "apiserver" + subsystem = "storage" +) + var ( transformerLatencies = prometheus.NewHistogramVec( prometheus.HistogramOpts{ - Namespace: "apiserver", - Subsystem: "storage", + Namespace: namespace, + Subsystem: subsystem, Name: "transformation_latencies_microseconds", Help: "Latencies in microseconds of value transformation operations.", // In-process transformations (ex. AES CBC) complete on the order of 20 microseconds. However, when @@ -36,6 +41,42 @@ var ( }, []string{"transformation_type"}, ) + transformerFailuresTotal = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "transformation_failures_total", + Help: "Total number of failed transformation operations.", + }, + []string{"transformation_type"}, + ) + + envelopeTransformationCacheMissTotal = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "envelope_transformation_cache_misses_total", + Help: "Total number of cache misses while accessing key decryption key(KEK).", + }, + ) + + dataKeyGenerationLatencies = prometheus.NewHistogram( + prometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "data_key_generation_latencies_microseconds", + Help: "Latencies in microseconds of data encryption key(DEK) generation operations.", + Buckets: prometheus.ExponentialBuckets(5, 2, 14), + }, + ) + dataKeyGenerationFailuresTotal = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "data_key_generation_failures_total", + Help: "Total number of failed data encryption key(DEK) generation operations.", + }, + ) ) var registerMetrics sync.Once @@ -43,14 +84,40 @@ var registerMetrics sync.Once func RegisterMetrics() { registerMetrics.Do(func() { prometheus.MustRegister(transformerLatencies) + prometheus.MustRegister(transformerFailuresTotal) + prometheus.MustRegister(envelopeTransformationCacheMissTotal) + prometheus.MustRegister(dataKeyGenerationLatencies) + prometheus.MustRegister(dataKeyGenerationFailuresTotal) }) } -func RecordTransformation(transformationType string, start time.Time) { +// RecordTransformation records latencies and count of TransformFromStorage and TransformToStorage operations. +func RecordTransformation(transformationType string, start time.Time, err error) { + if err != nil { + transformerFailuresTotal.WithLabelValues(transformationType).Inc() + return + } + since := sinceInMicroseconds(start) transformerLatencies.WithLabelValues(transformationType).Observe(float64(since)) } +// RecordCacheMiss records a miss on Key Encryption Key(KEK) - call to KMS was required to decrypt KEK. +func RecordCacheMiss() { + envelopeTransformationCacheMissTotal.Inc() +} + +// RecordDataKeyGeneration records latencies and count of Data Encryption Key generation operations. +func RecordDataKeyGeneration(start time.Time, err error) { + if err != nil { + dataKeyGenerationFailuresTotal.Inc() + return + } + + since := sinceInMicroseconds(start) + dataKeyGenerationLatencies.Observe(float64(since)) +} + func sinceInMicroseconds(start time.Time) int64 { elapsedNanoseconds := time.Since(start).Nanoseconds() return elapsedNanoseconds / int64(time.Microsecond) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go b/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go index 8998147169e..bad6ed58e33 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go @@ -85,14 +85,18 @@ func (t *MutableTransformer) Set(transformer Transformer) { } func (t *MutableTransformer) TransformFromStorage(data []byte, context Context) (out []byte, stale bool, err error) { - defer RecordTransformation("from_storage", time.Now()) + defer func(start time.Time) { + RecordTransformation("from_storage", start, err) + }(time.Now()) t.lock.RLock() transformer := t.transformer t.lock.RUnlock() return transformer.TransformFromStorage(data, context) } func (t *MutableTransformer) TransformToStorage(data []byte, context Context) (out []byte, err error) { - defer RecordTransformation("to_storage", time.Now()) + defer func(start time.Time) { + RecordTransformation("to_storage", start, err) + }(time.Now()) t.lock.RLock() transformer := t.transformer t.lock.RUnlock() diff --git a/staging/src/k8s.io/apiserver/pkg/util/flag/BUILD b/staging/src/k8s.io/apiserver/pkg/util/flag/BUILD index 7a73ad0d5fe..1883510d566 100644 --- a/staging/src/k8s.io/apiserver/pkg/util/flag/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/util/flag/BUILD @@ -40,6 +40,7 @@ go_library( deps = [ "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/util/flag/ciphersuites_flag.go b/staging/src/k8s.io/apiserver/pkg/util/flag/ciphersuites_flag.go index 73fd62c100a..764747c2591 100644 --- a/staging/src/k8s.io/apiserver/pkg/util/flag/ciphersuites_flag.go +++ b/staging/src/k8s.io/apiserver/pkg/util/flag/ciphersuites_flag.go @@ -19,6 +19,8 @@ package flag import ( "crypto/tls" "fmt" + + "k8s.io/apimachinery/pkg/util/sets" ) // ciphers maps strings into tls package cipher constants in @@ -48,6 +50,14 @@ var ciphers = map[string]uint16{ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, } +func TLSCipherPossibleValues() []string { + cipherKeys := sets.NewString() + for key := range ciphers { + cipherKeys.Insert(key) + } + return cipherKeys.List() +} + func TLSCipherSuites(cipherNames []string) ([]uint16, error) { if len(cipherNames) == 0 { return nil, nil @@ -69,6 +79,14 @@ var versions = map[string]uint16{ "VersionTLS12": tls.VersionTLS12, } +func TLSPossibleVersions() []string { + versionsKeys := sets.NewString() + for key := range versions { + versionsKeys.Insert(key) + } + return versionsKeys.List() +} + func TLSVersion(versionName string) (uint16, error) { if len(versionName) == 0 { return DefaultTLSVersion(), nil diff --git a/staging/src/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md b/staging/src/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md index e559c074bb5..6aed9889cf1 100644 --- a/staging/src/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md +++ b/staging/src/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md @@ -1,2 +1,3 @@ -Sorry, we do not accept changes directly against this repository. Please see -CONTRIBUTING.md for information on where and how to contribute instead. +Sorry, we do not accept changes directly against this repository, unless the +change is to the `README.md` itself. Please see +`CONTRIBUTING.md` for information on where and how to contribute instead. diff --git a/staging/src/k8s.io/client-go/Godeps/Godeps.json b/staging/src/k8s.io/client-go/Godeps/Godeps.json index f314634d39f..d076c5c0112 100644 --- a/staging/src/k8s.io/client-go/Godeps/Godeps.json +++ b/staging/src/k8s.io/client-go/Godeps/Godeps.json @@ -68,23 +68,23 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -156,7 +156,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "2ddf6d758266fcb080a4f9e054b9f292c85e6798" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/modern-go/concurrent", @@ -588,7 +588,7 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" } ] } diff --git a/staging/src/k8s.io/client-go/OWNERS b/staging/src/k8s.io/client-go/OWNERS index 13af74c628a..b3991682993 100644 --- a/staging/src/k8s.io/client-go/OWNERS +++ b/staging/src/k8s.io/client-go/OWNERS @@ -1,45 +1,15 @@ approvers: - caesarxuchao - deads2k -- krousey - lavalamp +- liggitt - smarterclayton - sttts -- liggitt reviewers: -- thockin -- lavalamp -- smarterclayton -- wojtek-t -- deads2k -- yujuhong -- derekwaynecarr - caesarxuchao -- vishh -- mikedanese +- deads2k +- lavalamp - liggitt -- nikhiljindal -- gmarek -- erictune -- davidopp -- pmorie -- sttts -- dchen1107 -- saad-ali -- zmerlynn -- luxas -- janetkuo -- justinsb -- roberthbailey -- ncdc -- tallclair -- yifan-gu -- eparis -- mwielgus -- timothysc -- feiskyer -- jlowdermilk - soltysh -- piosz -- jsafrane -- awly +- sttts +- yliaog diff --git a/staging/src/k8s.io/client-go/SECURITY_CONTACTS b/staging/src/k8s.io/client-go/SECURITY_CONTACTS new file mode 100644 index 00000000000..0648a8ebff7 --- /dev/null +++ b/staging/src/k8s.io/client-go/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# 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/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/BUILD b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/BUILD index 64cdd678da7..9536954e0d3 100644 --- a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/BUILD +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/BUILD @@ -30,6 +30,7 @@ filegroup( ":package-srcs", "//staging/src/k8s.io/client-go/pkg/apis/clientauthentication/install:all-srcs", "//staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/types.go b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/types.go index 5c05825f67b..6fb53cecf94 100644 --- a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/types.go +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/types.go @@ -57,7 +57,14 @@ type ExecCredentialStatus struct { // +optional ExpirationTimestamp *metav1.Time // Token is a bearer token used by the client for request authentication. + // +optional Token string + // PEM-encoded client TLS certificate. + // +optional + ClientCertificateData string + // PEM-encoded client TLS private key. + // +optional + ClientKeyData string } // Response defines metadata about a failed request, including HTTP status code and 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 8920d31876e..921f3a2b94d 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 @@ -52,12 +52,20 @@ type ExecCredentialSpec struct { } // ExecCredentialStatus holds credentials for the transport to use. +// +// Token and ClientKeyData are sensitive fields. This data should only be +// transmitted in-memory between client and exec plugin process. Exec plugin +// itself should at least be protected via file permissions. type ExecCredentialStatus struct { // ExpirationTimestamp indicates a time when the provided credentials expire. // +optional ExpirationTimestamp *metav1.Time `json:"expirationTimestamp,omitempty"` // Token is a bearer token used by the client for request authentication. Token string `json:"token,omitempty"` + // PEM-encoded client TLS certificates (including intermediates, if any). + ClientCertificateData string `json:"clientCertificateData,omitempty"` + // PEM-encoded private key for the above certificate. + ClientKeyData string `json:"clientKeyData,omitempty"` } // Response defines metadata about a failed request, including HTTP status code and diff --git a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go index 032eaf38f27..9921c7ee580 100644 --- a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go @@ -99,6 +99,8 @@ func Convert_clientauthentication_ExecCredentialSpec_To_v1alpha1_ExecCredentialS func autoConvert_v1alpha1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in *ExecCredentialStatus, out *clientauthentication.ExecCredentialStatus, s conversion.Scope) error { out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData return nil } @@ -110,6 +112,8 @@ func Convert_v1alpha1_ExecCredentialStatus_To_clientauthentication_ExecCredentia func autoConvert_clientauthentication_ExecCredentialStatus_To_v1alpha1_ExecCredentialStatus(in *clientauthentication.ExecCredentialStatus, out *ExecCredentialStatus, s conversion.Scope) error { out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData return nil } diff --git a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/BUILD b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/BUILD new file mode 100644 index 00000000000..6431610f3b9 --- /dev/null +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/BUILD @@ -0,0 +1,37 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "conversion.go", + "doc.go", + "register.go", + "types.go", + "zz_generated.conversion.go", + "zz_generated.deepcopy.go", + "zz_generated.defaults.go", + ], + importpath = "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/pkg/apis/clientauthentication: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/client-go/pkg/apis/clientauthentication/v1beta1/conversion.go b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/conversion.go new file mode 100644 index 00000000000..f543806ac95 --- /dev/null +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/conversion.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 v1beta1 + +import ( + conversion "k8s.io/apimachinery/pkg/conversion" + clientauthentication "k8s.io/client-go/pkg/apis/clientauthentication" +) + +func Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(in *clientauthentication.ExecCredentialSpec, out *ExecCredentialSpec, s conversion.Scope) error { + return nil +} diff --git a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/doc.go b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/doc.go new file mode 100644 index 00000000000..fbcd9b7fea2 --- /dev/null +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/doc.go @@ -0,0 +1,23 @@ +/* +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:conversion-gen=k8s.io/client-go/pkg/apis/clientauthentication +// +k8s:openapi-gen=true +// +k8s:defaulter-gen=TypeMeta + +// +groupName=client.authentication.k8s.io +package v1beta1 // import "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1" diff --git a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/register.go b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/register.go new file mode 100644 index 00000000000..0bb92f16a44 --- /dev/null +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/register.go @@ -0,0 +1,55 @@ +/* +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 v1beta1 + +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 = "client.authentication.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// 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.SchemeBuilder + localSchemeBuilder = &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(addKnownTypes) +} + +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ExecCredential{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/types.go b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/types.go new file mode 100644 index 00000000000..d6e267452e9 --- /dev/null +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/types.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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ExecCredentials is used by exec-based plugins to communicate credentials to +// HTTP transports. +type ExecCredential struct { + metav1.TypeMeta `json:",inline"` + + // Spec holds information passed to the plugin by the transport. This contains + // request and runtime specific information, such as if the session is interactive. + Spec ExecCredentialSpec `json:"spec,omitempty"` + + // Status is filled in by the plugin and holds the credentials that the transport + // should use to contact the API. + // +optional + Status *ExecCredentialStatus `json:"status,omitempty"` +} + +// ExecCredenitalSpec holds request and runtime specific information provided by +// the transport. +type ExecCredentialSpec struct{} + +// ExecCredentialStatus holds credentials for the transport to use. +// +// Token and ClientKeyData are sensitive fields. This data should only be +// transmitted in-memory between client and exec plugin process. Exec plugin +// itself should at least be protected via file permissions. +type ExecCredentialStatus struct { + // ExpirationTimestamp indicates a time when the provided credentials expire. + // +optional + ExpirationTimestamp *metav1.Time `json:"expirationTimestamp,omitempty"` + // Token is a bearer token used by the client for request authentication. + Token string `json:"token,omitempty"` + // PEM-encoded client TLS certificates (including intermediates, if any). + ClientCertificateData string `json:"clientCertificateData,omitempty"` + // PEM-encoded private key for the above certificate. + ClientKeyData string `json:"clientKeyData,omitempty"` +} diff --git a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.conversion.go b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.conversion.go new file mode 100644 index 00000000000..80e9b31595c --- /dev/null +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.conversion.go @@ -0,0 +1,114 @@ +// +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 v1beta1 + +import ( + unsafe "unsafe" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + clientauthentication "k8s.io/client-go/pkg/apis/clientauthentication" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(scheme *runtime.Scheme) error { + return scheme.AddGeneratedConversionFuncs( + Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential, + Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential, + Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec, + Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec, + Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus, + Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus, + ) +} + +func autoConvert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in *ExecCredential, out *clientauthentication.ExecCredential, s conversion.Scope) error { + if err := Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + out.Status = (*clientauthentication.ExecCredentialStatus)(unsafe.Pointer(in.Status)) + return nil +} + +// Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential is an autogenerated conversion function. +func Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in *ExecCredential, out *clientauthentication.ExecCredential, s conversion.Scope) error { + return autoConvert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in, out, s) +} + +func autoConvert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in *clientauthentication.ExecCredential, out *ExecCredential, s conversion.Scope) error { + if err := Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + out.Status = (*ExecCredentialStatus)(unsafe.Pointer(in.Status)) + return nil +} + +// Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential is an autogenerated conversion function. +func Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in *clientauthentication.ExecCredential, out *ExecCredential, s conversion.Scope) error { + return autoConvert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in, out, s) +} + +func autoConvert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in *ExecCredentialSpec, out *clientauthentication.ExecCredentialSpec, s conversion.Scope) error { + return nil +} + +// Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec is an autogenerated conversion function. +func Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in *ExecCredentialSpec, out *clientauthentication.ExecCredentialSpec, s conversion.Scope) error { + return autoConvert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in, out, s) +} + +func autoConvert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(in *clientauthentication.ExecCredentialSpec, out *ExecCredentialSpec, s conversion.Scope) error { + // WARNING: in.Response requires manual conversion: does not exist in peer-type + // WARNING: in.Interactive requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in *ExecCredentialStatus, out *clientauthentication.ExecCredentialStatus, s conversion.Scope) error { + out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) + out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData + return nil +} + +// Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus is an autogenerated conversion function. +func Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in *ExecCredentialStatus, out *clientauthentication.ExecCredentialStatus, s conversion.Scope) error { + return autoConvert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in, out, s) +} + +func autoConvert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in *clientauthentication.ExecCredentialStatus, out *ExecCredentialStatus, s conversion.Scope) error { + out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) + out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData + return nil +} + +// Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus is an autogenerated conversion function. +func Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in *clientauthentication.ExecCredentialStatus, out *ExecCredentialStatus, s conversion.Scope) error { + return autoConvert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in, out, s) +} diff --git a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.deepcopy.go b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..656fea4d871 --- /dev/null +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,100 @@ +// +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 v1beta1 + +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 *ExecCredential) DeepCopyInto(out *ExecCredential) { + *out = *in + out.TypeMeta = in.TypeMeta + out.Spec = in.Spec + if in.Status != nil { + in, out := &in.Status, &out.Status + if *in == nil { + *out = nil + } else { + *out = new(ExecCredentialStatus) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredential. +func (in *ExecCredential) DeepCopy() *ExecCredential { + if in == nil { + return nil + } + out := new(ExecCredential) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExecCredential) 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 *ExecCredentialSpec) DeepCopyInto(out *ExecCredentialSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredentialSpec. +func (in *ExecCredentialSpec) DeepCopy() *ExecCredentialSpec { + if in == nil { + return nil + } + out := new(ExecCredentialSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecCredentialStatus) DeepCopyInto(out *ExecCredentialStatus) { + *out = *in + if in.ExpirationTimestamp != nil { + in, out := &in.ExpirationTimestamp, &out.ExpirationTimestamp + if *in == nil { + *out = nil + } else { + *out = (*in).DeepCopy() + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredentialStatus. +func (in *ExecCredentialStatus) DeepCopy() *ExecCredentialStatus { + if in == nil { + return nil + } + out := new(ExecCredentialStatus) + in.DeepCopyInto(out) + return out +} diff --git a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.defaults.go b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.defaults.go new file mode 100644 index 00000000000..73e63fc114d --- /dev/null +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/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 v1beta1 + +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/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/BUILD b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/BUILD index 38cf9bdc299..9af48cf309d 100644 --- a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/BUILD +++ b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/BUILD @@ -14,7 +14,10 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/client-go/pkg/apis/clientauthentication:go_default_library", "//vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1:go_default_library", + "//vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", + "//vendor/k8s.io/client-go/transport:go_default_library", + "//vendor/k8s.io/client-go/util/connrotation:go_default_library", ], ) @@ -24,8 +27,11 @@ go_test( data = glob(["testdata/**"]), embed = [":go_default_library"], deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/pkg/apis/clientauthentication:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", + "//vendor/k8s.io/client-go/transport:go_default_library", ], ) diff --git a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go index dfd434d0c2f..2d05ac622cd 100644 --- a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go +++ b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go @@ -18,11 +18,15 @@ package exec import ( "bytes" + "context" + "crypto/tls" "fmt" "io" + "net" "net/http" "os" "os/exec" + "reflect" "sync" "time" @@ -34,7 +38,10 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/client-go/pkg/apis/clientauthentication" "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1" + "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1" "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/client-go/transport" + "k8s.io/client-go/util/connrotation" ) const execInfoEnv = "KUBERNETES_EXEC_INFO" @@ -45,6 +52,7 @@ var codecs = serializer.NewCodecFactory(scheme) func init() { v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) v1alpha1.AddToScheme(scheme) + v1beta1.AddToScheme(scheme) clientauthentication.AddToScheme(scheme) } @@ -55,6 +63,7 @@ var ( // The list of API versions we accept. apiVersions = map[string]schema.GroupVersion{ v1alpha1.SchemeGroupVersion.String(): v1alpha1.SchemeGroupVersion, + v1beta1.SchemeGroupVersion.String(): v1beta1.SchemeGroupVersion, } ) @@ -147,14 +156,55 @@ type Authenticator struct { // The mutex also guards calling the plugin. Since the plugin could be // interactive we want to make sure it's only called once. mu sync.Mutex - cachedToken string + cachedCreds *credentials exp time.Time + + onRotate func() } -// WrapTransport instruments an existing http.RoundTripper with credentials returned -// by the plugin. -func (a *Authenticator) WrapTransport(rt http.RoundTripper) http.RoundTripper { - return &roundTripper{a, rt} +type credentials struct { + token string + cert *tls.Certificate +} + +// UpdateTransportConfig updates the transport.Config to use credentials +// returned by the plugin. +func (a *Authenticator) UpdateTransportConfig(c *transport.Config) error { + wt := c.WrapTransport + c.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { + if wt != nil { + rt = wt(rt) + } + return &roundTripper{a, rt} + } + + getCert := c.TLS.GetCert + c.TLS.GetCert = func() (*tls.Certificate, error) { + // If previous GetCert is present and returns a valid non-nil + // certificate, use that. Otherwise use cert from exec plugin. + if getCert != nil { + cert, err := getCert() + if err != nil { + return nil, err + } + if cert != nil { + return cert, nil + } + } + return a.cert() + } + + var dial func(ctx context.Context, network, addr string) (net.Conn, error) + if c.Dial != nil { + dial = c.Dial + } else { + dial = (&net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}).DialContext + } + d := connrotation.NewDialer(dial) + a.onRotate = d.CloseAll + c.Dial = d.DialContext + + return nil } type roundTripper struct { @@ -169,11 +219,13 @@ func (r *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { return r.base.RoundTrip(req) } - token, err := r.a.token() + creds, err := r.a.getCreds() if err != nil { - return nil, fmt.Errorf("getting token: %v", err) + return nil, fmt.Errorf("getting credentials: %v", err) + } + if creds.token != "" { + req.Header.Set("Authorization", "Bearer "+creds.token) } - req.Header.Set("Authorization", "Bearer "+token) res, err := r.base.RoundTrip(req) if err != nil { @@ -184,47 +236,60 @@ func (r *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { Header: res.Header, Code: int32(res.StatusCode), } - if err := r.a.refresh(token, resp); err != nil { - glog.Errorf("refreshing token: %v", err) + if err := r.a.maybeRefreshCreds(creds, resp); err != nil { + glog.Errorf("refreshing credentials: %v", err) } } return res, nil } -func (a *Authenticator) tokenExpired() bool { +func (a *Authenticator) credsExpired() bool { if a.exp.IsZero() { return false } return a.now().After(a.exp) } -func (a *Authenticator) token() (string, error) { - a.mu.Lock() - defer a.mu.Unlock() - if a.cachedToken != "" && !a.tokenExpired() { - return a.cachedToken, nil +func (a *Authenticator) cert() (*tls.Certificate, error) { + creds, err := a.getCreds() + if err != nil { + return nil, err } - - return a.getToken(nil) + return creds.cert, nil } -// refresh executes the plugin to force a rotation of the token. -func (a *Authenticator) refresh(token string, r *clientauthentication.Response) error { +func (a *Authenticator) getCreds() (*credentials, error) { + a.mu.Lock() + defer a.mu.Unlock() + if a.cachedCreds != nil && !a.credsExpired() { + return a.cachedCreds, nil + } + + if err := a.refreshCredsLocked(nil); err != nil { + return nil, err + } + return a.cachedCreds, nil +} + +// maybeRefreshCreds executes the plugin to force a rotation of the +// credentials, unless they were rotated already. +func (a *Authenticator) maybeRefreshCreds(creds *credentials, r *clientauthentication.Response) error { a.mu.Lock() defer a.mu.Unlock() - if token != a.cachedToken { - // Token already rotated. + // Since we're not making a new pointer to a.cachedCreds in getCreds, no + // need to do deep comparison. + if creds != a.cachedCreds { + // Credentials already rotated. return nil } - _, err := a.getToken(r) - return err + return a.refreshCredsLocked(r) } -// getToken executes the plugin and reads the credentials from stdout. It must be -// called while holding the Authenticator's mutex. -func (a *Authenticator) getToken(r *clientauthentication.Response) (string, error) { +// refreshCredsLocked executes the plugin and reads the credentials from +// stdout. It must be called while holding the Authenticator's mutex. +func (a *Authenticator) refreshCredsLocked(r *clientauthentication.Response) error { cred := &clientauthentication.ExecCredential{ Spec: clientauthentication.ExecCredentialSpec{ Response: r, @@ -232,13 +297,18 @@ func (a *Authenticator) getToken(r *clientauthentication.Response) (string, erro }, } - data, err := runtime.Encode(codecs.LegacyCodec(a.group), cred) - if err != nil { - return "", fmt.Errorf("encode ExecCredentials: %v", err) - } - env := append(a.environ(), a.env...) - env = append(env, fmt.Sprintf("%s=%s", execInfoEnv, data)) + if a.group == v1alpha1.SchemeGroupVersion { + // Input spec disabled for beta due to lack of use. Possibly re-enable this later if + // someone wants it back. + // + // See: https://github.com/kubernetes/kubernetes/issues/61796 + data, err := runtime.Encode(codecs.LegacyCodec(a.group), cred) + if err != nil { + return fmt.Errorf("encode ExecCredentials: %v", err) + } + env = append(env, fmt.Sprintf("%s=%s", execInfoEnv, data)) + } stdout := &bytes.Buffer{} cmd := exec.Command(a.cmd, a.args...) @@ -250,23 +320,26 @@ func (a *Authenticator) getToken(r *clientauthentication.Response) (string, erro } if err := cmd.Run(); err != nil { - return "", fmt.Errorf("exec: %v", err) + return fmt.Errorf("exec: %v", err) } _, gvk, err := codecs.UniversalDecoder(a.group).Decode(stdout.Bytes(), nil, cred) if err != nil { - return "", fmt.Errorf("decode stdout: %v", err) + return fmt.Errorf("decoding stdout: %v", err) } if gvk.Group != a.group.Group || gvk.Version != a.group.Version { - return "", fmt.Errorf("exec plugin is configured to use API version %s, plugin returned version %s", + return fmt.Errorf("exec plugin is configured to use API version %s, plugin returned version %s", a.group, schema.GroupVersion{Group: gvk.Group, Version: gvk.Version}) } if cred.Status == nil { - return "", fmt.Errorf("exec plugin didn't return a status field") + return fmt.Errorf("exec plugin didn't return a status field") } - if cred.Status.Token == "" { - return "", fmt.Errorf("exec plugin didn't return a token") + if cred.Status.Token == "" && cred.Status.ClientCertificateData == "" && cred.Status.ClientKeyData == "" { + return fmt.Errorf("exec plugin didn't return a token or cert/key pair") + } + if (cred.Status.ClientCertificateData == "") != (cred.Status.ClientKeyData == "") { + return fmt.Errorf("exec plugin returned only certificate or key, not both") } if cred.Status.ExpirationTimestamp != nil { @@ -274,7 +347,24 @@ func (a *Authenticator) getToken(r *clientauthentication.Response) (string, erro } else { a.exp = time.Time{} } - a.cachedToken = cred.Status.Token - return a.cachedToken, nil + newCreds := &credentials{ + token: cred.Status.Token, + } + if cred.Status.ClientKeyData != "" && cred.Status.ClientCertificateData != "" { + cert, err := tls.X509KeyPair([]byte(cred.Status.ClientCertificateData), []byte(cred.Status.ClientKeyData)) + if err != nil { + return fmt.Errorf("failed parsing client key/certificate: %v", err) + } + newCreds.cert = &cert + } + + oldCreds := a.cachedCreds + a.cachedCreds = newCreds + // Only close all connections when TLS cert rotates. Token rotation doesn't + // need the extra noise. + if a.onRotate != nil && oldCreds != nil && !reflect.DeepEqual(oldCreds.cert, a.cachedCreds.cert) { + a.onRotate() + } + return nil } diff --git a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go index 28137eb8477..e3398e821ef 100644 --- a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go +++ b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go @@ -18,19 +18,88 @@ package exec import ( "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" "encoding/json" + "encoding/pem" "fmt" "io/ioutil" + "math/big" "net/http" "net/http/httptest" + "reflect" "strings" "testing" "time" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/pkg/apis/clientauthentication" "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/client-go/transport" ) +var ( + certData = []byte(`-----BEGIN CERTIFICATE----- +MIIC6jCCAdSgAwIBAgIBCzALBgkqhkiG9w0BAQswIzEhMB8GA1UEAwwYMTAuMTMu +MTI5LjEwNkAxNDIxMzU5MDU4MB4XDTE1MDExNTIyMDEzMVoXDTE2MDExNTIyMDEz +MlowGzEZMBcGA1UEAxMQb3BlbnNoaWZ0LWNsaWVudDCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKtdhz0+uCLXw5cSYns9rU/XifFSpb/x24WDdrm72S/v +b9BPYsAStiP148buylr1SOuNi8sTAZmlVDDIpIVwMLff+o2rKYDicn9fjbrTxTOj +lI4pHJBH+JU3AJ0tbajupioh70jwFS0oYpwtneg2zcnE2Z4l6mhrj2okrc5Q1/X2 +I2HChtIU4JYTisObtin10QKJX01CLfYXJLa8upWzKZ4/GOcHG+eAV3jXWoXidtjb +1Usw70amoTZ6mIVCkiu1QwCoa8+ycojGfZhvqMsAp1536ZcCul+Na+AbCv4zKS7F +kQQaImVrXdUiFansIoofGlw/JNuoKK6ssVpS5Ic3pgcCAwEAAaM1MDMwDgYDVR0P +AQH/BAQDAgCgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJ +KoZIhvcNAQELA4IBAQCKLREH7bXtXtZ+8vI6cjD7W3QikiArGqbl36bAhhWsJLp/ +p/ndKz39iFNaiZ3GlwIURWOOKx3y3GA0x9m8FR+Llthf0EQ8sUjnwaknWs0Y6DQ3 +jjPFZOpV3KPCFrdMJ3++E3MgwFC/Ih/N2ebFX9EcV9Vcc6oVWMdwT0fsrhu683rq +6GSR/3iVX1G/pmOiuaR0fNUaCyCfYrnI4zHBDgSfnlm3vIvN2lrsR/DQBakNL8DJ +HBgKxMGeUPoneBv+c8DMXIL0EhaFXRlBv9QW45/GiAIOuyFJ0i6hCtGZpJjq4OpQ +BRjCI+izPzFTjsxD4aORE+WOkyWFCGPWKfNejfw0 +-----END CERTIFICATE-----`) + keyData = []byte(`-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAq12HPT64ItfDlxJiez2tT9eJ8VKlv/HbhYN2ubvZL+9v0E9i +wBK2I/Xjxu7KWvVI642LyxMBmaVUMMikhXAwt9/6jaspgOJyf1+NutPFM6OUjikc +kEf4lTcAnS1tqO6mKiHvSPAVLShinC2d6DbNycTZniXqaGuPaiStzlDX9fYjYcKG +0hTglhOKw5u2KfXRAolfTUIt9hcktry6lbMpnj8Y5wcb54BXeNdaheJ22NvVSzDv +RqahNnqYhUKSK7VDAKhrz7JyiMZ9mG+oywCnXnfplwK6X41r4BsK/jMpLsWRBBoi +ZWtd1SIVqewiih8aXD8k26gorqyxWlLkhzemBwIDAQABAoIBAD2XYRs3JrGHQUpU +FkdbVKZkvrSY0vAZOqBTLuH0zUv4UATb8487anGkWBjRDLQCgxH+jucPTrztekQK +aW94clo0S3aNtV4YhbSYIHWs1a0It0UdK6ID7CmdWkAj6s0T8W8lQT7C46mWYVLm +5mFnCTHi6aB42jZrqmEpC7sivWwuU0xqj3Ml8kkxQCGmyc9JjmCB4OrFFC8NNt6M +ObvQkUI6Z3nO4phTbpxkE1/9dT0MmPIF7GhHVzJMS+EyyRYUDllZ0wvVSOM3qZT0 +JMUaBerkNwm9foKJ1+dv2nMKZZbJajv7suUDCfU44mVeaEO+4kmTKSGCGjjTBGkr +7L1ySDECgYEA5ElIMhpdBzIivCuBIH8LlUeuzd93pqssO1G2Xg0jHtfM4tz7fyeI +cr90dc8gpli24dkSxzLeg3Tn3wIj/Bu64m2TpZPZEIlukYvgdgArmRIPQVxerYey +OkrfTNkxU1HXsYjLCdGcGXs5lmb+K/kuTcFxaMOs7jZi7La+jEONwf8CgYEAwCs/ +rUOOA0klDsWWisbivOiNPII79c9McZCNBqncCBfMUoiGe8uWDEO4TFHN60vFuVk9 +8PkwpCfvaBUX+ajvbafIfHxsnfk1M04WLGCeqQ/ym5Q4sQoQOcC1b1y9qc/xEWfg +nIUuia0ukYRpl7qQa3tNg+BNFyjypW8zukUAC/kCgYB1/Kojuxx5q5/oQVPrx73k +2bevD+B3c+DYh9MJqSCNwFtUpYIWpggPxoQan4LwdsmO0PKzocb/ilyNFj4i/vII +NToqSc/WjDFpaDIKyuu9oWfhECye45NqLWhb/6VOuu4QA/Nsj7luMhIBehnEAHW+ +GkzTKM8oD1PxpEG3nPKXYQKBgQC6AuMPRt3XBl1NkCrpSBy/uObFlFaP2Enpf39S +3OZ0Gv0XQrnSaL1kP8TMcz68rMrGX8DaWYsgytstR4W+jyy7WvZwsUu+GjTJ5aMG +77uEcEBpIi9CBzivfn7hPccE8ZgqPf+n4i6q66yxBJflW5xhvafJqDtW2LcPNbW/ +bvzdmQKBgExALRUXpq+5dbmkdXBHtvXdRDZ6rVmrnjy4nI5bPw+1GqQqk6uAR6B/ +F6NmLCQOO4PDG/cuatNHIr2FrwTmGdEL6ObLUGWn9Oer9gJhHVqqsY5I4sEPo4XX +stR0Yiw0buV6DL/moUO0HIM9Bjh96HJp+LxiIS6UCdIhMPp5HoQa +-----END RSA PRIVATE KEY-----`) + validCert *tls.Certificate +) + +func init() { + cert, err := tls.X509KeyPair(certData, keyData) + if err != nil { + panic(err) + } + validCert = &cert +} + func TestCacheKey(t *testing.T) { c1 := &api.ExecConfig{ Command: "foo-bar", @@ -93,7 +162,7 @@ func compJSON(t *testing.T, got, want []byte) { } } -func TestGetToken(t *testing.T) { +func TestRefreshCreds(t *testing.T) { tests := []struct { name string config api.ExecConfig @@ -101,7 +170,7 @@ func TestGetToken(t *testing.T) { interactive bool response *clientauthentication.Response wantInput string - wantToken string + wantCreds credentials wantExpiry time.Time wantErr bool }{ @@ -122,7 +191,7 @@ func TestGetToken(t *testing.T) { "token": "foo-bar" } }`, - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "interactive", @@ -144,7 +213,7 @@ func TestGetToken(t *testing.T) { "token": "foo-bar" } }`, - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "response", @@ -178,7 +247,7 @@ func TestGetToken(t *testing.T) { "token": "foo-bar" } }`, - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "expiry", @@ -199,7 +268,7 @@ func TestGetToken(t *testing.T) { } }`, wantExpiry: time.Date(2006, 01, 02, 15, 04, 05, 0, time.UTC), - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "no-group-version", @@ -236,7 +305,7 @@ func TestGetToken(t *testing.T) { wantErr: true, }, { - name: "no-token", + name: "no-creds", config: api.ExecConfig{ APIVersion: "client.authentication.k8s.io/v1alpha1", }, @@ -252,6 +321,131 @@ func TestGetToken(t *testing.T) { }`, wantErr: true, }, + { + name: "TLS credentials", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1alpha1", + }, + wantInput: `{ + "kind":"ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1alpha1", + "spec": {} + }`, + output: fmt.Sprintf(`{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1alpha1", + "status": { + "clientKeyData": %q, + "clientCertificateData": %q + } + }`, keyData, certData), + wantCreds: credentials{cert: validCert}, + }, + { + name: "bad TLS credentials", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1alpha1", + }, + wantInput: `{ + "kind":"ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1alpha1", + "spec": {} + }`, + output: `{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1alpha1", + "status": { + "clientKeyData": "foo", + "clientCertificateData": "bar" + } + }`, + wantErr: true, + }, + { + name: "cert but no key", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1alpha1", + }, + wantInput: `{ + "kind":"ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1alpha1", + "spec": {} + }`, + output: fmt.Sprintf(`{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1alpha1", + "status": { + "clientCertificateData": %q + } + }`, certData), + wantErr: true, + }, + { + name: "beta-basic-request", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1beta1", + "status": { + "token": "foo-bar" + } + }`, + wantCreds: credentials{token: "foo-bar"}, + }, + { + name: "beta-expiry", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1beta1", + "status": { + "token": "foo-bar", + "expirationTimestamp": "2006-01-02T15:04:05Z" + } + }`, + wantExpiry: time.Date(2006, 01, 02, 15, 04, 05, 0, time.UTC), + wantCreds: credentials{token: "foo-bar"}, + }, + { + name: "beta-no-group-version", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "status": { + "token": "foo-bar" + } + }`, + wantErr: true, + }, + { + name: "beta-no-status", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1beta1" + }`, + wantErr: true, + }, + { + name: "beta-no-token", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1beta1", + "status": {} + }`, + wantErr: true, + }, } for _, test := range tests { @@ -274,8 +468,7 @@ func TestGetToken(t *testing.T) { a.interactive = test.interactive a.environ = func() []string { return nil } - token, err := a.getToken(test.response) - if err != nil { + if err := a.refreshCredsLocked(test.response); err != nil { if !test.wantErr { t.Errorf("get token %v", err) } @@ -285,14 +478,21 @@ func TestGetToken(t *testing.T) { t.Fatal("expected error getting token") } - if token != test.wantToken { - t.Errorf("expected token %q got %q", test.wantToken, token) + if !reflect.DeepEqual(a.cachedCreds, &test.wantCreds) { + t.Errorf("expected credentials %+v got %+v", &test.wantCreds, a.cachedCreds) } if !a.exp.Equal(test.wantExpiry) { t.Errorf("expected expiry %v got %v", test.wantExpiry, a.exp) } + if test.wantInput == "" { + if got := strings.TrimSpace(stderr.String()); got != "" { + t.Errorf("expected no input parameters, got %q", got) + } + return + } + compJSON(t, stderr.Bytes(), []byte(test.wantInput)) }) } @@ -342,8 +542,12 @@ func TestRoundTripper(t *testing.T) { a.now = now a.stderr = ioutil.Discard + tc := &transport.Config{} + if err := a.UpdateTransportConfig(tc); err != nil { + t.Fatal(err) + } client := http.Client{ - Transport: a.WrapTransport(http.DefaultTransport), + Transport: tc.WrapTransport(http.DefaultTransport), } get := func(t *testing.T, statusCode int) { @@ -411,3 +615,134 @@ func TestRoundTripper(t *testing.T) { // Old token is expired, should refresh automatically without hitting a 401. get(t, http.StatusOK) } + +func TestTLSCredentials(t *testing.T) { + now := time.Now() + + certPool := x509.NewCertPool() + cert, key := genClientCert(t) + if !certPool.AppendCertsFromPEM(cert) { + t.Fatal("failed to add client cert to CertPool") + } + + server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "ok") + })) + server.TLS = &tls.Config{ + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: certPool, + } + server.StartTLS() + defer server.Close() + + a, err := newAuthenticator(newCache(), &api.ExecConfig{ + Command: "./testdata/test-plugin.sh", + APIVersion: "client.authentication.k8s.io/v1alpha1", + }) + if err != nil { + t.Fatal(err) + } + var output *clientauthentication.ExecCredential + a.environ = func() []string { + data, err := runtime.Encode(codecs.LegacyCodec(a.group), output) + if err != nil { + t.Fatal(err) + } + return []string{"TEST_OUTPUT=" + string(data)} + } + a.now = func() time.Time { return now } + a.stderr = ioutil.Discard + + // We're not interested in server's cert, this test is about client cert. + tc := &transport.Config{TLS: transport.TLSConfig{Insecure: true}} + if err := a.UpdateTransportConfig(tc); err != nil { + t.Fatal(err) + } + + get := func(t *testing.T, desc string, wantErr bool) { + t.Run(desc, func(t *testing.T) { + tlsCfg, err := transport.TLSConfigFor(tc) + if err != nil { + t.Fatal("TLSConfigFor:", err) + } + client := http.Client{ + Transport: &http.Transport{TLSClientConfig: tlsCfg}, + } + resp, err := client.Get(server.URL) + switch { + case err != nil && !wantErr: + t.Errorf("got client.Get error: %q, want nil", err) + case err == nil && wantErr: + t.Error("got nil client.Get error, want non-nil") + } + if err == nil { + resp.Body.Close() + } + }) + } + + output = &clientauthentication.ExecCredential{ + Status: &clientauthentication.ExecCredentialStatus{ + ClientCertificateData: string(cert), + ClientKeyData: string(key), + ExpirationTimestamp: &v1.Time{now.Add(time.Hour)}, + }, + } + get(t, "valid TLS cert", false) + + // Advance time to force re-exec. + nCert, nKey := genClientCert(t) + now = now.Add(time.Hour * 2) + output = &clientauthentication.ExecCredential{ + Status: &clientauthentication.ExecCredentialStatus{ + ClientCertificateData: string(nCert), + ClientKeyData: string(nKey), + ExpirationTimestamp: &v1.Time{now.Add(time.Hour)}, + }, + } + get(t, "untrusted TLS cert", true) + + now = now.Add(time.Hour * 2) + output = &clientauthentication.ExecCredential{ + Status: &clientauthentication.ExecCredentialStatus{ + ClientCertificateData: string(cert), + ClientKeyData: string(key), + ExpirationTimestamp: &v1.Time{now.Add(time.Hour)}, + }, + } + get(t, "valid TLS cert again", false) +} + +// genClientCert generates an x509 certificate for testing. Certificate and key +// are returned in PEM encoding. +func genClientCert(t *testing.T) ([]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: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + + 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/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh index 6b9bb100c7b..aa7daad5fd4 100755 --- a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh +++ b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh @@ -1,4 +1,4 @@ -#!/bin/sh -e +#!/bin/bash -e # Copyright 2018 The Kubernetes Authors. # diff --git a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go index 1fe52c5241d..9c3ea0ab8d5 100644 --- a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go +++ b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go @@ -279,7 +279,7 @@ func (p *oidcAuthProvider) idToken() (string, error) { // Persist new config and if successful, update the in memory config. if err = p.persister.Persist(newCfg); err != nil { - return "", fmt.Errorf("could not perist new tokens: %v", err) + return "", fmt.Errorf("could not persist new tokens: %v", err) } p.cfg = newCfg diff --git a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go index 3c1c896addb..e6d7f04934a 100644 --- a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go +++ b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go @@ -140,6 +140,7 @@ func newOpenstackAuthProvider(_ string, config map[string]string, persister rest var ttlDuration time.Duration var err error + glog.Warningf("WARNING: in-tree openstack auth plugin is now deprecated. please use the \"client-keystone-auth\" kubectl/client-go credential plugin instead") ttl, found := config["ttl"] if !found { ttlDuration = DefaultTTLDuration diff --git a/staging/src/k8s.io/client-go/rest/transport.go b/staging/src/k8s.io/client-go/rest/transport.go index b6a0676326e..25c1801b67b 100644 --- a/staging/src/k8s.io/client-go/rest/transport.go +++ b/staging/src/k8s.io/client-go/rest/transport.go @@ -18,6 +18,7 @@ package rest import ( "crypto/tls" + "errors" "net/http" "k8s.io/client-go/plugin/pkg/client/auth/exec" @@ -59,39 +60,10 @@ func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTrip // TransportConfig converts a client config to an appropriate transport config. func (c *Config) TransportConfig() (*transport.Config, error) { - wt := c.WrapTransport - if c.ExecProvider != nil { - provider, err := exec.GetAuthenticator(c.ExecProvider) - if err != nil { - return nil, err - } - if wt != nil { - previousWT := wt - wt = func(rt http.RoundTripper) http.RoundTripper { - return provider.WrapTransport(previousWT(rt)) - } - } else { - wt = provider.WrapTransport - } - } - if c.AuthProvider != nil { - provider, err := GetAuthProvider(c.Host, c.AuthProvider, c.AuthConfigPersister) - if err != nil { - return nil, err - } - if wt != nil { - previousWT := wt - wt = func(rt http.RoundTripper) http.RoundTripper { - return provider.WrapTransport(previousWT(rt)) - } - } else { - wt = provider.WrapTransport - } - } - return &transport.Config{ + conf := &transport.Config{ UserAgent: c.UserAgent, Transport: c.Transport, - WrapTransport: wt, + WrapTransport: c.WrapTransport, TLS: transport.TLSConfig{ Insecure: c.Insecure, ServerName: c.ServerName, @@ -111,5 +83,34 @@ func (c *Config) TransportConfig() (*transport.Config, error) { Extra: c.Impersonate.Extra, }, Dial: c.Dial, - }, nil + } + + if c.ExecProvider != nil && c.AuthProvider != nil { + return nil, errors.New("execProvider and authProvider cannot be used in combination") + } + + if c.ExecProvider != nil { + provider, err := exec.GetAuthenticator(c.ExecProvider) + if err != nil { + return nil, err + } + if err := provider.UpdateTransportConfig(conf); err != nil { + return nil, err + } + } + if c.AuthProvider != nil { + provider, err := GetAuthProvider(c.Host, c.AuthProvider, c.AuthConfigPersister) + if err != nil { + return nil, err + } + wt := conf.WrapTransport + if wt != nil { + conf.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { + return provider.WrapTransport(wt(rt)) + } + } else { + conf.WrapTransport = provider.WrapTransport + } + } + return conf, nil } diff --git a/staging/src/k8s.io/client-go/testing/BUILD b/staging/src/k8s.io/client-go/testing/BUILD index d6821abfb37..5b8684c2653 100644 --- a/staging/src/k8s.io/client-go/testing/BUILD +++ b/staging/src/k8s.io/client-go/testing/BUILD @@ -22,6 +22,8 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], diff --git a/staging/src/k8s.io/client-go/testing/fixture.go b/staging/src/k8s.io/client-go/testing/fixture.go index 13192f92d16..00c4c49fce4 100644 --- a/staging/src/k8s.io/client-go/testing/fixture.go +++ b/staging/src/k8s.io/client-go/testing/fixture.go @@ -25,6 +25,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/json" + "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/watch" restclient "k8s.io/client-go/rest" ) @@ -72,7 +74,6 @@ func ObjectReaction(tracker ObjectTracker) ReactionFunc { return func(action Action) (bool, runtime.Object, error) { ns := action.GetNamespace() gvr := action.GetResource() - // Here and below we need to switch on implementation types, // not on interfaces, as some interfaces are identical // (e.g. UpdateAction and CreateAction), so if we use them, @@ -125,6 +126,34 @@ func ObjectReaction(tracker ObjectTracker) ReactionFunc { } return true, nil, nil + case PatchActionImpl: + obj, err := tracker.Get(gvr, ns, action.GetName()) + if err != nil { + // object is not registered + return false, nil, err + } + + old, err := json.Marshal(obj) + if err != nil { + return true, nil, err + } + // Only supports strategic merge patch + // TODO: Add support for other Patch types + mergedByte, err := strategicpatch.StrategicMergePatch(old, action.GetPatch(), obj) + if err != nil { + return true, nil, err + } + + if err = json.Unmarshal(mergedByte, obj); err != nil { + return true, nil, err + } + + if err = tracker.Update(gvr, obj, ns); err != nil { + return true, nil, err + } + + return true, obj, nil + default: return false, nil, fmt.Errorf("no reaction implemented for %s", action) } diff --git a/staging/src/k8s.io/client-go/tools/bootstrap/token/api/OWNERS b/staging/src/k8s.io/client-go/tools/bootstrap/token/OWNERS similarity index 100% rename from staging/src/k8s.io/client-go/tools/bootstrap/token/api/OWNERS rename to staging/src/k8s.io/client-go/tools/bootstrap/token/OWNERS diff --git a/staging/src/k8s.io/client-go/tools/bootstrap/token/api/doc.go b/staging/src/k8s.io/client-go/tools/bootstrap/token/api/doc.go index b9910c35aab..249e0a059a6 100644 --- a/staging/src/k8s.io/client-go/tools/bootstrap/token/api/doc.go +++ b/staging/src/k8s.io/client-go/tools/bootstrap/token/api/doc.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package api (pkg/bootstrap/token/api) contains constants and types needed for +// Package api (k8s.io/client-go/tools/bootstrap/token/api) contains constants and types needed for // bootstrap tokens as maintained by the BootstrapSigner and TokenCleaner -// controllers (in pkg/controller/bootstrap) +// controllers (in k8s.io/kubernetes/pkg/controller/bootstrap) package api // import "k8s.io/client-go/tools/bootstrap/token/api" diff --git a/staging/src/k8s.io/client-go/tools/bootstrap/token/api/types.go b/staging/src/k8s.io/client-go/tools/bootstrap/token/api/types.go index c30814c0e26..3bea78b1766 100644 --- a/staging/src/k8s.io/client-go/tools/bootstrap/token/api/types.go +++ b/staging/src/k8s.io/client-go/tools/bootstrap/token/api/types.go @@ -86,14 +86,26 @@ const ( // authenticate as. The full username given is "system:bootstrap:". BootstrapUserPrefix = "system:bootstrap:" - // BootstrapGroupPattern is the valid regex pattern that all groups - // assigned to a bootstrap token by BootstrapTokenExtraGroupsKey must match. - // See also ValidateBootstrapGroupName(). - BootstrapGroupPattern = "system:bootstrappers:[a-z0-9:-]{0,255}[a-z0-9]" - // BootstrapDefaultGroup is the default group for bootstrapping bearer // tokens (in addition to any groups from BootstrapTokenExtraGroupsKey). BootstrapDefaultGroup = "system:bootstrappers" + + // BootstrapGroupPattern is the valid regex pattern that all groups + // assigned to a bootstrap token by BootstrapTokenExtraGroupsKey must match. + // See also util.ValidateBootstrapGroupName() + BootstrapGroupPattern = `\Asystem:bootstrappers:[a-z0-9:-]{0,255}[a-z0-9]\z` + + // BootstrapTokenPattern defines the {id}.{secret} regular expression pattern + BootstrapTokenPattern = `\A([a-z0-9]{6})\.([a-z0-9]{16})\z` + + // BootstrapTokenIDPattern defines token's id regular expression pattern + BootstrapTokenIDPattern = `\A([a-z0-9]{6})\z` + + // BootstrapTokenIDBytes defines the number of bytes used for the Bootstrap Token's ID field + BootstrapTokenIDBytes = 6 + + // BootstrapTokenSecretBytes defines the number of bytes used the Bootstrap Token's Secret field + BootstrapTokenSecretBytes = 16 ) // KnownTokenUsages specifies the known functions a token will get. diff --git a/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers.go b/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers.go index d28fd28f2ec..bb1fbeb6580 100644 --- a/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers.go +++ b/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers.go @@ -17,20 +17,101 @@ limitations under the License. package util import ( + "bufio" + "crypto/rand" "fmt" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/client-go/tools/bootstrap/token/api" "regexp" "strings" + + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/tools/bootstrap/token/api" ) -var bootstrapGroupRegexp = regexp.MustCompile(`\A` + api.BootstrapGroupPattern + `\z`) +// validBootstrapTokenChars defines the characters a bootstrap token can consist of +const validBootstrapTokenChars = "0123456789abcdefghijklmnopqrstuvwxyz" + +var ( + // BootstrapTokenRegexp is a compiled regular expression of TokenRegexpString + BootstrapTokenRegexp = regexp.MustCompile(api.BootstrapTokenPattern) + // BootstrapTokenIDRegexp is a compiled regular expression of TokenIDRegexpString + BootstrapTokenIDRegexp = regexp.MustCompile(api.BootstrapTokenIDPattern) + // BootstrapGroupRegexp is a compiled regular expression of BootstrapGroupPattern + BootstrapGroupRegexp = regexp.MustCompile(api.BootstrapGroupPattern) +) + +// GenerateBootstrapToken generates a new, random Bootstrap Token. +func GenerateBootstrapToken() (string, error) { + tokenID, err := randBytes(api.BootstrapTokenIDBytes) + if err != nil { + return "", err + } + + tokenSecret, err := randBytes(api.BootstrapTokenSecretBytes) + if err != nil { + return "", err + } + + return TokenFromIDAndSecret(tokenID, tokenSecret), nil +} + +// randBytes returns a random string consisting of the characters in +// validBootstrapTokenChars, with the length customized by the parameter +func randBytes(length int) (string, error) { + // len("0123456789abcdefghijklmnopqrstuvwxyz") = 36 which doesn't evenly divide + // the possible values of a byte: 256 mod 36 = 4. Discard any random bytes we + // read that are >= 252 so the bytes we evenly divide the character set. + const maxByteValue = 252 + + var ( + b byte + err error + token = make([]byte, length) + ) + + reader := bufio.NewReaderSize(rand.Reader, length*2) + for i := range token { + for { + if b, err = reader.ReadByte(); err != nil { + return "", err + } + if b < maxByteValue { + break + } + } + + token[i] = validBootstrapTokenChars[int(b)%len(validBootstrapTokenChars)] + } + + return string(token), nil +} + +// TokenFromIDAndSecret returns the full token which is of the form "{id}.{secret}" +func TokenFromIDAndSecret(id, secret string) string { + return fmt.Sprintf("%s.%s", id, secret) +} + +// IsValidBootstrapToken returns whether the given string is valid as a Bootstrap Token and +// in other words satisfies the BootstrapTokenRegexp +func IsValidBootstrapToken(token string) bool { + return BootstrapTokenRegexp.MatchString(token) +} + +// IsValidBootstrapTokenID returns whether the given string is valid as a Bootstrap Token ID and +// in other words satisfies the BootstrapTokenIDRegexp +func IsValidBootstrapTokenID(tokenID string) bool { + return BootstrapTokenIDRegexp.MatchString(tokenID) +} + +// BootstrapTokenSecretName returns the expected name for the Secret storing the +// Bootstrap Token in the Kubernetes API. +func BootstrapTokenSecretName(tokenID string) string { + return fmt.Sprintf("%s%s", api.BootstrapTokenSecretPrefix, tokenID) +} // ValidateBootstrapGroupName checks if the provided group name is a valid // bootstrap group name. Returns nil if valid or a validation error if invalid. -// TODO(mattmoyer): this validation should migrate out to client-go (see https://github.com/kubernetes/client-go/issues/114) func ValidateBootstrapGroupName(name string) error { - if bootstrapGroupRegexp.Match([]byte(name)) { + if BootstrapGroupRegexp.Match([]byte(name)) { return nil } return fmt.Errorf("bootstrap group %q is invalid (must match %s)", name, api.BootstrapGroupPattern) @@ -46,7 +127,7 @@ func ValidateUsages(usages []string) error { } } if len(invalidUsages) > 0 { - return fmt.Errorf("invalide bootstrap token usage string: %s, valid usage options: %s", strings.Join(invalidUsages.List(), ","), strings.Join(api.KnownTokenUsages, ",")) + return fmt.Errorf("invalid bootstrap token usage string: %s, valid usage options: %s", strings.Join(invalidUsages.List(), ","), strings.Join(api.KnownTokenUsages, ",")) } return nil } diff --git a/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go b/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go index 915bf754026..a1fe6092ff6 100644 --- a/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go +++ b/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go @@ -21,6 +21,143 @@ import ( "testing" ) +func TestGenerateBootstrapToken(t *testing.T) { + token, err := GenerateBootstrapToken() + if err != nil { + t.Fatalf("GenerateBootstrapToken returned an unexpected error: %+v", err) + } + if !IsValidBootstrapToken(token) { + t.Errorf("GenerateBootstrapToken didn't generate a valid token: %q", token) + } +} + +func TestRandBytes(t *testing.T) { + var randTest = []int{ + 0, + 1, + 2, + 3, + 100, + } + + for _, rt := range randTest { + actual, err := randBytes(rt) + if err != nil { + t.Errorf("failed randBytes: %v", err) + } + if len(actual) != rt { + t.Errorf("failed randBytes:\n\texpected: %d\n\t actual: %d\n", rt, len(actual)) + } + } +} + +func TestTokenFromIDAndSecret(t *testing.T) { + var tests = []struct { + id string + secret string + expected string + }{ + {"foo", "bar", "foo.bar"}, // should use default + {"abcdef", "abcdef0123456789", "abcdef.abcdef0123456789"}, + {"h", "b", "h.b"}, + } + for _, rt := range tests { + actual := TokenFromIDAndSecret(rt.id, rt.secret) + if actual != rt.expected { + t.Errorf( + "failed TokenFromIDAndSecret:\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + } +} + +func TestIsValidBootstrapToken(t *testing.T) { + var tests = []struct { + token string + expected bool + }{ + {token: "", expected: false}, + {token: ".", expected: false}, + {token: "1234567890123456789012", expected: false}, // invalid parcel size + {token: "12345.1234567890123456", expected: false}, // invalid parcel size + {token: ".1234567890123456", expected: false}, // invalid parcel size + {token: "123456.", expected: false}, // invalid parcel size + {token: "123456:1234567890.123456", expected: false}, // invalid separation + {token: "abcdef:1234567890123456", expected: false}, // invalid separation + {token: "Abcdef.1234567890123456", expected: false}, // invalid token id + {token: "123456.AABBCCDDEEFFGGHH", expected: false}, // invalid token secret + {token: "123456.AABBCCD-EEFFGGHH", expected: false}, // invalid character + {token: "abc*ef.1234567890123456", expected: false}, // invalid character + {token: "abcdef.1234567890123456", expected: true}, + {token: "123456.aabbccddeeffgghh", expected: true}, + {token: "ABCDEF.abcdef0123456789", expected: false}, + {token: "abcdef.abcdef0123456789", expected: true}, + {token: "123456.1234560123456789", expected: true}, + } + for _, rt := range tests { + actual := IsValidBootstrapToken(rt.token) + if actual != rt.expected { + t.Errorf( + "failed IsValidBootstrapToken for the token %q\n\texpected: %t\n\t actual: %t", + rt.token, + rt.expected, + actual, + ) + } + } +} + +func TestIsValidBootstrapTokenID(t *testing.T) { + var tests = []struct { + tokenID string + expected bool + }{ + {tokenID: "", expected: false}, + {tokenID: "1234567890123456789012", expected: false}, + {tokenID: "12345", expected: false}, + {tokenID: "Abcdef", expected: false}, + {tokenID: "ABCDEF", expected: false}, + {tokenID: "abcdef.", expected: false}, + {tokenID: "abcdef", expected: true}, + {tokenID: "123456", expected: true}, + } + for _, rt := range tests { + actual := IsValidBootstrapTokenID(rt.tokenID) + if actual != rt.expected { + t.Errorf( + "failed IsValidBootstrapTokenID for the token %q\n\texpected: %t\n\t actual: %t", + rt.tokenID, + rt.expected, + actual, + ) + } + } +} + +func TestBootstrapTokenSecretName(t *testing.T) { + var tests = []struct { + tokenID string + expected string + }{ + {"foo", "bootstrap-token-foo"}, + {"bar", "bootstrap-token-bar"}, + {"", "bootstrap-token-"}, + {"abcdef", "bootstrap-token-abcdef"}, + } + for _, rt := range tests { + actual := BootstrapTokenSecretName(rt.tokenID) + if actual != rt.expected { + t.Errorf( + "failed BootstrapTokenSecretName:\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + } +} + func TestValidateBootstrapGroupName(t *testing.T) { tests := []struct { name string diff --git a/staging/src/k8s.io/client-go/tools/cache/reflector.go b/staging/src/k8s.io/client-go/tools/cache/reflector.go index 054a7373c96..dfe3191dc3e 100644 --- a/staging/src/k8s.io/client-go/tools/cache/reflector.go +++ b/staging/src/k8s.io/client-go/tools/cache/reflector.go @@ -76,8 +76,6 @@ type Reflector struct { var ( // We try to spread the load on apiserver by setting timeouts for // watch requests - it is random in [minWatchTimeout, 2*minWatchTimeout]. - // However, it can be modified to avoid periodic resync to break the - // TCP connection. minWatchTimeout = 5 * time.Minute ) diff --git a/staging/src/k8s.io/client-go/tools/record/event.go b/staging/src/k8s.io/client-go/tools/record/event.go index cc665d74e63..168dfa80c56 100644 --- a/staging/src/k8s.io/client-go/tools/record/event.go +++ b/staging/src/k8s.io/client-go/tools/record/event.go @@ -72,6 +72,9 @@ type EventRecorder interface { // PastEventf is just like Eventf, but with an option to specify the event's 'timestamp' field. PastEventf(object runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) + + // AnnotatedEventf is just like eventf, but with annotations attached + AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) } // EventBroadcaster knows how to receive events and send them to any EventSink, watcher, or log. @@ -250,7 +253,7 @@ type recorderImpl struct { clock clock.Clock } -func (recorder *recorderImpl) generateEvent(object runtime.Object, timestamp metav1.Time, eventtype, reason, message string) { +func (recorder *recorderImpl) generateEvent(object runtime.Object, annotations map[string]string, timestamp metav1.Time, eventtype, reason, message string) { ref, err := ref.GetReference(recorder.scheme, object) if err != nil { glog.Errorf("Could not construct reference to: '%#v' due to: '%v'. Will not report event: '%v' '%v' '%v'", object, err, eventtype, reason, message) @@ -262,7 +265,7 @@ func (recorder *recorderImpl) generateEvent(object runtime.Object, timestamp met return } - event := recorder.makeEvent(ref, eventtype, reason, message) + event := recorder.makeEvent(ref, annotations, eventtype, reason, message) event.Source = recorder.source go func() { @@ -281,7 +284,7 @@ func validateEventType(eventtype string) bool { } func (recorder *recorderImpl) Event(object runtime.Object, eventtype, reason, message string) { - recorder.generateEvent(object, metav1.Now(), eventtype, reason, message) + recorder.generateEvent(object, nil, metav1.Now(), eventtype, reason, message) } func (recorder *recorderImpl) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) { @@ -289,10 +292,14 @@ func (recorder *recorderImpl) Eventf(object runtime.Object, eventtype, reason, m } func (recorder *recorderImpl) PastEventf(object runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) { - recorder.generateEvent(object, timestamp, eventtype, reason, fmt.Sprintf(messageFmt, args...)) + recorder.generateEvent(object, nil, timestamp, eventtype, reason, fmt.Sprintf(messageFmt, args...)) } -func (recorder *recorderImpl) makeEvent(ref *v1.ObjectReference, eventtype, reason, message string) *v1.Event { +func (recorder *recorderImpl) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { + recorder.generateEvent(object, annotations, metav1.Now(), eventtype, reason, fmt.Sprintf(messageFmt, args...)) +} + +func (recorder *recorderImpl) makeEvent(ref *v1.ObjectReference, annotations map[string]string, eventtype, reason, message string) *v1.Event { t := metav1.Time{Time: recorder.clock.Now()} namespace := ref.Namespace if namespace == "" { @@ -300,8 +307,9 @@ func (recorder *recorderImpl) makeEvent(ref *v1.ObjectReference, eventtype, reas } return &v1.Event{ ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%v.%x", ref.Name, t.UnixNano()), - Namespace: namespace, + Name: fmt.Sprintf("%v.%x", ref.Name, t.UnixNano()), + Namespace: namespace, + Annotations: annotations, }, InvolvedObject: *ref, Reason: reason, diff --git a/staging/src/k8s.io/client-go/tools/record/fake.go b/staging/src/k8s.io/client-go/tools/record/fake.go index c0e8eedbb73..6e031daaff8 100644 --- a/staging/src/k8s.io/client-go/tools/record/fake.go +++ b/staging/src/k8s.io/client-go/tools/record/fake.go @@ -45,6 +45,10 @@ func (f *FakeRecorder) Eventf(object runtime.Object, eventtype, reason, messageF func (f *FakeRecorder) PastEventf(object runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) { } +func (f *FakeRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { + f.Eventf(object, eventtype, reason, messageFmt, args) +} + // NewFakeRecorder creates new fake event recorder with event channel with // buffer of given size. func NewFakeRecorder(bufferSize int) *FakeRecorder { diff --git a/staging/src/k8s.io/client-go/transport/cache.go b/staging/src/k8s.io/client-go/transport/cache.go index 540af849460..7cffe2a5faf 100644 --- a/staging/src/k8s.io/client-go/transport/cache.go +++ b/staging/src/k8s.io/client-go/transport/cache.go @@ -43,6 +43,7 @@ type tlsCacheKey struct { caData string certData string keyData string + getCert string serverName string dial string } @@ -52,7 +53,7 @@ func (t tlsCacheKey) String() string { if len(t.keyData) > 0 { keyText = "" } - return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, serverName:%s, dial:%s", t.insecure, t.caData, t.certData, keyText, t.serverName, t.dial) + return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, getCert: %s, serverName:%s, dial:%s", t.insecure, t.caData, t.certData, keyText, t.getCert, t.serverName, t.dial) } func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { @@ -109,6 +110,7 @@ func tlsConfigKey(c *Config) (tlsCacheKey, error) { caData: string(c.TLS.CAData), certData: string(c.TLS.CertData), keyData: string(c.TLS.KeyData), + getCert: fmt.Sprintf("%p", c.TLS.GetCert), serverName: c.TLS.ServerName, dial: fmt.Sprintf("%p", c.Dial), }, nil diff --git a/staging/src/k8s.io/client-go/transport/cache_test.go b/staging/src/k8s.io/client-go/transport/cache_test.go index 61f3affc62c..9b740cdeca8 100644 --- a/staging/src/k8s.io/client-go/transport/cache_test.go +++ b/staging/src/k8s.io/client-go/transport/cache_test.go @@ -18,6 +18,7 @@ package transport import ( "context" + "crypto/tls" "net" "net/http" "testing" @@ -54,6 +55,7 @@ func TestTLSConfigKey(t *testing.T) { // Make sure config fields that affect the tls config affect the cache key dialer := net.Dialer{} + getCert := func() (*tls.Certificate, error) { return nil, nil } uniqueConfigurations := map[string]*Config{ "no tls": {}, "dialer": {Dial: dialer.DialContext}, @@ -106,6 +108,24 @@ func TestTLSConfigKey(t *testing.T) { KeyData: []byte{1}, }, }, + "getCert1": { + TLS: TLSConfig{ + KeyData: []byte{1}, + GetCert: getCert, + }, + }, + "getCert2": { + TLS: TLSConfig{ + KeyData: []byte{1}, + GetCert: func() (*tls.Certificate, error) { return nil, nil }, + }, + }, + "getCert1, key 2": { + TLS: TLSConfig{ + KeyData: []byte{2}, + GetCert: getCert, + }, + }, } for nameA, valueA := range uniqueConfigurations { for nameB, valueB := range uniqueConfigurations { diff --git a/staging/src/k8s.io/client-go/transport/config.go b/staging/src/k8s.io/client-go/transport/config.go index 90f705d25f5..4081c23e7ff 100644 --- a/staging/src/k8s.io/client-go/transport/config.go +++ b/staging/src/k8s.io/client-go/transport/config.go @@ -18,6 +18,7 @@ package transport import ( "context" + "crypto/tls" "net" "net/http" ) @@ -84,7 +85,12 @@ func (c *Config) HasTokenAuth() bool { // HasCertAuth returns whether the configuration has certificate authentication or not. func (c *Config) HasCertAuth() bool { - return len(c.TLS.CertData) != 0 || len(c.TLS.CertFile) != 0 + return (len(c.TLS.CertData) != 0 || len(c.TLS.CertFile) != 0) && (len(c.TLS.KeyData) != 0 || len(c.TLS.KeyFile) != 0) +} + +// HasCertCallbacks returns whether the configuration has certificate callback or not. +func (c *Config) HasCertCallback() bool { + return c.TLS.GetCert != nil } // TLSConfig holds the information needed to set up a TLS transport. @@ -99,4 +105,6 @@ type TLSConfig struct { CAData []byte // Bytes of the PEM-encoded server trusted root certificates. Supercedes CAFile. CertData []byte // Bytes of the PEM-encoded client certificate. Supercedes CertFile. KeyData []byte // Bytes of the PEM-encoded client key. Supercedes KeyFile. + + GetCert func() (*tls.Certificate, error) // Callback that returns a TLS client certificate. CertData, CertFile, KeyData and KeyFile supercede this field. } diff --git a/staging/src/k8s.io/client-go/transport/transport.go b/staging/src/k8s.io/client-go/transport/transport.go index c2bb7ae5e44..c19739fdfe8 100644 --- a/staging/src/k8s.io/client-go/transport/transport.go +++ b/staging/src/k8s.io/client-go/transport/transport.go @@ -28,7 +28,7 @@ import ( // or transport level security defined by the provided Config. func New(config *Config) (http.RoundTripper, error) { // Set transport level security - if config.Transport != nil && (config.HasCA() || config.HasCertAuth() || config.TLS.Insecure) { + if config.Transport != nil && (config.HasCA() || config.HasCertAuth() || config.HasCertCallback() || config.TLS.Insecure) { return nil, fmt.Errorf("using a custom transport with TLS certificate options or the insecure flag is not allowed") } @@ -52,7 +52,7 @@ func New(config *Config) (http.RoundTripper, error) { // TLSConfigFor returns a tls.Config that will provide the transport level security defined // by the provided Config. Will return nil if no transport level security is requested. func TLSConfigFor(c *Config) (*tls.Config, error) { - if !(c.HasCA() || c.HasCertAuth() || c.TLS.Insecure || len(c.TLS.ServerName) > 0) { + if !(c.HasCA() || c.HasCertAuth() || c.HasCertCallback() || c.TLS.Insecure || len(c.TLS.ServerName) > 0) { return nil, nil } if c.HasCA() && c.TLS.Insecure { @@ -75,12 +75,40 @@ func TLSConfigFor(c *Config) (*tls.Config, error) { tlsConfig.RootCAs = rootCertPool(c.TLS.CAData) } + var staticCert *tls.Certificate if c.HasCertAuth() { + // If key/cert were provided, verify them before setting up + // tlsConfig.GetClientCertificate. cert, err := tls.X509KeyPair(c.TLS.CertData, c.TLS.KeyData) if err != nil { return nil, err } - tlsConfig.Certificates = []tls.Certificate{cert} + staticCert = &cert + } + + if c.HasCertAuth() || c.HasCertCallback() { + tlsConfig.GetClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { + // Note: static key/cert data always take precedence over cert + // callback. + if staticCert != nil { + return staticCert, nil + } + if c.HasCertCallback() { + cert, err := c.TLS.GetCert() + if err != nil { + return nil, err + } + // GetCert may return empty value, meaning no cert. + if cert != nil { + return cert, nil + } + } + + // Both c.TLS.CertData/KeyData were unset and GetCert didn't return + // anything. Return an empty tls.Certificate, no client cert will + // be sent to the server. + return &tls.Certificate{}, nil + } } return tlsConfig, nil diff --git a/staging/src/k8s.io/client-go/transport/transport_test.go b/staging/src/k8s.io/client-go/transport/transport_test.go index 8de751562d6..2e9896a08b1 100644 --- a/staging/src/k8s.io/client-go/transport/transport_test.go +++ b/staging/src/k8s.io/client-go/transport/transport_test.go @@ -17,6 +17,8 @@ limitations under the License. package transport import ( + "crypto/tls" + "errors" "net/http" "testing" ) @@ -94,6 +96,8 @@ func TestNew(t *testing.T) { Config *Config Err bool TLS bool + TLSCert bool + TLSErr bool Default bool }{ "default transport": { @@ -135,7 +139,8 @@ func TestNew(t *testing.T) { }, "cert transport": { - TLS: true, + TLS: true, + TLSCert: true, Config: &Config{ TLS: TLSConfig{ CAData: []byte(rootCACert), @@ -165,7 +170,8 @@ func TestNew(t *testing.T) { }, }, "key data overriding bad file cert transport": { - TLS: true, + TLS: true, + TLSCert: true, Config: &Config{ TLS: TLSConfig{ CAData: []byte(rootCACert), @@ -175,37 +181,108 @@ func TestNew(t *testing.T) { }, }, }, + "callback cert and key": { + TLS: true, + TLSCert: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + crt, err := tls.X509KeyPair([]byte(certData), []byte(keyData)) + return &crt, err + }, + }, + }, + }, + "cert callback error": { + TLS: true, + TLSCert: true, + TLSErr: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + return nil, errors.New("GetCert failure") + }, + }, + }, + }, + "cert data overrides empty callback result": { + TLS: true, + TLSCert: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + return nil, nil + }, + CertData: []byte(certData), + KeyData: []byte(keyData), + }, + }, + }, + "callback returns nothing": { + TLS: true, + TLSCert: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + return nil, nil + }, + }, + }, + }, } for k, testCase := range testCases { - transport, err := New(testCase.Config) - switch { - case testCase.Err && err == nil: - t.Errorf("%s: unexpected non-error", k) - continue - case !testCase.Err && err != nil: - t.Errorf("%s: unexpected error: %v", k, err) - continue - } + t.Run(k, func(t *testing.T) { + rt, err := New(testCase.Config) + switch { + case testCase.Err && err == nil: + t.Fatal("unexpected non-error") + case !testCase.Err && err != nil: + t.Fatalf("unexpected error: %v", err) + } + if testCase.Err { + return + } - switch { - case testCase.Default && transport != http.DefaultTransport: - t.Errorf("%s: expected the default transport, got %#v", k, transport) - continue - case !testCase.Default && transport == http.DefaultTransport: - t.Errorf("%s: expected non-default transport, got %#v", k, transport) - continue - } + switch { + case testCase.Default && rt != http.DefaultTransport: + t.Fatalf("got %#v, expected the default transport", rt) + case !testCase.Default && rt == http.DefaultTransport: + t.Fatalf("got %#v, expected non-default transport", rt) + } - // We only know how to check TLSConfig on http.Transports - if transport, ok := transport.(*http.Transport); ok { + // We only know how to check TLSConfig on http.Transports + transport := rt.(*http.Transport) switch { case testCase.TLS && transport.TLSClientConfig == nil: - t.Errorf("%s: expected TLSClientConfig, got %#v", k, transport) - continue + t.Fatalf("got %#v, expected TLSClientConfig", transport) case !testCase.TLS && transport.TLSClientConfig != nil: - t.Errorf("%s: expected no TLSClientConfig, got %#v", k, transport) - continue + t.Fatalf("got %#v, expected no TLSClientConfig", transport) } - } + if !testCase.TLS { + return + } + + switch { + case testCase.TLSCert && transport.TLSClientConfig.GetClientCertificate == nil: + t.Fatalf("got %#v, expected TLSClientConfig.GetClientCertificate", transport.TLSClientConfig) + case !testCase.TLSCert && transport.TLSClientConfig.GetClientCertificate != nil: + t.Fatalf("got %#v, expected no TLSClientConfig.GetClientCertificate", transport.TLSClientConfig) + } + if !testCase.TLSCert { + return + } + + _, err = transport.TLSClientConfig.GetClientCertificate(nil) + switch { + case testCase.TLSErr && err == nil: + t.Error("got nil error from GetClientCertificate, expected non-nil") + case !testCase.TLSErr && err != nil: + t.Errorf("got error from GetClientCertificate: %q, expected nil", err) + } + }) } } diff --git a/staging/src/k8s.io/client-go/util/cert/io.go b/staging/src/k8s.io/client-go/util/cert/io.go index 374e8cae658..a57bf09d5eb 100644 --- a/staging/src/k8s.io/client-go/util/cert/io.go +++ b/staging/src/k8s.io/client-go/util/cert/io.go @@ -88,7 +88,8 @@ func WriteKey(keyPath string, data []byte) error { // can't find one, it will generate a new key and store it there. func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err error) { loadedData, err := ioutil.ReadFile(keyPath) - if err == nil { + // Call verifyKeyData to ensure the file wasn't empty/corrupt. + if err == nil && verifyKeyData(loadedData) { return loadedData, false, err } if !os.IsNotExist(err) { @@ -181,3 +182,12 @@ func PublicKeysFromFile(file string) ([]interface{}, error) { } return keys, nil } + +// verifyKeyData returns true if the provided data appears to be a valid private key. +func verifyKeyData(data []byte) bool { + if len(data) == 0 { + return false + } + _, err := ParsePrivateKeyPEM(data) + return err == nil +} diff --git a/staging/src/k8s.io/code-generator/Godeps/Godeps.json b/staging/src/k8s.io/code-generator/Godeps/Godeps.json index 15a35e1fe01..a4aca68986b 100644 --- a/staging/src/k8s.io/code-generator/Godeps/Godeps.json +++ b/staging/src/k8s.io/code-generator/Godeps/Godeps.json @@ -260,11 +260,11 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/generators", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" } ] } diff --git a/staging/src/k8s.io/code-generator/SECURITY_CONTACTS b/staging/src/k8s.io/code-generator/SECURITY_CONTACTS new file mode 100644 index 00000000000..0648a8ebff7 --- /dev/null +++ b/staging/src/k8s.io/code-generator/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# 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/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/staging/src/k8s.io/code-generator/generate-groups.sh b/staging/src/k8s.io/code-generator/generate-groups.sh index b92296d96d7..6707221e42e 100755 --- a/staging/src/k8s.io/code-generator/generate-groups.sh +++ b/staging/src/k8s.io/code-generator/generate-groups.sh @@ -46,7 +46,13 @@ APIS_PKG="$3" GROUPS_WITH_VERSIONS="$4" shift 4 -go install ./$(dirname "${0}")/cmd/{defaulter-gen,client-gen,lister-gen,informer-gen,deepcopy-gen} +( + # To support running this script from anywhere, we have to first cd into this directory + # so we can install the tools. + cd $(dirname "${0}") + go install ./cmd/{defaulter-gen,client-gen,lister-gen,informer-gen,deepcopy-gen} +) + function codegen::join() { local IFS="$1"; shift; echo "$*"; } # enumerate group versions diff --git a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json index 9a0970403aa..6dfae40f1dc 100644 --- a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json +++ b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json @@ -148,27 +148,27 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/protoc-gen-go/descriptor", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -216,7 +216,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "2ddf6d758266fcb080a4f9e054b9f292c85e6798" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/mailru/easyjson/buffer", @@ -1586,6 +1586,10 @@ "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" @@ -1654,6 +1658,10 @@ "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" @@ -1676,27 +1684,27 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/aggregator", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" } ] } diff --git a/staging/src/k8s.io/kube-aggregator/SECURITY_CONTACTS b/staging/src/k8s.io/kube-aggregator/SECURITY_CONTACTS new file mode 100644 index 00000000000..0648a8ebff7 --- /dev/null +++ b/staging/src/k8s.io/kube-aggregator/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# 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/ + +cjcullen +jessfraz +liggitt +philips +tallclair 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 a9bbe08a1fd..367b60dbeb8 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 @@ -176,6 +176,22 @@ func (c *AvailableConditionController) sync(key string) error { } if service.Spec.Type == v1.ServiceTypeClusterIP { + // if we have a cluster IP service, it must be listening on 443 and we can check that + foundPort := false + for _, port := range service.Spec.Ports { + if port.Port == 443 { + foundPort = true + } + } + if !foundPort { + availableCondition.Status = apiregistration.ConditionFalse + 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) + return err + } + endpoints, err := c.endpointsLister.Endpoints(apiService.Spec.Service.Namespace).Get(apiService.Spec.Service.Name) if apierrors.IsNotFound(err) { availableCondition.Status = apiregistration.ConditionFalse 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 d0dbff24776..d82a0a0bd39 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 @@ -55,6 +55,9 @@ func newService(namespace, name string) *v1.Service { ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name}, Spec: v1.ServiceSpec{ Type: v1.ServiceTypeClusterIP, + Ports: []v1.ServicePort{ + {Port: 443}, + }, }, } } @@ -110,6 +113,27 @@ func TestSync(t *testing.T) { Message: `service/bar in "foo" is not present`, }, }, + { + name: "service on bad port", + apiServiceName: "remote.group", + apiServices: []*apiregistration.APIService{newRemoteAPIService("remote.group")}, + services: []*v1.Service{{ + ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"}, + Spec: v1.ServiceSpec{ + Type: v1.ServiceTypeClusterIP, + Ports: []v1.ServicePort{ + {Port: 6443}, + }, + }, + }}, + endpoints: []*v1.Endpoints{newEndpointsWithAddress("foo", "bar")}, + expectedAvailability: apiregistration.APIServiceCondition{ + Type: apiregistration.Available, + Status: apiregistration.ConditionFalse, + Reason: "ServicePortError", + Message: `service/bar in "foo" is not listening on port 443`, + }, + }, { name: "no endpoints", apiServiceName: "remote.group", diff --git a/staging/src/k8s.io/metrics/Godeps/Godeps.json b/staging/src/k8s.io/metrics/Godeps/Godeps.json index 9415da5b540..ddc8bd40d68 100644 --- a/staging/src/k8s.io/metrics/Godeps/Godeps.json +++ b/staging/src/k8s.io/metrics/Godeps/Godeps.json @@ -6,6 +6,10 @@ "./..." ], "Deps": [ + { + "ImportPath": "github.com/davecgh/go-spew/spew", + "Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8" + }, { "ImportPath": "github.com/ghodss/yaml", "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" @@ -24,23 +28,23 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -72,7 +76,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "2ddf6d758266fcb080a4f9e054b9f292c85e6798" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/modern-go/concurrent", @@ -362,6 +366,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/net", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -374,6 +382,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" @@ -398,6 +410,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" @@ -422,6 +438,10 @@ "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" @@ -458,6 +478,10 @@ "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" @@ -465,6 +489,10 @@ { "ImportPath": "k8s.io/client-go/util/integer", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" } ] } diff --git a/staging/src/k8s.io/metrics/SECURITY_CONTACTS b/staging/src/k8s.io/metrics/SECURITY_CONTACTS new file mode 100644 index 00000000000..0648a8ebff7 --- /dev/null +++ b/staging/src/k8s.io/metrics/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# 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/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json index f0635220789..1a7e9da2d73 100644 --- a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json @@ -140,27 +140,27 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/protoc-gen-go/descriptor", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -208,7 +208,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "2ddf6d758266fcb080a4f9e054b9f292c85e6798" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/mailru/easyjson/buffer", @@ -1554,6 +1554,10 @@ "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" @@ -1622,6 +1626,10 @@ "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" @@ -1640,23 +1648,23 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" } ] } diff --git a/staging/src/k8s.io/sample-apiserver/SECURITY_CONTACTS b/staging/src/k8s.io/sample-apiserver/SECURITY_CONTACTS new file mode 100644 index 00000000000..0648a8ebff7 --- /dev/null +++ b/staging/src/k8s.io/sample-apiserver/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# 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/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/staging/src/k8s.io/sample-controller/Godeps/Godeps.json b/staging/src/k8s.io/sample-controller/Godeps/Godeps.json index 9d2e0acd719..8986162cf0f 100644 --- a/staging/src/k8s.io/sample-controller/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-controller/Godeps/Godeps.json @@ -32,23 +32,23 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -92,7 +92,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "2ddf6d758266fcb080a4f9e054b9f292c85e6798" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/modern-go/concurrent", @@ -974,6 +974,10 @@ "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" @@ -1046,6 +1050,10 @@ "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" @@ -1068,7 +1076,7 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5" + "Rev": "8a9b82f00b3a86eac24681da3f9fe6c34c01cea2" } ] } diff --git a/staging/src/k8s.io/sample-controller/SECURITY_CONTACTS b/staging/src/k8s.io/sample-controller/SECURITY_CONTACTS new file mode 100644 index 00000000000..0648a8ebff7 --- /dev/null +++ b/staging/src/k8s.io/sample-controller/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# 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/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/test/conformance/testdata/conformance.txt b/test/conformance/testdata/conformance.txt index 9411ea594f1..4b72cee5fc6 100755 --- a/test/conformance/testdata/conformance.txt +++ b/test/conformance/testdata/conformance.txt @@ -6,6 +6,10 @@ test/e2e/apimachinery/garbage_collector.go: "should orphan RS created by deploym test/e2e/apimachinery/garbage_collector.go: "should keep the rc around until all its pods are deleted if the deleteOptions says so" test/e2e/apimachinery/garbage_collector.go: "should not delete dependents that have both valid owner and owner that's waiting for dependents to be deleted" test/e2e/apimachinery/garbage_collector.go: "should not be blocked by dependency circle" +test/e2e/apimachinery/watch.go: "should observe add, update, and delete watch notifications on configmaps" +test/e2e/apimachinery/watch.go: "should be able to start watching from a specific resource version" +test/e2e/apimachinery/watch.go: "should be able to restart watching from the last resource version observed by the previous watch" +test/e2e/apimachinery/watch.go: "should observe an object deletion if it stops meeting the requirements of the selector" test/e2e/apps/daemon_set.go: "should run and stop simple daemon" test/e2e/apps/daemon_set.go: "should run and stop complex daemon" test/e2e/apps/daemon_set.go: "should retry creating failed daemon pods" diff --git a/test/e2e/apimachinery/BUILD b/test/e2e/apimachinery/BUILD index 8d2164afae9..dedd9067da2 100644 --- a/test/e2e/apimachinery/BUILD +++ b/test/e2e/apimachinery/BUILD @@ -59,6 +59,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", diff --git a/test/e2e/apimachinery/aggregator.go b/test/e2e/apimachinery/aggregator.go index a1139655e41..9b08fcbdc1b 100644 --- a/test/e2e/apimachinery/aggregator.go +++ b/test/e2e/apimachinery/aggregator.go @@ -319,7 +319,16 @@ func TestSampleAPIServer(f *framework.Framework, image string) { }) framework.ExpectNoError(err, "creating apiservice %s with namespace %s", "v1alpha1.wardle.k8s.io", namespace) - err = wait.Poll(100*time.Millisecond, 30*time.Second, func() (bool, error) { + var ( + currentAPIService *apiregistrationv1beta1.APIService + currentPods *v1.PodList + ) + + err = pollTimed(100*time.Millisecond, 60*time.Second, func() (bool, error) { + + currentAPIService, _ = aggrclient.ApiregistrationV1beta1().APIServices().Get("v1alpha1.wardle.k8s.io", metav1.GetOptions{}) + currentPods, _ = client.CoreV1().Pods(namespace).List(metav1.ListOptions{}) + request := restClient.Get().AbsPath("/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders") request.SetHeader("Accept", "application/json") _, err := request.DoRaw() @@ -337,7 +346,23 @@ func TestSampleAPIServer(f *framework.Framework, image string) { return false, err } return true, nil - }) + }, "Waited %s for the sample-apiserver to be ready to handle requests.") + if err != nil { + currentAPIServiceJSON, _ := json.Marshal(currentAPIService) + framework.Logf("current APIService: %s", string(currentAPIServiceJSON)) + + currentPodsJSON, _ := json.Marshal(currentPods) + framework.Logf("current pods: %s", string(currentPodsJSON)) + + if currentPods != nil { + for _, pod := range currentPods.Items { + for _, container := range pod.Spec.Containers { + logs, err := framework.GetPodLogs(client, namespace, pod.Name, container.Name) + framework.Logf("logs of %s/%s (error: %v): %s", pod.Name, container.Name, err, logs) + } + } + } + } framework.ExpectNoError(err, "gave up waiting for apiservice wardle to come up successfully") flunderName := generateFlunderName("rest-flunder") @@ -435,6 +460,17 @@ func TestSampleAPIServer(f *framework.Framework, image string) { cleanTest(client, aggrclient, namespace) } +// pollTimed will call Poll but time how long Poll actually took. +// It will then framework.logf the msg with the duration of the Poll. +// It is assumed that msg will contain one %s for the elapsed time. +func pollTimed(interval, timeout time.Duration, condition wait.ConditionFunc, msg string) error { + defer func(start time.Time, msg string) { + elapsed := time.Since(start) + framework.Logf(msg, elapsed) + }(time.Now(), msg) + return wait.Poll(interval, timeout, condition) +} + func validateErrorWithDebugInfo(f *framework.Framework, err error, pods *v1.PodList, msg string, fields ...interface{}) { if err != nil { namespace := f.Namespace.Name diff --git a/test/e2e/apimachinery/garbage_collector.go b/test/e2e/apimachinery/garbage_collector.go index f9e3c74938c..9bb8d0a3850 100644 --- a/test/e2e/apimachinery/garbage_collector.go +++ b/test/e2e/apimachinery/garbage_collector.go @@ -33,6 +33,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/storage/names" clientset "k8s.io/client-go/kubernetes" @@ -175,7 +176,7 @@ func verifyRemainingDeploymentsReplicaSetsPods( } if len(deployments.Items) != deploymentNum { ret = false - By(fmt.Sprintf("expected %d Deploymentss, got %d Deployments", deploymentNum, len(deployments.Items))) + By(fmt.Sprintf("expected %d Deployments, got %d Deployments", deploymentNum, len(deployments.Items))) } pods, err := clientSet.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{}) if err != nil { @@ -451,17 +452,13 @@ var _ = SIGDescribe("Garbage collector", func() { framework.Failf("%v", err) } By("wait for 30 seconds to see if the garbage collector mistakenly deletes the pods") - if err := wait.Poll(5*time.Second, 30*time.Second, func() (bool, error) { - pods, err := podClient.List(metav1.ListOptions{}) - if err != nil { - return false, fmt.Errorf("Failed to list pods: %v", err) - } - if e, a := int(*(rc.Spec.Replicas)), len(pods.Items); e != a { - return false, fmt.Errorf("expect %d pods, got %d pods", e, a) - } - return false, nil - }); err != nil && err != wait.ErrWaitTimeout { - framework.Failf("%v", err) + time.Sleep(30 * time.Second) + pods, err := podClient.List(metav1.ListOptions{}) + if err != nil { + framework.Failf("Failed to list pods: %v", err) + } + if e, a := int(*(rc.Spec.Replicas)), len(pods.Items); e != a { + framework.Failf("expect %d pods, got %d pods", e, a) } gatherMetrics(f) }) @@ -499,17 +496,13 @@ var _ = SIGDescribe("Garbage collector", func() { framework.Failf("failed to delete the rc: %v", err) } By("wait for 30 seconds to see if the garbage collector mistakenly deletes the pods") - if err := wait.Poll(5*time.Second, 30*time.Second, func() (bool, error) { - pods, err := podClient.List(metav1.ListOptions{}) - if err != nil { - return false, fmt.Errorf("Failed to list pods: %v", err) - } - if e, a := int(*(rc.Spec.Replicas)), len(pods.Items); e != a { - return false, fmt.Errorf("expect %d pods, got %d pods", e, a) - } - return false, nil - }); err != nil && err != wait.ErrWaitTimeout { - framework.Failf("%v", err) + time.Sleep(30 * time.Second) + pods, err := podClient.List(metav1.ListOptions{}) + if err != nil { + framework.Failf("Failed to list pods: %v", err) + } + if e, a := int(*(rc.Spec.Replicas)), len(pods.Items); e != a { + framework.Failf("expect %d pods, got %d pods", e, a) } gatherMetrics(f) }) @@ -556,14 +549,17 @@ var _ = SIGDescribe("Garbage collector", func() { err = wait.PollImmediate(500*time.Millisecond, 1*time.Minute, func() (bool, error) { return verifyRemainingDeploymentsReplicaSetsPods(f, clientSet, deployment, 0, 0, 0) }) - if err == wait.ErrWaitTimeout { - err = fmt.Errorf("Failed to wait for all rs to be garbage collected: %v", err) + if err != nil { + errList := make([]error, 0) + errList = append(errList, err) remainingRSs, err := rsClient.List(metav1.ListOptions{}) if err != nil { - framework.Failf("failed to list RSs post mortem: %v", err) + errList = append(errList, fmt.Errorf("failed to list RSs post mortem: %v", err)) } else { - framework.Failf("remaining rs are: %#v", remainingRSs) + errList = append(errList, fmt.Errorf("remaining rs are: %#v", remainingRSs)) } + aggregatedError := utilerrors.NewAggregate(errList) + framework.Failf("Failed to wait for all rs to be garbage collected: %v", aggregatedError) } @@ -608,24 +604,28 @@ var _ = SIGDescribe("Garbage collector", func() { if err := deployClient.Delete(deployment.ObjectMeta.Name, deleteOptions); err != nil { framework.Failf("failed to delete the deployment: %v", err) } - By("wait for 2 Minute to see if the garbage collector mistakenly deletes the rs") - err = wait.PollImmediate(5*time.Second, 2*time.Minute, func() (bool, error) { - return verifyRemainingDeploymentsReplicaSetsPods(f, clientSet, deployment, 0, 1, 2) - }) + By("wait for 30 seconds to see if the garbage collector mistakenly deletes the rs") + time.Sleep(30 * time.Second) + ok, err := verifyRemainingDeploymentsReplicaSetsPods(f, clientSet, deployment, 0, 1, 2) if err != nil { - err = fmt.Errorf("Failed to wait to see if the garbage collecter mistakenly deletes the rs: %v", err) + framework.Failf("Unexpected error while verifying remaining deployments, rs, and pods: %v", err) + } + if !ok { + errList := make([]error, 0) remainingRSs, err := rsClient.List(metav1.ListOptions{}) if err != nil { - framework.Failf("failed to list RSs post mortem: %v", err) + errList = append(errList, fmt.Errorf("failed to list RSs post mortem: %v", err)) } else { - framework.Failf("remaining rs post mortem: %#v", remainingRSs) + errList = append(errList, fmt.Errorf("remaining rs post mortem: %#v", remainingRSs)) } remainingDSs, err := deployClient.List(metav1.ListOptions{}) if err != nil { - framework.Failf("failed to list Deployments post mortem: %v", err) + errList = append(errList, fmt.Errorf("failed to list Deployments post mortem: %v", err)) } else { - framework.Failf("remaining deployment's post mortem: %#v", remainingDSs) + errList = append(errList, fmt.Errorf("remaining deployment's post mortem: %#v", remainingDSs)) } + 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{}) if err != nil { @@ -998,6 +998,109 @@ var _ = SIGDescribe("Garbage collector", func() { } }) + It("should support orphan deletion of custom resources", func() { + config, err := framework.LoadConfig() + if err != nil { + framework.Failf("failed to load config: %v", err) + } + + apiExtensionClient, err := apiextensionsclientset.NewForConfig(config) + if err != nil { + framework.Failf("failed to initialize apiExtensionClient: %v", err) + } + + // Create a random custom resource definition and ensure it's available for + // use. + definition := apiextensionstestserver.NewRandomNameCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) + defer func() { + err = apiextensionstestserver.DeleteCustomResourceDefinition(definition, apiExtensionClient) + if err != nil && !errors.IsNotFound(err) { + framework.Failf("failed to delete CustomResourceDefinition: %v", err) + } + }() + definition, err = apiextensionstestserver.CreateNewCustomResourceDefinition(definition, apiExtensionClient, f.DynamicClient) + if err != nil { + framework.Failf("failed to create CustomResourceDefinition: %v", err) + } + + // Get a client for the custom resource. + gvr := schema.GroupVersionResource{Group: definition.Spec.Group, Version: definition.Spec.Version, Resource: definition.Spec.Names.Plural} + resourceClient := f.DynamicClient.Resource(gvr) + + apiVersion := definition.Spec.Group + "/" + definition.Spec.Version + + // Create a custom owner resource. + ownerName := names.SimpleNameGenerator.GenerateName("owner") + owner := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": apiVersion, + "kind": definition.Spec.Names.Kind, + "metadata": map[string]interface{}{ + "name": ownerName, + }, + }, + } + persistedOwner, err := resourceClient.Create(owner) + if err != nil { + framework.Failf("failed to create owner resource %q: %v", ownerName, err) + } + framework.Logf("created owner resource %q", ownerName) + + // Create a custom dependent resource. + dependentName := names.SimpleNameGenerator.GenerateName("dependent") + dependent := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": apiVersion, + "kind": definition.Spec.Names.Kind, + "metadata": map[string]interface{}{ + "name": dependentName, + "ownerReferences": []map[string]string{ + { + "uid": string(persistedOwner.GetUID()), + "apiVersion": apiVersion, + "kind": definition.Spec.Names.Kind, + "name": ownerName, + }, + }, + }, + }, + } + _, err = resourceClient.Create(dependent) + if err != nil { + framework.Failf("failed to create dependent resource %q: %v", dependentName, err) + } + framework.Logf("created dependent resource %q", dependentName) + + // Delete the owner and orphan the dependent. + err = resourceClient.Delete(ownerName, getOrphanOptions()) + if err != nil { + framework.Failf("failed to delete owner resource %q: %v", ownerName, err) + } + + By("wait for the owner to be deleted") + if err := wait.Poll(5*time.Second, 120*time.Second, func() (bool, error) { + _, err = resourceClient.Get(ownerName, metav1.GetOptions{}) + if err == nil { + return false, nil + } + if err != nil && !errors.IsNotFound(err) { + return false, fmt.Errorf("Failed to get owner: %v", err) + } + return true, nil + }); err != nil { + framework.Failf("timeout in waiting for the owner to be deleted: %v", err) + } + + // Wait 30s and ensure the dependent is not deleted. + By("wait for 30 seconds to see if the garbage collector mistakenly deletes the dependent crd") + if err := wait.Poll(5*time.Second, 30*time.Second, func() (bool, error) { + _, err := resourceClient.Get(dependentName, metav1.GetOptions{}) + return false, err + }); err != nil && err != wait.ErrWaitTimeout { + framework.Failf("failed to ensure the dependent is not deleted: %v", err) + } + }) + It("should delete jobs and pods created by cronjob", func() { framework.SkipIfMissingResource(f.DynamicClient, CronJobGroupVersionResource, f.Namespace.Name) diff --git a/test/e2e/apimachinery/watch.go b/test/e2e/apimachinery/watch.go index eadbe3180e2..2ca292bda2c 100644 --- a/test/e2e/apimachinery/watch.go +++ b/test/e2e/apimachinery/watch.go @@ -21,10 +21,8 @@ import ( "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" - "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" "k8s.io/kubernetes/test/e2e/framework" @@ -33,118 +31,307 @@ import ( ) const ( - watchPodLabelKey = "watch-this-pod" - watchPodLabelValueA = "AAA" - watchPodLabelValueB = "BBB" + watchConfigMapLabelKey = "watch-this-configmap" + + multipleWatchersLabelValueA = "multiple-watchers-A" + multipleWatchersLabelValueB = "multiple-watchers-B" + fromResourceVersionLabelValue = "from-resource-version" + watchRestartedLabelValue = "watch-closed-and-restarted" + toBeChangedLabelValue = "label-changed-and-restored" ) var _ = SIGDescribe("Watchers", func() { f := framework.NewDefaultFramework("watch") - It("should observe add, update, and delete events on pods", func() { + /* + Testname: watch-configmaps-with-multiple-watchers + Description: Ensure that multiple watchers are able to receive all add, + update, and delete notifications on configmaps that match a label selector and do + not receive notifications for configmaps which do not match that label selector. + */ + framework.ConformanceIt("should observe add, update, and delete watch notifications on configmaps", func() { c := f.ClientSet ns := f.Namespace.Name - By("creating multiple similar watches on pods") - watchA, err := watchPodsWithLabels(f, watchPodLabelValueA) + By("creating a watch on configmaps with label A") + watchA, err := watchConfigMaps(f, "", multipleWatchersLabelValueA) Expect(err).NotTo(HaveOccurred()) - watchB, err := watchPodsWithLabels(f, watchPodLabelValueB) + By("creating a watch on configmaps with label B") + watchB, err := watchConfigMaps(f, "", multipleWatchersLabelValueB) Expect(err).NotTo(HaveOccurred()) - watchAB, err := watchPodsWithLabels(f, watchPodLabelValueA, watchPodLabelValueB) + By("creating a watch on configmaps with label A or B") + watchAB, err := watchConfigMaps(f, "", multipleWatchersLabelValueA, multipleWatchersLabelValueB) Expect(err).NotTo(HaveOccurred()) - By("creating, modifying, and deleting pods") - testPodA := &v1.Pod{ + testConfigMapA := &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: "e2e-watch-test-pod-a", + Name: "e2e-watch-test-configmap-a", Labels: map[string]string{ - watchPodLabelKey: watchPodLabelValueA, - }, - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "example", - Image: framework.GetPauseImageName(c), - }, + watchConfigMapLabelKey: multipleWatchersLabelValueA, }, }, } - testPodB := &v1.Pod{ + testConfigMapB := &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: "e2e-watch-test-pod-b", + Name: "e2e-watch-test-configmap-b", Labels: map[string]string{ - watchPodLabelKey: watchPodLabelValueB, - }, - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "example", - Image: framework.GetPauseImageName(c), - }, + watchConfigMapLabelKey: multipleWatchersLabelValueB, }, }, } - testPodA, err = c.CoreV1().Pods(ns).Create(testPodA) - Expect(err).NotTo(HaveOccurred()) - expectEvent(watchA, watch.Added, testPodA) - expectEvent(watchAB, watch.Added, testPodA) - expectNoEvent(watchB, watch.Added, testPodA) - testPodA, err = updatePod(f, testPodA.GetName(), func(p *v1.Pod) { - p.ObjectMeta.Labels["mutation"] = "1" + By("creating a configmap with label A and ensuring the correct watchers observe the notification") + testConfigMapA, err = c.CoreV1().ConfigMaps(ns).Create(testConfigMapA) + Expect(err).NotTo(HaveOccurred()) + expectEvent(watchA, watch.Added, testConfigMapA) + expectEvent(watchAB, watch.Added, testConfigMapA) + expectNoEvent(watchB, watch.Added, testConfigMapA) + + By("modifying configmap A and ensuring the correct watchers observe the notification") + testConfigMapA, err = updateConfigMap(c, ns, testConfigMapA.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "1") }) Expect(err).NotTo(HaveOccurred()) - expectEvent(watchA, watch.Modified, testPodA) - expectEvent(watchAB, watch.Modified, testPodA) - expectNoEvent(watchB, watch.Modified, testPodA) + expectEvent(watchA, watch.Modified, testConfigMapA) + expectEvent(watchAB, watch.Modified, testConfigMapA) + expectNoEvent(watchB, watch.Modified, testConfigMapA) - testPodA, err = updatePod(f, testPodA.GetName(), func(p *v1.Pod) { - p.ObjectMeta.Labels["mutation"] = "2" + By("modifying configmap A again and ensuring the correct watchers observe the notification") + testConfigMapA, err = updateConfigMap(c, ns, testConfigMapA.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "2") }) Expect(err).NotTo(HaveOccurred()) - expectEvent(watchA, watch.Modified, testPodA) - expectEvent(watchAB, watch.Modified, testPodA) - expectNoEvent(watchB, watch.Modified, testPodA) + expectEvent(watchA, watch.Modified, testConfigMapA) + expectEvent(watchAB, watch.Modified, testConfigMapA) + expectNoEvent(watchB, watch.Modified, testConfigMapA) - err = c.CoreV1().Pods(ns).Delete(testPodA.GetName(), nil) + By("deleting configmap A and ensuring the correct watchers observe the notification") + err = c.CoreV1().ConfigMaps(ns).Delete(testConfigMapA.GetName(), nil) Expect(err).NotTo(HaveOccurred()) expectEvent(watchA, watch.Deleted, nil) expectEvent(watchAB, watch.Deleted, nil) expectNoEvent(watchB, watch.Deleted, nil) - testPodB, err = c.CoreV1().Pods(ns).Create(testPodB) + By("creating a configmap with label B and ensuring the correct watchers observe the notification") + testConfigMapB, err = c.CoreV1().ConfigMaps(ns).Create(testConfigMapB) Expect(err).NotTo(HaveOccurred()) - expectEvent(watchB, watch.Added, testPodB) - expectEvent(watchAB, watch.Added, testPodB) - expectNoEvent(watchA, watch.Added, testPodB) + expectEvent(watchB, watch.Added, testConfigMapB) + expectEvent(watchAB, watch.Added, testConfigMapB) + expectNoEvent(watchA, watch.Added, testConfigMapB) - err = c.CoreV1().Pods(ns).Delete(testPodB.GetName(), nil) + By("deleting configmap B and ensuring the correct watchers observe the notification") + err = c.CoreV1().ConfigMaps(ns).Delete(testConfigMapB.GetName(), nil) Expect(err).NotTo(HaveOccurred()) expectEvent(watchB, watch.Deleted, nil) expectEvent(watchAB, watch.Deleted, nil) expectNoEvent(watchA, watch.Deleted, nil) }) + + /* + Testname: watch-configmaps-from-resource-version + Description: Ensure that a watch can be opened from a particular resource version + in the past and only notifications happening after that resource version are observed. + */ + framework.ConformanceIt("should be able to start watching from a specific resource version", func() { + c := f.ClientSet + ns := f.Namespace.Name + + testConfigMap := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "e2e-watch-test-resource-version", + Labels: map[string]string{ + watchConfigMapLabelKey: fromResourceVersionLabelValue, + }, + }, + } + + By("creating a new configmap") + testConfigMap, err := c.CoreV1().ConfigMaps(ns).Create(testConfigMap) + Expect(err).NotTo(HaveOccurred()) + + By("modifying the configmap once") + testConfigMapFirstUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "1") + }) + Expect(err).NotTo(HaveOccurred()) + + By("modifying the configmap a second time") + testConfigMapSecondUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "2") + }) + Expect(err).NotTo(HaveOccurred()) + + By("deleting the configmap") + err = c.CoreV1().ConfigMaps(ns).Delete(testConfigMap.GetName(), nil) + Expect(err).NotTo(HaveOccurred()) + + By("creating a watch on configmaps from the resource version returned by the first update") + testWatch, err := watchConfigMaps(f, testConfigMapFirstUpdate.ObjectMeta.ResourceVersion, fromResourceVersionLabelValue) + Expect(err).NotTo(HaveOccurred()) + + By("Expecting to observe notifications for all changes to the configmap after the first update") + expectEvent(testWatch, watch.Modified, testConfigMapSecondUpdate) + expectEvent(testWatch, watch.Deleted, nil) + }) + + /* + Testname: watch-configmaps-closed-and-restarted + Description: Ensure that a watch can be reopened from the last resource version + observed by the previous watch, and it will continue delivering notifications from + that point in time. + */ + framework.ConformanceIt("should be able to restart watching from the last resource version observed by the previous watch", func() { + c := f.ClientSet + ns := f.Namespace.Name + + testConfigMap := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "e2e-watch-test-watch-closed", + Labels: map[string]string{ + watchConfigMapLabelKey: watchRestartedLabelValue, + }, + }, + } + + By("creating a watch on configmaps") + testWatchBroken, err := watchConfigMaps(f, "", watchRestartedLabelValue) + Expect(err).NotTo(HaveOccurred()) + + By("creating a new configmap") + testConfigMap, err = c.CoreV1().ConfigMaps(ns).Create(testConfigMap) + Expect(err).NotTo(HaveOccurred()) + + By("modifying the configmap once") + _, err = updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "1") + }) + Expect(err).NotTo(HaveOccurred()) + + By("closing the watch once it receives two notifications") + expectEvent(testWatchBroken, watch.Added, testConfigMap) + lastEvent, ok := waitForEvent(testWatchBroken, watch.Modified, nil, 1*time.Minute) + if !ok { + framework.Failf("Timed out waiting for second watch notification") + } + testWatchBroken.Stop() + + By("modifying the configmap a second time, while the watch is closed") + testConfigMapSecondUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "2") + }) + Expect(err).NotTo(HaveOccurred()) + + By("creating a new watch on configmaps from the last resource version observed by the first watch") + lastEventConfigMap, ok := lastEvent.Object.(*v1.ConfigMap) + if !ok { + framework.Failf("Expected last notfication to refer to a configmap but got: %v", lastEvent) + } + testWatchRestarted, err := watchConfigMaps(f, lastEventConfigMap.ObjectMeta.ResourceVersion, watchRestartedLabelValue) + Expect(err).NotTo(HaveOccurred()) + + By("deleting the configmap") + err = c.CoreV1().ConfigMaps(ns).Delete(testConfigMap.GetName(), nil) + Expect(err).NotTo(HaveOccurred()) + + By("Expecting to observe notifications for all changes to the configmap since the first watch closed") + expectEvent(testWatchRestarted, watch.Modified, testConfigMapSecondUpdate) + expectEvent(testWatchRestarted, watch.Deleted, nil) + }) + + /* + Testname: watch-configmaps-label-changed + Description: Ensure that a watched object stops meeting the requirements of + a watch's selector, the watch will observe a delete, and will not observe + notifications for that object until it meets the selector's requirements again. + */ + framework.ConformanceIt("should observe an object deletion if it stops meeting the requirements of the selector", func() { + c := f.ClientSet + ns := f.Namespace.Name + + testConfigMap := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "e2e-watch-test-label-changed", + Labels: map[string]string{ + watchConfigMapLabelKey: toBeChangedLabelValue, + }, + }, + } + + By("creating a watch on configmaps with a certain label") + testWatch, err := watchConfigMaps(f, "", toBeChangedLabelValue) + Expect(err).NotTo(HaveOccurred()) + + By("creating a new configmap") + testConfigMap, err = c.CoreV1().ConfigMaps(ns).Create(testConfigMap) + Expect(err).NotTo(HaveOccurred()) + + By("modifying the configmap once") + testConfigMapFirstUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "1") + }) + Expect(err).NotTo(HaveOccurred()) + + By("changing the label value of the configmap") + _, err = updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + cm.ObjectMeta.Labels[watchConfigMapLabelKey] = "wrong-value" + }) + Expect(err).NotTo(HaveOccurred()) + + By("Expecting to observe a delete notification for the watched object") + expectEvent(testWatch, watch.Added, testConfigMap) + expectEvent(testWatch, watch.Modified, testConfigMapFirstUpdate) + expectEvent(testWatch, watch.Deleted, nil) + + By("modifying the configmap a second time") + testConfigMapSecondUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "2") + }) + Expect(err).NotTo(HaveOccurred()) + + By("Expecting not to observe a notification because the object no longer meets the selector's requirements") + expectNoEvent(testWatch, watch.Modified, testConfigMapSecondUpdate) + + By("changing the label value of the configmap back") + testConfigMapLabelRestored, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + cm.ObjectMeta.Labels[watchConfigMapLabelKey] = toBeChangedLabelValue + }) + Expect(err).NotTo(HaveOccurred()) + + By("modifying the configmap a third time") + testConfigMapThirdUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "3") + }) + Expect(err).NotTo(HaveOccurred()) + + By("deleting the configmap") + err = c.CoreV1().ConfigMaps(ns).Delete(testConfigMap.GetName(), nil) + Expect(err).NotTo(HaveOccurred()) + + By("Expecting to observe an add notification for the watched object when the label value was restored") + expectEvent(testWatch, watch.Added, testConfigMapLabelRestored) + expectEvent(testWatch, watch.Modified, testConfigMapThirdUpdate) + expectEvent(testWatch, watch.Deleted, nil) + }) }) -func watchPodsWithLabels(f *framework.Framework, labels ...string) (watch.Interface, error) { +func watchConfigMaps(f *framework.Framework, resourceVersion string, labels ...string) (watch.Interface, error) { c := f.ClientSet ns := f.Namespace.Name opts := metav1.ListOptions{ + ResourceVersion: resourceVersion, LabelSelector: metav1.FormatLabelSelector(&metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{ { - Key: watchPodLabelKey, + Key: watchConfigMapLabelKey, Operator: metav1.LabelSelectorOpIn, Values: labels, }, }, }), } - return c.CoreV1().Pods(ns).Watch(opts) + return c.CoreV1().ConfigMaps(ns).Watch(opts) } func int64ptr(i int) *int64 { @@ -152,39 +339,22 @@ func int64ptr(i int) *int64 { return &i64 } -type updatePodFunc func(p *v1.Pod) - -func updatePod(f *framework.Framework, name string, update updatePodFunc) (*v1.Pod, error) { - c := f.ClientSet - ns := f.Namespace.Name - var p *v1.Pod - pollErr := wait.PollImmediate(2*time.Second, 1*time.Minute, func() (bool, error) { - var err error - if p, err = c.CoreV1().Pods(ns).Get(name, metav1.GetOptions{}); err != nil { - return false, err - } - update(p) - if p, err = c.CoreV1().Pods(ns).Update(p); err == nil { - return true, nil - } - // Only retry update on conflict - if !errors.IsConflict(err) { - return false, err - } - return false, nil - }) - return p, pollErr +func setConfigMapData(cm *v1.ConfigMap, key, value string) { + if cm.Data == nil { + cm.Data = make(map[string]string) + } + cm.Data[key] = value } func expectEvent(w watch.Interface, eventType watch.EventType, object runtime.Object) { if event, ok := waitForEvent(w, eventType, object, 1*time.Minute); !ok { - framework.Failf("Timed out waiting for expected event: %v", event) + framework.Failf("Timed out waiting for expected watch notification: %v", event) } } func expectNoEvent(w watch.Interface, eventType watch.EventType, object runtime.Object) { if event, ok := waitForEvent(w, eventType, object, 10*time.Second); ok { - framework.Failf("Unexpected event occurred: %v", event) + framework.Failf("Unexpected watch notification observed: %v", event) } } diff --git a/test/e2e/apps/BUILD b/test/e2e/apps/BUILD index a0cf78546b2..ad93b6b9528 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/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/util/pointer:go_default_library", "//test/e2e/common:go_default_library", "//test/e2e/framework:go_default_library", diff --git a/test/e2e/apps/daemon_set.go b/test/e2e/apps/daemon_set.go index c58b95e600a..86f5aab8ac0 100644 --- a/test/e2e/apps/daemon_set.go +++ b/test/e2e/apps/daemon_set.go @@ -36,7 +36,7 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/controller/daemon" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/test/e2e/framework" . "github.com/onsi/ginkgo" diff --git a/test/e2e/apps/job.go b/test/e2e/apps/job.go index d10a444f07d..29b5afd7f3a 100644 --- a/test/e2e/apps/job.go +++ b/test/e2e/apps/job.go @@ -174,7 +174,8 @@ var _ = SIGDescribe("Job", func() { It("should exceed backoffLimit", func() { By("Creating a job") - job := framework.NewTestJob("fail", "backofflimit", v1.RestartPolicyNever, 1, 1, nil, 0) + backoff := 1 + job := framework.NewTestJob("fail", "backofflimit", v1.RestartPolicyNever, 1, 1, nil, int32(backoff)) job, err := framework.CreateJob(f.ClientSet, f.Namespace.Name, job) Expect(err).NotTo(HaveOccurred()) By("Ensuring job exceed backofflimit") @@ -182,11 +183,18 @@ var _ = SIGDescribe("Job", func() { err = framework.WaitForJobFailure(f.ClientSet, f.Namespace.Name, job.Name, framework.JobTimeout, "BackoffLimitExceeded") Expect(err).NotTo(HaveOccurred()) - By("Checking that only one pod created and status is failed") + By(fmt.Sprintf("Checking that %d pod created and status is failed", backoff+1)) pods, err := framework.GetJobPods(f.ClientSet, f.Namespace.Name, job.Name) Expect(err).NotTo(HaveOccurred()) - Expect(pods.Items).To(HaveLen(1)) - pod := pods.Items[0] - Expect(pod.Status.Phase).To(Equal(v1.PodFailed)) + // Expect(pods.Items).To(HaveLen(backoff + 1)) + // due to NumRequeus not being stable enough, especially with failed status + // updates we need to allow more than backoff+1 + // TODO revert this back to above when https://github.com/kubernetes/kubernetes/issues/64787 gets fixed + if len(pods.Items) < backoff+1 { + framework.Failf("Not enough pod created expected at least %d, got %#v", backoff+1, pods.Items) + } + for _, pod := range pods.Items { + Expect(pod.Status.Phase).To(Equal(v1.PodFailed)) + } }) }) diff --git a/test/e2e/autoscaling/BUILD b/test/e2e/autoscaling/BUILD index b7070d24687..217f5fd9c1e 100644 --- a/test/e2e/autoscaling/BUILD +++ b/test/e2e/autoscaling/BUILD @@ -34,7 +34,7 @@ go_library( "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/test/e2e/autoscaling/cluster_size_autoscaling.go b/test/e2e/autoscaling/cluster_size_autoscaling.go index 51015b95239..9b5699af310 100644 --- a/test/e2e/autoscaling/cluster_size_autoscaling.go +++ b/test/e2e/autoscaling/cluster_size_autoscaling.go @@ -30,7 +30,7 @@ import ( "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1beta1" - "k8s.io/api/scheduling/v1alpha1" + schedulerapi "k8s.io/api/scheduling/v1beta1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" @@ -207,101 +207,107 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { It("should increase cluster size if pending pods are small [Feature:ClusterSizeAutoscalingScaleUp]", func() { simpleScaleUpTest(0) }) - It("Should scale up GPU pool from 0 [Feature:ClusterSizeAutoscalingGpu]", func() { - framework.SkipUnlessProviderIs("gke") + supportedGpuTypes := []string{"nvidia-tesla-k80", "nvidia-tesla-v100", "nvidia-tesla-p100"} + for _, gpuType := range supportedGpuTypes { + gpuType := gpuType // create new variable for each iteration step - const gpuPoolName = "gpu-pool" - addGpuNodePool(gpuPoolName, "nvidia-tesla-k80", 1, 0) - defer deleteNodePool(gpuPoolName) + It(fmt.Sprintf("Should scale up GPU pool from 0 [GpuType:%s] [Feature:ClusterSizeAutoscalingGpu]", gpuType), func() { + framework.SkipUnlessProviderIs("gke") - installNvidiaDriversDaemonSet() + const gpuPoolName = "gpu-pool" + addGpuNodePool(gpuPoolName, gpuType, 1, 0) + defer deleteNodePool(gpuPoolName) - By("Enable autoscaler") - framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 1)) - defer disableAutoscaler(gpuPoolName, 0, 1) - Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) + installNvidiaDriversDaemonSet() - By("Schedule a pod which requires GPU") - framework.ExpectNoError(scheduleGpuPod(f, "gpu-pod-rc")) + By("Enable autoscaler") + framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 1)) + defer disableAutoscaler(gpuPoolName, 0, 1) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size == nodeCount+1 }, scaleUpTimeout)) - Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(1)) - }) + By("Schedule a pod which requires GPU") + framework.ExpectNoError(scheduleGpuPod(f, "gpu-pod-rc")) - It("Should scale up GPU pool from 1 [Feature:ClusterSizeAutoscalingGpu]", func() { - framework.SkipUnlessProviderIs("gke") + framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, + func(size int) bool { return size == nodeCount+1 }, scaleUpTimeout)) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(1)) + }) - const gpuPoolName = "gpu-pool" - addGpuNodePool(gpuPoolName, "nvidia-tesla-k80", 1, 1) - defer deleteNodePool(gpuPoolName) + It(fmt.Sprintf("Should scale up GPU pool from 1 [GpuType:%s] [Feature:ClusterSizeAutoscalingGpu]", gpuType), func() { + framework.SkipUnlessProviderIs("gke") - installNvidiaDriversDaemonSet() + const gpuPoolName = "gpu-pool" + addGpuNodePool(gpuPoolName, gpuType, 1, 1) + defer deleteNodePool(gpuPoolName) - By("Schedule a single pod which requires GPU") - framework.ExpectNoError(scheduleGpuPod(f, "gpu-pod-rc")) + installNvidiaDriversDaemonSet() - By("Enable autoscaler") - framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 2)) - defer disableAutoscaler(gpuPoolName, 0, 2) - Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(1)) + By("Schedule a single pod which requires GPU") + framework.ExpectNoError(scheduleGpuPod(f, "gpu-pod-rc")) - framework.ScaleRC(f.ClientSet, f.ScalesGetter, f.Namespace.Name, "gpu-pod-rc", 2, false) + By("Enable autoscaler") + framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 2)) + defer disableAutoscaler(gpuPoolName, 0, 2) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(1)) - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size == nodeCount+2 }, scaleUpTimeout)) - Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(2)) - }) + By("Scale GPU deployment") + framework.ScaleRC(f.ClientSet, f.ScalesGetter, f.Namespace.Name, "gpu-pod-rc", 2, true) - It("Should not scale GPU pool up if pod does not require GPUs [Feature:ClusterSizeAutoscalingGpu]", func() { - framework.SkipUnlessProviderIs("gke") + framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, + func(size int) bool { return size == nodeCount+2 }, scaleUpTimeout)) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(2)) + }) - const gpuPoolName = "gpu-pool" - addGpuNodePool(gpuPoolName, "nvidia-tesla-k80", 1, 0) - defer deleteNodePool(gpuPoolName) + It(fmt.Sprintf("Should not scale GPU pool up if pod does not require GPUs [GpuType:%s] [Feature:ClusterSizeAutoscalingGpu]", gpuType), func() { + framework.SkipUnlessProviderIs("gke") - installNvidiaDriversDaemonSet() + const gpuPoolName = "gpu-pool" + addGpuNodePool(gpuPoolName, gpuType, 1, 0) + defer deleteNodePool(gpuPoolName) - By("Enable autoscaler") - framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 1)) - defer disableAutoscaler(gpuPoolName, 0, 1) - Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) + installNvidiaDriversDaemonSet() - By("Schedule bunch of pods beyond point of filling default pool but do not request any GPUs") - ReserveMemory(f, "memory-reservation", 100, nodeCount*memAllocatableMb, false, 1*time.Second) - defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "memory-reservation") + By("Enable autoscaler") + framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 1)) + defer disableAutoscaler(gpuPoolName, 0, 1) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) - // Verify that cluster size is increased - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size >= nodeCount+1 }, scaleUpTimeout)) + By("Schedule bunch of pods beyond point of filling default pool but do not request any GPUs") + ReserveMemory(f, "memory-reservation", 100, nodeCount*memAllocatableMb, false, 1*time.Second) + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "memory-reservation") + // Verify that cluster size is increased + framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, + func(size int) bool { return size >= nodeCount+1 }, scaleUpTimeout)) - // Expect gpu pool to stay intact - Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) - }) + // Expect gpu pool to stay intact + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) + }) - It("Should scale down GPU pool from 1 [Feature:ClusterSizeAutoscalingGpu]", func() { - framework.SkipUnlessProviderIs("gke") + It(fmt.Sprintf("Should scale down GPU pool from 1 [GpuType:%s] [Feature:ClusterSizeAutoscalingGpu]", gpuType), func() { + framework.SkipUnlessProviderIs("gke") - const gpuPoolName = "gpu-pool" - addGpuNodePool(gpuPoolName, "nvidia-tesla-k80", 1, 1) - defer deleteNodePool(gpuPoolName) + const gpuPoolName = "gpu-pool" + addGpuNodePool(gpuPoolName, gpuType, 1, 1) + defer deleteNodePool(gpuPoolName) - installNvidiaDriversDaemonSet() + installNvidiaDriversDaemonSet() - By("Schedule a single pod which requires GPU") - framework.ExpectNoError(scheduleGpuPod(f, "gpu-pod-rc")) + By("Schedule a single pod which requires GPU") + framework.ExpectNoError(scheduleGpuPod(f, "gpu-pod-rc")) - By("Enable autoscaler") - framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 1)) - defer disableAutoscaler(gpuPoolName, 0, 1) - Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(1)) + By("Enable autoscaler") + framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 1)) + defer disableAutoscaler(gpuPoolName, 0, 1) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(1)) - framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "gpu-pod-rc") + By("Remove the only POD requiring GPU") + framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "gpu-pod-rc") - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size == nodeCount }, scaleDownTimeout)) - Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) - }) + framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, + func(size int) bool { return size == nodeCount }, scaleDownTimeout)) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) + }) + } It("should increase cluster size if pending pods are small and one node is broken [Feature:ClusterSizeAutoscalingScaleUp]", func() { @@ -2145,13 +2151,13 @@ func createPriorityClasses(f *framework.Framework) func() { highPriorityClassName: 1000, } for className, priority := range priorityClasses { - _, err := f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: className}, Value: priority}) + _, err := f.ClientSet.SchedulingV1beta1().PriorityClasses().Create(&schedulerapi.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: className}, Value: priority}) Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true)) } return func() { for className := range priorityClasses { - f.ClientSet.SchedulingV1alpha1().PriorityClasses().Delete(className, nil) + f.ClientSet.SchedulingV1beta1().PriorityClasses().Delete(className, nil) } } } diff --git a/test/e2e/common/BUILD b/test/e2e/common/BUILD index 4df32602f99..825706adc15 100644 --- a/test/e2e/common/BUILD +++ b/test/e2e/common/BUILD @@ -36,7 +36,6 @@ go_library( deps = [ "//pkg/api/v1/pod:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/core/v1/helper:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/conditions:go_default_library", "//pkg/kubelet:go_default_library", diff --git a/test/e2e/common/expansion.go b/test/e2e/common/expansion.go index eadb324fecf..5b6f504480c 100644 --- a/test/e2e/common/expansion.go +++ b/test/e2e/common/expansion.go @@ -21,6 +21,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/kubernetes/test/e2e/framework" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) // These tests exercise the Kubernetes expansion syntax $(VAR). @@ -144,4 +147,175 @@ var _ = framework.KubeDescribe("Variable Expansion", func() { "test-value", }) }) + + /* + Testname: var-expansion-subpath + Description: Make sure a container's subpath can be set using an + expansion of environment variables. + */ + It("should allow substituting values in a volume subpath [Feature:VolumeSubpathEnvExpansion][NodeAlphaFeature:VolumeSubpathEnvExpansion]", func() { + podName := "var-expansion-" + string(uuid.NewUUID()) + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Labels: map[string]string{"name": podName}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "dapi-container", + Image: busyboxImage, + Command: []string{"sh", "-c", "test -d /testcontainer/" + podName + ";echo $?"}, + Env: []v1.EnvVar{ + { + Name: "POD_NAME", + Value: podName, + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "workdir1", + MountPath: "/logscontainer", + SubPath: "$(POD_NAME)", + }, + { + Name: "workdir2", + MountPath: "/testcontainer", + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + Volumes: []v1.Volume{ + { + Name: "workdir1", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{Path: "/tmp"}, + }, + }, + { + Name: "workdir2", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{Path: "/tmp"}, + }, + }, + }, + }, + } + + f.TestContainerOutput("substitution in volume subpath", pod, 0, []string{ + "0", + }) + }) + + /* + Testname: var-expansion-subpath-with-backticks + Description: Make sure a container's subpath can not be set using an + expansion of environment variables when backticks are supplied. + */ + It("should fail substituting values in a volume subpath with backticks [Feature:VolumeSubpathEnvExpansion][NodeAlphaFeature:VolumeSubpathEnvExpansion][Slow]", func() { + + podName := "var-expansion-" + string(uuid.NewUUID()) + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Labels: map[string]string{"name": podName}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "dapi-container", + Image: busyboxImage, + Env: []v1.EnvVar{ + { + Name: "POD_NAME", + Value: "..", + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "workdir1", + MountPath: "/logscontainer", + SubPath: "$(POD_NAME)", + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + Volumes: []v1.Volume{ + { + Name: "workdir1", + VolumeSource: v1.VolumeSource{ + EmptyDir: &v1.EmptyDirVolumeSource{}, + }, + }, + }, + }, + } + + // Pod should fail + testPodFailSubpath(f, pod) + }) + + /* + Testname: var-expansion-subpath-with-absolute-path + Description: Make sure a container's subpath can not be set using an + expansion of environment variables when absolute path is supplied. + */ + It("should fail substituting values in a volume subpath with absolute path [Feature:VolumeSubpathEnvExpansion][NodeAlphaFeature:VolumeSubpathEnvExpansion][Slow]", func() { + + podName := "var-expansion-" + string(uuid.NewUUID()) + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Labels: map[string]string{"name": podName}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "dapi-container", + Image: busyboxImage, + Env: []v1.EnvVar{ + { + Name: "POD_NAME", + Value: "/tmp", + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "workdir1", + MountPath: "/logscontainer", + SubPath: "$(POD_NAME)", + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + Volumes: []v1.Volume{ + { + Name: "workdir1", + VolumeSource: v1.VolumeSource{ + EmptyDir: &v1.EmptyDirVolumeSource{}, + }, + }, + }, + }, + } + + // Pod should fail + testPodFailSubpath(f, pod) + }) }) + +func testPodFailSubpath(f *framework.Framework, pod *v1.Pod) { + + pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod) + Expect(err).ToNot(HaveOccurred(), "while creating pod") + + defer func() { + framework.DeletePodWithWait(f, f.ClientSet, pod) + }() + + err = framework.WaitTimeoutForPodRunningInNamespace(f.ClientSet, pod.Name, pod.Namespace, framework.PodStartShortTimeout) + Expect(err).To(HaveOccurred(), "while waiting for pod to be running") +} diff --git a/test/e2e/common/sysctl.go b/test/e2e/common/sysctl.go index 5f07371d02e..6ae2c5a0e85 100644 --- a/test/e2e/common/sysctl.go +++ b/test/e2e/common/sysctl.go @@ -20,7 +20,6 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/kubelet/sysctl" "k8s.io/kubernetes/test/e2e/framework" @@ -59,12 +58,14 @@ var _ = framework.KubeDescribe("Sysctls [NodeFeature:Sysctls]", func() { It("should support sysctls", func() { pod := testPod() - pod.Annotations[v1.SysctlsPodAnnotationKey] = v1helper.PodAnnotationsFromSysctls([]v1.Sysctl{ - { - Name: "kernel.shm_rmid_forced", - Value: "1", + pod.Spec.SecurityContext = &v1.PodSecurityContext{ + Sysctls: []v1.Sysctl{ + { + Name: "kernel.shm_rmid_forced", + Value: "1", + }, }, - }) + } pod.Spec.Containers[0].Command = []string{"/bin/sysctl", "kernel.shm_rmid_forced"} By("Creating a pod with the kernel.shm_rmid_forced sysctl") @@ -100,12 +101,14 @@ var _ = framework.KubeDescribe("Sysctls [NodeFeature:Sysctls]", func() { It("should support unsafe sysctls which are actually whitelisted", func() { pod := testPod() - pod.Annotations[v1.UnsafeSysctlsPodAnnotationKey] = v1helper.PodAnnotationsFromSysctls([]v1.Sysctl{ - { - Name: "kernel.shm_rmid_forced", - Value: "1", + pod.Spec.SecurityContext = &v1.PodSecurityContext{ + Sysctls: []v1.Sysctl{ + { + Name: "kernel.shm_rmid_forced", + Value: "1", + }, }, - }) + } pod.Spec.Containers[0].Command = []string{"/bin/sysctl", "kernel.shm_rmid_forced"} By("Creating a pod with the kernel.shm_rmid_forced sysctl") @@ -141,34 +144,27 @@ var _ = framework.KubeDescribe("Sysctls [NodeFeature:Sysctls]", func() { It("should reject invalid sysctls", func() { pod := testPod() - pod.Annotations[v1.SysctlsPodAnnotationKey] = v1helper.PodAnnotationsFromSysctls([]v1.Sysctl{ - { - Name: "foo-", - Value: "bar", + pod.Spec.SecurityContext = &v1.PodSecurityContext{ + Sysctls: []v1.Sysctl{ + // Safe parameters + { + Name: "foo-", + Value: "bar", + }, + { + Name: "kernel.shmmax", + Value: "100000000", + }, + { + Name: "safe-and-unsafe", + Value: "100000000", + }, + { + Name: "bar..", + Value: "42", + }, }, - { - Name: "kernel.shmmax", - Value: "100000000", - }, - { - Name: "safe-and-unsafe", - Value: "100000000", - }, - }) - pod.Annotations[v1.UnsafeSysctlsPodAnnotationKey] = v1helper.PodAnnotationsFromSysctls([]v1.Sysctl{ - { - Name: "kernel.shmall", - Value: "100000000", - }, - { - Name: "bar..", - Value: "42", - }, - { - Name: "safe-and-unsafe", - Value: "100000000", - }, - }) + } By("Creating a pod with one valid and two invalid sysctls") client := f.ClientSet.CoreV1().Pods(f.Namespace.Name) @@ -177,18 +173,20 @@ var _ = framework.KubeDescribe("Sysctls [NodeFeature:Sysctls]", func() { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(`Invalid value: "foo-"`)) Expect(err.Error()).To(ContainSubstring(`Invalid value: "bar.."`)) - Expect(err.Error()).To(ContainSubstring(`safe-and-unsafe`)) + Expect(err.Error()).NotTo(ContainSubstring(`safe-and-unsafe`)) Expect(err.Error()).NotTo(ContainSubstring("kernel.shmmax")) }) It("should not launch unsafe, but not explicitly enabled sysctls on the node", func() { pod := testPod() - pod.Annotations[v1.SysctlsPodAnnotationKey] = v1helper.PodAnnotationsFromSysctls([]v1.Sysctl{ - { - Name: "kernel.msgmax", - Value: "10000000000", + pod.Spec.SecurityContext = &v1.PodSecurityContext{ + Sysctls: []v1.Sysctl{ + { + Name: "kernel.msgmax", + Value: "10000000000", + }, }, - }) + } By("Creating a pod with a greylisted, but not whitelisted sysctl on the node") pod = podClient.Create(pod) diff --git a/test/e2e/framework/BUILD b/test/e2e/framework/BUILD index 49970164564..fc650ed9fcc 100644 --- a/test/e2e/framework/BUILD +++ b/test/e2e/framework/BUILD @@ -60,7 +60,6 @@ go_library( "//pkg/controller/deployment/util:go_default_library", "//pkg/controller/nodelifecycle:go_default_library", "//pkg/features:go_default_library", - "//pkg/kubectl:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/stats/v1alpha1:go_default_library", @@ -72,7 +71,8 @@ go_library( "//pkg/kubemark:go_default_library", "//pkg/master/ports:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/metrics:go_default_library", "//pkg/security/podsecuritypolicy/seccomp:go_default_library", "//pkg/ssh:go_default_library", "//pkg/util/file:go_default_library", diff --git a/test/e2e/framework/google_compute.go b/test/e2e/framework/google_compute.go index cf937b72f5b..3c1ed0d5cdb 100644 --- a/test/e2e/framework/google_compute.go +++ b/test/e2e/framework/google_compute.go @@ -145,6 +145,28 @@ func CreateManagedInstanceGroup(size int64, zone, template string) error { return nil } +func GetManagedInstanceGroupTemplateName(zone string) (string, error) { + // TODO(verult): make this hit the compute API directly instead of + // shelling out to gcloud. Use InstanceGroupManager to get Instance Template name. + + stdout, _, err := retryCmd("gcloud", "compute", "instance-groups", "managed", + "list", + fmt.Sprintf("--filter=name:%s", TestContext.CloudConfig.NodeInstanceGroup), + fmt.Sprintf("--project=%s", TestContext.CloudConfig.ProjectID), + fmt.Sprintf("--zones=%s", zone), + ) + + if err != nil { + return "", fmt.Errorf("gcloud compute instance-groups managed list call failed with err: %v", err) + } + + templateName, err := parseInstanceTemplateName(stdout) + if err != nil { + return "", fmt.Errorf("error parsing gcloud output: %v", err) + } + return templateName, nil +} + func DeleteManagedInstanceGroup(zone string) error { // TODO(verult): make this hit the compute API directly instead of // shelling out to gcloud. @@ -158,3 +180,29 @@ func DeleteManagedInstanceGroup(zone string) error { } return nil } + +func parseInstanceTemplateName(gcloudOutput string) (string, error) { + const templateNameField = "INSTANCE_TEMPLATE" + + lines := strings.Split(gcloudOutput, "\n") + if len(lines) <= 1 { // Empty output or only contains column names + return "", fmt.Errorf("the list is empty") + } + + // Otherwise, there should be exactly 1 entry, i.e. 2 lines + fieldNames := strings.Fields(lines[0]) + instanceTemplateColumn := 0 + for instanceTemplateColumn < len(fieldNames) && + fieldNames[instanceTemplateColumn] != templateNameField { + instanceTemplateColumn++ + } + + if instanceTemplateColumn == len(fieldNames) { + return "", fmt.Errorf("the list does not contain instance template information") + } + + fields := strings.Fields(lines[1]) + instanceTemplateName := fields[instanceTemplateColumn] + + return instanceTemplateName, nil +} diff --git a/test/e2e/framework/metrics_util.go b/test/e2e/framework/metrics_util.go index f9c53706461..2562dc47209 100644 --- a/test/e2e/framework/metrics_util.go +++ b/test/e2e/framework/metrics_util.go @@ -32,6 +32,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/pkg/master/ports" + schedulermetric "k8s.io/kubernetes/pkg/scheduler/metrics" "k8s.io/kubernetes/pkg/util/system" "k8s.io/kubernetes/test/e2e/framework/metrics" @@ -130,6 +131,8 @@ func (m *MetricsForE2E) SummaryKind() string { return "MetricsForE2E" } +var SchedulingLatencyMetricName = model.LabelValue(schedulermetric.SchedulerSubsystem + "_" + schedulermetric.SchedulingLatencyName) + var InterestingApiServerMetrics = []string{ "apiserver_request_count", "apiserver_request_latencies_summary", @@ -207,10 +210,12 @@ func (l *PodStartupLatency) PrintJSON() string { } type SchedulingMetrics struct { - SchedulingLatency LatencyMetric `json:"schedulingLatency"` - BindingLatency LatencyMetric `json:"bindingLatency"` - E2ELatency LatencyMetric `json:"e2eLatency"` - ThroughputSamples []float64 `json:"throughputSamples"` + SelectingNodeLatency LatencyMetric `json:"selectingNodeLatency"` + BindingLatency LatencyMetric `json:"bindingLatency"` + ThroughputAverage float64 `json:"throughputAverage"` + ThroughputPerc50 float64 `json:"throughputPerc50"` + ThroughputPerc90 float64 `json:"throughputPerc90"` + ThroughputPerc99 float64 `json:"throughputPerc99"` } func (l *SchedulingMetrics) SummaryKind() string { @@ -439,27 +444,29 @@ func getMetrics(c clientset.Interface) (string, error) { return string(body), nil } -// Retrieves scheduler latency metrics. -func getSchedulingLatency(c clientset.Interface) (*SchedulingMetrics, error) { - result := SchedulingMetrics{} +// Sends REST request to kube scheduler metrics +func sendRestRequestToScheduler(c clientset.Interface, op string) (string, error) { + opUpper := strings.ToUpper(op) + if opUpper != "GET" && opUpper != "DELETE" { + return "", fmt.Errorf("Unknown REST request") + } - // Check if master Node is registered nodes, err := c.CoreV1().Nodes().List(metav1.ListOptions{}) ExpectNoError(err) - var data string var masterRegistered = false for _, node := range nodes.Items { if system.IsMasterNode(node.Name) { masterRegistered = true } } + + var responseText string if masterRegistered { ctx, cancel := context.WithTimeout(context.Background(), SingleCallTimeout) defer cancel() - var rawData []byte - rawData, err = c.CoreV1().RESTClient().Get(). + body, err := c.CoreV1().RESTClient().Verb(opUpper). Context(ctx). Namespace(metav1.NamespaceSystem). Resource("pods"). @@ -469,45 +476,55 @@ func getSchedulingLatency(c clientset.Interface) (*SchedulingMetrics, error) { Do().Raw() ExpectNoError(err) - data = string(rawData) + responseText = string(body) } else { // If master is not registered fall back to old method of using SSH. if TestContext.Provider == "gke" { Logf("Not grabbing scheduler metrics through master SSH: unsupported for gke") - return nil, nil + return "", nil } - cmd := "curl http://localhost:10251/metrics" + + cmd := "curl -X " + opUpper + " http://localhost:10251/metrics" sshResult, err := SSH(cmd, GetMasterHost()+":22", TestContext.Provider) if err != nil || sshResult.Code != 0 { - return &result, fmt.Errorf("unexpected error (code: %d) in ssh connection to master: %#v", sshResult.Code, err) + return "", fmt.Errorf("unexpected error (code: %d) in ssh connection to master: %#v", sshResult.Code, err) } - data = sshResult.Stdout + responseText = sshResult.Stdout } + return responseText, nil +} + +// Retrieves scheduler latency metrics. +func getSchedulingLatency(c clientset.Interface) (*SchedulingMetrics, error) { + result := SchedulingMetrics{} + data, err := sendRestRequestToScheduler(c, "GET") + samples, err := extractMetricSamples(data) if err != nil { return nil, err } for _, sample := range samples { + if sample.Metric[model.MetricNameLabel] != SchedulingLatencyMetricName { + continue + } + var metric *LatencyMetric = nil - switch sample.Metric[model.MetricNameLabel] { - case "scheduler_scheduling_algorithm_latency_microseconds": - metric = &result.SchedulingLatency - case "scheduler_binding_latency_microseconds": + switch sample.Metric[schedulermetric.OperationLabel] { + case schedulermetric.SelectingNode: + metric = &result.SelectingNodeLatency + case schedulermetric.Binding: metric = &result.BindingLatency - case "scheduler_e2e_scheduling_latency_microseconds": - metric = &result.E2ELatency } if metric == nil { continue } - latency := sample.Value quantile, err := strconv.ParseFloat(string(sample.Metric[model.QuantileLabel]), 64) if err != nil { return nil, err } - setQuantile(metric, quantile, time.Duration(int64(latency))*time.Microsecond) + setQuantile(metric, quantile, time.Duration(int64(float64(sample.Value)*float64(time.Second)))) } return &result, nil } @@ -521,6 +538,14 @@ func VerifySchedulerLatency(c clientset.Interface) (*SchedulingMetrics, error) { return latency, nil } +func ResetSchedulerMetrics(c clientset.Interface) error { + responseText, err := sendRestRequestToScheduler(c, "DELETE") + if err != nil || responseText != "metrics reset\n" { + return fmt.Errorf("Unexpected response: %q", responseText) + } + return nil +} + func PrettyPrintJSON(metrics interface{}) string { output := &bytes.Buffer{} if err := json.NewEncoder(output).Encode(metrics); err != nil { diff --git a/test/e2e/framework/nodes_util.go b/test/e2e/framework/nodes_util.go index 4212899e74f..a58a6e62859 100644 --- a/test/e2e/framework/nodes_util.go +++ b/test/e2e/framework/nodes_util.go @@ -205,16 +205,7 @@ func NodeUpgrade(f *Framework, v string, img string) error { if err != nil { return err } - - // Wait for it to complete and validate nodes are healthy. - // - // TODO(ihmccreery) We shouldn't have to wait for nodes to be ready in - // GKE; the operation shouldn't return until they all are. - Logf("Waiting up to %v for all nodes to be ready after the upgrade", RestartNodeReadyAgainTimeout) - if _, err := CheckNodesReady(f.ClientSet, TestContext.CloudConfig.NumNodes, RestartNodeReadyAgainTimeout); err != nil { - return err - } - return nil + return waitForNodesReadyAfterUpgrade(f) } // TODO(mrhohn): Remove this function when kube-proxy is run as a DaemonSet by default. @@ -223,9 +214,20 @@ func NodeUpgradeGCEWithKubeProxyDaemonSet(f *Framework, v string, img string, en if err := nodeUpgradeGCE(v, img, enableKubeProxyDaemonSet); err != nil { return err } + return waitForNodesReadyAfterUpgrade(f) +} + +func waitForNodesReadyAfterUpgrade(f *Framework) error { // Wait for it to complete and validate nodes are healthy. - Logf("Waiting up to %v for all nodes to be ready after the upgrade", RestartNodeReadyAgainTimeout) - if _, err := CheckNodesReady(f.ClientSet, TestContext.CloudConfig.NumNodes, RestartNodeReadyAgainTimeout); err != nil { + // + // TODO(ihmccreery) We shouldn't have to wait for nodes to be ready in + // GKE; the operation shouldn't return until they all are. + numNodes, err := NumberOfRegisteredNodes(f.ClientSet) + if err != nil { + return fmt.Errorf("couldn't detect number of nodes") + } + Logf("Waiting up to %v for all %d nodes to be ready after the upgrade", RestartNodeReadyAgainTimeout, numNodes) + if _, err := CheckNodesReady(f.ClientSet, numNodes, RestartNodeReadyAgainTimeout); err != nil { return err } return nil diff --git a/test/e2e/framework/psp_util.go b/test/e2e/framework/psp_util.go index 4e6e4f8a701..cd281f00d54 100644 --- a/test/e2e/framework/psp_util.go +++ b/test/e2e/framework/psp_util.go @@ -71,6 +71,7 @@ func PrivilegedPSP(name string) *extensionsv1beta1.PodSecurityPolicy { Rule: extensionsv1beta1.FSGroupStrategyRunAsAny, }, ReadOnlyRootFilesystem: false, + AllowedUnsafeSysctls: []string{"*"}, }, } } diff --git a/test/e2e/framework/test_context.go b/test/e2e/framework/test_context.go index cb7109f6acc..5c3099c8208 100644 --- a/test/e2e/framework/test_context.go +++ b/test/e2e/framework/test_context.go @@ -113,6 +113,8 @@ type TestContextType struct { FeatureGates map[string]bool // Node e2e specific test context NodeTestContextType + // Storage e2e specific test context + StorageTestContextType // Monitoring solution that is used in current cluster. ClusterMonitoringMode string // Separate Prometheus monitoring deployed in cluster @@ -160,6 +162,14 @@ type NodeTestContextType struct { SystemSpecName string } +// StorageConfig contains the shared settings for storage 2e2 tests. +type StorageTestContextType struct { + // CSIImageVersion overrides the builtin stable version numbers if set. + CSIImageVersion string + // CSIImageRegistry defines the image registry hosting the CSI container images. + CSIImageRegistry string +} + type CloudConfig struct { ApiEndpoint string ProjectID string @@ -264,7 +274,7 @@ func RegisterClusterFlags() { flag.StringVar(&cloudConfig.ClusterTag, "cluster-tag", "", "Tag used to identify resources. Only required if provider is aws.") flag.StringVar(&cloudConfig.ConfigFile, "cloud-config-file", "", "Cloud config file. Only required if provider is azure.") - flag.IntVar(&TestContext.MinStartupPods, "minStartupPods", 8, "The number of pods which we need to see in 'Running' state with a 'Ready' condition of true, before we try running tests. This is useful in any cluster which needs some base pod-based services running before it can be used.") + flag.IntVar(&TestContext.MinStartupPods, "minStartupPods", 0, "The number of pods which we need to see in 'Running' state with a 'Ready' condition of true, before we try running tests. This is useful in any cluster which needs some base pod-based services running before it can be used.") flag.DurationVar(&TestContext.SystemPodsStartupTimeout, "system-pods-startup-timeout", 10*time.Minute, "Timeout for waiting for all system pods to be running before starting tests.") flag.DurationVar(&TestContext.NodeSchedulableTimeout, "node-schedulable-timeout", 30*time.Minute, "Timeout for waiting for all nodes to be schedulable.") flag.StringVar(&TestContext.UpgradeTarget, "upgrade-target", "ci/latest", "Version to upgrade to (e.g. 'release/stable', 'release/latest', 'ci/latest', '0.19.1', '0.19.1-669-gabac8c8') if doing an upgrade test.") @@ -293,6 +303,11 @@ func RegisterNodeFlags() { flag.StringVar(&TestContext.SystemSpecName, "system-spec-name", "", "The name of the system spec (e.g., gke) that's used in the node e2e test. The system specs are in test/e2e_node/system/specs/. This is used by the test framework to determine which tests to run for validating the system requirements.") } +func RegisterStorageFlags() { + flag.StringVar(&TestContext.CSIImageVersion, "csiImageVersion", "", "overrides the default tag used for hostpathplugin/csi-attacher/csi-provisioner/driver-registrar images") + flag.StringVar(&TestContext.CSIImageRegistry, "csiImageRegistry", "quay.io/k8scsi", "overrides the default repository used for hostpathplugin/csi-attacher/csi-provisioner/driver-registrar images") +} + // ViperizeFlags sets up all flag and config processing. Future configuration info should be added to viper, not to flags. func ViperizeFlags() { @@ -301,6 +316,7 @@ func ViperizeFlags() { // since go test 'flag's are sort of incompatible w/ flag, glog, etc. RegisterCommonFlags() RegisterClusterFlags() + RegisterStorageFlags() flag.Parse() // Part 2: Set Viper provided flags. diff --git a/test/e2e/framework/util.go b/test/e2e/framework/util.go index 5dc45815b6f..889c403afec 100644 --- a/test/e2e/framework/util.go +++ b/test/e2e/framework/util.go @@ -88,12 +88,11 @@ import ( "k8s.io/kubernetes/pkg/controller" nodectlr "k8s.io/kubernetes/pkg/controller/nodelifecycle" "k8s.io/kubernetes/pkg/features" - "k8s.io/kubernetes/pkg/kubectl" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/kubelet/util/format" "k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" sshutil "k8s.io/kubernetes/pkg/ssh" "k8s.io/kubernetes/pkg/util/system" taintutils "k8s.io/kubernetes/pkg/util/taints" @@ -2847,8 +2846,7 @@ func ScaleResource( gr schema.GroupResource, ) error { By(fmt.Sprintf("Scaling %v %s in namespace %s to %d", kind, name, ns, size)) - scaler := kubectl.NewScaler(scalesGetter) - if err := testutils.ScaleResourceWithRetries(scaler, ns, name, size, gr); err != nil { + if err := testutils.ScaleResourceWithRetries(scalesGetter, ns, name, size, gr); err != nil { return fmt.Errorf("error while scaling RC %s to %d replicas: %v", name, size, err) } if !wait { @@ -3030,6 +3028,8 @@ func getReplicasFromRuntimeObject(obj runtime.Object) (int32, error) { return *typed.Spec.Replicas, nil } return 0, nil + case *extensions.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. diff --git a/test/e2e/framework/volume_util.go b/test/e2e/framework/volume_util.go index 1f0a8e019f7..ce97bcf2dcf 100644 --- a/test/e2e/framework/volume_util.go +++ b/test/e2e/framework/volume_util.go @@ -66,7 +66,7 @@ const ( TiB int64 = 1024 * GiB // Waiting period for volume server (Ceph, ...) to initialize itself. - VolumeServerPodStartupSleep = 20 * time.Second + VolumeServerPodStartupTimeout = 1 * time.Minute // Waiting period for pod to be cleaned up and unmount its volumes so we // don't tear down containers with NFS/Ceph/Gluster server too early. @@ -92,6 +92,8 @@ type VolumeTestConfig struct { // map -> // if is empty, mount a tmpfs emptydir ServerVolumes map[string]string + // Message to wait for before starting clients + ServerReadyMessage string // Wait for the pod to terminate successfully // False indicates that the pod is long running WaitForCompletion bool @@ -114,11 +116,12 @@ type VolumeTest struct { // NFS-specific wrapper for CreateStorageServer. func NewNFSServer(cs clientset.Interface, namespace string, args []string) (config VolumeTestConfig, pod *v1.Pod, ip string) { config = VolumeTestConfig{ - Namespace: namespace, - Prefix: "nfs", - ServerImage: imageutils.GetE2EImage(imageutils.VolumeNFSServer), - ServerPorts: []int{2049}, - ServerVolumes: map[string]string{"": "/exports"}, + Namespace: namespace, + Prefix: "nfs", + ServerImage: imageutils.GetE2EImage(imageutils.VolumeNFSServer), + ServerPorts: []int{2049}, + ServerVolumes: map[string]string{"": "/exports"}, + ServerReadyMessage: "NFS started", } if len(args) > 0 { config.ServerArgs = args @@ -180,13 +183,14 @@ func NewISCSIServer(cs clientset.Interface, namespace string) (config VolumeTest // iSCSI container needs to insert modules from the host "/lib/modules": "/lib/modules", }, + ServerReadyMessage: "Configuration restored from /etc/target/saveconfig.json", } pod, ip = CreateStorageServer(cs, config) return config, pod, ip } // CephRBD-specific wrapper for CreateStorageServer. -func NewRBDServer(cs clientset.Interface, namespace string) (config VolumeTestConfig, pod *v1.Pod, ip string) { +func NewRBDServer(cs clientset.Interface, namespace string) (config VolumeTestConfig, pod *v1.Pod, secret *v1.Secret, ip string) { config = VolumeTestConfig{ Namespace: namespace, Prefix: "rbd", @@ -195,17 +199,31 @@ func NewRBDServer(cs clientset.Interface, namespace string) (config VolumeTestCo ServerVolumes: map[string]string{ "/lib/modules": "/lib/modules", }, + ServerReadyMessage: "Ceph is ready", } pod, ip = CreateStorageServer(cs, config) + // create secrets for the server + secret = &v1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "Secret", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: config.Prefix + "-secret", + }, + Data: map[string][]byte{ + // from test/images/volumes-tester/rbd/keyring + "key": []byte("AQDRrKNVbEevChAAEmRC+pW/KBVHxa0w/POILA=="), + }, + Type: "kubernetes.io/rbd", + } - // Ceph server container needs some time to start. Tests continue working if - // this sleep is removed, however kubelet logs (and kubectl describe - // ) would be cluttered with error messages about non-existing - // image. - Logf("sleeping a bit to give ceph server time to initialize") - time.Sleep(VolumeServerPodStartupSleep) + secret, err := cs.CoreV1().Secrets(config.Namespace).Create(secret) + if err != nil { + Failf("Failed to create secrets for Ceph RBD: %v", err) + } - return config, pod, ip + return config, pod, secret, ip } // Wrapper for StartVolumeServer(). A storage server config is passed in, and a pod pointer @@ -329,6 +347,10 @@ func StartVolumeServer(client clientset.Interface, config VolumeTestConfig) *v1. ExpectNoError(err, "Cannot locate the server pod %q: %v", serverPodName, err) } } + if config.ServerReadyMessage != "" { + _, err := LookForStringInLog(pod.Namespace, pod.Name, serverPodName, config.ServerReadyMessage, VolumeServerPodStartupTimeout) + ExpectNoError(err, "Failed to find %q in pod logs: %s", config.ServerReadyMessage, err) + } return pod } diff --git a/test/e2e/kubectl/kubectl.go b/test/e2e/kubectl/kubectl.go index 254391188d5..3132d2c11a9 100644 --- a/test/e2e/kubectl/kubectl.go +++ b/test/e2e/kubectl/kubectl.go @@ -1545,7 +1545,7 @@ metadata: Expect(runOutput).To(ContainSubstring("abcd1234")) Expect(runOutput).To(ContainSubstring("stdin closed")) - err := framework.WaitForJobGone(c, ns, jobName, 10*time.Second) + err := framework.WaitForJobGone(c, ns, jobName, wait.ForeverTestTimeout) Expect(err).NotTo(HaveOccurred()) By("verifying the job " + jobName + " was deleted") diff --git a/test/e2e/lifecycle/cluster_upgrade.go b/test/e2e/lifecycle/cluster_upgrade.go index d70a62d67a7..3a2d7ce7235 100644 --- a/test/e2e/lifecycle/cluster_upgrade.go +++ b/test/e2e/lifecycle/cluster_upgrade.go @@ -54,6 +54,10 @@ var upgradeTests = []upgrades.Test{ &upgrades.AppArmorUpgradeTest{}, } +var gpuUpgradeTests = []upgrades.Test{ + &upgrades.NvidiaGPUUpgradeTest{}, +} + var statefulsetUpgradeTests = []upgrades.Test{ &upgrades.MySqlUpgradeTest{}, &upgrades.EtcdUpgradeTest{}, @@ -256,6 +260,52 @@ var _ = SIGDescribe("ingress Downgrade [Feature:IngressDowngrade]", func() { }) }) +var _ = SIGDescribe("gpu Upgrade [Feature:GPUUpgrade]", func() { + f := framework.NewDefaultFramework("gpu-upgrade") + + // Create the frameworks here because we can only create them + // in a "Describe". + testFrameworks := createUpgradeFrameworks(gpuUpgradeTests) + Describe("master upgrade", func() { + It("should NOT disrupt gpu pod [Feature:GPUMasterUpgrade]", func() { + upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), framework.TestContext.UpgradeTarget) + framework.ExpectNoError(err) + + testSuite := &junit.TestSuite{Name: "GPU master upgrade"} + gpuUpgradeTest := &junit.TestCase{Name: "[sig-node] gpu-master-upgrade", Classname: "upgrade_tests"} + testSuite.TestCases = append(testSuite.TestCases, gpuUpgradeTest) + upgradeFunc := func() { + start := time.Now() + defer finalizeUpgradeTest(start, gpuUpgradeTest) + target := upgCtx.Versions[1].Version.String() + framework.ExpectNoError(framework.MasterUpgrade(target)) + framework.ExpectNoError(framework.CheckMasterVersion(f.ClientSet, target)) + } + runUpgradeSuite(f, gpuUpgradeTests, testFrameworks, testSuite, upgCtx, upgrades.MasterUpgrade, upgradeFunc) + }) + }) + Describe("cluster upgrade", func() { + It("should be able to run gpu pod after upgrade [Feature:GPUClusterUpgrade]", func() { + upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), framework.TestContext.UpgradeTarget) + framework.ExpectNoError(err) + + testSuite := &junit.TestSuite{Name: "GPU cluster upgrade"} + gpuUpgradeTest := &junit.TestCase{Name: "[sig-node] gpu-cluster-upgrade", Classname: "upgrade_tests"} + testSuite.TestCases = append(testSuite.TestCases, gpuUpgradeTest) + upgradeFunc := func() { + start := time.Now() + defer finalizeUpgradeTest(start, gpuUpgradeTest) + target := upgCtx.Versions[1].Version.String() + framework.ExpectNoError(framework.MasterUpgrade(target)) + framework.ExpectNoError(framework.CheckMasterVersion(f.ClientSet, target)) + framework.ExpectNoError(framework.NodeUpgrade(f, target, framework.TestContext.UpgradeImage)) + framework.ExpectNoError(framework.CheckNodesVersions(f.ClientSet, target)) + } + runUpgradeSuite(f, gpuUpgradeTests, testFrameworks, testSuite, upgCtx, upgrades.ClusterUpgrade, upgradeFunc) + }) + }) +}) + var _ = Describe("[sig-apps] stateful Upgrade [Feature:StatefulUpgrade]", func() { f := framework.NewDefaultFramework("stateful-upgrade") diff --git a/test/e2e/network/BUILD b/test/e2e/network/BUILD index 60ac1f73e08..ac6ae0df02c 100644 --- a/test/e2e/network/BUILD +++ b/test/e2e/network/BUILD @@ -11,6 +11,7 @@ go_library( "dns.go", "dns_common.go", "dns_configmap.go", + "dns_scale_records.go", "doc.go", "example_cluster_dns.go", "firewall.go", @@ -70,6 +71,7 @@ go_library( "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", + "//vendor/k8s.io/client-go/util/workqueue:go_default_library", ], ) diff --git a/test/e2e/network/dns_common.go b/test/e2e/network/dns_common.go index 35af935c261..d4696319fb6 100644 --- a/test/e2e/network/dns_common.go +++ b/test/e2e/network/dns_common.go @@ -111,7 +111,7 @@ func (t *dnsTestCommon) runDig(dnsName, target string) []string { cmd = append(cmd, "@"+t.dnsPod.Status.PodIP) case "kube-dns": cmd = append(cmd, "@"+t.dnsPod.Status.PodIP, "-p", "10053") - case "dnsmasq": + case "cluster-dns": break default: panic(fmt.Errorf("invalid target: " + target)) @@ -193,7 +193,7 @@ func (t *dnsTestCommon) deleteConfigMap() { Expect(err).NotTo(HaveOccurred()) } -func (t *dnsTestCommon) createUtilPod() { +func (t *dnsTestCommon) createUtilPodLabel(baseName string) { // Actual port # doesn't matter, just needs to exist. const servicePort = 10101 @@ -203,8 +203,8 @@ func (t *dnsTestCommon) createUtilPod() { }, ObjectMeta: metav1.ObjectMeta{ Namespace: t.f.Namespace.Name, - Labels: map[string]string{"app": "e2e-dns-configmap"}, - GenerateName: "e2e-dns-configmap-", + Labels: map[string]string{"app": baseName}, + GenerateName: baseName + "-", }, Spec: v1.PodSpec{ Containers: []v1.Container{ @@ -232,10 +232,10 @@ func (t *dnsTestCommon) createUtilPod() { }, ObjectMeta: metav1.ObjectMeta{ Namespace: t.f.Namespace.Name, - Name: "e2e-dns-configmap", + Name: baseName, }, Spec: v1.ServiceSpec{ - Selector: map[string]string{"app": "e2e-dns-configmap"}, + Selector: map[string]string{"app": baseName}, Ports: []v1.ServicePort{ { Protocol: "TCP", diff --git a/test/e2e/network/dns_configmap.go b/test/e2e/network/dns_configmap.go index 332b84d590f..c067fc22aab 100644 --- a/test/e2e/network/dns_configmap.go +++ b/test/e2e/network/dns_configmap.go @@ -55,7 +55,7 @@ func (t *dnsFederationsConfigMapTest) run() { t.init() defer t.c.CoreV1().ConfigMaps(t.ns).Delete(t.name, nil) - t.createUtilPod() + t.createUtilPodLabel("e2e-dns-configmap") defer t.deleteUtilPod() t.validate() @@ -149,7 +149,7 @@ type dnsNameserverTest struct { func (t *dnsNameserverTest) run() { t.init() - t.createUtilPod() + t.createUtilPodLabel("e2e-dns-configmap") defer t.deleteUtilPod() originalConfigMapData := t.fetchDNSConfigMapData() defer t.restoreDNSConfigMap(originalConfigMapData) @@ -187,17 +187,17 @@ func (t *dnsNameserverTest) run() { t.checkDNSRecordFrom( "abc.acme.local", func(actual []string) bool { return len(actual) == 1 && actual[0] == "1.1.1.1" }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) t.checkDNSRecordFrom( "def.acme.local", func(actual []string) bool { return len(actual) == 1 && actual[0] == "2.2.2.2" }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) t.checkDNSRecordFrom( "widget.local", func(actual []string) bool { return len(actual) == 1 && actual[0] == "3.3.3.3" }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) t.restoreDNSConfigMap(originalConfigMapData) @@ -206,7 +206,7 @@ func (t *dnsNameserverTest) run() { t.checkDNSRecordFrom( "abc.acme.local", func(actual []string) bool { return len(actual) == 0 }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) } @@ -217,7 +217,7 @@ type dnsPtrFwdTest struct { func (t *dnsPtrFwdTest) run() { t.init() - t.createUtilPod() + t.createUtilPodLabel("e2e-dns-configmap") defer t.deleteUtilPod() originalConfigMapData := t.fetchDNSConfigMapData() defer t.restoreDNSConfigMap(originalConfigMapData) @@ -229,7 +229,7 @@ func (t *dnsPtrFwdTest) run() { t.checkDNSRecordFrom( "8.8.8.8.in-addr.arpa", func(actual []string) bool { return len(actual) == 1 && actual[0] == googleDnsHostname+"." }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) if t.name == "coredns" { @@ -254,14 +254,14 @@ func (t *dnsPtrFwdTest) run() { t.checkDNSRecordFrom( "123.2.0.192.in-addr.arpa", func(actual []string) bool { return len(actual) == 1 && actual[0] == "my.test." }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) t.restoreDNSConfigMap(originalConfigMapData) t.checkDNSRecordFrom( "123.2.0.192.in-addr.arpa", func(actual []string) bool { return len(actual) == 0 }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) } @@ -272,7 +272,7 @@ type dnsExternalNameTest struct { func (t *dnsExternalNameTest) run() { t.init() - t.createUtilPod() + t.createUtilPodLabel("e2e-dns-configmap") defer t.deleteUtilPod() originalConfigMapData := t.fetchDNSConfigMapData() defer t.restoreDNSConfigMap(originalConfigMapData) @@ -306,7 +306,7 @@ func (t *dnsExternalNameTest) run() { func(actual []string) bool { return len(actual) >= 1 && actual[0] == googleDnsHostname+"." }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) if t.name == "coredns" { @@ -333,7 +333,7 @@ func (t *dnsExternalNameTest) run() { func(actual []string) bool { return len(actual) == 2 && actual[0] == fooHostname+"." && actual[1] == "192.0.2.123" }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) t.restoreDNSConfigMap(originalConfigMapData) diff --git a/test/e2e/network/dns_scale_records.go b/test/e2e/network/dns_scale_records.go new file mode 100644 index 00000000000..c22cbd7e640 --- /dev/null +++ b/test/e2e/network/dns_scale_records.go @@ -0,0 +1,105 @@ +/* +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 network + +import ( + "fmt" + "strconv" + "time" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/util/workqueue" + "k8s.io/kubernetes/test/e2e/framework" + testutils "k8s.io/kubernetes/test/utils" + + . "github.com/onsi/ginkgo" +) + +const ( + parallelCreateServiceWorkers = 1 + maxServicesPerCluster = 10000 + checkServicePercent = 0.05 +) + +var _ = SIGDescribe("[Feature:PerformanceDNS]", func() { + f := framework.NewDefaultFramework("performancedns") + + BeforeEach(func() { + framework.ExpectNoError(framework.WaitForAllNodesSchedulable(f.ClientSet, framework.TestContext.NodeSchedulableTimeout)) + framework.WaitForAllNodesHealthy(f.ClientSet, time.Minute) + + err := framework.CheckTestingNSDeletedExcept(f.ClientSet, f.Namespace.Name) + framework.ExpectNoError(err) + }) + + // answers dns for service - creates the maximum number of services, and then check dns record for one + It("Should answer DNS query for maximum number of services per cluster", func() { + services := generateServicesInNamespace(f.Namespace.Name, maxServicesPerCluster) + createService := func(i int) { + defer GinkgoRecover() + framework.ExpectNoError(testutils.CreateServiceWithRetries(f.ClientSet, f.Namespace.Name, services[i])) + } + framework.Logf("Creating %v test services", maxServicesPerCluster) + workqueue.Parallelize(parallelCreateServiceWorkers, len(services), createService) + dnsTest := dnsTestCommon{ + f: f, + c: f.ClientSet, + ns: f.Namespace.Name, + } + dnsTest.createUtilPodLabel("e2e-dns-scale-records") + defer dnsTest.deleteUtilPod() + framework.Logf("Querying %v%% of service records", checkServicePercent*100) + for i := 0; i < len(services); i++ { + if i%(1/checkServicePercent) != 0 { + continue + } + s := services[i] + svc, err := f.ClientSet.CoreV1().Services(s.Namespace).Get(s.Name, metav1.GetOptions{}) + framework.ExpectNoError(err) + qname := fmt.Sprintf("%v.%v.svc.cluster.local", s.Name, s.Namespace) + framework.Logf("Querying %v expecting %v", qname, svc.Spec.ClusterIP) + dnsTest.checkDNSRecordFrom( + qname, + func(actual []string) bool { + return len(actual) == 1 && actual[0] == svc.Spec.ClusterIP + }, + "cluster-dns", + wait.ForeverTestTimeout, + ) + } + }) +}) + +func generateServicesInNamespace(namespace string, num int) []*v1.Service { + services := make([]*v1.Service, num) + for i := 0; i < num; i++ { + services[i] = &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-" + strconv.Itoa(i), + Namespace: namespace, + }, + Spec: v1.ServiceSpec{ + Ports: []v1.ServicePort{{ + Port: 80, + }}, + }, + } + } + return services +} diff --git a/test/e2e/scalability/density.go b/test/e2e/scalability/density.go index 1ef125d8744..30df63e7afe 100644 --- a/test/e2e/scalability/density.go +++ b/test/e2e/scalability/density.go @@ -222,12 +222,30 @@ func density30AddonResourceVerifier(numNodes int) map[string]framework.ResourceC return constraints } +func computeAverage(sample []float64) float64 { + sum := 0.0 + for _, value := range sample { + sum += value + } + return sum / float64(len(sample)) +} + +func computeQuantile(sample []float64, quantile float64) float64 { + Expect(sort.Float64sAreSorted(sample)).To(Equal(true)) + Expect(quantile >= 0.0 && quantile <= 1.0).To(Equal(true)) + index := int(quantile*float64(len(sample))) - 1 + if index < 0 { + return math.NaN() + } + return sample[index] +} + func logPodStartupStatus( c clientset.Interface, expectedPods int, observedLabels map[string]string, period time.Duration, - scheduleThroughputs []float64, + scheduleThroughputs *[]float64, stopCh chan struct{}) { label := labels.SelectorFromSet(labels.Set(observedLabels)) @@ -250,14 +268,14 @@ func logPodStartupStatus( framework.Logf(startupStatus.String("Density")) // Compute scheduling throughput for the latest time period. throughput := float64(startupStatus.Scheduled-lastScheduledCount) / float64(period/time.Second) - scheduleThroughputs = append(scheduleThroughputs, throughput) + *scheduleThroughputs = append(*scheduleThroughputs, throughput) lastScheduledCount = startupStatus.Scheduled } } // runDensityTest will perform a density test and return the time it took for // all pods to start -func runDensityTest(dtc DensityTestConfig, testPhaseDurations *timer.TestPhaseTimer, scheduleThroughputs []float64) time.Duration { +func runDensityTest(dtc DensityTestConfig, testPhaseDurations *timer.TestPhaseTimer, scheduleThroughputs *[]float64) time.Duration { defer GinkgoRecover() // Create all secrets, configmaps and daemons. @@ -395,12 +413,19 @@ var _ = SIGDescribe("Density", func() { } // Verify scheduler metrics. - // TODO: Reset metrics at the beginning of the test. - // We should do something similar to how we do it for APIserver. latency, err := framework.VerifySchedulerLatency(c) framework.ExpectNoError(err) if err == nil { - latency.ThroughputSamples = scheduleThroughputs + // Compute avg and quantiles of throughput (excluding last element, that's usually an outlier). + sampleSize := len(scheduleThroughputs) + if sampleSize > 1 { + scheduleThroughputs = scheduleThroughputs[:sampleSize-1] + sort.Float64s(scheduleThroughputs) + latency.ThroughputAverage = computeAverage(scheduleThroughputs) + latency.ThroughputPerc50 = computeQuantile(scheduleThroughputs, 0.5) + latency.ThroughputPerc90 = computeQuantile(scheduleThroughputs, 0.9) + latency.ThroughputPerc99 = computeQuantile(scheduleThroughputs, 0.99) + } summaries = append(summaries, latency) } summaries = append(summaries, testPhaseDurations) @@ -442,6 +467,7 @@ var _ = SIGDescribe("Density", func() { uuid = string(utiluuid.NewUUID()) + framework.ExpectNoError(framework.ResetSchedulerMetrics(c)) framework.ExpectNoError(framework.ResetMetrics(c)) framework.ExpectNoError(os.Mkdir(fmt.Sprintf(framework.TestContext.OutputDir+"/%s", uuid), 0777)) @@ -647,7 +673,7 @@ var _ = SIGDescribe("Density", func() { LogFunc: framework.Logf, }) } - e2eStartupTime = runDensityTest(dConfig, testPhaseDurations, scheduleThroughputs) + e2eStartupTime = runDensityTest(dConfig, testPhaseDurations, &scheduleThroughputs) if itArg.runLatencyTest { By("Scheduling additional Pods to measure startup latencies") diff --git a/test/e2e/scheduling/BUILD b/test/e2e/scheduling/BUILD index 33a4eda78ed..f149eec6629 100644 --- a/test/e2e/scheduling/BUILD +++ b/test/e2e/scheduling/BUILD @@ -20,8 +20,8 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/api/v1/pod:go_default_library", - "//pkg/apis/apps:go_default_library", "//pkg/apis/core:go_default_library", + "//pkg/apis/extensions:go_default_library", "//pkg/apis/scheduling:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/quota/evaluator/core:go_default_library", @@ -37,7 +37,7 @@ go_library( "//vendor/google.golang.org/api/compute/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/test/e2e/scheduling/nvidia-gpus.go b/test/e2e/scheduling/nvidia-gpus.go index 5e08e339c5f..b0b4c62e7c9 100644 --- a/test/e2e/scheduling/nvidia-gpus.go +++ b/test/e2e/scheduling/nvidia-gpus.go @@ -25,7 +25,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" - "k8s.io/kubernetes/pkg/apis/apps" + extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/test/e2e/framework" imageutils "k8s.io/kubernetes/test/utils/image" @@ -137,10 +137,10 @@ func SetupNVIDIAGPUNode(f *framework.Framework, setupResourceGatherer bool) *fra framework.ExpectNoError(err, "failed to create nvidia-driver-installer daemonset") framework.Logf("Successfully created daemonset to install Nvidia drivers.") - pods, err := framework.WaitForControlledPods(f.ClientSet, ds.Namespace, ds.Name, apps.Kind("DaemonSet")) + pods, err := framework.WaitForControlledPods(f.ClientSet, ds.Namespace, ds.Name, extensionsinternal.Kind("DaemonSet")) framework.ExpectNoError(err, "failed to get pods controlled by the nvidia-driver-installer daemonset") - devicepluginPods, err := framework.WaitForControlledPods(f.ClientSet, "kube-system", "nvidia-gpu-device-plugin", apps.Kind("DaemonSet")) + devicepluginPods, err := framework.WaitForControlledPods(f.ClientSet, "kube-system", "nvidia-gpu-device-plugin", extensionsinternal.Kind("DaemonSet")) if err == nil { framework.Logf("Adding deviceplugin addon pod.") pods.Items = append(pods.Items, devicepluginPods.Items...) diff --git a/test/e2e/scheduling/preemption.go b/test/e2e/scheduling/preemption.go index b67c6bf8130..d545493bc59 100644 --- a/test/e2e/scheduling/preemption.go +++ b/test/e2e/scheduling/preemption.go @@ -21,7 +21,7 @@ import ( "time" "k8s.io/api/core/v1" - "k8s.io/api/scheduling/v1alpha1" + schedulerapi "k8s.io/api/scheduling/v1beta1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -51,12 +51,11 @@ var _ = SIGDescribe("SchedulerPreemption [Serial] [Feature:PodPreemption]", func cs = f.ClientSet ns = f.Namespace.Name nodeList = &v1.NodeList{} - - _, err := f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: highPriorityClassName}, Value: highPriority}) + _, err := f.ClientSet.SchedulingV1beta1().PriorityClasses().Create(&schedulerapi.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: highPriorityClassName}, Value: highPriority}) Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true)) - _, err = f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: mediumPriorityClassName}, Value: mediumPriority}) + _, err = f.ClientSet.SchedulingV1beta1().PriorityClasses().Create(&schedulerapi.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: mediumPriorityClassName}, Value: mediumPriority}) Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true)) - _, err = f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: lowPriorityClassName}, Value: lowPriority}) + _, err = f.ClientSet.SchedulingV1beta1().PriorityClasses().Create(&schedulerapi.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: lowPriorityClassName}, Value: lowPriority}) Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true)) framework.WaitForAllNodesHealthy(cs, time.Minute) diff --git a/test/e2e/storage/BUILD b/test/e2e/storage/BUILD index fcb91637b0e..f0430685ae3 100644 --- a/test/e2e/storage/BUILD +++ b/test/e2e/storage/BUILD @@ -6,6 +6,7 @@ go_library( "csi_objects.go", "csi_volumes.go", "empty_dir_wrapper.go", + "ephemeral_volume.go", "flexvolume.go", "generic_persistent_volume-disruptive.go", "mounted_volume_resize.go", diff --git a/test/e2e/storage/csi_objects.go b/test/e2e/storage/csi_objects.go index d888abdbb5c..15fd7cf3282 100644 --- a/test/e2e/storage/csi_objects.go +++ b/test/e2e/storage/csi_objects.go @@ -37,12 +37,23 @@ import ( . "github.com/onsi/ginkgo" ) -const ( - csiHostPathPluginImage string = "quay.io/k8scsi/hostpathplugin:v0.2.0" - csiExternalAttacherImage string = "quay.io/k8scsi/csi-attacher:v0.2.0" - csiExternalProvisionerImage string = "quay.io/k8scsi/csi-provisioner:v0.2.1" - csiDriverRegistrarImage string = "quay.io/k8scsi/driver-registrar:v0.2.0" -) +var csiImageVersions = map[string]string{ + "hostpathplugin": "v0.2.0", + "csi-attacher": "v0.2.0", + "csi-provisioner": "v0.2.1", + "driver-registrar": "v0.2.0", +} + +func csiContainerImage(image string) string { + var fullName string + fullName += framework.TestContext.CSIImageRegistry + "/" + image + ":" + if framework.TestContext.CSIImageVersion != "" { + fullName += framework.TestContext.CSIImageVersion + } else { + fullName += csiImageVersions[image] + } + return fullName +} // Create the driver registrar cluster role if it doesn't exist, no teardown so that tests // are parallelizable. This role will be shared with many of the CSI tests. @@ -207,7 +218,7 @@ func csiHostPathPod( Containers: []v1.Container{ { Name: "external-provisioner", - Image: csiExternalProvisionerImage, + Image: csiContainerImage("csi-provisioner"), ImagePullPolicy: v1.PullAlways, Args: []string{ "--v=5", @@ -223,7 +234,7 @@ func csiHostPathPod( }, { Name: "driver-registrar", - Image: csiDriverRegistrarImage, + Image: csiContainerImage("driver-registrar"), ImagePullPolicy: v1.PullAlways, Args: []string{ "--v=5", @@ -248,7 +259,7 @@ func csiHostPathPod( }, { Name: "external-attacher", - Image: csiExternalAttacherImage, + Image: csiContainerImage("csi-attacher"), ImagePullPolicy: v1.PullAlways, Args: []string{ "--v=5", @@ -269,7 +280,7 @@ func csiHostPathPod( }, { Name: "hostpath-driver", - Image: csiHostPathPluginImage, + Image: csiContainerImage("hostpathplugin"), ImagePullPolicy: v1.PullAlways, SecurityContext: &v1.SecurityContext{ Privileged: &priv, diff --git a/test/e2e/storage/ephemeral_volume.go b/test/e2e/storage/ephemeral_volume.go new file mode 100644 index 00000000000..5d1948e4b4e --- /dev/null +++ b/test/e2e/storage/ephemeral_volume.go @@ -0,0 +1,138 @@ +/* +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 storage + +import ( + "fmt" + "strings" + "time" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/rand" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/framework" + "k8s.io/kubernetes/test/e2e/storage/utils" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = utils.SIGDescribe("Ephemeralstorage", func() { + var ( + c clientset.Interface + ) + + f := framework.NewDefaultFramework("pv") + + BeforeEach(func() { + c = f.ClientSet + }) + + Describe("When pod refers to non-existent ephemeral storage", func() { + for _, testSource := range invalidEphemeralSource("pod-ephm-test") { + It(fmt.Sprintf("should allow deletion of pod with invalid volume : %s", testSource.volumeType), func() { + pod := testEphemeralVolumePod(f, testSource.volumeType, testSource.source) + pod, err := c.CoreV1().Pods(f.Namespace.Name).Create(pod) + Expect(err).NotTo(HaveOccurred()) + + // Allow it to sleep for 30 seconds + time.Sleep(30 * time.Second) + framework.Logf("Deleting pod %q/%q", pod.Namespace, pod.Name) + framework.ExpectNoError(framework.DeletePodWithWait(f, c, pod)) + }) + } + }) +}) + +type ephemeralTestInfo struct { + volumeType string + source *v1.VolumeSource +} + +func testEphemeralVolumePod(f *framework.Framework, volumeType string, source *v1.VolumeSource) *v1.Pod { + var ( + suffix = strings.ToLower(fmt.Sprintf("%s-%s", volumeType, rand.String(4))) + ) + return &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("pod-ephm-test-%s", suffix), + Namespace: f.Namespace.Name, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: fmt.Sprintf("test-container-subpath-%s", suffix), + Image: mountImage, + VolumeMounts: []v1.VolumeMount{ + { + Name: volumeName, + MountPath: volumePath, + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + Volumes: []v1.Volume{ + { + Name: volumeName, + VolumeSource: *source, + }, + }, + }, + } +} + +func invalidEphemeralSource(suffix string) []ephemeralTestInfo { + testInfo := []ephemeralTestInfo{ + { + volumeType: "secret", + source: &v1.VolumeSource{ + Secret: &v1.SecretVolumeSource{ + SecretName: fmt.Sprintf("secert-%s", suffix), + }, + }, + }, + { + volumeType: "configmap", + source: &v1.VolumeSource{ + ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: fmt.Sprintf("configmap-%s", suffix), + }, + }, + }, + }, + { + volumeType: "projected", + source: &v1.VolumeSource{ + Projected: &v1.ProjectedVolumeSource{ + Sources: []v1.VolumeProjection{ + { + Secret: &v1.SecretProjection{ + LocalObjectReference: v1.LocalObjectReference{ + Name: fmt.Sprintf("secret-%s", suffix), + }, + }, + }, + }, + }, + }, + }, + } + return testInfo +} diff --git a/test/e2e/storage/regional_pd.go b/test/e2e/storage/regional_pd.go index ff3c3858035..cc77ad13594 100644 --- a/test/e2e/storage/regional_pd.go +++ b/test/e2e/storage/regional_pd.go @@ -205,6 +205,9 @@ func testZonalFailover(c clientset.Interface, ns string) { instanceGroup, err := cloud.GetInstanceGroup(instanceGroupName, podZone) Expect(err).NotTo(HaveOccurred(), "Error getting instance group %s in zone %s", instanceGroupName, podZone) + templateName, err := framework.GetManagedInstanceGroupTemplateName(podZone) + Expect(err).NotTo(HaveOccurred(), + "Error getting instance group template in zone %s", podZone) err = framework.DeleteManagedInstanceGroup(podZone) Expect(err).NotTo(HaveOccurred(), "Error deleting instance group in zone %s", podZone) @@ -212,9 +215,6 @@ func testZonalFailover(c clientset.Interface, ns string) { defer func() { framework.Logf("recreating instance group %s", instanceGroup.Name) - // HACK improve this when Managed Instance Groups are available through the cloud provider API - templateName := strings.Replace(instanceGroupName, "group", "template", 1 /* n */) - framework.ExpectNoError(framework.CreateManagedInstanceGroup(instanceGroup.Size, podZone, templateName), "Error recreating instance group %s in zone %s", instanceGroup.Name, podZone) framework.ExpectNoError(framework.WaitForReadyNodes(c, nodeCount, framework.RestartNodeReadyAgainTimeout), diff --git a/test/e2e/storage/subpath.go b/test/e2e/storage/subpath.go index 4b7394fa3db..4e357b6eb9c 100644 --- a/test/e2e/storage/subpath.go +++ b/test/e2e/storage/subpath.go @@ -110,6 +110,13 @@ var _ = utils.SIGDescribe("Subpath", func() { testBasicSubpath(f, "configmap-value", pod) }) + It("should support subpaths with configmap pod with mountPath of existing file", func() { + pod := testPodSubpath(f, "configmap-key", "configmap", &v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{LocalObjectReference: v1.LocalObjectReference{Name: "my-configmap"}}}) + file := "/etc/resolv.conf" + pod.Spec.Containers[0].VolumeMounts[0].MountPath = file + testBasicSubpathFile(f, "configmap-value", pod, file) + }) + It("should support subpaths with downward pod", func() { pod := testPodSubpath(f, "downward/podname", "downwardAPI", &v1.VolumeSource{ DownwardAPI: &v1.DownwardAPIVolumeSource{ @@ -199,7 +206,7 @@ var _ = utils.SIGDescribe("Subpath", func() { setInitCommand(pod, fmt.Sprintf("ln -s /bin %s", subPathDir)) // Pod should fail - testPodFailSupath(f, pod) + testPodFailSubpath(f, pod) }) It("should fail if subpath file is outside the volume [Slow]", func() { @@ -207,7 +214,7 @@ var _ = utils.SIGDescribe("Subpath", func() { setInitCommand(pod, fmt.Sprintf("ln -s /bin/sh %s", subPathDir)) // Pod should fail - testPodFailSupath(f, pod) + testPodFailSubpath(f, pod) }) It("should fail if non-existent subpath is outside the volume [Slow]", func() { @@ -215,7 +222,7 @@ var _ = utils.SIGDescribe("Subpath", func() { setInitCommand(pod, fmt.Sprintf("ln -s /bin/notanexistingpath %s", subPathDir)) // Pod should fail - testPodFailSupath(f, pod) + testPodFailSubpath(f, pod) }) It("should fail if subpath with backstepping is outside the volume [Slow]", func() { @@ -223,7 +230,7 @@ var _ = utils.SIGDescribe("Subpath", func() { setInitCommand(pod, fmt.Sprintf("ln -s ../ %s", subPathDir)) // Pod should fail - testPodFailSupath(f, pod) + testPodFailSubpath(f, pod) }) It("should support creating multiple subpath from same volumes [Slow]", func() { @@ -297,7 +304,7 @@ var _ = utils.SIGDescribe("Subpath", func() { testReadFile(f, volumePath, pod, 0) }) - It("should support readOnly directory specified in the volumeSource", func() { + It("should support existing directories when readOnly specified in the volumeSource", func() { roVol := vol.getReadOnlyVolumeSpec() if roVol == nil { framework.Skipf("Volume type %v doesn't support readOnly source", curVolType) @@ -312,6 +319,19 @@ var _ = utils.SIGDescribe("Subpath", func() { // Read it from inside the subPath from container 0 testReadFile(f, filePathInSubpath, pod, 0) }) + + It("should fail for new directories when readOnly specified in the volumeSource", func() { + roVol := vol.getReadOnlyVolumeSpec() + if roVol == nil { + framework.Skipf("Volume type %v doesn't support readOnly source", curVolType) + } + + // Set volume source to read only + pod.Spec.Volumes[0].VolumeSource = *roVol + + // Pod should fail + testPodFailSubpathError(f, pod, "") + }) }) } @@ -319,7 +339,11 @@ var _ = utils.SIGDescribe("Subpath", func() { }) func testBasicSubpath(f *framework.Framework, contents string, pod *v1.Pod) { - setReadCommand(volumePath, &pod.Spec.Containers[0]) + testBasicSubpathFile(f, contents, pod, volumePath) +} + +func testBasicSubpathFile(f *framework.Framework, contents string, pod *v1.Pod, filepath string) { + setReadCommand(filepath, &pod.Spec.Containers[0]) By(fmt.Sprintf("Creating pod %s", pod.Name)) f.TestContainerOutput("atomic-volume-subpath", pod, 0, []string{contents}) @@ -412,6 +436,11 @@ func testPodSubpath(f *framework.Framework, subpath, volumeType string, source * }, }, }, + SecurityContext: &v1.PodSecurityContext{ + SELinuxOptions: &v1.SELinuxOptions{ + Level: "s0:c0,c1", + }, + }, }, } } @@ -473,7 +502,11 @@ func testReadFile(f *framework.Framework, file string, pod *v1.Pod, containerInd Expect(err).NotTo(HaveOccurred(), "while deleting pod") } -func testPodFailSupath(f *framework.Framework, pod *v1.Pod) { +func testPodFailSubpath(f *framework.Framework, pod *v1.Pod) { + testPodFailSubpathError(f, pod, "subPath") +} + +func testPodFailSubpathError(f *framework.Framework, pod *v1.Pod, errorMsg string) { 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") @@ -494,7 +527,7 @@ func testPodFailSupath(f *framework.Framework, pod *v1.Pod) { events, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).List(options) Expect(err).NotTo(HaveOccurred(), "while getting pod events") Expect(len(events.Items)).NotTo(Equal(0), "no events found") - Expect(events.Items[0].Message).To(ContainSubstring("subPath"), "subpath error not found") + Expect(events.Items[0].Message).To(ContainSubstring(errorMsg), fmt.Sprintf("%q error not found", errorMsg)) } // Tests that the existing subpath mount is detected when a container restarts @@ -785,6 +818,47 @@ func (s *gcepdPVCSource) createVolume(f *framework.Framework) volInfo { s.pvc, err = framework.CreatePVC(f.ClientSet, f.Namespace.Name, pvc) framework.ExpectNoError(err, "Error creating PVC") + // Launch pod to format the PD first + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("gcepd-prep-%s", f.Namespace.Name), + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: fmt.Sprintf("init-volume-%s", f.Namespace.Name), + Image: "busybox", + Command: []string{"/bin/sh", "-ec", "echo nothing"}, + VolumeMounts: []v1.VolumeMount{ + { + Name: volumeName, + MountPath: "/vol", + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + Volumes: []v1.Volume{ + { + Name: volumeName, + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: s.pvc.Name, + }, + }, + }, + }, + }, + } + pod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod) + Expect(err).ToNot(HaveOccurred(), "while creating gce pd init pod") + + err = framework.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, pod.Namespace) + Expect(err).ToNot(HaveOccurred(), "while waiting for gce pd init pod to succeed") + + err = framework.DeletePodWithWait(f, f.ClientSet, pod) + Expect(err).ToNot(HaveOccurred(), "while deleting gce pd init pod") + return volInfo{ source: &v1.VolumeSource{ PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ diff --git a/test/e2e/storage/volume_io.go b/test/e2e/storage/volume_io.go index 04c803b78cd..9ed5e245fff 100644 --- a/test/e2e/storage/volume_io.go +++ b/test/e2e/storage/volume_io.go @@ -385,33 +385,11 @@ var _ = utils.SIGDescribe("Volume plugin streaming [Slow]", func() { Describe("Ceph-RBD [Feature:Volumes]", func() { var ( secret *v1.Secret - name string ) testFile := "ceph-rbd_io_test" BeforeEach(func() { - config, serverPod, serverIP = framework.NewRBDServer(cs, ns) - name = config.Prefix + "-server" - - // create server secret - secret = &v1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Data: map[string][]byte{ - // from test/images/volumes-tester/rbd/keyring - "key": []byte("AQDRrKNVbEevChAAEmRC+pW/KBVHxa0w/POILA=="), - }, - Type: "kubernetes.io/rbd", - } - var err error - secret, err = cs.CoreV1().Secrets(ns).Create(secret) - Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("BeforeEach: failed to create secret %q for Ceph-RBD: %v", name, err)) - + config, serverPod, secret, serverIP = framework.NewRBDServer(cs, ns) volSource = v1.VolumeSource{ RBD: &v1.RBDVolumeSource{ CephMonitors: []string{serverIP}, @@ -419,7 +397,7 @@ var _ = utils.SIGDescribe("Volume plugin streaming [Slow]", func() { RBDImage: "foo", RadosUser: "admin", SecretRef: &v1.LocalObjectReference{ - Name: name, + Name: secret.Name, }, FSType: "ext2", ReadOnly: false, @@ -428,13 +406,13 @@ var _ = utils.SIGDescribe("Volume plugin streaming [Slow]", func() { }) AfterEach(func() { - framework.Logf("AfterEach: deleting Ceph-RDB server secret %q...", name) - secErr := cs.CoreV1().Secrets(ns).Delete(name, &metav1.DeleteOptions{}) + framework.Logf("AfterEach: deleting Ceph-RDB server secret %q...", secret.Name) + secErr := cs.CoreV1().Secrets(ns).Delete(secret.Name, &metav1.DeleteOptions{}) framework.Logf("AfterEach: deleting Ceph-RDB server pod %q...", serverPod.Name) err := framework.DeletePodWithWait(f, cs, serverPod) if secErr != nil || err != nil { if secErr != nil { - framework.Logf("AfterEach: Ceph-RDB delete secret failed: %v", err) + framework.Logf("AfterEach: Ceph-RDB delete secret failed: %v", secErr) } if err != nil { framework.Logf("AfterEach: Ceph-RDB server pod delete failed: %v", err) diff --git a/test/e2e/storage/volume_provisioning.go b/test/e2e/storage/volume_provisioning.go index 8dd4a4cffcd..7b936ee3606 100644 --- a/test/e2e/storage/volume_provisioning.go +++ b/test/e2e/storage/volume_provisioning.go @@ -57,6 +57,7 @@ type storageClassTest struct { pvCheck func(volume *v1.PersistentVolume) error nodeName string attach bool + volumeMode *v1.PersistentVolumeMode } const ( @@ -120,6 +121,10 @@ func testDynamicProvisioning(t storageClassTest, client clientset.Interface, cla Expect(pv.Spec.PersistentVolumeReclaimPolicy).To(Equal(*class.ReclaimPolicy)) Expect(pv.Spec.MountOptions).To(Equal(class.MountOptions)) } + if t.volumeMode != nil { + Expect(pv.Spec.VolumeMode).NotTo(BeNil()) + Expect(*pv.Spec.VolumeMode).To(Equal(*t.volumeMode)) + } // Run the checker if t.pvCheck != nil { @@ -818,6 +823,34 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { testDynamicProvisioning(test, c, claim, class) }) }) + + Describe("Block volume provisioning [Feature:BlockVolume]", func() { + It("should create and delete block persistent volumes", func() { + + // TODO: add openstack once Cinder volume plugin supports block volumes + framework.SkipUnlessProviderIs("gce", "aws", "gke", "vsphere", "azure") + + By("creating a claim with default class") + block := v1.PersistentVolumeBlock + test := storageClassTest{ + name: "default", + claimSize: "2Gi", + expectedSize: "2Gi", + volumeMode: &block, + } + // gce or gke + if getDefaultPluginName() == "kubernetes.io/gce-pd" { + // using GB not GiB as e2e test unit since gce-pd returns GB, + // or expectedSize may be greater than claimSize. + test.claimSize = "2G" + test.expectedSize = "2G" + } + + claim := newClaim(test, ns, "default") + claim.Spec.VolumeMode = &block + testDynamicProvisioning(test, c, claim, nil) + }) + }) }) func getDefaultStorageClassName(c clientset.Interface) string { diff --git a/test/e2e/storage/volumes.go b/test/e2e/storage/volumes.go index 3be74537258..0a4a2e944a8 100644 --- a/test/e2e/storage/volumes.go +++ b/test/e2e/storage/volumes.go @@ -57,7 +57,6 @@ import ( "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/utils" vspheretest "k8s.io/kubernetes/test/e2e/storage/vsphere" - imageutils "k8s.io/kubernetes/test/utils/image" ) func DeleteCinderVolume(name string) error { @@ -200,34 +199,9 @@ var _ = utils.SIGDescribe("Volumes", func() { Describe("Ceph RBD [Feature:Volumes]", func() { It("should be mountable", func() { - config, _, serverIP := framework.NewRBDServer(cs, namespace.Name) + config, _, secret, serverIP := framework.NewRBDServer(cs, namespace.Name) defer framework.VolumeTestCleanup(f, config) - - // create secrets for the server - secret := v1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: config.Prefix + "-secret", - }, - Data: map[string][]byte{ - // from test/images/volumes-tester/rbd/keyring - "key": []byte("AQDRrKNVbEevChAAEmRC+pW/KBVHxa0w/POILA=="), - }, - Type: "kubernetes.io/rbd", - } - - secClient := cs.CoreV1().Secrets(config.Namespace) - - defer func() { - secClient.Delete(config.Prefix+"-secret", nil) - }() - - if _, err := secClient.Create(&secret); err != nil { - framework.Failf("Failed to create secrets for Ceph RBD: %v", err) - } + defer cs.CoreV1().Secrets(config.Namespace).Delete(secret.Name, nil) tests := []framework.VolumeTest{ { @@ -238,7 +212,7 @@ var _ = utils.SIGDescribe("Volumes", func() { RBDImage: "foo", RadosUser: "admin", SecretRef: &v1.LocalObjectReference{ - Name: config.Prefix + "-secret", + Name: secret.Name, }, FSType: "ext2", }, @@ -258,44 +232,9 @@ var _ = utils.SIGDescribe("Volumes", func() { //////////////////////////////////////////////////////////////////////// Describe("CephFS [Feature:Volumes]", func() { It("should be mountable", func() { - config := framework.VolumeTestConfig{ - Namespace: namespace.Name, - Prefix: "cephfs", - ServerImage: imageutils.GetE2EImage(imageutils.VolumeRBDServer), - ServerPorts: []int{6789}, - } - + config, _, secret, serverIP := framework.NewRBDServer(cs, namespace.Name) defer framework.VolumeTestCleanup(f, config) - _, serverIP := framework.CreateStorageServer(cs, config) - By("sleeping a bit to give ceph server time to initialize") - time.Sleep(framework.VolumeServerPodStartupSleep) - - // create ceph secret - secret := &v1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: config.Prefix + "-secret", - }, - // from test/images/volumes-tester/rbd/keyring - Data: map[string][]byte{ - "key": []byte("AQDRrKNVbEevChAAEmRC+pW/KBVHxa0w/POILA=="), - }, - Type: "kubernetes.io/cephfs", - } - - defer func() { - if err := cs.CoreV1().Secrets(namespace.Name).Delete(secret.Name, nil); err != nil { - framework.Failf("unable to delete secret %v: %v", secret.Name, err) - } - }() - - var err error - if secret, err = cs.CoreV1().Secrets(namespace.Name).Create(secret); err != nil { - framework.Failf("unable to create test secret %s: %v", secret.Name, err) - } + defer cs.CoreV1().Secrets(config.Namespace).Delete(secret.Name, nil) tests := []framework.VolumeTest{ { @@ -303,7 +242,7 @@ var _ = utils.SIGDescribe("Volumes", func() { CephFS: &v1.CephFSVolumeSource{ Monitors: []string{serverIP + ":6789"}, User: "kube", - SecretRef: &v1.LocalObjectReference{Name: config.Prefix + "-secret"}, + SecretRef: &v1.LocalObjectReference{Name: secret.Name}, ReadOnly: true, }, }, diff --git a/test/e2e/upgrades/BUILD b/test/e2e/upgrades/BUILD index a3db3528724..d8355c417f8 100644 --- a/test/e2e/upgrades/BUILD +++ b/test/e2e/upgrades/BUILD @@ -16,6 +16,7 @@ go_library( "ingress.go", "kube_proxy_migration.go", "mysql.go", + "nvidia-gpu.go", "secrets.go", "services.go", "sysctl.go", @@ -23,11 +24,11 @@ go_library( ], importpath = "k8s.io/kubernetes/test/e2e/upgrades", deps = [ - "//pkg/apis/core/v1/helper:go_default_library", "//pkg/kubelet/sysctl:go_default_library", "//pkg/util/version:go_default_library", "//test/e2e/common:go_default_library", "//test/e2e/framework:go_default_library", + "//test/e2e/scheduling:go_default_library", "//test/utils/image:go_default_library", "//vendor/github.com/davecgh/go-spew/spew:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", @@ -38,6 +39,7 @@ go_library( "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", diff --git a/test/e2e/upgrades/nvidia-gpu.go b/test/e2e/upgrades/nvidia-gpu.go new file mode 100644 index 00000000000..12abd0e34ac --- /dev/null +++ b/test/e2e/upgrades/nvidia-gpu.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 upgrades + +import ( + "regexp" + "time" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/kubernetes/test/e2e/framework" + "k8s.io/kubernetes/test/e2e/scheduling" + imageutils "k8s.io/kubernetes/test/utils/image" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +// NvidiaGPUUpgradeTest tests that gpu resource is available before and after +// a cluster upgrade. +type NvidiaGPUUpgradeTest struct { +} + +func (NvidiaGPUUpgradeTest) Name() string { return "nvidia-gpu-upgrade [sig-node] [sig-scheduling]" } + +// Setup creates a job requesting gpu. +func (t *NvidiaGPUUpgradeTest) Setup(f *framework.Framework) { + scheduling.SetupNVIDIAGPUNode(f, false) + By("Creating a job requesting gpu") + t.startJob(f) +} + +// Test waits for the upgrade to complete, and then verifies that the +// cuda pod started by the gpu job can successfully finish. +func (t *NvidiaGPUUpgradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade UpgradeType) { + <-done + By("Verifying gpu job success") + t.verifyJobPodSuccess(f) + if upgrade == MasterUpgrade { + // MasterUpgrade should be totally hitless. + job, err := framework.GetJob(f.ClientSet, f.Namespace.Name, "cuda-add") + Expect(err).NotTo(HaveOccurred()) + Expect(job.Status.Failed).To(BeZero(), "Job pods failed during master upgrade: %v", job.Status.Failed) + } +} + +// Teardown cleans up any remaining resources. +func (t *NvidiaGPUUpgradeTest) Teardown(f *framework.Framework) { + // rely on the namespace deletion to clean up everything +} + +// startJob creates a job that requests gpu and runs a simple cuda container. +func (t *NvidiaGPUUpgradeTest) startJob(f *framework.Framework) { + var activeSeconds int64 = 3600 + // Specifies 100 completions to make sure the job life spans across the upgrade. + testJob := framework.NewTestJob("succeed", "cuda-add", v1.RestartPolicyAlways, 1, 100, &activeSeconds, 6) + testJob.Spec.Template.Spec = v1.PodSpec{ + RestartPolicy: v1.RestartPolicyOnFailure, + Containers: []v1.Container{ + { + Name: "vector-addition", + Image: imageutils.GetE2EImage(imageutils.CudaVectorAdd), + Command: []string{"/bin/sh", "-c", "./vectorAdd && sleep 60"}, + Resources: v1.ResourceRequirements{ + Limits: v1.ResourceList{ + framework.NVIDIAGPUResourceName: *resource.NewQuantity(1, resource.DecimalSI), + }, + }, + }, + }, + } + ns := f.Namespace.Name + _, err := framework.CreateJob(f.ClientSet, ns, testJob) + Expect(err).NotTo(HaveOccurred()) + framework.Logf("Created job %v", testJob) + By("Waiting for gpu job pod start") + err = framework.WaitForAllJobPodsRunning(f.ClientSet, ns, testJob.Name, 1) + Expect(err).NotTo(HaveOccurred()) + By("Done with gpu job pod start") +} + +// verifyJobPodSuccess verifies that the started cuda pod successfully passes. +func (t *NvidiaGPUUpgradeTest) verifyJobPodSuccess(f *framework.Framework) { + // Wait for client pod to complete. + ns := f.Namespace.Name + err := framework.WaitForAllJobPodsRunning(f.ClientSet, f.Namespace.Name, "cuda-add", 1) + Expect(err).NotTo(HaveOccurred()) + pods, err := framework.GetJobPods(f.ClientSet, f.Namespace.Name, "cuda-add") + Expect(err).NotTo(HaveOccurred()) + createdPod := pods.Items[0].Name + framework.Logf("Created pod %v", createdPod) + f.PodClient().WaitForSuccess(createdPod, 5*time.Minute) + logs, err := framework.GetPodLogs(f.ClientSet, ns, createdPod, "vector-addition") + framework.ExpectNoError(err, "Should be able to get pod logs") + framework.Logf("Got pod logs: %v", logs) + regex := regexp.MustCompile("PASSED") + Expect(regex.MatchString(logs)).To(BeTrue()) +} diff --git a/test/e2e/upgrades/sysctl.go b/test/e2e/upgrades/sysctl.go index 1b9a0a71a7f..8ba3fdaefff 100644 --- a/test/e2e/upgrades/sysctl.go +++ b/test/e2e/upgrades/sysctl.go @@ -26,7 +26,6 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/kubelet/sysctl" "k8s.io/kubernetes/test/e2e/framework" @@ -123,9 +122,6 @@ func sysctlTestPod(name string, sysctls map[string]string) *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: name, - Annotations: map[string]string{ - v1.SysctlsPodAnnotationKey: v1helper.PodAnnotationsFromSysctls(sysctlList), - }, }, Spec: v1.PodSpec{ Containers: []v1.Container{ @@ -136,6 +132,9 @@ func sysctlTestPod(name string, sysctls map[string]string) *v1.Pod { }, }, RestartPolicy: v1.RestartPolicyNever, + SecurityContext: &v1.PodSecurityContext{ + Sysctls: sysctlList, + }, }, } } diff --git a/test/e2e_node/BUILD b/test/e2e_node/BUILD index 2520218911e..9d39a0de9f5 100644 --- a/test/e2e_node/BUILD +++ b/test/e2e_node/BUILD @@ -154,6 +154,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", diff --git a/test/e2e_node/dynamic_kubelet_config_test.go b/test/e2e_node/dynamic_kubelet_config_test.go index 3d710ad1a9d..b30fbccb1b5 100644 --- a/test/e2e_node/dynamic_kubelet_config_test.go +++ b/test/e2e_node/dynamic_kubelet_config_test.go @@ -69,7 +69,7 @@ type nodeConfigTestCase struct { } // This test is marked [Disruptive] because the Kubelet restarts several times during this test. -var _ = framework.KubeDescribe("[Feature:DynamicKubeletConfig][NodeAlphaFeature:DynamicKubeletConfig][Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("[Feature:DynamicKubeletConfig][NodeFeature:DynamicKubeletConfig][Serial][Disruptive]", func() { f := framework.NewDefaultFramework("dynamic-kubelet-configuration-test") var beforeNode *apiv1.Node var beforeConfigMap *apiv1.ConfigMap diff --git a/test/e2e_node/eviction_test.go b/test/e2e_node/eviction_test.go index dcd29e43982..5160578be08 100644 --- a/test/e2e_node/eviction_test.go +++ b/test/e2e_node/eviction_test.go @@ -20,11 +20,13 @@ import ( "fmt" "path/filepath" "strconv" + "strings" "time" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" nodeutil "k8s.io/kubernetes/pkg/api/v1/node" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" @@ -50,18 +52,21 @@ const ( // pressure conditions often surface after evictions because the kubelet only updates // node conditions periodically. // we wait this period after evictions to make sure that we wait out this delay - pressureDelay = 20 * time.Second - testContextFmt = "when we run containers that should cause %s" - noPressure = v1.NodeConditionType("NoPressure") - lotsOfDisk = 10240 // 10 Gb in Mb - lotsOfFiles = 1000000000 // 1 billion + pressureDelay = 20 * time.Second + testContextFmt = "when we run containers that should cause %s" + noPressure = v1.NodeConditionType("NoPressure") + lotsOfDisk = 10240 // 10 Gb in Mb + lotsOfFiles = 1000000000 // 1 billion + resourceInodes = v1.ResourceName("inodes") + noStarvedResource = v1.ResourceName("none") ) // InodeEviction tests that the node responds to node disk pressure by evicting only responsible pods. // Node disk pressure is induced by consuming all inodes on the node. -var _ = framework.KubeDescribe("InodeEviction [Slow] [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("InodeEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("inode-eviction-test") expectedNodeCondition := v1.NodeDiskPressure + expectedStarvedResource := resourceInodes pressureTimeout := 15 * time.Minute inodesConsumed := uint64(200000) Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { @@ -75,7 +80,7 @@ var _ = framework.KubeDescribe("InodeEviction [Slow] [Serial] [Disruptive]", fun initialConfig.EvictionHard = map[string]string{"nodefs.inodesFree": fmt.Sprintf("%d", inodesFree-inodesConsumed)} initialConfig.EvictionMinimumReclaim = map[string]string{} }) - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logInodeMetrics, []podEvictSpec{ + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logInodeMetrics, []podEvictSpec{ { evictionPriority: 1, pod: inodeConsumingPod("container-inode-hog", lotsOfFiles, nil), @@ -98,6 +103,7 @@ var _ = framework.KubeDescribe("ImageGCNoEviction [Slow] [Serial] [Disruptive][N f := framework.NewDefaultFramework("image-gc-eviction-test") pressureTimeout := 10 * time.Minute expectedNodeCondition := v1.NodeDiskPressure + expectedStarvedResource := resourceInodes inodesConsumed := uint64(100000) Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { @@ -112,7 +118,7 @@ var _ = framework.KubeDescribe("ImageGCNoEviction [Slow] [Serial] [Disruptive][N }) // Consume enough inodes to induce disk pressure, // but expect that image garbage collection can reduce it enough to avoid an eviction - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logDiskMetrics, []podEvictSpec{ + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logDiskMetrics, []podEvictSpec{ { evictionPriority: 0, pod: inodeConsumingPod("container-inode", 110000, nil), @@ -123,9 +129,10 @@ var _ = framework.KubeDescribe("ImageGCNoEviction [Slow] [Serial] [Disruptive][N // MemoryAllocatableEviction tests that the node responds to node memory pressure by evicting only responsible pods. // Node memory pressure is only encountered because we reserve the majority of the node's capacity via kube-reserved. -var _ = framework.KubeDescribe("MemoryAllocatableEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction", func() { +var _ = framework.KubeDescribe("MemoryAllocatableEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("memory-allocatable-eviction-test") expectedNodeCondition := v1.NodeMemoryPressure + expectedStarvedResource := v1.ResourceMemory pressureTimeout := 10 * time.Minute Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { @@ -140,7 +147,7 @@ var _ = framework.KubeDescribe("MemoryAllocatableEviction [Slow] [Serial] [Disru initialConfig.EnforceNodeAllocatable = []string{kubetypes.NodeAllocatableEnforcementKey} initialConfig.CgroupsPerQOS = true }) - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logMemoryMetrics, []podEvictSpec{ + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logMemoryMetrics, []podEvictSpec{ { evictionPriority: 1, pod: getMemhogPod("memory-hog-pod", "memory-hog", v1.ResourceRequirements{}), @@ -155,10 +162,11 @@ var _ = framework.KubeDescribe("MemoryAllocatableEviction [Slow] [Serial] [Disru // LocalStorageEviction tests that the node responds to node disk pressure by evicting only responsible pods // Disk pressure is induced by running pods which consume disk space. -var _ = framework.KubeDescribe("LocalStorageEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction", func() { +var _ = framework.KubeDescribe("LocalStorageEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("localstorage-eviction-test") pressureTimeout := 10 * time.Minute expectedNodeCondition := v1.NodeDiskPressure + expectedStarvedResource := v1.ResourceEphemeralStorage Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { diskConsumed := resource.MustParse("100Mi") @@ -167,7 +175,7 @@ var _ = framework.KubeDescribe("LocalStorageEviction [Slow] [Serial] [Disruptive initialConfig.EvictionHard = map[string]string{"nodefs.available": fmt.Sprintf("%d", availableBytes-uint64(diskConsumed.Value()))} initialConfig.EvictionMinimumReclaim = map[string]string{} }) - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logDiskMetrics, []podEvictSpec{ + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logDiskMetrics, []podEvictSpec{ { evictionPriority: 1, pod: diskConsumingPod("container-disk-hog", lotsOfDisk, nil, v1.ResourceRequirements{}), @@ -183,10 +191,11 @@ var _ = framework.KubeDescribe("LocalStorageEviction [Slow] [Serial] [Disruptive // LocalStorageEviction tests that the node responds to node disk pressure by evicting only responsible pods // Disk pressure is induced by running pods which consume disk space, which exceed the soft eviction threshold. // Note: This test's purpose is to test Soft Evictions. Local storage was chosen since it is the least costly to run. -var _ = framework.KubeDescribe("LocalStorageSoftEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction", func() { +var _ = framework.KubeDescribe("LocalStorageSoftEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("localstorage-eviction-test") pressureTimeout := 10 * time.Minute expectedNodeCondition := v1.NodeDiskPressure + expectedStarvedResource := v1.ResourceEphemeralStorage Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { diskConsumed := resource.MustParse("100Mi") @@ -204,7 +213,7 @@ var _ = framework.KubeDescribe("LocalStorageSoftEviction [Slow] [Serial] [Disrup // setting a threshold to 0% disables; non-empty map overrides default value (necessary due to omitempty) initialConfig.EvictionHard = map[string]string{"memory.available": "0%"} }) - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logDiskMetrics, []podEvictSpec{ + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logDiskMetrics, []podEvictSpec{ { evictionPriority: 1, pod: diskConsumingPod("container-disk-hog", lotsOfDisk, nil, v1.ResourceRequirements{}), @@ -232,7 +241,7 @@ var _ = framework.KubeDescribe("LocalStorageCapacityIsolationEviction [Slow] [Se useUnderLimit := 99 /* Mb */ containerLimit := v1.ResourceList{v1.ResourceEphemeralStorage: sizeLimit} - runEvictionTest(f, evictionTestTimeout, noPressure, logDiskMetrics, []podEvictSpec{ + runEvictionTest(f, evictionTestTimeout, noPressure, noStarvedResource, logDiskMetrics, []podEvictSpec{ { evictionPriority: 1, // This pod should be evicted because emptyDir (default storage type) usage violation pod: diskConsumingPod("emptydir-disk-sizelimit", useOverLimit, &v1.VolumeSource{ @@ -271,9 +280,10 @@ var _ = framework.KubeDescribe("LocalStorageCapacityIsolationEviction [Slow] [Se // PriorityMemoryEvictionOrdering tests that the node responds to node memory pressure by evicting pods. // This test tests that the guaranteed pod is never evicted, and that the lower-priority pod is evicted before // the higher priority pod. -var _ = framework.KubeDescribe("PriorityMemoryEvictionOrdering [Slow] [Serial] [Disruptive][NodeFeature:Eviction", func() { +var _ = framework.KubeDescribe("PriorityMemoryEvictionOrdering [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("priority-memory-eviction-ordering-test") expectedNodeCondition := v1.NodeMemoryPressure + expectedStarvedResource := v1.ResourceMemory pressureTimeout := 10 * time.Minute Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { @@ -310,16 +320,17 @@ var _ = framework.KubeDescribe("PriorityMemoryEvictionOrdering [Slow] [Serial] [ } systemPriority := int32(2147483647) specs[1].pod.Spec.Priority = &systemPriority - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logMemoryMetrics, specs) + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logMemoryMetrics, specs) }) }) // PriorityLocalStorageEvictionOrdering tests that the node responds to node disk pressure by evicting pods. // This test tests that the guaranteed pod is never evicted, and that the lower-priority pod is evicted before // the higher priority pod. -var _ = framework.KubeDescribe("PriorityLocalStorageEvictionOrdering [Slow] [Serial] [Disruptive][NodeFeature:Eviction", func() { +var _ = framework.KubeDescribe("PriorityLocalStorageEvictionOrdering [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("priority-disk-eviction-ordering-test") expectedNodeCondition := v1.NodeDiskPressure + expectedStarvedResource := v1.ResourceEphemeralStorage pressureTimeout := 10 * time.Minute Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { @@ -358,7 +369,7 @@ var _ = framework.KubeDescribe("PriorityLocalStorageEvictionOrdering [Slow] [Ser } systemPriority := int32(2147483647) specs[1].pod.Spec.Priority = &systemPriority - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logDiskMetrics, specs) + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logDiskMetrics, specs) }) }) @@ -377,7 +388,7 @@ type podEvictSpec struct { // It ensures that lower evictionPriority pods are always evicted before higher evictionPriority pods (2 evicted before 1, etc.) // It ensures that all pods with non-zero evictionPriority are eventually evicted. // runEvictionTest then cleans up the testing environment by deleting provided pods, and ensures that expectedNodeCondition no longer exists -func runEvictionTest(f *framework.Framework, pressureTimeout time.Duration, expectedNodeCondition v1.NodeConditionType, logFunc func(), testSpecs []podEvictSpec) { +func runEvictionTest(f *framework.Framework, pressureTimeout time.Duration, expectedNodeCondition v1.NodeConditionType, expectedStarvedResource v1.ResourceName, logFunc func(), testSpecs []podEvictSpec) { // Place the remainder of the test within a context so that the kubelet config is set before and after the test. Context("", func() { BeforeEach(func() { @@ -442,6 +453,9 @@ func runEvictionTest(f *framework.Framework, pressureTimeout time.Duration, expe logKubeletLatencyMetrics(kubeletmetrics.EvictionStatsAgeKey) return verifyEvictionOrdering(f, testSpecs) }, postTestConditionMonitoringPeriod, evictionPollInterval).Should(BeNil()) + + By("checking for correctly formatted eviction events") + verifyEvictionEvents(f, testSpecs, expectedStarvedResource) }) AfterEach(func() { @@ -549,6 +563,60 @@ func verifyEvictionOrdering(f *framework.Framework, testSpecs []podEvictSpec) er return fmt.Errorf("pods that should be evicted are still running") } +func verifyEvictionEvents(f *framework.Framework, testSpecs []podEvictSpec, expectedStarvedResource v1.ResourceName) { + for _, spec := range testSpecs { + pod := spec.pod + if spec.evictionPriority != 0 { + selector := fields.Set{ + "involvedObject.kind": "Pod", + "involvedObject.name": pod.Name, + "involvedObject.namespace": f.Namespace.Name, + "reason": eviction.Reason, + }.AsSelector().String() + podEvictEvents, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).List(metav1.ListOptions{FieldSelector: selector}) + Expect(err).To(BeNil(), "Unexpected error getting events during eviction test: %v", err) + Expect(len(podEvictEvents.Items)).To(Equal(1), "Expected to find 1 eviction event for pod %s, got %d", pod.Name, len(podEvictEvents.Items)) + event := podEvictEvents.Items[0] + + if expectedStarvedResource != noStarvedResource { + // Check the eviction.StarvedResourceKey + starved, found := event.Annotations[eviction.StarvedResourceKey] + Expect(found).To(BeTrue(), "Expected to find an annotation on the eviction event for pod %s containing the starved resource %s, but it was not found", + pod.Name, expectedStarvedResource) + starvedResource := v1.ResourceName(starved) + Expect(starvedResource).To(Equal(expectedStarvedResource), "Expected to the starved_resource annotation on pod %s to contain %s, but got %s instead", + pod.Name, expectedStarvedResource, starvedResource) + + // We only check these keys for memory, because ephemeral storage evictions may be due to volume usage, in which case these values are not present + if expectedStarvedResource == v1.ResourceMemory { + // Check the eviction.OffendingContainersKey + offendersString, found := event.Annotations[eviction.OffendingContainersKey] + Expect(found).To(BeTrue(), "Expected to find an annotation on the eviction event for pod %s containing the offending containers, but it was not found", + pod.Name) + offendingContainers := strings.Split(offendersString, ",") + Expect(len(offendingContainers)).To(Equal(1), "Expected to find the offending container's usage in the %s annotation, but no container was found", + eviction.OffendingContainersKey) + Expect(offendingContainers[0]).To(Equal(pod.Spec.Containers[0].Name), "Expected to find the offending container: %s's usage in the %s annotation, but found %s instead", + pod.Spec.Containers[0].Name, eviction.OffendingContainersKey, offendingContainers[0]) + + // Check the eviction.OffendingContainersUsageKey + offendingUsageString, found := event.Annotations[eviction.OffendingContainersUsageKey] + Expect(found).To(BeTrue(), "Expected to find an annotation on the eviction event for pod %s containing the offending containers' usage, but it was not found", + pod.Name) + offendingContainersUsage := strings.Split(offendingUsageString, ",") + Expect(len(offendingContainersUsage)).To(Equal(1), "Expected to find the offending container's usage in the %s annotation, but found %+v", + eviction.OffendingContainersUsageKey, offendingContainersUsage) + usageQuantity, err := resource.ParseQuantity(offendingContainersUsage[0]) + Expect(err).To(BeNil(), "Expected to be able to parse pod %s's %s annotation as a quantity, but got err: %v", pod.Name, eviction.OffendingContainersUsageKey, err) + request := pod.Spec.Containers[0].Resources.Requests[starvedResource] + Expect(usageQuantity.Cmp(request)).To(Equal(1), "Expected usage of offending container: %s in pod %s to exceed its request %s", + usageQuantity.String(), pod.Name, request.String()) + } + } + } + } +} + // Returns TRUE if the node has the node condition, FALSE otherwise func hasNodeCondition(f *framework.Framework, expectedNodeCondition v1.NodeConditionType) bool { localNodeStatus := getLocalNode(f).Status diff --git a/test/e2e_node/pods_container_manager_test.go b/test/e2e_node/pods_container_manager_test.go index 1768e7d9fa7..128860b17c0 100644 --- a/test/e2e_node/pods_container_manager_test.go +++ b/test/e2e_node/pods_container_manager_test.go @@ -152,7 +152,7 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { f := framework.NewDefaultFramework("kubelet-cgroup-manager") Describe("QOS containers", func() { Context("On enabling QOS cgroup hierarchy", func() { - It("Top level QoS containers should have been created", func() { + It("Top level QoS containers should have been created [NodeConformance]", func() { if !framework.TestContext.KubeletConfig.CgroupsPerQOS { return } diff --git a/test/e2e_node/services/kubelet.go b/test/e2e_node/services/kubelet.go index 18c62413b3e..e9a9a807918 100644 --- a/test/e2e_node/services/kubelet.go +++ b/test/e2e_node/services/kubelet.go @@ -219,7 +219,7 @@ func (e *E2EServices) startKubelet() (*server, error) { // if we will generate a kubelet config file, we need to mount that path into the container too if genKubeletConfigFile { - cmdArgs = append(cmdArgs, "-v", filepath.Dir(kubeletConfigPath)+":"+filepath.Dir(kubeletConfigPath)+":ro") + cmdArgs = append(cmdArgs, "-v", filepath.Dir(kubeletConfigPath)+":"+filepath.Dir(kubeletConfigPath)+":rw") } cmdArgs = append(cmdArgs, hyperkubeImage, "/hyperkube", "kubelet", "--containerized") diff --git a/test/e2e_node/util.go b/test/e2e_node/util.go index 918622ed4a0..a33ae7cc699 100644 --- a/test/e2e_node/util.go +++ b/test/e2e_node/util.go @@ -138,7 +138,7 @@ func isKubeletConfigEnabled(f *framework.Framework) (bool, error) { } v, ok := cfgz.FeatureGates[string(features.DynamicKubeletConfig)] if !ok { - return false, nil + return true, nil } return v, nil } diff --git a/test/images/Makefile b/test/images/Makefile index 6b7e7439b3a..81be891ce49 100644 --- a/test/images/Makefile +++ b/test/images/Makefile @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +include ../../hack/make-rules/Makefile.manifest + REGISTRY ?= gcr.io/kubernetes-e2e-test-images GOARM=7 QEMUVERSION=v2.9.1 diff --git a/test/images/image-util.sh b/test/images/image-util.sh index 0c092a4a99a..238bade4382 100755 --- a/test/images/image-util.sh +++ b/test/images/image-util.sh @@ -90,15 +90,23 @@ build() { # This function will push the docker images push() { + TAG=$(<${IMAGE}/VERSION) if [[ -f ${IMAGE}/BASEIMAGE ]]; then archs=$(listArchs) else archs=${!QEMUARCHS[@]} fi for arch in ${archs}; do - TAG=$(<${IMAGE}/VERSION) docker push ${REGISTRY}/${IMAGE}-${arch}:${TAG} done + + # Make archs list into image manifest. Eg: 'amd64 ppc64le' to '${REGISTRY}/${IMAGE}-amd64:${TAG} ${REGISTRY}/${IMAGE}-ppc64le:${TAG}' + manifest=$(echo $archs | sed -e "s~[^ ]*~$REGISTRY\/$IMAGE\-&:$TAG~g") + docker manifest create --amend ${REGISTRY}/${IMAGE}:${TAG} ${manifest} + for arch in ${archs}; do + docker manifest annotate --arch ${arch} ${REGISTRY}/${IMAGE}:${TAG} ${REGISTRY}/${IMAGE}-${arch}:${TAG} + done + docker manifest push ${REGISTRY}/${IMAGE}:${TAG} } # This function is for building the go code diff --git a/test/integration/apiserver/BUILD b/test/integration/apiserver/BUILD index aad43852e8d..91d9695c032 100644 --- a/test/integration/apiserver/BUILD +++ b/test/integration/apiserver/BUILD @@ -34,7 +34,7 @@ go_test( "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/test/integration/apiserver/print_test.go b/test/integration/apiserver/print_test.go index 8af6cd9b0e9..65e5dde0d4c 100644 --- a/test/integration/apiserver/print_test.go +++ b/test/integration/apiserver/print_test.go @@ -28,7 +28,7 @@ import ( batchv2alpha1 "k8s.io/api/batch/v2alpha1" rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" - schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" + schedulerapi "k8s.io/api/scheduling/v1beta1" settingsv1alpha1 "k8s.io/api/settings/v1alpha1" storagev1alpha1 "k8s.io/api/storage/v1alpha1" "k8s.io/apimachinery/pkg/api/meta" @@ -140,7 +140,7 @@ func TestServerSidePrint(t *testing.T) { batchv2alpha1.SchemeGroupVersion, rbacv1alpha1.SchemeGroupVersion, settingsv1alpha1.SchemeGroupVersion, - schedulingv1alpha1.SchemeGroupVersion, + schedulerapi.SchemeGroupVersion, storagev1alpha1.SchemeGroupVersion) defer closeFn() diff --git a/test/integration/auth/BUILD b/test/integration/auth/BUILD index 619c3df4a09..e5ed620905f 100644 --- a/test/integration/auth/BUILD +++ b/test/integration/auth/BUILD @@ -51,6 +51,7 @@ go_test( "//test/integration:go_default_library", "//test/integration/framework:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/gopkg.in/square/go-jose.v2/jwt:go_default_library", "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/authentication/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", diff --git a/test/integration/auth/svcaccttoken_test.go b/test/integration/auth/svcaccttoken_test.go index 65edcc44dc5..ac7ba22edae 100644 --- a/test/integration/auth/svcaccttoken_test.go +++ b/test/integration/auth/svcaccttoken_test.go @@ -24,17 +24,20 @@ import ( "testing" "time" + "gopkg.in/square/go-jose.v2/jwt" authenticationv1 "k8s.io/api/authentication/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/authentication/request/bearertoken" + apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount" "k8s.io/apiserver/pkg/authorization/authorizerfactory" utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" clientset "k8s.io/client-go/kubernetes" externalclientset "k8s.io/client-go/kubernetes" certutil "k8s.io/client-go/util/cert" + "k8s.io/kubernetes/pkg/apis/core" serviceaccountgetter "k8s.io/kubernetes/pkg/controller/serviceaccount" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/serviceaccount" @@ -118,7 +121,6 @@ func TestServiceAccountTokenCreate(t *testing.T) { }, } - one = int64(1) wrongUID = types.UID("wrong") noUID = types.UID("") ) @@ -126,8 +128,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("bound to service account", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, }, } @@ -157,8 +158,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("bound to service account and pod", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, BoundObjectRef: &authenticationv1.BoundObjectReference{ Kind: "Pod", APIVersion: "v1", @@ -211,8 +211,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("bound to service account and secret", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, BoundObjectRef: &authenticationv1.BoundObjectReference{ Kind: "Secret", APIVersion: "v1", @@ -266,8 +265,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("bound to service account and pod running as different service account", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, BoundObjectRef: &authenticationv1.BoundObjectReference{ Kind: "Pod", APIVersion: "v1", @@ -289,8 +287,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("expired token", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, }, } @@ -303,7 +300,26 @@ func TestServiceAccountTokenCreate(t *testing.T) { } doTokenReview(t, cs, treq, false) - time.Sleep(63 * time.Second) + + // backdate the token + then := time.Now().Add(-2 * time.Hour) + sc := &jwt.Claims{ + Subject: apiserverserviceaccount.MakeUsername(sa.Namespace, sa.Name), + Audience: jwt.Audience([]string{"api"}), + IssuedAt: jwt.NewNumericDate(then), + NotBefore: jwt.NewNumericDate(then), + Expiry: jwt.NewNumericDate(then.Add(time.Duration(60*60) * time.Second)), + } + coresa := core.ServiceAccount{ + ObjectMeta: sa.ObjectMeta, + } + _, pc := serviceaccount.Claims(coresa, nil, nil, 0, nil) + tok, err := masterConfig.ExtraConfig.ServiceAccountIssuer.GenerateToken(sc, pc) + if err != nil { + t.Fatalf("err signing expired token: %v", err) + } + + treq.Status.Token = tok doTokenReview(t, cs, treq, true) }) @@ -346,8 +362,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("a token should be invalid after recreating same name pod", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, BoundObjectRef: &authenticationv1.BoundObjectReference{ Kind: "Pod", APIVersion: "v1", @@ -386,8 +401,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("a token should be invalid after recreating same name secret", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, BoundObjectRef: &authenticationv1.BoundObjectReference{ Kind: "Secret", APIVersion: "v1", diff --git a/test/integration/daemonset/BUILD b/test/integration/daemonset/BUILD index 138dddfb5bf..a1c60537057 100644 --- a/test/integration/daemonset/BUILD +++ b/test/integration/daemonset/BUILD @@ -14,23 +14,32 @@ go_test( ], tags = ["integration"], deps = [ + "//pkg/api/legacyscheme:go_default_library", "//pkg/api/v1/pod:go_default_library", "//pkg/controller/daemon:go_default_library", + "//pkg/features:go_default_library", + "//pkg/scheduler:go_default_library", + "//pkg/scheduler/algorithm:go_default_library", + "//pkg/scheduler/algorithmprovider:go_default_library", + "//pkg/scheduler/factory:go_default_library", "//pkg/util/metrics:go_default_library", "//test/integration/framework:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) diff --git a/test/integration/daemonset/daemonset_test.go b/test/integration/daemonset/daemonset_test.go index 5c8cf8ee276..0a7a72ca16e 100644 --- a/test/integration/daemonset/daemonset_test.go +++ b/test/integration/daemonset/daemonset_test.go @@ -24,19 +24,30 @@ import ( apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" appstyped "k8s.io/client-go/kubernetes/typed/apps/v1" + clientv1core "k8s.io/client-go/kubernetes/typed/core/v1" corev1typed "k8s.io/client-go/kubernetes/typed/core/v1" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/kubernetes/pkg/api/legacyscheme" podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/controller/daemon" + "k8s.io/kubernetes/pkg/features" + "k8s.io/kubernetes/pkg/scheduler" + "k8s.io/kubernetes/pkg/scheduler/algorithm" + "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" + _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" + "k8s.io/kubernetes/pkg/scheduler/factory" "k8s.io/kubernetes/pkg/util/metrics" "k8s.io/kubernetes/test/integration/framework" ) @@ -69,6 +80,62 @@ func setup(t *testing.T) (*httptest.Server, framework.CloseFunc, *daemon.DaemonS return server, closeFn, dc, informers, clientSet } +func setupScheduler( + t *testing.T, + cs clientset.Interface, + informerFactory informers.SharedInformerFactory, + stopCh chan struct{}, +) { + // If ScheduleDaemonSetPods is disabled, do not start scheduler. + if !utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { + return + } + + schedulerConfigFactory := factory.NewConfigFactory( + v1.DefaultSchedulerName, + cs, + informerFactory.Core().V1().Nodes(), + informerFactory.Core().V1().Pods(), + informerFactory.Core().V1().PersistentVolumes(), + informerFactory.Core().V1().PersistentVolumeClaims(), + informerFactory.Core().V1().ReplicationControllers(), + informerFactory.Extensions().V1beta1().ReplicaSets(), + informerFactory.Apps().V1beta1().StatefulSets(), + informerFactory.Core().V1().Services(), + informerFactory.Policy().V1beta1().PodDisruptionBudgets(), + informerFactory.Storage().V1().StorageClasses(), + v1.DefaultHardPodAffinitySymmetricWeight, + true, + false, + ) + + schedulerConfig, err := schedulerConfigFactory.Create() + if err != nil { + t.Fatalf("Couldn't create scheduler config: %v", err) + } + + schedulerConfig.StopEverything = stopCh + + eventBroadcaster := record.NewBroadcaster() + schedulerConfig.Recorder = eventBroadcaster.NewRecorder( + legacyscheme.Scheme, + v1.EventSource{Component: v1.DefaultSchedulerName}, + ) + eventBroadcaster.StartRecordingToSink(&clientv1core.EventSinkImpl{ + Interface: cs.CoreV1().Events(""), + }) + + sched, err := scheduler.NewFromConfigurator( + &scheduler.FakeConfigurator{Config: schedulerConfig}, nil...) + if err != nil { + t.Fatalf("error creating scheduler: %v", err) + } + + algorithmprovider.ApplyFeatureGates() + + go sched.Run() +} + func testLabels() map[string]string { return map[string]string{"name": "test"} } @@ -162,6 +229,12 @@ func updateStrategies() []*apps.DaemonSetUpdateStrategy { return []*apps.DaemonSetUpdateStrategy{newOnDeleteStrategy(), newRollbackStrategy()} } +func featureGates() []utilfeature.Feature { + return []utilfeature.Feature{ + features.ScheduleDaemonSetPods, + } +} + func allocatableResources(memory, cpu string) v1.ResourceList { return v1.ResourceList{ v1.ResourceMemory: resource.MustParse(memory), @@ -242,7 +315,7 @@ func validateDaemonSetPodsAndMarkReady( t.Errorf("controllerRef.Controller is not set to true") } - if !podutil.IsPodReady(pod) { + if !podutil.IsPodReady(pod) && len(pod.Spec.NodeName) != 0 { podCopy := pod.DeepCopy() podCopy.Status = v1.PodStatus{ Phase: v1.PodRunning, @@ -261,6 +334,44 @@ func validateDaemonSetPodsAndMarkReady( } } +// 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 { + 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 + } +} + +// waitForPodUnscheduleWithTimeout waits for a pod to fail scheduling and returns +// an error if it does not become unschedulable within the given timeout. +func waitForPodUnschedulableWithTimeout(cs clientset.Interface, pod *v1.Pod, timeout time.Duration) error { + return wait.Poll(100*time.Millisecond, timeout, podUnschedulable(cs, pod.Namespace, pod.Name)) +} + +// waitForPodUnschedule waits for a pod to fail scheduling and returns +// an error if it does not become unschedulable within the timeout duration (30 seconds). +func waitForPodUnschedulable(cs clientset.Interface, pod *v1.Pod) error { + return waitForPodUnschedulableWithTimeout(cs, pod, 10*time.Second) +} + +// waitForPodsCreated waits for number of pods are created. +func waitForPodsCreated(podInformer cache.SharedIndexInformer, num int) error { + return wait.Poll(100*time.Millisecond, 10*time.Second, func() (bool, error) { + objects := podInformer.GetIndexer().List() + return len(objects) == num, nil + }) +} + func validateDaemonSetStatus( dsClient appstyped.DaemonSetInterface, dsName string, @@ -302,6 +413,22 @@ func validateFailedPlacementEvent(eventClient corev1typed.EventInterface, t *tes } } +func forEachFeatureGate(t *testing.T, tf func(t *testing.T)) { + for _, fg := range featureGates() { + func() { + enabled := utilfeature.DefaultFeatureGate.Enabled(fg) + defer func() { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%v=%t", fg, enabled)) + }() + + for _, f := range []bool{true, false} { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%v=%t", fg, f)) + t.Run(fmt.Sprintf("%v (%t)", fg, f), tf) + } + }() + } +} + func forEachStrategy(t *testing.T, tf func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy)) { for _, strategy := range updateStrategies() { t.Run(fmt.Sprintf("%s (%v)", t.Name(), strategy), @@ -310,69 +437,152 @@ func forEachStrategy(t *testing.T, tf func(t *testing.T, strategy *apps.DaemonSe } func TestOneNodeDaemonLaunchesPod(t *testing.T) { - forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { - server, closeFn, dc, informers, clientset := setup(t) - defer closeFn() - ns := framework.CreateTestingNamespace("one-node-daemonset-test", server, t) - defer framework.DeleteTestingNamespace(ns, server, t) + forEachFeatureGate(t, func(t *testing.T) { + forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { + server, closeFn, dc, informers, clientset := setup(t) + defer closeFn() + ns := framework.CreateTestingNamespace("one-node-daemonset-test", server, t) + defer framework.DeleteTestingNamespace(ns, server, t) - dsClient := clientset.AppsV1().DaemonSets(ns.Name) - podClient := clientset.CoreV1().Pods(ns.Name) - nodeClient := clientset.CoreV1().Nodes() - podInformer := informers.Core().V1().Pods().Informer() + dsClient := clientset.AppsV1().DaemonSets(ns.Name) + podClient := clientset.CoreV1().Pods(ns.Name) + nodeClient := clientset.CoreV1().Nodes() + podInformer := informers.Core().V1().Pods().Informer() - stopCh := make(chan struct{}) - informers.Start(stopCh) - go dc.Run(5, stopCh) - defer close(stopCh) + stopCh := make(chan struct{}) + defer close(stopCh) - ds := newDaemonSet("foo", ns.Name) - ds.Spec.UpdateStrategy = *strategy - _, err := dsClient.Create(ds) - if err != nil { - t.Fatalf("Failed to create DaemonSet: %v", err) - } - defer cleanupDaemonSets(t, clientset, ds) + informers.Start(stopCh) + go dc.Run(5, stopCh) - _, err = nodeClient.Create(newNode("single-node", nil)) - if err != nil { - t.Fatalf("Failed to create node: %v", err) - } + // Start Scheduler + setupScheduler(t, clientset, informers, stopCh) - validateDaemonSetPodsAndMarkReady(podClient, podInformer, 1, t) - validateDaemonSetStatus(dsClient, ds.Name, 1, t) + ds := newDaemonSet("foo", ns.Name) + ds.Spec.UpdateStrategy = *strategy + _, err := dsClient.Create(ds) + if err != nil { + t.Fatalf("Failed to create DaemonSet: %v", err) + } + defer cleanupDaemonSets(t, clientset, ds) + + _, err = nodeClient.Create(newNode("single-node", nil)) + if err != nil { + t.Fatalf("Failed to create node: %v", err) + } + + validateDaemonSetPodsAndMarkReady(podClient, podInformer, 1, t) + validateDaemonSetStatus(dsClient, ds.Name, 1, t) + }) }) } func TestSimpleDaemonSetLaunchesPods(t *testing.T) { - forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { - server, closeFn, dc, informers, clientset := setup(t) - defer closeFn() - ns := framework.CreateTestingNamespace("simple-daemonset-test", server, t) - defer framework.DeleteTestingNamespace(ns, server, t) + forEachFeatureGate(t, func(t *testing.T) { + forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { + server, closeFn, dc, informers, clientset := setup(t) + defer closeFn() + ns := framework.CreateTestingNamespace("simple-daemonset-test", server, t) + defer framework.DeleteTestingNamespace(ns, server, t) - dsClient := clientset.AppsV1().DaemonSets(ns.Name) - podClient := clientset.CoreV1().Pods(ns.Name) - nodeClient := clientset.CoreV1().Nodes() - podInformer := informers.Core().V1().Pods().Informer() + dsClient := clientset.AppsV1().DaemonSets(ns.Name) + podClient := clientset.CoreV1().Pods(ns.Name) + nodeClient := clientset.CoreV1().Nodes() + podInformer := informers.Core().V1().Pods().Informer() - stopCh := make(chan struct{}) - informers.Start(stopCh) - go dc.Run(5, stopCh) - defer close(stopCh) + stopCh := make(chan struct{}) + defer close(stopCh) - ds := newDaemonSet("foo", ns.Name) - ds.Spec.UpdateStrategy = *strategy - _, err := dsClient.Create(ds) - if err != nil { - t.Fatalf("Failed to create DaemonSet: %v", err) - } - defer cleanupDaemonSets(t, clientset, ds) + informers.Start(stopCh) + go dc.Run(5, stopCh) - addNodes(nodeClient, 0, 5, nil, t) + // Start Scheduler + setupScheduler(t, clientset, informers, stopCh) - validateDaemonSetPodsAndMarkReady(podClient, podInformer, 5, t) - validateDaemonSetStatus(dsClient, ds.Name, 5, t) + ds := newDaemonSet("foo", ns.Name) + ds.Spec.UpdateStrategy = *strategy + _, err := dsClient.Create(ds) + if err != nil { + t.Fatalf("Failed to create DaemonSet: %v", err) + } + defer cleanupDaemonSets(t, clientset, ds) + + addNodes(nodeClient, 0, 5, nil, t) + + validateDaemonSetPodsAndMarkReady(podClient, podInformer, 5, t) + validateDaemonSetStatus(dsClient, ds.Name, 5, t) + }) + }) +} + +func TestDaemonSetWithNodeSelectorLaunchesPods(t *testing.T) { + forEachFeatureGate(t, func(t *testing.T) { + forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { + server, closeFn, dc, informers, clientset := setup(t) + defer closeFn() + ns := framework.CreateTestingNamespace("simple-daemonset-test", server, t) + defer framework.DeleteTestingNamespace(ns, server, t) + + dsClient := clientset.AppsV1().DaemonSets(ns.Name) + podClient := clientset.CoreV1().Pods(ns.Name) + nodeClient := clientset.CoreV1().Nodes() + podInformer := informers.Core().V1().Pods().Informer() + + stopCh := make(chan struct{}) + defer close(stopCh) + + informers.Start(stopCh) + go dc.Run(5, stopCh) + + // Start Scheduler + setupScheduler(t, clientset, informers, stopCh) + + ds := newDaemonSet("foo", ns.Name) + ds.Spec.UpdateStrategy = *strategy + + ds.Spec.Template.Spec.Affinity = &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "zone", + Operator: v1.NodeSelectorOpIn, + Values: []string{"test"}, + }, + }, + }, + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node-1"}, + }, + }, + }, + }, + }, + }, + } + + _, err := dsClient.Create(ds) + if err != nil { + t.Fatalf("Failed to create DaemonSet: %v", err) + } + defer cleanupDaemonSets(t, clientset, ds) + + addNodes(nodeClient, 0, 2, nil, t) + // Two nodes with labels + addNodes(nodeClient, 2, 2, map[string]string{ + "zone": "test", + }, t) + addNodes(nodeClient, 4, 2, nil, t) + + validateDaemonSetPodsAndMarkReady(podClient, podInformer, 3, t) + validateDaemonSetStatus(dsClient, ds.Name, 3, t) + }) }) } @@ -389,9 +599,13 @@ func TestNotReadyNodeDaemonDoesLaunchPod(t *testing.T) { podInformer := informers.Core().V1().Pods().Informer() stopCh := make(chan struct{}) + defer close(stopCh) + informers.Start(stopCh) go dc.Run(5, stopCh) - defer close(stopCh) + + // Start Scheduler + setupScheduler(t, clientset, informers, stopCh) ds := newDaemonSet("foo", ns.Name) ds.Spec.UpdateStrategy = *strategy @@ -399,6 +613,7 @@ func TestNotReadyNodeDaemonDoesLaunchPod(t *testing.T) { if err != nil { t.Fatalf("Failed to create DaemonSet: %v", err) } + defer cleanupDaemonSets(t, clientset, ds) node := newNode("single-node", nil) @@ -427,9 +642,10 @@ func TestInsufficientCapacityNodeDaemonDoesNotLaunchPod(t *testing.T) { eventClient := clientset.CoreV1().Events(ns.Namespace) stopCh := make(chan struct{}) + defer close(stopCh) + informers.Start(stopCh) go dc.Run(5, stopCh) - defer close(stopCh) ds := newDaemonSet("foo", ns.Name) ds.Spec.Template.Spec = resourcePodSpec("node-with-limited-memory", "120M", "75m") @@ -450,3 +666,77 @@ func TestInsufficientCapacityNodeDaemonDoesNotLaunchPod(t *testing.T) { validateFailedPlacementEvent(eventClient, t) }) } + +// TestInsufficientCapacityNodeDaemonSetCreateButNotLaunchPod tests that when "ScheduleDaemonSetPods" +// feature is enabled, the DaemonSet should create Pods for all the nodes regardless of available resource +// on the nodes, and kube-scheduler should not schedule Pods onto the nodes with insufficient resource. +func TestInsufficientCapacityNodeWhenScheduleDaemonSetPodsEnabled(t *testing.T) { + enabled := utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) + defer func() { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=%t", + features.ScheduleDaemonSetPods, enabled)) + }() + + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=%t", features.ScheduleDaemonSetPods, true)) + + forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { + server, closeFn, dc, informers, clientset := setup(t) + defer closeFn() + ns := framework.CreateTestingNamespace("insufficient-capacity", server, t) + defer framework.DeleteTestingNamespace(ns, server, t) + + dsClient := clientset.AppsV1().DaemonSets(ns.Name) + podClient := clientset.CoreV1().Pods(ns.Name) + podInformer := informers.Core().V1().Pods().Informer() + nodeClient := clientset.CoreV1().Nodes() + stopCh := make(chan struct{}) + defer close(stopCh) + + informers.Start(stopCh) + go dc.Run(5, stopCh) + + // Start Scheduler + setupScheduler(t, clientset, informers, stopCh) + + ds := newDaemonSet("foo", ns.Name) + ds.Spec.Template.Spec = resourcePodSpec("", "120M", "75m") + ds.Spec.UpdateStrategy = *strategy + ds, err := dsClient.Create(ds) + if err != nil { + t.Fatalf("Failed to create DaemonSet: %v", err) + } + + defer cleanupDaemonSets(t, clientset, ds) + + node := newNode("node-with-limited-memory", nil) + node.Status.Allocatable = allocatableResources("100M", "200m") + _, err = nodeClient.Create(node) + if err != nil { + t.Fatalf("Failed to create node: %v", err) + } + + if err := waitForPodsCreated(podInformer, 1); err != nil { + t.Errorf("Failed to wait for pods created: %v", err) + } + + objects := podInformer.GetIndexer().List() + for _, object := range objects { + pod := object.(*v1.Pod) + if err := waitForPodUnschedulable(clientset, pod); err != nil { + t.Errorf("Failed to wait for unschedulable status of pod %+v", pod) + } + } + + node1 := newNode("node-with-enough-memory", nil) + node1.Status.Allocatable = allocatableResources("200M", "2000m") + _, err = nodeClient.Create(node1) + if err != nil { + t.Fatalf("Failed to create node: %v", err) + } + + // When ScheduleDaemonSetPods enabled, 2 pods are created. But only one + // of two Pods is scheduled by default scheduler. + validateDaemonSetPodsAndMarkReady(podClient, podInformer, 2, t) + validateDaemonSetStatus(dsClient, ds.Name, 1, t) + }) +} diff --git a/test/integration/master/kms_transformation_test.go b/test/integration/master/kms_transformation_test.go index 89d96749b7f..f3cfa201c2c 100644 --- a/test/integration/master/kms_transformation_test.go +++ b/test/integration/master/kms_transformation_test.go @@ -144,6 +144,7 @@ func TestKMSProvider(t *testing.T) { if secretVal != string(s.Data[secretKey]) { t.Fatalf("expected %s from KubeAPI, but got %s", secretVal, string(s.Data[secretKey])) } + test.printMetrics() } func getDEKFromKMSPlugin(pluginMock *base64Plugin) ([]byte, error) { diff --git a/test/integration/master/transformation_testcase.go b/test/integration/master/transformation_testcase.go index aa692a561ed..bfe3bc8415e 100644 --- a/test/integration/master/transformation_testcase.go +++ b/test/integration/master/transformation_testcase.go @@ -43,12 +43,12 @@ import ( ) const ( - secretKey = "api_key" - secretVal = "086a7ffc-0225-11e8-ba89-0ed5f89f718b" - encryptionConfigFileName = "encryption.conf" - testNamespace = "secret-encryption-test" - testSecret = "test-secret" - latencySummaryMetricsFamily = "apiserver_storage_transformation_latencies_microseconds" + secretKey = "api_key" + secretVal = "086a7ffc-0225-11e8-ba89-0ed5f89f718b" + encryptionConfigFileName = "encryption.conf" + testNamespace = "secret-encryption-test" + testSecret = "test-secret" + metricsPrefix = "apiserver_storage_" ) type unSealSecret func(cipherText []byte, ctx value.Context, config encryptionconfig.ProviderConfig) ([]byte, error) @@ -247,9 +247,9 @@ func (e *transformTest) printMetrics() error { return fmt.Errorf("failed to gather metrics: %s", err) } - metricsOfInterest := []string{latencySummaryMetricsFamily} for _, mf := range metrics { - if contains(metricsOfInterest, *mf.Name) { + if strings.HasPrefix(*mf.Name, metricsPrefix) { + e.logger.Logf("%s", *mf.Name) for _, metric := range mf.GetMetric() { e.logger.Logf("%v", metric) } diff --git a/test/integration/scheduler/BUILD b/test/integration/scheduler/BUILD index d39015f2eb4..3d669eb66aa 100644 --- a/test/integration/scheduler/BUILD +++ b/test/integration/scheduler/BUILD @@ -36,8 +36,8 @@ go_test( "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithmprovider:go_default_library", "//pkg/scheduler/api:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/factory:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//plugin/pkg/admission/podtolerationrestriction:go_default_library", "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library", "//test/integration/framework:go_default_library", diff --git a/test/integration/scheduler/scheduler_test.go b/test/integration/scheduler/scheduler_test.go index 28ff6d8abb0..14b065bdf64 100644 --- a/test/integration/scheduler/scheduler_test.go +++ b/test/integration/scheduler/scheduler_test.go @@ -50,8 +50,8 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm" _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/factory" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" "k8s.io/kubernetes/test/integration/framework" ) diff --git a/test/integration/scheduler/volume_binding_test.go b/test/integration/scheduler/volume_binding_test.go index 9f3e484855a..6a554590417 100644 --- a/test/integration/scheduler/volume_binding_test.go +++ b/test/integration/scheduler/volume_binding_test.go @@ -384,6 +384,7 @@ func setupCluster(t *testing.T, nsName string, numberOfNodes int) *testConfig { ClaimInformer: informers.Core().V1().PersistentVolumeClaims(), ClassInformer: informers.Storage().V1().StorageClasses(), PodInformer: informers.Core().V1().Pods(), + NodeInformer: informers.Core().V1().Nodes(), EnableDynamicProvisioning: true, } ctrl, err := persistentvolume.NewController(params) diff --git a/test/integration/volume/persistent_volumes_test.go b/test/integration/volume/persistent_volumes_test.go index e449f2adb9b..189af2bb502 100644 --- a/test/integration/volume/persistent_volumes_test.go +++ b/test/integration/volume/persistent_volumes_test.go @@ -1136,6 +1136,7 @@ func createClients(ns *v1.Namespace, t *testing.T, s *httptest.Server, syncPerio ClaimInformer: informers.Core().V1().PersistentVolumeClaims(), ClassInformer: informers.Storage().V1().StorageClasses(), PodInformer: informers.Core().V1().Pods(), + NodeInformer: informers.Core().V1().Nodes(), EnableDynamicProvisioning: true, }) if err != nil { diff --git a/test/test_owners.csv b/test/test_owners.csv index 8443512f204..14beadb05b0 100644 --- a/test/test_owners.csv +++ b/test/test_owners.csv @@ -764,9 +764,9 @@ 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/core,madhusudancs,1, k8s.io/kubernetes/pkg/scheduler/factory,fgrzadkowski,0, -k8s.io/kubernetes/pkg/scheduler/schedulercache,fgrzadkowski,0, k8s.io/kubernetes/pkg/scheduler/util,wojtek-t,1, k8s.io/kubernetes/pkg/security/apparmor,bgrant0607,1, k8s.io/kubernetes/pkg/security/podsecuritypolicy,erictune,0, diff --git a/test/utils/update_resources.go b/test/utils/update_resources.go index b666454e54a..210847cb379 100644 --- a/test/utils/update_resources.go +++ b/test/utils/update_resources.go @@ -21,6 +21,8 @@ import ( "time" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/scale" "k8s.io/kubernetes/pkg/kubectl" ) @@ -30,13 +32,32 @@ const ( updateRetryInterval = 5 * time.Second updateRetryTimeout = 1 * time.Minute waitRetryInterval = 5 * time.Second - waitRetryTImeout = 5 * time.Minute + waitRetryTimeout = 5 * time.Minute ) -func ScaleResourceWithRetries(scaler kubectl.Scaler, namespace, name string, size uint, gr schema.GroupResource) error { - waitForScale := kubectl.NewRetryParams(updateRetryInterval, updateRetryTimeout) - waitForReplicas := kubectl.NewRetryParams(waitRetryInterval, waitRetryTImeout) - if err := scaler.Scale(namespace, name, size, nil, waitForScale, waitForReplicas, gr); err != nil { +func RetryErrorCondition(condition wait.ConditionFunc) wait.ConditionFunc { + return func() (bool, error) { + done, err := condition() + if err != nil && IsRetryableAPIError(err) { + return false, nil + } + return done, err + } +} + +func ScaleResourceWithRetries(scalesGetter scale.ScalesGetter, namespace, name string, size uint, gr schema.GroupResource) error { + scaler := kubectl.NewScaler(scalesGetter) + preconditions := &kubectl.ScalePrecondition{ + Size: -1, + ResourceVersion: "", + } + waitForReplicas := kubectl.NewRetryParams(waitRetryInterval, waitRetryTimeout) + cond := RetryErrorCondition(kubectl.ScaleCondition(scaler, preconditions, namespace, name, size, nil, gr)) + err := wait.PollImmediate(updateRetryInterval, updateRetryTimeout, cond) + if err == nil { + err = kubectl.WaitForScaleHasDesiredReplicas(scalesGetter, gr, name, namespace, size, waitForReplicas) + } + if err != nil { return fmt.Errorf("Error while scaling %s to %d replicas: %v", name, size, err) } return nil diff --git a/translations/kubectl/zh_CN/LC_MESSAGES/k8s.po b/translations/kubectl/zh_CN/LC_MESSAGES/k8s.po index 1db8ac6ea3c..fc91db119f9 100644 --- a/translations/kubectl/zh_CN/LC_MESSAGES/k8s.po +++ b/translations/kubectl/zh_CN/LC_MESSAGES/k8s.po @@ -2390,7 +2390,7 @@ msgstr "显示一个或更多 resources" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/current_context.go#L48 #: pkg/kubectl/cmd/config/current_context.go:49 msgid "Displays the current-context" -msgstr "显示 current_context" +msgstr "显示当前的 context" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/explain.go#L50 #: pkg/kubectl/cmd/explain.go:51 diff --git a/vendor/BUILD b/vendor/BUILD index 4a24181225b..a1308be9a62 100644 --- a/vendor/BUILD +++ b/vendor/BUILD @@ -287,6 +287,7 @@ filegroup( "//vendor/github.com/mailru/easyjson/jlexer:all-srcs", "//vendor/github.com/mailru/easyjson/jwriter:all-srcs", "//vendor/github.com/marstr/guid:all-srcs", + "//vendor/github.com/mattn/go-shellwords:all-srcs", "//vendor/github.com/matttproud/golang_protobuf_extensions/pbutil:all-srcs", "//vendor/github.com/mholt/caddy/caddyfile:all-srcs", "//vendor/github.com/miekg/dns:all-srcs", @@ -402,7 +403,7 @@ filegroup( "//vendor/google.golang.org/api/logging/v2beta1:all-srcs", "//vendor/google.golang.org/api/monitoring/v3:all-srcs", "//vendor/google.golang.org/api/pubsub/v1:all-srcs", - "//vendor/google.golang.org/api/tpu/v1alpha1:all-srcs", + "//vendor/google.golang.org/api/tpu/v1:all-srcs", "//vendor/google.golang.org/genproto/googleapis/api/annotations:all-srcs", "//vendor/google.golang.org/genproto/googleapis/rpc/status:all-srcs", "//vendor/google.golang.org/grpc:all-srcs", diff --git a/vendor/github.com/Microsoft/hcsshim/BUILD b/vendor/github.com/Microsoft/hcsshim/BUILD index 051601e3dab..3ad3b768ab6 100644 --- a/vendor/github.com/Microsoft/hcsshim/BUILD +++ b/vendor/github.com/Microsoft/hcsshim/BUILD @@ -29,10 +29,13 @@ go_library( "layerexists.go", "layerutils.go", "legacy.go", + "legacy18.go", + "legacy19.go", "nametoguid.go", "preparelayer.go", "process.go", "processimage.go", + "safeopen.go", "unpreparelayer.go", "utils.go", "version.go", diff --git a/vendor/github.com/Microsoft/hcsshim/README.md b/vendor/github.com/Microsoft/hcsshim/README.md index 30991a12e4c..deca9a97e3b 100644 --- a/vendor/github.com/Microsoft/hcsshim/README.md +++ b/vendor/github.com/Microsoft/hcsshim/README.md @@ -4,9 +4,30 @@ This package supports launching Windows Server containers from Go. It is primarily used in the [Docker Engine](https://github.com/docker/docker) project, but it can be freely used by other projects as well. -This project has adopted the [Microsoft Open Source Code of -Conduct](https://opensource.microsoft.com/codeofconduct/). For more information -see the [Code of Conduct -FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact -[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional -questions or comments. + +## Contributing +--------------- +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + + +## Reporting Security Issues + +Security issues and bugs should be reported privately, via email, to the Microsoft Security +Response Center (MSRC) at [secure@microsoft.com](mailto:secure@microsoft.com). You should +receive a response within 24 hours. If for some reason you do not, please follow up via +email to ensure we received your original message. Further information, including the +[MSRC PGP](https://technet.microsoft.com/en-us/security/dn606155) key, can be found in +the [Security TechCenter](https://technet.microsoft.com/en-us/security/default). + +------------------------------------------- +Copyright (c) 2018 Microsoft Corp. All rights reserved. diff --git a/vendor/github.com/Microsoft/hcsshim/baselayer.go b/vendor/github.com/Microsoft/hcsshim/baselayer.go index 9babd4e18ab..860185c3572 100644 --- a/vendor/github.com/Microsoft/hcsshim/baselayer.go +++ b/vendor/github.com/Microsoft/hcsshim/baselayer.go @@ -10,7 +10,7 @@ import ( ) type baseLayerWriter struct { - root string + root *os.File f *os.File bw *winio.BackupFileWriter err error @@ -26,10 +26,10 @@ type dirInfo struct { // reapplyDirectoryTimes reapplies directory modification, creation, etc. times // after processing of the directory tree has completed. The times are expected // to be ordered such that parent directories come before child directories. -func reapplyDirectoryTimes(dis []dirInfo) error { +func reapplyDirectoryTimes(root *os.File, dis []dirInfo) error { for i := range dis { di := &dis[len(dis)-i-1] // reverse order: process child directories first - f, err := winio.OpenForBackup(di.path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, syscall.OPEN_EXISTING) + f, err := openRelative(di.path, root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, _FILE_OPEN, _FILE_DIRECTORY_FILE) if err != nil { return err } @@ -75,12 +75,6 @@ func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err e w.hasUtilityVM = true } - path := filepath.Join(w.root, name) - path, err = makeLongAbsPath(path) - if err != nil { - return err - } - var f *os.File defer func() { if f != nil { @@ -88,27 +82,23 @@ func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err e } }() - createmode := uint32(syscall.CREATE_NEW) + extraFlags := uint32(0) if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { - err := os.Mkdir(path, 0) - if err != nil && !os.IsExist(err) { - return err - } - createmode = syscall.OPEN_EXISTING + extraFlags |= _FILE_DIRECTORY_FILE if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 { - w.dirInfo = append(w.dirInfo, dirInfo{path, *fileInfo}) + w.dirInfo = append(w.dirInfo, dirInfo{name, *fileInfo}) } } mode := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | winio.WRITE_DAC | winio.WRITE_OWNER | winio.ACCESS_SYSTEM_SECURITY) - f, err = winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createmode) + f, err = openRelative(name, w.root, mode, syscall.FILE_SHARE_READ, _FILE_CREATE, extraFlags) if err != nil { - return makeError(err, "Failed to OpenForBackup", path) + return makeError(err, "Failed to openRelative", name) } err = winio.SetFileBasicInfo(f, fileInfo) if err != nil { - return makeError(err, "Failed to SetFileBasicInfo", path) + return makeError(err, "Failed to SetFileBasicInfo", name) } w.f = f @@ -129,17 +119,7 @@ func (w *baseLayerWriter) AddLink(name string, target string) (err error) { return err } - linkpath, err := makeLongAbsPath(filepath.Join(w.root, name)) - if err != nil { - return err - } - - linktarget, err := makeLongAbsPath(filepath.Join(w.root, target)) - if err != nil { - return err - } - - return os.Link(linktarget, linkpath) + return linkRelative(target, w.root, name, w.root) } func (w *baseLayerWriter) Remove(name string) error { @@ -155,6 +135,10 @@ func (w *baseLayerWriter) Write(b []byte) (int, error) { } func (w *baseLayerWriter) Close() error { + defer func() { + w.root.Close() + w.root = nil + }() err := w.closeCurrentFile() if err != nil { return err @@ -162,18 +146,22 @@ func (w *baseLayerWriter) Close() error { if w.err == nil { // Restore the file times of all the directories, since they may have // been modified by creating child directories. - err = reapplyDirectoryTimes(w.dirInfo) + err = reapplyDirectoryTimes(w.root, w.dirInfo) if err != nil { return err } - err = ProcessBaseLayer(w.root) + err = ProcessBaseLayer(w.root.Name()) if err != nil { return err } if w.hasUtilityVM { - err = ProcessUtilityVMImage(filepath.Join(w.root, "UtilityVM")) + err := ensureNotReparsePointRelative("UtilityVM", w.root) + if err != nil { + return err + } + err = ProcessUtilityVMImage(filepath.Join(w.root.Name(), "UtilityVM")) if err != nil { return err } diff --git a/vendor/github.com/Microsoft/hcsshim/container.go b/vendor/github.com/Microsoft/hcsshim/container.go index b924d39f46b..3354f70efc7 100644 --- a/vendor/github.com/Microsoft/hcsshim/container.go +++ b/vendor/github.com/Microsoft/hcsshim/container.go @@ -201,12 +201,18 @@ func createContainerWithJSON(id string, c *ContainerConfig, additionalJSON strin if createError == nil || IsPending(createError) { if err := container.registerCallback(); err != nil { + // Terminate the container if it still exists. We're okay to ignore a failure here. + container.Terminate() return nil, makeContainerError(container, operation, "", err) } } err = processAsyncHcsResult(createError, resultp, container.callbackNumber, hcsNotificationSystemCreateCompleted, &defaultTimeout) if err != nil { + if err == ErrTimeout { + // Terminate the container if it still exists. We're okay to ignore a failure here. + container.Terminate() + } return nil, makeContainerError(container, operation, configuration, err) } diff --git a/vendor/github.com/Microsoft/hcsshim/errors.go b/vendor/github.com/Microsoft/hcsshim/errors.go index d2f9cc8bd20..c0c6cac87cc 100644 --- a/vendor/github.com/Microsoft/hcsshim/errors.go +++ b/vendor/github.com/Microsoft/hcsshim/errors.go @@ -72,6 +72,22 @@ var ( ErrPlatformNotSupported = errors.New("unsupported platform request") ) +type EndpointNotFoundError struct { + EndpointName string +} + +func (e EndpointNotFoundError) Error() string { + return fmt.Sprintf("Endpoint %s not found", e.EndpointName) +} + +type NetworkNotFoundError struct { + NetworkName string +} + +func (e NetworkNotFoundError) Error() string { + return fmt.Sprintf("Network %s not found", e.NetworkName) +} + // ProcessError is an error encountered in HCS during an operation on a Process object type ProcessError struct { Process *process @@ -174,6 +190,12 @@ func makeProcessError(process *process, operation string, extraInfo string, err // will currently return true when the error is ErrElementNotFound or ErrProcNotFound. func IsNotExist(err error) bool { err = getInnerError(err) + if _, ok := err.(EndpointNotFoundError); ok { + return true + } + if _, ok := err.(NetworkNotFoundError); ok { + return true + } return err == ErrComputeSystemDoesNotExist || err == ErrElementNotFound || err == ErrProcNotFound diff --git a/vendor/github.com/Microsoft/hcsshim/hcsshim.go b/vendor/github.com/Microsoft/hcsshim/hcsshim.go index 236ba1fa30d..b65953191c0 100644 --- a/vendor/github.com/Microsoft/hcsshim/hcsshim.go +++ b/vendor/github.com/Microsoft/hcsshim/hcsshim.go @@ -11,7 +11,7 @@ import ( "github.com/sirupsen/logrus" ) -//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go +//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go safeopen.go //sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree //sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId diff --git a/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go b/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go index 92afc0c249c..90689cb1ee0 100644 --- a/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go +++ b/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go @@ -1,318 +1,323 @@ -package hcsshim - -import ( - "encoding/json" - "fmt" - "net" - - "github.com/sirupsen/logrus" -) - -// HNSEndpoint represents a network endpoint in HNS -type HNSEndpoint struct { - Id string `json:"ID,omitempty"` - Name string `json:",omitempty"` - VirtualNetwork string `json:",omitempty"` - VirtualNetworkName string `json:",omitempty"` - Policies []json.RawMessage `json:",omitempty"` - MacAddress string `json:",omitempty"` - IPAddress net.IP `json:",omitempty"` - DNSSuffix string `json:",omitempty"` - DNSServerList string `json:",omitempty"` - GatewayAddress string `json:",omitempty"` - EnableInternalDNS bool `json:",omitempty"` - DisableICC bool `json:",omitempty"` - PrefixLength uint8 `json:",omitempty"` - IsRemoteEndpoint bool `json:",omitempty"` -} - -//SystemType represents the type of the system on which actions are done -type SystemType string - -// SystemType const -const ( - ContainerType SystemType = "Container" - VirtualMachineType SystemType = "VirtualMachine" - HostType SystemType = "Host" -) - -// EndpointAttachDetachRequest is the structure used to send request to the container to modify the system -// Supported resource types are Network and Request Types are Add/Remove -type EndpointAttachDetachRequest struct { - ContainerID string `json:"ContainerId,omitempty"` - SystemType SystemType `json:"SystemType"` - CompartmentID uint16 `json:"CompartmentId,omitempty"` - VirtualNICName string `json:"VirtualNicName,omitempty"` -} - -// EndpointResquestResponse is object to get the endpoint request response -type EndpointResquestResponse struct { - Success bool - Error string -} - -// HNSEndpointRequest makes a HNS call to modify/query a network endpoint -func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) { - endpoint := &HNSEndpoint{} - err := hnsCall(method, "/endpoints/"+path, request, &endpoint) - if err != nil { - return nil, err - } - - return endpoint, nil -} - -// HNSListEndpointRequest makes a HNS call to query the list of available endpoints -func HNSListEndpointRequest() ([]HNSEndpoint, error) { - var endpoint []HNSEndpoint - err := hnsCall("GET", "/endpoints/", "", &endpoint) - if err != nil { - return nil, err - } - - return endpoint, nil -} - -// HotAttachEndpoint makes a HCS Call to attach the endpoint to the container -func HotAttachEndpoint(containerID string, endpointID string) error { - return modifyNetworkEndpoint(containerID, endpointID, Add) -} - -// HotDetachEndpoint makes a HCS Call to detach the endpoint from the container -func HotDetachEndpoint(containerID string, endpointID string) error { - return modifyNetworkEndpoint(containerID, endpointID, Remove) -} - -// ModifyContainer corresponding to the container id, by sending a request -func modifyContainer(id string, request *ResourceModificationRequestResponse) error { - container, err := OpenContainer(id) - if err != nil { - if IsNotExist(err) { - return ErrComputeSystemDoesNotExist - } - return getInnerError(err) - } - defer container.Close() - err = container.Modify(request) - if err != nil { - if IsNotSupported(err) { - return ErrPlatformNotSupported - } - return getInnerError(err) - } - - return nil -} - -func modifyNetworkEndpoint(containerID string, endpointID string, request RequestType) error { - requestMessage := &ResourceModificationRequestResponse{ - Resource: Network, - Request: request, - Data: endpointID, - } - err := modifyContainer(containerID, requestMessage) - - if err != nil { - return err - } - - return nil -} - -// GetHNSEndpointByID get the Endpoint by ID -func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) { - return HNSEndpointRequest("GET", endpointID, "") -} - -// GetHNSEndpointByName gets the endpoint filtered by Name -func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) { - hnsResponse, err := HNSListEndpointRequest() - if err != nil { - return nil, err - } - for _, hnsEndpoint := range hnsResponse { - if hnsEndpoint.Name == endpointName { - return &hnsEndpoint, nil - } - } - return nil, fmt.Errorf("Endpoint %v not found", endpointName) -} - -// Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods -func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) { - operation := "Create" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - jsonString, err := json.Marshal(endpoint) - if err != nil { - return nil, err - } - return HNSEndpointRequest("POST", "", string(jsonString)) -} - -// Delete Endpoint by sending EndpointRequest to HNS -func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) { - operation := "Delete" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - return HNSEndpointRequest("DELETE", endpoint.Id, "") -} - -// Update Endpoint -func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) { - operation := "Update" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - jsonString, err := json.Marshal(endpoint) - if err != nil { - return nil, err - } - err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint) - - return endpoint, err -} - -// ContainerHotAttach attaches an endpoint to a running container -func (endpoint *HNSEndpoint) ContainerHotAttach(containerID string) error { - operation := "ContainerHotAttach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) - - return modifyNetworkEndpoint(containerID, endpoint.Id, Add) -} - -// ContainerHotDetach detaches an endpoint from a running container -func (endpoint *HNSEndpoint) ContainerHotDetach(containerID string) error { - operation := "ContainerHotDetach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) - - return modifyNetworkEndpoint(containerID, endpoint.Id, Remove) -} - -// ApplyACLPolicy applies Acl Policy on the Endpoint -func (endpoint *HNSEndpoint) ApplyACLPolicy(policy *ACLPolicy) error { - operation := "ApplyACLPolicy" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - jsonString, err := json.Marshal(policy) - if err != nil { - return err - } - endpoint.Policies[0] = jsonString - _, err = endpoint.Update() - return err -} - -// ContainerAttach attaches an endpoint to container -func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error { - operation := "ContainerAttach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - requestMessage := &EndpointAttachDetachRequest{ - ContainerID: containerID, - CompartmentID: compartmentID, - SystemType: ContainerType, - } - response := &EndpointResquestResponse{} - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) -} - -// ContainerDetach detaches an endpoint from container -func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error { - operation := "ContainerDetach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - requestMessage := &EndpointAttachDetachRequest{ - ContainerID: containerID, - SystemType: ContainerType, - } - response := &EndpointResquestResponse{} - - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) -} - -// HostAttach attaches a nic on the host -func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error { - operation := "HostAttach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - requestMessage := &EndpointAttachDetachRequest{ - CompartmentID: compartmentID, - SystemType: HostType, - } - response := &EndpointResquestResponse{} - - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) - -} - -// HostDetach detaches a nic on the host -func (endpoint *HNSEndpoint) HostDetach() error { - operation := "HostDetach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - requestMessage := &EndpointAttachDetachRequest{ - SystemType: HostType, - } - response := &EndpointResquestResponse{} - - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) -} - -// VirtualMachineNICAttach attaches a endpoint to a virtual machine -func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error { - operation := "VirtualMachineNicAttach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - requestMessage := &EndpointAttachDetachRequest{ - VirtualNICName: virtualMachineNICName, - SystemType: VirtualMachineType, - } - response := &EndpointResquestResponse{} - - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) -} - -// VirtualMachineNICDetach detaches a endpoint from a virtual machine -func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error { - operation := "VirtualMachineNicDetach" - title := "HCSShim::HNSEndpoint::" + operation - logrus.Debugf(title+" id=%s", endpoint.Id) - - requestMessage := &EndpointAttachDetachRequest{ - SystemType: VirtualMachineType, - } - response := &EndpointResquestResponse{} - - jsonString, err := json.Marshal(requestMessage) - if err != nil { - return err - } - return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) -} +package hcsshim + +import ( + "encoding/json" + "net" + + "github.com/sirupsen/logrus" +) + +// HNSEndpoint represents a network endpoint in HNS +type HNSEndpoint struct { + Id string `json:"ID,omitempty"` + Name string `json:",omitempty"` + VirtualNetwork string `json:",omitempty"` + VirtualNetworkName string `json:",omitempty"` + Policies []json.RawMessage `json:",omitempty"` + MacAddress string `json:",omitempty"` + IPAddress net.IP `json:",omitempty"` + DNSSuffix string `json:",omitempty"` + DNSServerList string `json:",omitempty"` + GatewayAddress string `json:",omitempty"` + EnableInternalDNS bool `json:",omitempty"` + DisableICC bool `json:",omitempty"` + PrefixLength uint8 `json:",omitempty"` + IsRemoteEndpoint bool `json:",omitempty"` +} + +//SystemType represents the type of the system on which actions are done +type SystemType string + +// SystemType const +const ( + ContainerType SystemType = "Container" + VirtualMachineType SystemType = "VirtualMachine" + HostType SystemType = "Host" +) + +// EndpointAttachDetachRequest is the structure used to send request to the container to modify the system +// Supported resource types are Network and Request Types are Add/Remove +type EndpointAttachDetachRequest struct { + ContainerID string `json:"ContainerId,omitempty"` + SystemType SystemType `json:"SystemType"` + CompartmentID uint16 `json:"CompartmentId,omitempty"` + VirtualNICName string `json:"VirtualNicName,omitempty"` +} + +// EndpointResquestResponse is object to get the endpoint request response +type EndpointResquestResponse struct { + Success bool + Error string +} + +// HNSEndpointRequest makes a HNS call to modify/query a network endpoint +func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) { + endpoint := &HNSEndpoint{} + err := hnsCall(method, "/endpoints/"+path, request, &endpoint) + if err != nil { + return nil, err + } + + return endpoint, nil +} + +// HNSListEndpointRequest makes a HNS call to query the list of available endpoints +func HNSListEndpointRequest() ([]HNSEndpoint, error) { + var endpoint []HNSEndpoint + err := hnsCall("GET", "/endpoints/", "", &endpoint) + if err != nil { + return nil, err + } + + return endpoint, nil +} + +// HotAttachEndpoint makes a HCS Call to attach the endpoint to the container +func HotAttachEndpoint(containerID string, endpointID string) error { + return modifyNetworkEndpoint(containerID, endpointID, Add) +} + +// HotDetachEndpoint makes a HCS Call to detach the endpoint from the container +func HotDetachEndpoint(containerID string, endpointID string) error { + return modifyNetworkEndpoint(containerID, endpointID, Remove) +} + +// ModifyContainer corresponding to the container id, by sending a request +func modifyContainer(id string, request *ResourceModificationRequestResponse) error { + container, err := OpenContainer(id) + if err != nil { + if IsNotExist(err) { + return ErrComputeSystemDoesNotExist + } + return getInnerError(err) + } + defer container.Close() + err = container.Modify(request) + if err != nil { + if IsNotSupported(err) { + return ErrPlatformNotSupported + } + return getInnerError(err) + } + + return nil +} + +func modifyNetworkEndpoint(containerID string, endpointID string, request RequestType) error { + requestMessage := &ResourceModificationRequestResponse{ + Resource: Network, + Request: request, + Data: endpointID, + } + err := modifyContainer(containerID, requestMessage) + + if err != nil { + return err + } + + return nil +} + +// GetHNSEndpointByID get the Endpoint by ID +func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) { + return HNSEndpointRequest("GET", endpointID, "") +} + +// GetHNSEndpointByName gets the endpoint filtered by Name +func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) { + hnsResponse, err := HNSListEndpointRequest() + if err != nil { + return nil, err + } + for _, hnsEndpoint := range hnsResponse { + if hnsEndpoint.Name == endpointName { + return &hnsEndpoint, nil + } + } + return nil, EndpointNotFoundError{EndpointName: endpointName} +} + +// Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods +func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) { + operation := "Create" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + jsonString, err := json.Marshal(endpoint) + if err != nil { + return nil, err + } + return HNSEndpointRequest("POST", "", string(jsonString)) +} + +// Delete Endpoint by sending EndpointRequest to HNS +func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) { + operation := "Delete" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + return HNSEndpointRequest("DELETE", endpoint.Id, "") +} + +// Update Endpoint +func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) { + operation := "Update" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + jsonString, err := json.Marshal(endpoint) + if err != nil { + return nil, err + } + err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint) + + return endpoint, err +} + +// ContainerHotAttach attaches an endpoint to a running container +func (endpoint *HNSEndpoint) ContainerHotAttach(containerID string) error { + operation := "ContainerHotAttach" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) + + return modifyNetworkEndpoint(containerID, endpoint.Id, Add) +} + +// ContainerHotDetach detaches an endpoint from a running container +func (endpoint *HNSEndpoint) ContainerHotDetach(containerID string) error { + operation := "ContainerHotDetach" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) + + return modifyNetworkEndpoint(containerID, endpoint.Id, Remove) +} + +// ApplyACLPolicy applies a set of ACL Policies on the Endpoint +func (endpoint *HNSEndpoint) ApplyACLPolicy(policies ...*ACLPolicy) error { + operation := "ApplyACLPolicy" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + for _, policy := range policies { + if policy == nil { + continue + } + jsonString, err := json.Marshal(policy) + if err != nil { + return err + } + endpoint.Policies = append(endpoint.Policies, jsonString) + } + + _, err := endpoint.Update() + return err +} + +// ContainerAttach attaches an endpoint to container +func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error { + operation := "ContainerAttach" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + requestMessage := &EndpointAttachDetachRequest{ + ContainerID: containerID, + CompartmentID: compartmentID, + SystemType: ContainerType, + } + response := &EndpointResquestResponse{} + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) +} + +// ContainerDetach detaches an endpoint from container +func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error { + operation := "ContainerDetach" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + requestMessage := &EndpointAttachDetachRequest{ + ContainerID: containerID, + SystemType: ContainerType, + } + response := &EndpointResquestResponse{} + + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) +} + +// HostAttach attaches a nic on the host +func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error { + operation := "HostAttach" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + requestMessage := &EndpointAttachDetachRequest{ + CompartmentID: compartmentID, + SystemType: HostType, + } + response := &EndpointResquestResponse{} + + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) + +} + +// HostDetach detaches a nic on the host +func (endpoint *HNSEndpoint) HostDetach() error { + operation := "HostDetach" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + requestMessage := &EndpointAttachDetachRequest{ + SystemType: HostType, + } + response := &EndpointResquestResponse{} + + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) +} + +// VirtualMachineNICAttach attaches a endpoint to a virtual machine +func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error { + operation := "VirtualMachineNicAttach" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + requestMessage := &EndpointAttachDetachRequest{ + VirtualNICName: virtualMachineNICName, + SystemType: VirtualMachineType, + } + response := &EndpointResquestResponse{} + + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) +} + +// VirtualMachineNICDetach detaches a endpoint from a virtual machine +func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error { + operation := "VirtualMachineNicDetach" + title := "HCSShim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + requestMessage := &EndpointAttachDetachRequest{ + SystemType: VirtualMachineType, + } + response := &EndpointResquestResponse{} + + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) +} diff --git a/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go b/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go index 3345bfa3f27..398583a4e4e 100644 --- a/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go +++ b/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go @@ -1,142 +1,141 @@ -package hcsshim - -import ( - "encoding/json" - "fmt" - "net" - - "github.com/sirupsen/logrus" -) - -// Subnet is assoicated with a network and represents a list -// of subnets available to the network -type Subnet struct { - AddressPrefix string `json:",omitempty"` - GatewayAddress string `json:",omitempty"` - Policies []json.RawMessage `json:",omitempty"` -} - -// MacPool is assoicated with a network and represents a list -// of macaddresses available to the network -type MacPool struct { - StartMacAddress string `json:",omitempty"` - EndMacAddress string `json:",omitempty"` -} - -// HNSNetwork represents a network in HNS -type HNSNetwork struct { - Id string `json:"ID,omitempty"` - Name string `json:",omitempty"` - Type string `json:",omitempty"` - NetworkAdapterName string `json:",omitempty"` - SourceMac string `json:",omitempty"` - Policies []json.RawMessage `json:",omitempty"` - MacPools []MacPool `json:",omitempty"` - Subnets []Subnet `json:",omitempty"` - DNSSuffix string `json:",omitempty"` - DNSServerList string `json:",omitempty"` - DNSServerCompartment uint32 `json:",omitempty"` - ManagementIP string `json:",omitempty"` - AutomaticDNS bool `json:",omitempty"` -} - -type hnsNetworkResponse struct { - Success bool - Error string - Output HNSNetwork -} - -type hnsResponse struct { - Success bool - Error string - Output json.RawMessage -} - -// HNSNetworkRequest makes a call into HNS to update/query a single network -func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) { - var network HNSNetwork - err := hnsCall(method, "/networks/"+path, request, &network) - if err != nil { - return nil, err - } - - return &network, nil -} - -// HNSListNetworkRequest makes a HNS call to query the list of available networks -func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) { - var network []HNSNetwork - err := hnsCall(method, "/networks/"+path, request, &network) - if err != nil { - return nil, err - } - - return network, nil -} - -// GetHNSNetworkByID -func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) { - return HNSNetworkRequest("GET", networkID, "") -} - -// GetHNSNetworkName filtered by Name -func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) { - hsnnetworks, err := HNSListNetworkRequest("GET", "", "") - if err != nil { - return nil, err - } - for _, hnsnetwork := range hsnnetworks { - if hnsnetwork.Name == networkName { - return &hnsnetwork, nil - } - } - return nil, fmt.Errorf("Network %v not found", networkName) -} - -// Create Network by sending NetworkRequest to HNS. -func (network *HNSNetwork) Create() (*HNSNetwork, error) { - operation := "Create" - title := "HCSShim::HNSNetwork::" + operation - logrus.Debugf(title+" id=%s", network.Id) - - jsonString, err := json.Marshal(network) - if err != nil { - return nil, err - } - return HNSNetworkRequest("POST", "", string(jsonString)) -} - -// Delete Network by sending NetworkRequest to HNS -func (network *HNSNetwork) Delete() (*HNSNetwork, error) { - operation := "Delete" - title := "HCSShim::HNSNetwork::" + operation - logrus.Debugf(title+" id=%s", network.Id) - - return HNSNetworkRequest("DELETE", network.Id, "") -} - -// Creates an endpoint on the Network. -func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint { - return &HNSEndpoint{ - VirtualNetwork: network.Id, - IPAddress: ipAddress, - MacAddress: string(macAddress), - } -} - -func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { - operation := "CreateEndpoint" - title := "HCSShim::HNSNetwork::" + operation - logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id) - - endpoint.VirtualNetwork = network.Id - return endpoint.Create() -} - -func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { - operation := "CreateRemoteEndpoint" - title := "HCSShim::HNSNetwork::" + operation - logrus.Debugf(title+" id=%s", network.Id) - endpoint.IsRemoteEndpoint = true - return network.CreateEndpoint(endpoint) -} +package hcsshim + +import ( + "encoding/json" + "net" + + "github.com/sirupsen/logrus" +) + +// Subnet is assoicated with a network and represents a list +// of subnets available to the network +type Subnet struct { + AddressPrefix string `json:",omitempty"` + GatewayAddress string `json:",omitempty"` + Policies []json.RawMessage `json:",omitempty"` +} + +// MacPool is assoicated with a network and represents a list +// of macaddresses available to the network +type MacPool struct { + StartMacAddress string `json:",omitempty"` + EndMacAddress string `json:",omitempty"` +} + +// HNSNetwork represents a network in HNS +type HNSNetwork struct { + Id string `json:"ID,omitempty"` + Name string `json:",omitempty"` + Type string `json:",omitempty"` + NetworkAdapterName string `json:",omitempty"` + SourceMac string `json:",omitempty"` + Policies []json.RawMessage `json:",omitempty"` + MacPools []MacPool `json:",omitempty"` + Subnets []Subnet `json:",omitempty"` + DNSSuffix string `json:",omitempty"` + DNSServerList string `json:",omitempty"` + DNSServerCompartment uint32 `json:",omitempty"` + ManagementIP string `json:",omitempty"` + AutomaticDNS bool `json:",omitempty"` +} + +type hnsNetworkResponse struct { + Success bool + Error string + Output HNSNetwork +} + +type hnsResponse struct { + Success bool + Error string + Output json.RawMessage +} + +// HNSNetworkRequest makes a call into HNS to update/query a single network +func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) { + var network HNSNetwork + err := hnsCall(method, "/networks/"+path, request, &network) + if err != nil { + return nil, err + } + + return &network, nil +} + +// HNSListNetworkRequest makes a HNS call to query the list of available networks +func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) { + var network []HNSNetwork + err := hnsCall(method, "/networks/"+path, request, &network) + if err != nil { + return nil, err + } + + return network, nil +} + +// GetHNSNetworkByID +func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) { + return HNSNetworkRequest("GET", networkID, "") +} + +// GetHNSNetworkName filtered by Name +func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) { + hsnnetworks, err := HNSListNetworkRequest("GET", "", "") + if err != nil { + return nil, err + } + for _, hnsnetwork := range hsnnetworks { + if hnsnetwork.Name == networkName { + return &hnsnetwork, nil + } + } + return nil, NetworkNotFoundError{NetworkName: networkName} +} + +// Create Network by sending NetworkRequest to HNS. +func (network *HNSNetwork) Create() (*HNSNetwork, error) { + operation := "Create" + title := "HCSShim::HNSNetwork::" + operation + logrus.Debugf(title+" id=%s", network.Id) + + jsonString, err := json.Marshal(network) + if err != nil { + return nil, err + } + return HNSNetworkRequest("POST", "", string(jsonString)) +} + +// Delete Network by sending NetworkRequest to HNS +func (network *HNSNetwork) Delete() (*HNSNetwork, error) { + operation := "Delete" + title := "HCSShim::HNSNetwork::" + operation + logrus.Debugf(title+" id=%s", network.Id) + + return HNSNetworkRequest("DELETE", network.Id, "") +} + +// Creates an endpoint on the Network. +func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint { + return &HNSEndpoint{ + VirtualNetwork: network.Id, + IPAddress: ipAddress, + MacAddress: string(macAddress), + } +} + +func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { + operation := "CreateEndpoint" + title := "HCSShim::HNSNetwork::" + operation + logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id) + + endpoint.VirtualNetwork = network.Id + return endpoint.Create() +} + +func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { + operation := "CreateRemoteEndpoint" + title := "HCSShim::HNSNetwork::" + operation + logrus.Debugf(title+" id=%s", network.Id) + endpoint.IsRemoteEndpoint = true + return network.CreateEndpoint(endpoint) +} diff --git a/vendor/github.com/Microsoft/hcsshim/hnspolicy.go b/vendor/github.com/Microsoft/hcsshim/hnspolicy.go index ecfbf0eda37..bf860e9387f 100644 --- a/vendor/github.com/Microsoft/hcsshim/hnspolicy.go +++ b/vendor/github.com/Microsoft/hcsshim/hnspolicy.go @@ -1,95 +1,94 @@ -package hcsshim - -// Type of Request Support in ModifySystem -type PolicyType string - -// RequestType const -const ( - Nat PolicyType = "NAT" - ACL PolicyType = "ACL" - PA PolicyType = "PA" - VLAN PolicyType = "VLAN" - VSID PolicyType = "VSID" - VNet PolicyType = "VNET" - L2Driver PolicyType = "L2Driver" - Isolation PolicyType = "Isolation" - QOS PolicyType = "QOS" - OutboundNat PolicyType = "OutBoundNAT" - ExternalLoadBalancer PolicyType = "ELB" - Route PolicyType = "ROUTE" -) - -type NatPolicy struct { - Type PolicyType `json:"Type"` - Protocol string - InternalPort uint16 - ExternalPort uint16 -} - -type QosPolicy struct { - Type PolicyType `json:"Type"` - MaximumOutgoingBandwidthInBytes uint64 -} - -type IsolationPolicy struct { - Type PolicyType `json:"Type"` - VLAN uint - VSID uint - InDefaultIsolation bool -} - -type VlanPolicy struct { - Type PolicyType `json:"Type"` - VLAN uint -} - -type VsidPolicy struct { - Type PolicyType `json:"Type"` - VSID uint -} - -type PaPolicy struct { - Type PolicyType `json:"Type"` - PA string `json:"PA"` -} - -type OutboundNatPolicy struct { - Policy - VIP string `json:"VIP,omitempty"` - Exceptions []string `json:"ExceptionList,omitempty"` -} - -type ActionType string -type DirectionType string -type RuleType string - -const ( - Allow ActionType = "Allow" - Block ActionType = "Block" - - In DirectionType = "In" - Out DirectionType = "Out" - - Host RuleType = "Host" - Switch RuleType = "Switch" -) - -type ACLPolicy struct { - Type PolicyType `json:"Type"` - Protocol uint16 - InternalPort uint16 - Action ActionType - Direction DirectionType - LocalAddress string - RemoteAddress string - LocalPort uint16 - RemotePort uint16 - RuleType RuleType `json:"RuleType,omitempty"` - - Priority uint16 - ServiceName string -} - -type Policy struct { - Type PolicyType `json:"Type"` -} +package hcsshim + +// Type of Request Support in ModifySystem +type PolicyType string + +// RequestType const +const ( + Nat PolicyType = "NAT" + ACL PolicyType = "ACL" + PA PolicyType = "PA" + VLAN PolicyType = "VLAN" + VSID PolicyType = "VSID" + VNet PolicyType = "VNET" + L2Driver PolicyType = "L2Driver" + Isolation PolicyType = "Isolation" + QOS PolicyType = "QOS" + OutboundNat PolicyType = "OutBoundNAT" + ExternalLoadBalancer PolicyType = "ELB" + Route PolicyType = "ROUTE" +) + +type NatPolicy struct { + Type PolicyType `json:"Type"` + Protocol string + InternalPort uint16 + ExternalPort uint16 +} + +type QosPolicy struct { + Type PolicyType `json:"Type"` + MaximumOutgoingBandwidthInBytes uint64 +} + +type IsolationPolicy struct { + Type PolicyType `json:"Type"` + VLAN uint + VSID uint + InDefaultIsolation bool +} + +type VlanPolicy struct { + Type PolicyType `json:"Type"` + VLAN uint +} + +type VsidPolicy struct { + Type PolicyType `json:"Type"` + VSID uint +} + +type PaPolicy struct { + Type PolicyType `json:"Type"` + PA string `json:"PA"` +} + +type OutboundNatPolicy struct { + Policy + VIP string `json:"VIP,omitempty"` + Exceptions []string `json:"ExceptionList,omitempty"` +} + +type ActionType string +type DirectionType string +type RuleType string + +const ( + Allow ActionType = "Allow" + Block ActionType = "Block" + + In DirectionType = "In" + Out DirectionType = "Out" + + Host RuleType = "Host" + Switch RuleType = "Switch" +) + +type ACLPolicy struct { + Type PolicyType `json:"Type"` + Protocol uint16 + InternalPort uint16 + Action ActionType + Direction DirectionType + LocalAddresses string + RemoteAddresses string + LocalPort uint16 + RemotePort uint16 + RuleType RuleType `json:"RuleType,omitempty"` + Priority uint16 + ServiceName string +} + +type Policy struct { + Type PolicyType `json:"Type"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go b/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go index bbd7e1edb08..ef1ccab16e6 100644 --- a/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go +++ b/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go @@ -1,200 +1,200 @@ -package hcsshim - -import ( - "encoding/json" - - "github.com/sirupsen/logrus" -) - -// RoutePolicy is a structure defining schema for Route based Policy -type RoutePolicy struct { - Policy - DestinationPrefix string `json:"DestinationPrefix,omitempty"` - NextHop string `json:"NextHop,omitempty"` - EncapEnabled bool `json:"NeedEncap,omitempty"` -} - -// ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy -type ELBPolicy struct { - LBPolicy - SourceVIP string `json:"SourceVIP,omitempty"` - VIPs []string `json:"VIPs,omitempty"` - ILB bool `json:"ILB,omitempty"` -} - -// LBPolicy is a structure defining schema for LoadBalancing based Policy -type LBPolicy struct { - Policy - Protocol uint16 `json:"Protocol,omitempty"` - InternalPort uint16 - ExternalPort uint16 -} - -// PolicyList is a structure defining schema for Policy list request -type PolicyList struct { - ID string `json:"ID,omitempty"` - EndpointReferences []string `json:"References,omitempty"` - Policies []json.RawMessage `json:"Policies,omitempty"` -} - -// HNSPolicyListRequest makes a call into HNS to update/query a single network -func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) { - var policy PolicyList - err := hnsCall(method, "/policylists/"+path, request, &policy) - if err != nil { - return nil, err - } - - return &policy, nil -} - -// HNSListPolicyListRequest gets all the policy list -func HNSListPolicyListRequest() ([]PolicyList, error) { - var plist []PolicyList - err := hnsCall("GET", "/policylists/", "", &plist) - if err != nil { - return nil, err - } - - return plist, nil -} - -// PolicyListRequest makes a HNS call to modify/query a network policy list -func PolicyListRequest(method, path, request string) (*PolicyList, error) { - policylist := &PolicyList{} - err := hnsCall(method, "/policylists/"+path, request, &policylist) - if err != nil { - return nil, err - } - - return policylist, nil -} - -// GetPolicyListByID get the policy list by ID -func GetPolicyListByID(policyListID string) (*PolicyList, error) { - return PolicyListRequest("GET", policyListID, "") -} - -// Create PolicyList by sending PolicyListRequest to HNS. -func (policylist *PolicyList) Create() (*PolicyList, error) { - operation := "Create" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" id=%s", policylist.ID) - jsonString, err := json.Marshal(policylist) - if err != nil { - return nil, err - } - return PolicyListRequest("POST", "", string(jsonString)) -} - -// Delete deletes PolicyList -func (policylist *PolicyList) Delete() (*PolicyList, error) { - operation := "Delete" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" id=%s", policylist.ID) - - return PolicyListRequest("DELETE", policylist.ID, "") -} - -// AddEndpoint add an endpoint to a Policy List -func (policylist *PolicyList) AddEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { - operation := "AddEndpoint" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) - - _, err := policylist.Delete() - if err != nil { - return nil, err - } - - // Add Endpoint to the Existing List - policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) - - return policylist.Create() -} - -// RemoveEndpoint removes an endpoint from the Policy List -func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { - operation := "RemoveEndpoint" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) - - _, err := policylist.Delete() - if err != nil { - return nil, err - } - - elementToRemove := "/endpoints/" + endpoint.Id - - var references []string - - for _, endpointReference := range policylist.EndpointReferences { - if endpointReference == elementToRemove { - continue - } - references = append(references, endpointReference) - } - policylist.EndpointReferences = references - return policylist.Create() -} - -// AddLoadBalancer policy list for the specified endpoints -func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) { - operation := "AddLoadBalancer" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" endpointId=%v, isILB=%v, sourceVIP=%s, vip=%s, protocol=%v, internalPort=%v, externalPort=%v", endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort) - - policylist := &PolicyList{} - - elbPolicy := &ELBPolicy{ - SourceVIP: sourceVIP, - ILB: isILB, - } - - if len(vip) > 0 { - elbPolicy.VIPs = []string{vip} - } - elbPolicy.Type = ExternalLoadBalancer - elbPolicy.Protocol = protocol - elbPolicy.InternalPort = internalPort - elbPolicy.ExternalPort = externalPort - - for _, endpoint := range endpoints { - policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) - } - - jsonString, err := json.Marshal(elbPolicy) - if err != nil { - return nil, err - } - policylist.Policies = append(policylist.Policies, jsonString) - return policylist.Create() -} - -// AddRoute adds route policy list for the specified endpoints -func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) { - operation := "AddRoute" - title := "HCSShim::PolicyList::" + operation - logrus.Debugf(title+" destinationPrefix:%s", destinationPrefix) - - policylist := &PolicyList{} - - rPolicy := &RoutePolicy{ - DestinationPrefix: destinationPrefix, - NextHop: nextHop, - EncapEnabled: encapEnabled, - } - rPolicy.Type = Route - - for _, endpoint := range endpoints { - policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) - } - - jsonString, err := json.Marshal(rPolicy) - if err != nil { - return nil, err - } - - policylist.Policies = append(policylist.Policies, jsonString) - return policylist.Create() -} +package hcsshim + +import ( + "encoding/json" + + "github.com/sirupsen/logrus" +) + +// RoutePolicy is a structure defining schema for Route based Policy +type RoutePolicy struct { + Policy + DestinationPrefix string `json:"DestinationPrefix,omitempty"` + NextHop string `json:"NextHop,omitempty"` + EncapEnabled bool `json:"NeedEncap,omitempty"` +} + +// ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy +type ELBPolicy struct { + LBPolicy + SourceVIP string `json:"SourceVIP,omitempty"` + VIPs []string `json:"VIPs,omitempty"` + ILB bool `json:"ILB,omitempty"` +} + +// LBPolicy is a structure defining schema for LoadBalancing based Policy +type LBPolicy struct { + Policy + Protocol uint16 `json:"Protocol,omitempty"` + InternalPort uint16 + ExternalPort uint16 +} + +// PolicyList is a structure defining schema for Policy list request +type PolicyList struct { + ID string `json:"ID,omitempty"` + EndpointReferences []string `json:"References,omitempty"` + Policies []json.RawMessage `json:"Policies,omitempty"` +} + +// HNSPolicyListRequest makes a call into HNS to update/query a single network +func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) { + var policy PolicyList + err := hnsCall(method, "/policylists/"+path, request, &policy) + if err != nil { + return nil, err + } + + return &policy, nil +} + +// HNSListPolicyListRequest gets all the policy list +func HNSListPolicyListRequest() ([]PolicyList, error) { + var plist []PolicyList + err := hnsCall("GET", "/policylists/", "", &plist) + if err != nil { + return nil, err + } + + return plist, nil +} + +// PolicyListRequest makes a HNS call to modify/query a network policy list +func PolicyListRequest(method, path, request string) (*PolicyList, error) { + policylist := &PolicyList{} + err := hnsCall(method, "/policylists/"+path, request, &policylist) + if err != nil { + return nil, err + } + + return policylist, nil +} + +// GetPolicyListByID get the policy list by ID +func GetPolicyListByID(policyListID string) (*PolicyList, error) { + return PolicyListRequest("GET", policyListID, "") +} + +// Create PolicyList by sending PolicyListRequest to HNS. +func (policylist *PolicyList) Create() (*PolicyList, error) { + operation := "Create" + title := "HCSShim::PolicyList::" + operation + logrus.Debugf(title+" id=%s", policylist.ID) + jsonString, err := json.Marshal(policylist) + if err != nil { + return nil, err + } + return PolicyListRequest("POST", "", string(jsonString)) +} + +// Delete deletes PolicyList +func (policylist *PolicyList) Delete() (*PolicyList, error) { + operation := "Delete" + title := "HCSShim::PolicyList::" + operation + logrus.Debugf(title+" id=%s", policylist.ID) + + return PolicyListRequest("DELETE", policylist.ID, "") +} + +// AddEndpoint add an endpoint to a Policy List +func (policylist *PolicyList) AddEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { + operation := "AddEndpoint" + title := "HCSShim::PolicyList::" + operation + logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) + + _, err := policylist.Delete() + if err != nil { + return nil, err + } + + // Add Endpoint to the Existing List + policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) + + return policylist.Create() +} + +// RemoveEndpoint removes an endpoint from the Policy List +func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { + operation := "RemoveEndpoint" + title := "HCSShim::PolicyList::" + operation + logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) + + _, err := policylist.Delete() + if err != nil { + return nil, err + } + + elementToRemove := "/endpoints/" + endpoint.Id + + var references []string + + for _, endpointReference := range policylist.EndpointReferences { + if endpointReference == elementToRemove { + continue + } + references = append(references, endpointReference) + } + policylist.EndpointReferences = references + return policylist.Create() +} + +// AddLoadBalancer policy list for the specified endpoints +func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) { + operation := "AddLoadBalancer" + title := "HCSShim::PolicyList::" + operation + logrus.Debugf(title+" endpointId=%v, isILB=%v, sourceVIP=%s, vip=%s, protocol=%v, internalPort=%v, externalPort=%v", endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort) + + policylist := &PolicyList{} + + elbPolicy := &ELBPolicy{ + SourceVIP: sourceVIP, + ILB: isILB, + } + + if len(vip) > 0 { + elbPolicy.VIPs = []string{vip} + } + elbPolicy.Type = ExternalLoadBalancer + elbPolicy.Protocol = protocol + elbPolicy.InternalPort = internalPort + elbPolicy.ExternalPort = externalPort + + for _, endpoint := range endpoints { + policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) + } + + jsonString, err := json.Marshal(elbPolicy) + if err != nil { + return nil, err + } + policylist.Policies = append(policylist.Policies, jsonString) + return policylist.Create() +} + +// AddRoute adds route policy list for the specified endpoints +func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) { + operation := "AddRoute" + title := "HCSShim::PolicyList::" + operation + logrus.Debugf(title+" destinationPrefix:%s", destinationPrefix) + + policylist := &PolicyList{} + + rPolicy := &RoutePolicy{ + DestinationPrefix: destinationPrefix, + NextHop: nextHop, + EncapEnabled: encapEnabled, + } + rPolicy.Type = Route + + for _, endpoint := range endpoints { + policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) + } + + jsonString, err := json.Marshal(rPolicy) + if err != nil { + return nil, err + } + + policylist.Policies = append(policylist.Policies, jsonString) + return policylist.Create() +} diff --git a/vendor/github.com/Microsoft/hcsshim/importlayer.go b/vendor/github.com/Microsoft/hcsshim/importlayer.go index 3aed14376a4..2742b9f7500 100644 --- a/vendor/github.com/Microsoft/hcsshim/importlayer.go +++ b/vendor/github.com/Microsoft/hcsshim/importlayer.go @@ -129,37 +129,39 @@ type legacyLayerWriterWrapper struct { } func (r *legacyLayerWriterWrapper) Close() error { - defer os.RemoveAll(r.root) + defer os.RemoveAll(r.root.Name()) + defer r.legacyLayerWriter.CloseRoots() err := r.legacyLayerWriter.Close() if err != nil { return err } - // Use the original path here because ImportLayer does not support long paths for the source in TP5. - // But do use a long path for the destination to work around another bug with directories - // with MAX_PATH - 12 < length < MAX_PATH. info := r.info - fullPath, err := makeLongAbsPath(filepath.Join(info.HomeDir, r.layerID)) - if err != nil { + info.HomeDir = "" + if err = ImportLayer(info, r.destRoot.Name(), r.path, r.parentLayerPaths); err != nil { return err } - - info.HomeDir = "" - if err = ImportLayer(info, fullPath, r.path, r.parentLayerPaths); err != nil { - return err + for _, name := range r.Tombstones { + if err = removeRelative(name, r.destRoot); err != nil && !os.IsNotExist(err) { + return err + } } // Add any hard links that were collected. for _, lnk := range r.PendingLinks { - if err = os.Remove(lnk.Path); err != nil && !os.IsNotExist(err) { + if err = removeRelative(lnk.Path, r.destRoot); err != nil && !os.IsNotExist(err) { return err } - if err = os.Link(lnk.Target, lnk.Path); err != nil { + if err = linkRelative(lnk.Target, lnk.TargetRoot, lnk.Path, r.destRoot); err != nil { return err } } // Prepare the utility VM for use if one is present in the layer. if r.HasUtilityVM { - err = ProcessUtilityVMImage(filepath.Join(fullPath, "UtilityVM")) + err := ensureNotReparsePointRelative("UtilityVM", r.destRoot) + if err != nil { + return err + } + err = ProcessUtilityVMImage(filepath.Join(r.destRoot.Name(), "UtilityVM")) if err != nil { return err } @@ -173,8 +175,12 @@ func (r *legacyLayerWriterWrapper) Close() error { func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error) { if len(parentLayerPaths) == 0 { // This is a base layer. It gets imported differently. + f, err := openRoot(filepath.Join(info.HomeDir, layerID)) + if err != nil { + return nil, err + } return &baseLayerWriter{ - root: filepath.Join(info.HomeDir, layerID), + root: f, }, nil } @@ -185,8 +191,12 @@ func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) if err != nil { return nil, err } + w, err := newLegacyLayerWriter(path, parentLayerPaths, filepath.Join(info.HomeDir, layerID)) + if err != nil { + return nil, err + } return &legacyLayerWriterWrapper{ - legacyLayerWriter: newLegacyLayerWriter(path, parentLayerPaths, filepath.Join(info.HomeDir, layerID)), + legacyLayerWriter: w, info: info, layerID: layerID, path: path, diff --git a/vendor/github.com/Microsoft/hcsshim/interface.go b/vendor/github.com/Microsoft/hcsshim/interface.go index 9fc7852e41b..e21f30025ae 100644 --- a/vendor/github.com/Microsoft/hcsshim/interface.go +++ b/vendor/github.com/Microsoft/hcsshim/interface.go @@ -30,11 +30,12 @@ type Layer struct { } type MappedDir struct { - HostPath string - ContainerPath string - ReadOnly bool - BandwidthMaximum uint64 - IOPSMaximum uint64 + HostPath string + ContainerPath string + ReadOnly bool + BandwidthMaximum uint64 + IOPSMaximum uint64 + CreateInUtilityVM bool } type MappedPipe struct { diff --git a/vendor/github.com/Microsoft/hcsshim/legacy.go b/vendor/github.com/Microsoft/hcsshim/legacy.go index c7f6073ac3c..0b23b6c4d00 100644 --- a/vendor/github.com/Microsoft/hcsshim/legacy.go +++ b/vendor/github.com/Microsoft/hcsshim/legacy.go @@ -121,6 +121,16 @@ func (r *legacyLayerReader) walkUntilCancelled() error { if err != nil { return err } + + // Indirect fix for https://github.com/moby/moby/issues/32838#issuecomment-343610048. + // Handle failure from what may be a golang bug in the conversion of + // UTF16 to UTF8 in files which are left in the recycle bin. Os.Lstat + // which is called by filepath.Walk will fail when a filename contains + // unicode characters. Skip the recycle bin regardless which is goodness. + if strings.EqualFold(path, filepath.Join(r.root, `Files\$Recycle.Bin`)) && info.IsDir() { + return filepath.SkipDir + } + if path == r.root || path == filepath.Join(r.root, "tombstones.txt") || strings.HasSuffix(path, ".$wcidirs$") { return nil } @@ -326,59 +336,79 @@ func (r *legacyLayerReader) Close() error { type pendingLink struct { Path, Target string + TargetRoot *os.File +} + +type pendingDir struct { + Path string + Root *os.File } type legacyLayerWriter struct { - root string - parentRoots []string - destRoot string - currentFile *os.File - backupWriter *winio.BackupFileWriter - tombstones []string - pathFixed bool - HasUtilityVM bool - uvmDi []dirInfo - addedFiles map[string]bool - PendingLinks []pendingLink + root *os.File + destRoot *os.File + parentRoots []*os.File + currentFile *os.File + currentFileName string + currentFileRoot *os.File + backupWriter *winio.BackupFileWriter + Tombstones []string + HasUtilityVM bool + uvmDi []dirInfo + addedFiles map[string]bool + PendingLinks []pendingLink + pendingDirs []pendingDir + currentIsDir bool } // newLegacyLayerWriter returns a LayerWriter that can write the contaler layer // transport format to disk. -func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) *legacyLayerWriter { - return &legacyLayerWriter{ - root: root, - parentRoots: parentRoots, - destRoot: destRoot, - addedFiles: make(map[string]bool), +func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) (w *legacyLayerWriter, err error) { + w = &legacyLayerWriter{ + addedFiles: make(map[string]bool), } + defer func() { + if err != nil { + w.CloseRoots() + w = nil + } + }() + w.root, err = openRoot(root) + if err != nil { + return + } + w.destRoot, err = openRoot(destRoot) + if err != nil { + return + } + for _, r := range parentRoots { + f, err := openRoot(r) + if err != nil { + return w, err + } + w.parentRoots = append(w.parentRoots, f) + } + return } -func (w *legacyLayerWriter) init() error { - if !w.pathFixed { - path, err := makeLongAbsPath(w.root) - if err != nil { - return err - } - for i, p := range w.parentRoots { - w.parentRoots[i], err = makeLongAbsPath(p) - if err != nil { - return err - } - } - destPath, err := makeLongAbsPath(w.destRoot) - if err != nil { - return err - } - w.root = path - w.destRoot = destPath - w.pathFixed = true +func (w *legacyLayerWriter) CloseRoots() { + if w.root != nil { + w.root.Close() + w.root = nil } - return nil + if w.destRoot != nil { + w.destRoot.Close() + w.destRoot = nil + } + for i := range w.parentRoots { + w.parentRoots[i].Close() + } + w.parentRoots = nil } func (w *legacyLayerWriter) initUtilityVM() error { if !w.HasUtilityVM { - err := os.Mkdir(filepath.Join(w.destRoot, utilityVMPath), 0) + err := mkdirRelative(utilityVMPath, w.destRoot) if err != nil { return err } @@ -386,7 +416,7 @@ func (w *legacyLayerWriter) initUtilityVM() error { // clone the utility VM from the parent layer into this layer. Use hard // links to avoid unnecessary copying, since most of the files are // immutable. - err = cloneTree(filepath.Join(w.parentRoots[0], utilityVMFilesPath), filepath.Join(w.destRoot, utilityVMFilesPath), mutatedUtilityVMFiles) + err = cloneTree(w.parentRoots[0], w.destRoot, utilityVMFilesPath, mutatedUtilityVMFiles) if err != nil { return fmt.Errorf("cloning the parent utility VM image failed: %s", err) } @@ -395,7 +425,40 @@ func (w *legacyLayerWriter) initUtilityVM() error { return nil } -func (w *legacyLayerWriter) reset() { +func (w *legacyLayerWriter) reset() error { + if w.currentIsDir { + r := w.currentFile + br := winio.NewBackupStreamReader(r) + // Seek to the beginning of the backup stream, skipping the fileattrs + if _, err := r.Seek(4, io.SeekStart); err != nil { + return err + } + + for { + bhdr, err := br.Next() + if err == io.EOF { + // end of backupstream data + break + } + if err != nil { + return err + } + switch bhdr.Id { + case winio.BackupReparseData: + // The current file is a `.$wcidirs$` metadata file that + // describes a directory reparse point. Delete the placeholder + // directory to prevent future files being added into the + // destination of the reparse point during the ImportLayer call + if err := removeRelative(w.currentFileName, w.currentFileRoot); err != nil { + return err + } + w.pendingDirs = append(w.pendingDirs, pendingDir{Path: w.currentFileName, Root: w.currentFileRoot}) + default: + // ignore all other stream types, as we only care about directory reparse points + } + } + w.currentIsDir = false + } if w.backupWriter != nil { w.backupWriter.Close() w.backupWriter = nil @@ -403,21 +466,21 @@ func (w *legacyLayerWriter) reset() { if w.currentFile != nil { w.currentFile.Close() w.currentFile = nil + w.currentFileName = "" + w.currentFileRoot = nil } + return nil } // copyFileWithMetadata copies a file using the backup/restore APIs in order to preserve metadata -func copyFileWithMetadata(srcPath, destPath string, isDir bool) (fileInfo *winio.FileBasicInfo, err error) { - createDisposition := uint32(syscall.CREATE_NEW) - if isDir { - err = os.Mkdir(destPath, 0) - if err != nil { - return nil, err - } - createDisposition = syscall.OPEN_EXISTING - } - - src, err := openFileOrDir(srcPath, syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY, syscall.OPEN_EXISTING) +func copyFileWithMetadata(srcRoot, destRoot *os.File, subPath string, isDir bool) (fileInfo *winio.FileBasicInfo, err error) { + src, err := openRelative( + subPath, + srcRoot, + syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY, + syscall.FILE_SHARE_READ, + _FILE_OPEN, + _FILE_OPEN_REPARSE_POINT) if err != nil { return nil, err } @@ -430,7 +493,17 @@ func copyFileWithMetadata(srcPath, destPath string, isDir bool) (fileInfo *winio return nil, err } - dest, err := openFileOrDir(destPath, syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, createDisposition) + extraFlags := uint32(0) + if isDir { + extraFlags |= _FILE_DIRECTORY_FILE + } + dest, err := openRelative( + subPath, + destRoot, + syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, + syscall.FILE_SHARE_READ, + _FILE_CREATE, + extraFlags) if err != nil { return nil, err } @@ -459,39 +532,49 @@ func copyFileWithMetadata(srcPath, destPath string, isDir bool) (fileInfo *winio // cloneTree clones a directory tree using hard links. It skips hard links for // the file names in the provided map and just copies those files. -func cloneTree(srcPath, destPath string, mutatedFiles map[string]bool) error { +func cloneTree(srcRoot *os.File, destRoot *os.File, subPath string, mutatedFiles map[string]bool) error { var di []dirInfo - err := filepath.Walk(srcPath, func(srcFilePath string, info os.FileInfo, err error) error { + err := ensureNotReparsePointRelative(subPath, srcRoot) + if err != nil { + return err + } + err = filepath.Walk(filepath.Join(srcRoot.Name(), subPath), func(srcFilePath string, info os.FileInfo, err error) error { if err != nil { return err } - relPath, err := filepath.Rel(srcPath, srcFilePath) + relPath, err := filepath.Rel(srcRoot.Name(), srcFilePath) if err != nil { return err } - destFilePath := filepath.Join(destPath, relPath) + fileAttributes := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes // Directories, reparse points, and files that will be mutated during // utility VM import must be copied. All other files can be hard linked. - isReparsePoint := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 - if info.IsDir() || isReparsePoint || mutatedFiles[relPath] { - fi, err := copyFileWithMetadata(srcFilePath, destFilePath, info.IsDir()) + isReparsePoint := fileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 + // In go1.9, FileInfo.IsDir() returns false if the directory is also a symlink. + // See: https://github.com/golang/go/commit/1989921aef60c83e6f9127a8448fb5ede10e9acc + // Fixes the problem by checking syscall.FILE_ATTRIBUTE_DIRECTORY directly + isDir := fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 + + if isDir || isReparsePoint || mutatedFiles[relPath] { + fi, err := copyFileWithMetadata(srcRoot, destRoot, relPath, isDir) if err != nil { return err } - if info.IsDir() && !isReparsePoint { - di = append(di, dirInfo{path: destFilePath, fileInfo: *fi}) + if isDir && !isReparsePoint { + di = append(di, dirInfo{path: relPath, fileInfo: *fi}) } } else { - err = os.Link(srcFilePath, destFilePath) + err = linkRelative(relPath, srcRoot, relPath, destRoot) if err != nil { return err } } - // Don't recurse on reparse points. - if info.IsDir() && isReparsePoint { + // Don't recurse on reparse points in go1.8 and older. Filepath.Walk + // handles this in go1.9 and newer. + if isDir && isReparsePoint && shouldSkipDirectoryReparse { return filepath.SkipDir } @@ -501,13 +584,11 @@ func cloneTree(srcPath, destPath string, mutatedFiles map[string]bool) error { return err } - return reapplyDirectoryTimes(di) + return reapplyDirectoryTimes(destRoot, di) } func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error { - w.reset() - err := w.init() - if err != nil { + if err := w.reset(); err != nil { return err } @@ -515,6 +596,7 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro return w.initUtilityVM() } + name = filepath.Clean(name) if hasPathPrefix(name, utilityVMPath) { if !w.HasUtilityVM { return errors.New("missing UtilityVM directory") @@ -522,10 +604,9 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro if !hasPathPrefix(name, utilityVMFilesPath) && name != utilityVMFilesPath { return errors.New("invalid UtilityVM layer") } - path := filepath.Join(w.destRoot, name) - createDisposition := uint32(syscall.OPEN_EXISTING) + createDisposition := uint32(_FILE_OPEN) if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 { - st, err := os.Lstat(path) + st, err := lstatRelative(name, w.destRoot) if err != nil && !os.IsNotExist(err) { return err } @@ -533,37 +614,44 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro // Delete the existing file/directory if it is not the same type as this directory. existingAttr := st.Sys().(*syscall.Win32FileAttributeData).FileAttributes if (uint32(fileInfo.FileAttributes)^existingAttr)&(syscall.FILE_ATTRIBUTE_DIRECTORY|syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 { - if err = os.RemoveAll(path); err != nil { + if err = removeAllRelative(name, w.destRoot); err != nil { return err } st = nil } } if st == nil { - if err = os.Mkdir(path, 0); err != nil { + if err = mkdirRelative(name, w.destRoot); err != nil { return err } } if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 { - w.uvmDi = append(w.uvmDi, dirInfo{path: path, fileInfo: *fileInfo}) + w.uvmDi = append(w.uvmDi, dirInfo{path: name, fileInfo: *fileInfo}) } } else { // Overwrite any existing hard link. - err = os.Remove(path) + err := removeRelative(name, w.destRoot) if err != nil && !os.IsNotExist(err) { return err } - createDisposition = syscall.CREATE_NEW + createDisposition = _FILE_CREATE } - f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, createDisposition) + f, err := openRelative( + name, + w.destRoot, + syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, + syscall.FILE_SHARE_READ, + createDisposition, + _FILE_OPEN_REPARSE_POINT, + ) if err != nil { return err } defer func() { if f != nil { f.Close() - os.Remove(path) + removeRelative(name, w.destRoot) } }() @@ -574,28 +662,31 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro w.backupWriter = winio.NewBackupFileWriter(f, true) w.currentFile = f + w.currentFileName = name + w.currentFileRoot = w.destRoot w.addedFiles[name] = true f = nil return nil } - path := filepath.Join(w.root, name) + fname := name if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 { - err := os.Mkdir(path, 0) + err := mkdirRelative(name, w.root) if err != nil { return err } - path += ".$wcidirs$" + fname += ".$wcidirs$" + w.currentIsDir = true } - f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.CREATE_NEW) + f, err := openRelative(fname, w.root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, _FILE_CREATE, 0) if err != nil { return err } defer func() { if f != nil { f.Close() - os.Remove(path) + removeRelative(fname, w.root) } }() @@ -617,19 +708,20 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro } w.currentFile = f + w.currentFileName = name + w.currentFileRoot = w.root w.addedFiles[name] = true f = nil return nil } func (w *legacyLayerWriter) AddLink(name string, target string) error { - w.reset() - err := w.init() - if err != nil { + if err := w.reset(); err != nil { return err } - var roots []string + target = filepath.Clean(target) + var roots []*os.File if hasPathPrefix(target, filesPath) { // Look for cross-layer hard link targets in the parent layers, since // nothing is in the destination path yet. @@ -638,7 +730,7 @@ func (w *legacyLayerWriter) AddLink(name string, target string) error { // Since the utility VM is fully cloned into the destination path // already, look for cross-layer hard link targets directly in the // destination path. - roots = []string{w.destRoot} + roots = []*os.File{w.destRoot} } if roots == nil || (!hasPathPrefix(name, filesPath) && !hasPathPrefix(name, utilityVMFilesPath)) { @@ -647,12 +739,12 @@ func (w *legacyLayerWriter) AddLink(name string, target string) error { // Find to try the target of the link in a previously added file. If that // fails, search in parent layers. - var selectedRoot string + var selectedRoot *os.File if _, ok := w.addedFiles[target]; ok { selectedRoot = w.destRoot } else { for _, r := range roots { - if _, err = os.Lstat(filepath.Join(r, target)); err != nil { + if _, err := lstatRelative(target, r); err != nil { if !os.IsNotExist(err) { return err } @@ -661,22 +753,25 @@ func (w *legacyLayerWriter) AddLink(name string, target string) error { break } } - if selectedRoot == "" { + if selectedRoot == nil { return fmt.Errorf("failed to find link target for '%s' -> '%s'", name, target) } } + // The link can't be written until after the ImportLayer call. w.PendingLinks = append(w.PendingLinks, pendingLink{ - Path: filepath.Join(w.destRoot, name), - Target: filepath.Join(selectedRoot, target), + Path: name, + Target: target, + TargetRoot: selectedRoot, }) w.addedFiles[name] = true return nil } func (w *legacyLayerWriter) Remove(name string) error { + name = filepath.Clean(name) if hasPathPrefix(name, filesPath) { - w.tombstones = append(w.tombstones, name[len(filesPath)+1:]) + w.Tombstones = append(w.Tombstones, name) } else if hasPathPrefix(name, utilityVMFilesPath) { err := w.initUtilityVM() if err != nil { @@ -685,11 +780,10 @@ func (w *legacyLayerWriter) Remove(name string) error { // Make sure the path exists; os.RemoveAll will not fail if the file is // already gone, and this needs to be a fatal error for diagnostics // purposes. - path := filepath.Join(w.destRoot, name) - if _, err := os.Lstat(path); err != nil { + if _, err := lstatRelative(name, w.destRoot); err != nil { return err } - err = os.RemoveAll(path) + err = removeAllRelative(name, w.destRoot) if err != nil { return err } @@ -711,28 +805,20 @@ func (w *legacyLayerWriter) Write(b []byte) (int, error) { } func (w *legacyLayerWriter) Close() error { - w.reset() - err := w.init() - if err != nil { + if err := w.reset(); err != nil { return err } - tf, err := os.Create(filepath.Join(w.root, "tombstones.txt")) - if err != nil { + if err := removeRelative("tombstones.txt", w.root); err != nil && !os.IsNotExist(err) { return err } - defer tf.Close() - _, err = tf.Write([]byte("\xef\xbb\xbfVersion 1.0\n")) - if err != nil { - return err - } - for _, t := range w.tombstones { - _, err = tf.Write([]byte(filepath.Join(`\`, t) + "\n")) + for _, pd := range w.pendingDirs { + err := mkdirRelative(pd.Path, pd.Root) if err != nil { return err } } if w.HasUtilityVM { - err = reapplyDirectoryTimes(w.uvmDi) + err := reapplyDirectoryTimes(w.destRoot, w.uvmDi) if err != nil { return err } diff --git a/vendor/github.com/Microsoft/hcsshim/legacy18.go b/vendor/github.com/Microsoft/hcsshim/legacy18.go new file mode 100644 index 00000000000..0f593e8aba8 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/legacy18.go @@ -0,0 +1,7 @@ +// +build !go1.9 + +package hcsshim + +// Due to a bug in go1.8 and before, directory reparse points need to be skipped +// during filepath.Walk. This is fixed in go1.9 +var shouldSkipDirectoryReparse = true diff --git a/vendor/github.com/Microsoft/hcsshim/legacy19.go b/vendor/github.com/Microsoft/hcsshim/legacy19.go new file mode 100644 index 00000000000..fb0b7644fb6 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/legacy19.go @@ -0,0 +1,7 @@ +// +build go1.9 + +package hcsshim + +// Due to a bug in go1.8 and before, directory reparse points need to be skipped +// during filepath.Walk. This is fixed in go1.9 +var shouldSkipDirectoryReparse = false diff --git a/vendor/github.com/Microsoft/hcsshim/safeopen.go b/vendor/github.com/Microsoft/hcsshim/safeopen.go new file mode 100644 index 00000000000..5356456b908 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/safeopen.go @@ -0,0 +1,427 @@ +package hcsshim + +import ( + "errors" + "io" + "os" + "path/filepath" + "strings" + "syscall" + "unicode/utf16" + "unsafe" + + winio "github.com/Microsoft/go-winio" +) + +//sys ntCreateFile(handle *uintptr, accessMask uint32, oa *objectAttributes, iosb *ioStatusBlock, allocationSize *uint64, fileAttributes uint32, shareAccess uint32, createDisposition uint32, createOptions uint32, eaBuffer *byte, eaLength uint32) (status uint32) = ntdll.NtCreateFile +//sys ntSetInformationFile(handle uintptr, iosb *ioStatusBlock, information uintptr, length uint32, class uint32) (status uint32) = ntdll.NtSetInformationFile +//sys rtlNtStatusToDosError(status uint32) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb +//sys localAlloc(flags uint32, size int) (ptr uintptr) = kernel32.LocalAlloc +//sys localFree(ptr uintptr) = kernel32.LocalFree + +type ioStatusBlock struct { + Status, Information uintptr +} + +type objectAttributes struct { + Length uintptr + RootDirectory uintptr + ObjectName uintptr + Attributes uintptr + SecurityDescriptor uintptr + SecurityQoS uintptr +} + +type unicodeString struct { + Length uint16 + MaximumLength uint16 + Buffer uintptr +} + +type fileLinkInformation struct { + ReplaceIfExists bool + RootDirectory uintptr + FileNameLength uint32 + FileName [1]uint16 +} + +type fileDispositionInformationEx struct { + Flags uintptr +} + +const ( + _FileLinkInformation = 11 + _FileDispositionInformationEx = 64 + + _FILE_READ_ATTRIBUTES = 0x0080 + _FILE_WRITE_ATTRIBUTES = 0x0100 + _DELETE = 0x10000 + + _FILE_OPEN = 1 + _FILE_CREATE = 2 + + _FILE_DIRECTORY_FILE = 0x00000001 + _FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020 + _FILE_DELETE_ON_CLOSE = 0x00001000 + _FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000 + _FILE_OPEN_REPARSE_POINT = 0x00200000 + + _FILE_DISPOSITION_DELETE = 0x00000001 + + _OBJ_DONT_REPARSE = 0x1000 + + _STATUS_REPARSE_POINT_ENCOUNTERED = 0xC000050B +) + +func openRoot(path string) (*os.File, error) { + longpath, err := makeLongAbsPath(path) + if err != nil { + return nil, err + } + return winio.OpenForBackup(longpath, syscall.GENERIC_READ, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, syscall.OPEN_EXISTING) +} + +func ntRelativePath(path string) ([]uint16, error) { + path = filepath.Clean(path) + if strings.Contains(":", path) { + // Since alternate data streams must follow the file they + // are attached to, finding one here (out of order) is invalid. + return nil, errors.New("path contains invalid character `:`") + } + fspath := filepath.FromSlash(path) + if len(fspath) > 0 && fspath[0] == '\\' { + return nil, errors.New("expected relative path") + } + + path16 := utf16.Encode(([]rune)(fspath)) + if len(path16) > 32767 { + return nil, syscall.ENAMETOOLONG + } + + return path16, nil +} + +// openRelativeInternal opens a relative path from the given root, failing if +// any of the intermediate path components are reparse points. +func openRelativeInternal(path string, root *os.File, accessMask uint32, shareFlags uint32, createDisposition uint32, flags uint32) (*os.File, error) { + var ( + h uintptr + iosb ioStatusBlock + oa objectAttributes + ) + + path16, err := ntRelativePath(path) + if err != nil { + return nil, err + } + + if root == nil || root.Fd() == 0 { + return nil, errors.New("missing root directory") + } + + upathBuffer := localAlloc(0, int(unsafe.Sizeof(unicodeString{}))+len(path16)*2) + defer localFree(upathBuffer) + + upath := (*unicodeString)(unsafe.Pointer(upathBuffer)) + upath.Length = uint16(len(path16) * 2) + upath.MaximumLength = upath.Length + upath.Buffer = upathBuffer + unsafe.Sizeof(*upath) + copy((*[32768]uint16)(unsafe.Pointer(upath.Buffer))[:], path16) + + oa.Length = unsafe.Sizeof(oa) + oa.ObjectName = upathBuffer + oa.RootDirectory = uintptr(root.Fd()) + oa.Attributes = _OBJ_DONT_REPARSE + status := ntCreateFile( + &h, + accessMask|syscall.SYNCHRONIZE, + &oa, + &iosb, + nil, + 0, + shareFlags, + createDisposition, + _FILE_OPEN_FOR_BACKUP_INTENT|_FILE_SYNCHRONOUS_IO_NONALERT|flags, + nil, + 0, + ) + if status != 0 { + return nil, rtlNtStatusToDosError(status) + } + + fullPath, err := makeLongAbsPath(filepath.Join(root.Name(), path)) + if err != nil { + syscall.Close(syscall.Handle(h)) + return nil, err + } + + return os.NewFile(h, fullPath), nil +} + +// openRelative opens a relative path from the given root, failing if +// any of the intermediate path components are reparse points. +func openRelative(path string, root *os.File, accessMask uint32, shareFlags uint32, createDisposition uint32, flags uint32) (*os.File, error) { + f, err := openRelativeInternal(path, root, accessMask, shareFlags, createDisposition, flags) + if err != nil { + err = &os.PathError{Op: "open", Path: filepath.Join(root.Name(), path), Err: err} + } + return f, err +} + +// linkRelative creates a hard link from oldname to newname (relative to oldroot +// and newroot), failing if any of the intermediate path components are reparse +// points. +func linkRelative(oldname string, oldroot *os.File, newname string, newroot *os.File) error { + // Open the old file. + oldf, err := openRelativeInternal( + oldname, + oldroot, + syscall.FILE_WRITE_ATTRIBUTES, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + _FILE_OPEN, + 0, + ) + if err != nil { + return &os.LinkError{Op: "link", Old: filepath.Join(oldroot.Name(), oldname), New: filepath.Join(newroot.Name(), newname), Err: err} + } + defer oldf.Close() + + // Open the parent of the new file. + var parent *os.File + parentPath := filepath.Dir(newname) + if parentPath != "." { + parent, err = openRelativeInternal( + parentPath, + newroot, + syscall.GENERIC_READ, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + _FILE_OPEN, + _FILE_DIRECTORY_FILE) + if err != nil { + return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(newroot.Name(), newname), Err: err} + } + defer parent.Close() + + fi, err := winio.GetFileBasicInfo(parent) + if err != nil { + return err + } + if (fi.FileAttributes & syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 { + return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(newroot.Name(), newname), Err: rtlNtStatusToDosError(_STATUS_REPARSE_POINT_ENCOUNTERED)} + } + + } else { + parent = newroot + } + + // Issue an NT call to create the link. This will be safe because NT will + // not open any more directories to create the link, so it cannot walk any + // more reparse points. + newbase := filepath.Base(newname) + newbase16, err := ntRelativePath(newbase) + if err != nil { + return err + } + + size := int(unsafe.Offsetof(fileLinkInformation{}.FileName)) + len(newbase16)*2 + linkinfoBuffer := localAlloc(0, size) + defer localFree(linkinfoBuffer) + linkinfo := (*fileLinkInformation)(unsafe.Pointer(linkinfoBuffer)) + linkinfo.RootDirectory = parent.Fd() + linkinfo.FileNameLength = uint32(len(newbase16) * 2) + copy((*[32768]uint16)(unsafe.Pointer(&linkinfo.FileName[0]))[:], newbase16) + + var iosb ioStatusBlock + status := ntSetInformationFile( + oldf.Fd(), + &iosb, + linkinfoBuffer, + uint32(size), + _FileLinkInformation, + ) + if status != 0 { + return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(parent.Name(), newbase), Err: rtlNtStatusToDosError(status)} + } + + return nil +} + +// deleteOnClose marks a file to be deleted when the handle is closed. +func deleteOnClose(f *os.File) error { + disposition := fileDispositionInformationEx{Flags: _FILE_DISPOSITION_DELETE} + var iosb ioStatusBlock + status := ntSetInformationFile( + f.Fd(), + &iosb, + uintptr(unsafe.Pointer(&disposition)), + uint32(unsafe.Sizeof(disposition)), + _FileDispositionInformationEx, + ) + if status != 0 { + return rtlNtStatusToDosError(status) + } + return nil +} + +// clearReadOnly clears the readonly attribute on a file. +func clearReadOnly(f *os.File) error { + bi, err := winio.GetFileBasicInfo(f) + if err != nil { + return err + } + if bi.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY == 0 { + return nil + } + sbi := winio.FileBasicInfo{ + FileAttributes: bi.FileAttributes &^ syscall.FILE_ATTRIBUTE_READONLY, + } + if sbi.FileAttributes == 0 { + sbi.FileAttributes = syscall.FILE_ATTRIBUTE_NORMAL + } + return winio.SetFileBasicInfo(f, &sbi) +} + +// removeRelative removes a file or directory relative to a root, failing if any +// intermediate path components are reparse points. +func removeRelative(path string, root *os.File) error { + f, err := openRelativeInternal( + path, + root, + _FILE_READ_ATTRIBUTES|_FILE_WRITE_ATTRIBUTES|_DELETE, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + _FILE_OPEN, + _FILE_OPEN_REPARSE_POINT) + if err == nil { + defer f.Close() + err = deleteOnClose(f) + if err == syscall.ERROR_ACCESS_DENIED { + // Maybe the file is marked readonly. Clear the bit and retry. + clearReadOnly(f) + err = deleteOnClose(f) + } + } + if err != nil { + return &os.PathError{Op: "remove", Path: filepath.Join(root.Name(), path), Err: err} + } + return nil +} + +// removeAllRelative removes a directory tree relative to a root, failing if any +// intermediate path components are reparse points. +func removeAllRelative(path string, root *os.File) error { + fi, err := lstatRelative(path, root) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + fileAttributes := fi.Sys().(*syscall.Win32FileAttributeData).FileAttributes + if fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY == 0 || fileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 { + // If this is a reparse point, it can't have children. Simple remove will do. + err := removeRelative(path, root) + if err == nil || os.IsNotExist(err) { + return nil + } + return err + } + + // It is necessary to use os.Open as Readdirnames does not work with + // openRelative. This is safe because the above lstatrelative fails + // if the target is outside the root, and we know this is not a + // symlink from the above FILE_ATTRIBUTE_REPARSE_POINT check. + fd, err := os.Open(filepath.Join(root.Name(), path)) + if err != nil { + if os.IsNotExist(err) { + // Race. It was deleted between the Lstat and Open. + // Return nil per RemoveAll's docs. + return nil + } + return err + } + + // Remove contents & return first error. + for { + names, err1 := fd.Readdirnames(100) + for _, name := range names { + err1 := removeAllRelative(path+string(os.PathSeparator)+name, root) + if err == nil { + err = err1 + } + } + if err1 == io.EOF { + break + } + // If Readdirnames returned an error, use it. + if err == nil { + err = err1 + } + if len(names) == 0 { + break + } + } + fd.Close() + + // Remove directory. + err1 := removeRelative(path, root) + if err1 == nil || os.IsNotExist(err1) { + return nil + } + if err == nil { + err = err1 + } + return err +} + +// mkdirRelative creates a directory relative to a root, failing if any +// intermediate path components are reparse points. +func mkdirRelative(path string, root *os.File) error { + f, err := openRelativeInternal( + path, + root, + 0, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + _FILE_CREATE, + _FILE_DIRECTORY_FILE) + if err == nil { + f.Close() + } else { + err = &os.PathError{Op: "mkdir", Path: filepath.Join(root.Name(), path), Err: err} + } + return err +} + +// lstatRelative performs a stat operation on a file relative to a root, failing +// if any intermediate path components are reparse points. +func lstatRelative(path string, root *os.File) (os.FileInfo, error) { + f, err := openRelativeInternal( + path, + root, + _FILE_READ_ATTRIBUTES, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + _FILE_OPEN, + _FILE_OPEN_REPARSE_POINT) + if err != nil { + return nil, &os.PathError{Op: "stat", Path: filepath.Join(root.Name(), path), Err: err} + } + defer f.Close() + return f.Stat() +} + +// ensureNotReparsePointRelative validates that a given file (relative to a +// root) and all intermediate path components are not a reparse points. +func ensureNotReparsePointRelative(path string, root *os.File) error { + // Perform an open with OBJ_DONT_REPARSE but without specifying FILE_OPEN_REPARSE_POINT. + f, err := openRelative( + path, + root, + 0, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + _FILE_OPEN, + 0) + if err != nil { + return err + } + f.Close() + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/zhcsshim.go b/vendor/github.com/Microsoft/hcsshim/zhcsshim.go index 5d1a851ae87..5123e8d8e81 100644 --- a/vendor/github.com/Microsoft/hcsshim/zhcsshim.go +++ b/vendor/github.com/Microsoft/hcsshim/zhcsshim.go @@ -41,6 +41,8 @@ var ( modole32 = windows.NewLazySystemDLL("ole32.dll") modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll") modvmcompute = windows.NewLazySystemDLL("vmcompute.dll") + modntdll = windows.NewLazySystemDLL("ntdll.dll") + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") procSetCurrentThreadCompartmentId = modiphlpapi.NewProc("SetCurrentThreadCompartmentId") @@ -94,6 +96,11 @@ var ( procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback") procHcsModifyServiceSettings = modvmcompute.NewProc("HcsModifyServiceSettings") procHNSCall = modvmcompute.NewProc("HNSCall") + procNtCreateFile = modntdll.NewProc("NtCreateFile") + procNtSetInformationFile = modntdll.NewProc("NtSetInformationFile") + procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") + procLocalAlloc = modkernel32.NewProc("LocalAlloc") + procLocalFree = modkernel32.NewProc("LocalFree") ) func coTaskMemFree(buffer unsafe.Pointer) { @@ -1040,3 +1047,34 @@ func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16) } return } + +func ntCreateFile(handle *uintptr, accessMask uint32, oa *objectAttributes, iosb *ioStatusBlock, allocationSize *uint64, fileAttributes uint32, shareAccess uint32, createDisposition uint32, createOptions uint32, eaBuffer *byte, eaLength uint32) (status uint32) { + r0, _, _ := syscall.Syscall12(procNtCreateFile.Addr(), 11, uintptr(unsafe.Pointer(handle)), uintptr(accessMask), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(allocationSize)), uintptr(fileAttributes), uintptr(shareAccess), uintptr(createDisposition), uintptr(createOptions), uintptr(unsafe.Pointer(eaBuffer)), uintptr(eaLength), 0) + status = uint32(r0) + return +} + +func ntSetInformationFile(handle uintptr, iosb *ioStatusBlock, information uintptr, length uint32, class uint32) (status uint32) { + r0, _, _ := syscall.Syscall6(procNtSetInformationFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(information), uintptr(length), uintptr(class), 0) + status = uint32(r0) + return +} + +func rtlNtStatusToDosError(status uint32) (winerr error) { + r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) + if r0 != 0 { + winerr = syscall.Errno(r0) + } + return +} + +func localAlloc(flags uint32, size int) (ptr uintptr) { + r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(flags), uintptr(size), 0) + ptr = uintptr(r0) + return +} + +func localFree(ptr uintptr) { + syscall.Syscall(procLocalFree.Addr(), 1, uintptr(ptr), 0, 0) + return +} diff --git a/vendor/github.com/container-storage-interface/spec/lib/go/csi/v0/BUILD b/vendor/github.com/container-storage-interface/spec/lib/go/csi/v0/BUILD index a16a228e8cb..3d95ee31c1f 100644 --- a/vendor/github.com/container-storage-interface/spec/lib/go/csi/v0/BUILD +++ b/vendor/github.com/container-storage-interface/spec/lib/go/csi/v0/BUILD @@ -7,6 +7,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//vendor/github.com/golang/protobuf/proto:go_default_library", + "//vendor/github.com/golang/protobuf/ptypes/wrappers:go_default_library", "//vendor/golang.org/x/net/context:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", ], diff --git a/vendor/github.com/container-storage-interface/spec/lib/go/csi/v0/csi.pb.go b/vendor/github.com/container-storage-interface/spec/lib/go/csi/v0/csi.pb.go index 969362ff47d..612cfdd71dc 100644 --- a/vendor/github.com/container-storage-interface/spec/lib/go/csi/v0/csi.pb.go +++ b/vendor/github.com/container-storage-interface/spec/lib/go/csi/v0/csi.pb.go @@ -1,59 +1,12 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // source: csi.proto -/* -Package csi is a generated protocol buffer package. - -It is generated from these files: - csi.proto - -It has these top-level messages: - GetPluginInfoRequest - GetPluginInfoResponse - GetPluginCapabilitiesRequest - GetPluginCapabilitiesResponse - PluginCapability - ProbeRequest - ProbeResponse - CreateVolumeRequest - CreateVolumeResponse - VolumeCapability - CapacityRange - Volume - DeleteVolumeRequest - DeleteVolumeResponse - ControllerPublishVolumeRequest - ControllerPublishVolumeResponse - ControllerUnpublishVolumeRequest - ControllerUnpublishVolumeResponse - ValidateVolumeCapabilitiesRequest - ValidateVolumeCapabilitiesResponse - ListVolumesRequest - ListVolumesResponse - GetCapacityRequest - GetCapacityResponse - ControllerGetCapabilitiesRequest - ControllerGetCapabilitiesResponse - ControllerServiceCapability - NodeStageVolumeRequest - NodeStageVolumeResponse - NodeUnstageVolumeRequest - NodeUnstageVolumeResponse - NodePublishVolumeRequest - NodePublishVolumeResponse - NodeUnpublishVolumeRequest - NodeUnpublishVolumeResponse - NodeGetIdRequest - NodeGetIdResponse - NodeGetCapabilitiesRequest - NodeGetCapabilitiesResponse - NodeServiceCapability -*/ package csi import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" +import wrappers "github.com/golang/protobuf/ptypes/wrappers" import ( context "golang.org/x/net/context" @@ -84,22 +37,31 @@ const ( // attempt to invoke the REQUIRED ControllerService RPCs, as well // as specific RPCs as indicated by ControllerGetCapabilities. PluginCapability_Service_CONTROLLER_SERVICE PluginCapability_Service_Type = 1 + // ACCESSIBILITY_CONSTRAINTS indicates that the volumes for this + // plugin may not be equally accessible by all nodes in the + // cluster. The CO MUST use the topology information returned by + // CreateVolumeRequest along with the topology information + // returned by NodeGetInfo to ensure that a given volume is + // accessible from a given node when scheduling workloads. + PluginCapability_Service_ACCESSIBILITY_CONSTRAINTS PluginCapability_Service_Type = 2 ) var PluginCapability_Service_Type_name = map[int32]string{ 0: "UNKNOWN", 1: "CONTROLLER_SERVICE", + 2: "ACCESSIBILITY_CONSTRAINTS", } var PluginCapability_Service_Type_value = map[string]int32{ - "UNKNOWN": 0, - "CONTROLLER_SERVICE": 1, + "UNKNOWN": 0, + "CONTROLLER_SERVICE": 1, + "ACCESSIBILITY_CONSTRAINTS": 2, } func (x PluginCapability_Service_Type) String() string { return proto.EnumName(PluginCapability_Service_Type_name, int32(x)) } func (PluginCapability_Service_Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{4, 0, 0} + return fileDescriptor_csi_31237507707d37ec, []int{4, 0, 0} } type VolumeCapability_AccessMode_Mode int32 @@ -143,7 +105,7 @@ func (x VolumeCapability_AccessMode_Mode) String() string { return proto.EnumName(VolumeCapability_AccessMode_Mode_name, int32(x)) } func (VolumeCapability_AccessMode_Mode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{9, 2, 0} + return fileDescriptor_csi_31237507707d37ec, []int{10, 2, 0} } type ControllerServiceCapability_RPC_Type int32 @@ -154,6 +116,16 @@ const ( ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME ControllerServiceCapability_RPC_Type = 2 ControllerServiceCapability_RPC_LIST_VOLUMES ControllerServiceCapability_RPC_Type = 3 ControllerServiceCapability_RPC_GET_CAPACITY ControllerServiceCapability_RPC_Type = 4 + // Currently the only way to consume a snapshot is to create + // a volume from it. Therefore plugins supporting + // CREATE_DELETE_SNAPSHOT MUST support creating volume from + // snapshot. + ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT ControllerServiceCapability_RPC_Type = 5 + // LIST_SNAPSHOTS is NOT REQUIRED. For plugins that need to upload + // a snapshot after it is being cut, LIST_SNAPSHOTS COULD be used + // with the snapshot_id as the filter to query whether the + // uploading process is complete or not. + ControllerServiceCapability_RPC_LIST_SNAPSHOTS ControllerServiceCapability_RPC_Type = 6 ) var ControllerServiceCapability_RPC_Type_name = map[int32]string{ @@ -162,6 +134,8 @@ var ControllerServiceCapability_RPC_Type_name = map[int32]string{ 2: "PUBLISH_UNPUBLISH_VOLUME", 3: "LIST_VOLUMES", 4: "GET_CAPACITY", + 5: "CREATE_DELETE_SNAPSHOT", + 6: "LIST_SNAPSHOTS", } var ControllerServiceCapability_RPC_Type_value = map[string]int32{ "UNKNOWN": 0, @@ -169,13 +143,57 @@ var ControllerServiceCapability_RPC_Type_value = map[string]int32{ "PUBLISH_UNPUBLISH_VOLUME": 2, "LIST_VOLUMES": 3, "GET_CAPACITY": 4, + "CREATE_DELETE_SNAPSHOT": 5, + "LIST_SNAPSHOTS": 6, } func (x ControllerServiceCapability_RPC_Type) String() string { return proto.EnumName(ControllerServiceCapability_RPC_Type_name, int32(x)) } func (ControllerServiceCapability_RPC_Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{26, 0, 0} + return fileDescriptor_csi_31237507707d37ec, []int{29, 0, 0} +} + +type SnapshotStatus_Type int32 + +const ( + SnapshotStatus_UNKNOWN SnapshotStatus_Type = 0 + // A snapshot is ready for use. + SnapshotStatus_READY SnapshotStatus_Type = 1 + // A snapshot is cut and is now being uploaded. + // Some cloud providers and storage systems uploads the snapshot + // to the cloud after the snapshot is cut. During this phase, + // `thaw` can be done so the application can be running again if + // `freeze` was done before taking the snapshot. + SnapshotStatus_UPLOADING SnapshotStatus_Type = 2 + // An error occurred during the snapshot uploading process. + // This error status is specific for uploading because + // `CreateSnaphot` is a blocking call before the snapshot is + // cut and therefore it SHOULD NOT come back with an error + // status when an error occurs. Instead a gRPC error code SHALL + // be returned by `CreateSnapshot` when an error occurs before + // a snapshot is cut. + SnapshotStatus_ERROR_UPLOADING SnapshotStatus_Type = 3 +) + +var SnapshotStatus_Type_name = map[int32]string{ + 0: "UNKNOWN", + 1: "READY", + 2: "UPLOADING", + 3: "ERROR_UPLOADING", +} +var SnapshotStatus_Type_value = map[string]int32{ + "UNKNOWN": 0, + "READY": 1, + "UPLOADING": 2, + "ERROR_UPLOADING": 3, +} + +func (x SnapshotStatus_Type) String() string { + return proto.EnumName(SnapshotStatus_Type_name, int32(x)) +} +func (SnapshotStatus_Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{33, 0} } type NodeServiceCapability_RPC_Type int32 @@ -198,16 +216,38 @@ func (x NodeServiceCapability_RPC_Type) String() string { return proto.EnumName(NodeServiceCapability_RPC_Type_name, int32(x)) } func (NodeServiceCapability_RPC_Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{39, 0, 0} + return fileDescriptor_csi_31237507707d37ec, []int{50, 0, 0} } type GetPluginInfoRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *GetPluginInfoRequest) Reset() { *m = GetPluginInfoRequest{} } -func (m *GetPluginInfoRequest) String() string { return proto.CompactTextString(m) } -func (*GetPluginInfoRequest) ProtoMessage() {} -func (*GetPluginInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (m *GetPluginInfoRequest) Reset() { *m = GetPluginInfoRequest{} } +func (m *GetPluginInfoRequest) String() string { return proto.CompactTextString(m) } +func (*GetPluginInfoRequest) ProtoMessage() {} +func (*GetPluginInfoRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{0} +} +func (m *GetPluginInfoRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetPluginInfoRequest.Unmarshal(m, b) +} +func (m *GetPluginInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetPluginInfoRequest.Marshal(b, m, deterministic) +} +func (dst *GetPluginInfoRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetPluginInfoRequest.Merge(dst, src) +} +func (m *GetPluginInfoRequest) XXX_Size() int { + return xxx_messageInfo_GetPluginInfoRequest.Size(m) +} +func (m *GetPluginInfoRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetPluginInfoRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetPluginInfoRequest proto.InternalMessageInfo type GetPluginInfoResponse struct { // The name MUST follow reverse domain name notation format @@ -221,13 +261,35 @@ type GetPluginInfoResponse struct { // This field is REQUIRED. Value of this field is opaque to the CO. VendorVersion string `protobuf:"bytes,2,opt,name=vendor_version,json=vendorVersion" json:"vendor_version,omitempty"` // This field is OPTIONAL. Values are opaque to the CO. - Manifest map[string]string `protobuf:"bytes,3,rep,name=manifest" json:"manifest,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Manifest map[string]string `protobuf:"bytes,3,rep,name=manifest" json:"manifest,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *GetPluginInfoResponse) Reset() { *m = GetPluginInfoResponse{} } -func (m *GetPluginInfoResponse) String() string { return proto.CompactTextString(m) } -func (*GetPluginInfoResponse) ProtoMessage() {} -func (*GetPluginInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (m *GetPluginInfoResponse) Reset() { *m = GetPluginInfoResponse{} } +func (m *GetPluginInfoResponse) String() string { return proto.CompactTextString(m) } +func (*GetPluginInfoResponse) ProtoMessage() {} +func (*GetPluginInfoResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{1} +} +func (m *GetPluginInfoResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetPluginInfoResponse.Unmarshal(m, b) +} +func (m *GetPluginInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetPluginInfoResponse.Marshal(b, m, deterministic) +} +func (dst *GetPluginInfoResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetPluginInfoResponse.Merge(dst, src) +} +func (m *GetPluginInfoResponse) XXX_Size() int { + return xxx_messageInfo_GetPluginInfoResponse.Size(m) +} +func (m *GetPluginInfoResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetPluginInfoResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetPluginInfoResponse proto.InternalMessageInfo func (m *GetPluginInfoResponse) GetName() string { if m != nil { @@ -251,23 +313,67 @@ func (m *GetPluginInfoResponse) GetManifest() map[string]string { } type GetPluginCapabilitiesRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *GetPluginCapabilitiesRequest) Reset() { *m = GetPluginCapabilitiesRequest{} } -func (m *GetPluginCapabilitiesRequest) String() string { return proto.CompactTextString(m) } -func (*GetPluginCapabilitiesRequest) ProtoMessage() {} -func (*GetPluginCapabilitiesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (m *GetPluginCapabilitiesRequest) Reset() { *m = GetPluginCapabilitiesRequest{} } +func (m *GetPluginCapabilitiesRequest) String() string { return proto.CompactTextString(m) } +func (*GetPluginCapabilitiesRequest) ProtoMessage() {} +func (*GetPluginCapabilitiesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{2} +} +func (m *GetPluginCapabilitiesRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetPluginCapabilitiesRequest.Unmarshal(m, b) +} +func (m *GetPluginCapabilitiesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetPluginCapabilitiesRequest.Marshal(b, m, deterministic) +} +func (dst *GetPluginCapabilitiesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetPluginCapabilitiesRequest.Merge(dst, src) +} +func (m *GetPluginCapabilitiesRequest) XXX_Size() int { + return xxx_messageInfo_GetPluginCapabilitiesRequest.Size(m) +} +func (m *GetPluginCapabilitiesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetPluginCapabilitiesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetPluginCapabilitiesRequest proto.InternalMessageInfo type GetPluginCapabilitiesResponse struct { // All the capabilities that the controller service supports. This // field is OPTIONAL. - Capabilities []*PluginCapability `protobuf:"bytes,2,rep,name=capabilities" json:"capabilities,omitempty"` + Capabilities []*PluginCapability `protobuf:"bytes,2,rep,name=capabilities" json:"capabilities,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *GetPluginCapabilitiesResponse) Reset() { *m = GetPluginCapabilitiesResponse{} } -func (m *GetPluginCapabilitiesResponse) String() string { return proto.CompactTextString(m) } -func (*GetPluginCapabilitiesResponse) ProtoMessage() {} -func (*GetPluginCapabilitiesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (m *GetPluginCapabilitiesResponse) Reset() { *m = GetPluginCapabilitiesResponse{} } +func (m *GetPluginCapabilitiesResponse) String() string { return proto.CompactTextString(m) } +func (*GetPluginCapabilitiesResponse) ProtoMessage() {} +func (*GetPluginCapabilitiesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{3} +} +func (m *GetPluginCapabilitiesResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetPluginCapabilitiesResponse.Unmarshal(m, b) +} +func (m *GetPluginCapabilitiesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetPluginCapabilitiesResponse.Marshal(b, m, deterministic) +} +func (dst *GetPluginCapabilitiesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetPluginCapabilitiesResponse.Merge(dst, src) +} +func (m *GetPluginCapabilitiesResponse) XXX_Size() int { + return xxx_messageInfo_GetPluginCapabilitiesResponse.Size(m) +} +func (m *GetPluginCapabilitiesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetPluginCapabilitiesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetPluginCapabilitiesResponse proto.InternalMessageInfo func (m *GetPluginCapabilitiesResponse) GetCapabilities() []*PluginCapability { if m != nil { @@ -280,13 +386,35 @@ func (m *GetPluginCapabilitiesResponse) GetCapabilities() []*PluginCapability { type PluginCapability struct { // Types that are valid to be assigned to Type: // *PluginCapability_Service_ - Type isPluginCapability_Type `protobuf_oneof:"type"` + Type isPluginCapability_Type `protobuf_oneof:"type"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *PluginCapability) Reset() { *m = PluginCapability{} } -func (m *PluginCapability) String() string { return proto.CompactTextString(m) } -func (*PluginCapability) ProtoMessage() {} -func (*PluginCapability) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (m *PluginCapability) Reset() { *m = PluginCapability{} } +func (m *PluginCapability) String() string { return proto.CompactTextString(m) } +func (*PluginCapability) ProtoMessage() {} +func (*PluginCapability) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{4} +} +func (m *PluginCapability) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PluginCapability.Unmarshal(m, b) +} +func (m *PluginCapability) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PluginCapability.Marshal(b, m, deterministic) +} +func (dst *PluginCapability) XXX_Merge(src proto.Message) { + xxx_messageInfo_PluginCapability.Merge(dst, src) +} +func (m *PluginCapability) XXX_Size() int { + return xxx_messageInfo_PluginCapability.Size(m) +} +func (m *PluginCapability) XXX_DiscardUnknown() { + xxx_messageInfo_PluginCapability.DiscardUnknown(m) +} + +var xxx_messageInfo_PluginCapability proto.InternalMessageInfo type isPluginCapability_Type interface { isPluginCapability_Type() @@ -357,7 +485,7 @@ func _PluginCapability_OneofSizer(msg proto.Message) (n int) { switch x := m.Type.(type) { case *PluginCapability_Service_: s := proto.Size(x.Service) - n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += 1 // tag and wire n += proto.SizeVarint(uint64(s)) n += s case nil: @@ -368,13 +496,35 @@ func _PluginCapability_OneofSizer(msg proto.Message) (n int) { } type PluginCapability_Service struct { - Type PluginCapability_Service_Type `protobuf:"varint,1,opt,name=type,enum=csi.v0.PluginCapability_Service_Type" json:"type,omitempty"` + Type PluginCapability_Service_Type `protobuf:"varint,1,opt,name=type,enum=csi.v0.PluginCapability_Service_Type" json:"type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *PluginCapability_Service) Reset() { *m = PluginCapability_Service{} } -func (m *PluginCapability_Service) String() string { return proto.CompactTextString(m) } -func (*PluginCapability_Service) ProtoMessage() {} -func (*PluginCapability_Service) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4, 0} } +func (m *PluginCapability_Service) Reset() { *m = PluginCapability_Service{} } +func (m *PluginCapability_Service) String() string { return proto.CompactTextString(m) } +func (*PluginCapability_Service) ProtoMessage() {} +func (*PluginCapability_Service) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{4, 0} +} +func (m *PluginCapability_Service) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PluginCapability_Service.Unmarshal(m, b) +} +func (m *PluginCapability_Service) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PluginCapability_Service.Marshal(b, m, deterministic) +} +func (dst *PluginCapability_Service) XXX_Merge(src proto.Message) { + xxx_messageInfo_PluginCapability_Service.Merge(dst, src) +} +func (m *PluginCapability_Service) XXX_Size() int { + return xxx_messageInfo_PluginCapability_Service.Size(m) +} +func (m *PluginCapability_Service) XXX_DiscardUnknown() { + xxx_messageInfo_PluginCapability_Service.DiscardUnknown(m) +} + +var xxx_messageInfo_PluginCapability_Service proto.InternalMessageInfo func (m *PluginCapability_Service) GetType() PluginCapability_Service_Type { if m != nil { @@ -384,20 +534,92 @@ func (m *PluginCapability_Service) GetType() PluginCapability_Service_Type { } type ProbeRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *ProbeRequest) Reset() { *m = ProbeRequest{} } -func (m *ProbeRequest) String() string { return proto.CompactTextString(m) } -func (*ProbeRequest) ProtoMessage() {} -func (*ProbeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (m *ProbeRequest) Reset() { *m = ProbeRequest{} } +func (m *ProbeRequest) String() string { return proto.CompactTextString(m) } +func (*ProbeRequest) ProtoMessage() {} +func (*ProbeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{5} +} +func (m *ProbeRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ProbeRequest.Unmarshal(m, b) +} +func (m *ProbeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ProbeRequest.Marshal(b, m, deterministic) +} +func (dst *ProbeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProbeRequest.Merge(dst, src) +} +func (m *ProbeRequest) XXX_Size() int { + return xxx_messageInfo_ProbeRequest.Size(m) +} +func (m *ProbeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ProbeRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ProbeRequest proto.InternalMessageInfo type ProbeResponse struct { + // Readiness allows a plugin to report its initialization status back + // to the CO. Initialization for some plugins MAY be time consuming + // and it is important for a CO to distinguish between the following + // cases: + // + // 1) The plugin is in an unhealthy state and MAY need restarting. In + // this case a gRPC error code SHALL be returned. + // 2) The plugin is still initializing, but is otherwise perfectly + // healthy. In this case a successful response SHALL be returned + // with a readiness value of `false`. Calls to the plugin's + // Controller and/or Node services MAY fail due to an incomplete + // initialization state. + // 3) The plugin has finished initializing and is ready to service + // calls to its Controller and/or Node services. A successful + // response is returned with a readiness value of `true`. + // + // This field is OPTIONAL. If not present, the caller SHALL assume + // that the plugin is in a ready state and is accepting calls to its + // Controller and/or Node services (according to the plugin's reported + // capabilities). + Ready *wrappers.BoolValue `protobuf:"bytes,1,opt,name=ready" json:"ready,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *ProbeResponse) Reset() { *m = ProbeResponse{} } -func (m *ProbeResponse) String() string { return proto.CompactTextString(m) } -func (*ProbeResponse) ProtoMessage() {} -func (*ProbeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (m *ProbeResponse) Reset() { *m = ProbeResponse{} } +func (m *ProbeResponse) String() string { return proto.CompactTextString(m) } +func (*ProbeResponse) ProtoMessage() {} +func (*ProbeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{6} +} +func (m *ProbeResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ProbeResponse.Unmarshal(m, b) +} +func (m *ProbeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ProbeResponse.Marshal(b, m, deterministic) +} +func (dst *ProbeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProbeResponse.Merge(dst, src) +} +func (m *ProbeResponse) XXX_Size() int { + return xxx_messageInfo_ProbeResponse.Size(m) +} +func (m *ProbeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ProbeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ProbeResponse proto.InternalMessageInfo + +func (m *ProbeResponse) GetReady() *wrappers.BoolValue { + if m != nil { + return m.Ready + } + return nil +} type CreateVolumeRequest struct { // The suggested name for the storage space. This field is REQUIRED. @@ -415,10 +637,7 @@ type CreateVolumeRequest struct { // an identifier by which to refer to the newly provisioned // storage. If a storage system supports this, it can optionally // use this name as the identifier for the new volume. - Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - // This field is OPTIONAL. This allows the CO to specify the capacity - // requirement of the volume to be provisioned. If not specified, the - // Plugin MAY choose an implementation-defined capacity range. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` CapacityRange *CapacityRange `protobuf:"bytes,2,opt,name=capacity_range,json=capacityRange" json:"capacity_range,omitempty"` // The capabilities that the provisioned volume MUST have: the Plugin // MUST provision a volume that could satisfy ALL of the @@ -434,29 +653,52 @@ type CreateVolumeRequest struct { // validating these parameters. COs will treat these as opaque. Parameters map[string]string `protobuf:"bytes,4,rep,name=parameters" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Secrets required by plugin to complete volume creation request. - // A secret is a string to string map where the key identifies the - // name of the secret (e.g. "username" or "password"), and the value - // contains the secret data (e.g. "bob" or "abc123"). - // Each key MUST consist of alphanumeric characters, '-', '_' or '.'. - // Each value MUST contain a valid string. An SP MAY choose to accept - // binary (non-string) data by using a binary-to-text encoding scheme, - // like base64. - // An SP SHALL advertise the requirements for required secret keys and - // values in documentation. - // CO SHALL permit passing through the required secrets. - // A CO MAY pass the same secrets to all RPCs, therefore the keys for - // all unique secrets that an SP expects must be unique across all CSI - // operations. - // This information is sensitive and MUST be treated as such (not - // logged, etc.) by the CO. - // This field is OPTIONAL. + // This field is OPTIONAL. Refer to the `Secrets Requirements` + // section on how to use this field. ControllerCreateSecrets map[string]string `protobuf:"bytes,5,rep,name=controller_create_secrets,json=controllerCreateSecrets" json:"controller_create_secrets,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // If specified, the new volume will be pre-populated with data from + // this source. This field is OPTIONAL. + VolumeContentSource *VolumeContentSource `protobuf:"bytes,6,opt,name=volume_content_source,json=volumeContentSource" json:"volume_content_source,omitempty"` + // Specifies where (regions, zones, racks, etc.) the provisioned + // volume MUST be accessible from. + // An SP SHALL advertise the requirements for topological + // accessibility information in documentation. COs SHALL only specify + // topological accessibility information supported by the SP. + // This field is OPTIONAL. + // This field SHALL NOT be specified unless the SP has the + // ACCESSIBILITY_CONSTRAINTS plugin capability. + // If this field is not specified and the SP has the + // ACCESSIBILITY_CONSTRAINTS plugin capability, the SP MAY choose + // where the provisioned volume is accessible from. + AccessibilityRequirements *TopologyRequirement `protobuf:"bytes,7,opt,name=accessibility_requirements,json=accessibilityRequirements" json:"accessibility_requirements,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *CreateVolumeRequest) Reset() { *m = CreateVolumeRequest{} } -func (m *CreateVolumeRequest) String() string { return proto.CompactTextString(m) } -func (*CreateVolumeRequest) ProtoMessage() {} -func (*CreateVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (m *CreateVolumeRequest) Reset() { *m = CreateVolumeRequest{} } +func (m *CreateVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*CreateVolumeRequest) ProtoMessage() {} +func (*CreateVolumeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{7} +} +func (m *CreateVolumeRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CreateVolumeRequest.Unmarshal(m, b) +} +func (m *CreateVolumeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CreateVolumeRequest.Marshal(b, m, deterministic) +} +func (dst *CreateVolumeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_CreateVolumeRequest.Merge(dst, src) +} +func (m *CreateVolumeRequest) XXX_Size() int { + return xxx_messageInfo_CreateVolumeRequest.Size(m) +} +func (m *CreateVolumeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_CreateVolumeRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_CreateVolumeRequest proto.InternalMessageInfo func (m *CreateVolumeRequest) GetName() string { if m != nil { @@ -493,17 +735,209 @@ func (m *CreateVolumeRequest) GetControllerCreateSecrets() map[string]string { return nil } +func (m *CreateVolumeRequest) GetVolumeContentSource() *VolumeContentSource { + if m != nil { + return m.VolumeContentSource + } + return nil +} + +func (m *CreateVolumeRequest) GetAccessibilityRequirements() *TopologyRequirement { + if m != nil { + return m.AccessibilityRequirements + } + return nil +} + +// Specifies what source the volume will be created from. One of the +// type fields MUST be specified. +type VolumeContentSource struct { + // Types that are valid to be assigned to Type: + // *VolumeContentSource_Snapshot + Type isVolumeContentSource_Type `protobuf_oneof:"type"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *VolumeContentSource) Reset() { *m = VolumeContentSource{} } +func (m *VolumeContentSource) String() string { return proto.CompactTextString(m) } +func (*VolumeContentSource) ProtoMessage() {} +func (*VolumeContentSource) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{8} +} +func (m *VolumeContentSource) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VolumeContentSource.Unmarshal(m, b) +} +func (m *VolumeContentSource) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VolumeContentSource.Marshal(b, m, deterministic) +} +func (dst *VolumeContentSource) XXX_Merge(src proto.Message) { + xxx_messageInfo_VolumeContentSource.Merge(dst, src) +} +func (m *VolumeContentSource) XXX_Size() int { + return xxx_messageInfo_VolumeContentSource.Size(m) +} +func (m *VolumeContentSource) XXX_DiscardUnknown() { + xxx_messageInfo_VolumeContentSource.DiscardUnknown(m) +} + +var xxx_messageInfo_VolumeContentSource proto.InternalMessageInfo + +type isVolumeContentSource_Type interface { + isVolumeContentSource_Type() +} + +type VolumeContentSource_Snapshot struct { + Snapshot *VolumeContentSource_SnapshotSource `protobuf:"bytes,1,opt,name=snapshot,oneof"` +} + +func (*VolumeContentSource_Snapshot) isVolumeContentSource_Type() {} + +func (m *VolumeContentSource) GetType() isVolumeContentSource_Type { + if m != nil { + return m.Type + } + return nil +} + +func (m *VolumeContentSource) GetSnapshot() *VolumeContentSource_SnapshotSource { + if x, ok := m.GetType().(*VolumeContentSource_Snapshot); ok { + return x.Snapshot + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*VolumeContentSource) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _VolumeContentSource_OneofMarshaler, _VolumeContentSource_OneofUnmarshaler, _VolumeContentSource_OneofSizer, []interface{}{ + (*VolumeContentSource_Snapshot)(nil), + } +} + +func _VolumeContentSource_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*VolumeContentSource) + // type + switch x := m.Type.(type) { + case *VolumeContentSource_Snapshot: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Snapshot); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("VolumeContentSource.Type has unexpected type %T", x) + } + return nil +} + +func _VolumeContentSource_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*VolumeContentSource) + switch tag { + case 1: // type.snapshot + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(VolumeContentSource_SnapshotSource) + err := b.DecodeMessage(msg) + m.Type = &VolumeContentSource_Snapshot{msg} + return true, err + default: + return false, nil + } +} + +func _VolumeContentSource_OneofSizer(msg proto.Message) (n int) { + m := msg.(*VolumeContentSource) + // type + switch x := m.Type.(type) { + case *VolumeContentSource_Snapshot: + s := proto.Size(x.Snapshot) + n += 1 // tag and wire + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type VolumeContentSource_SnapshotSource struct { + // Contains identity information for the existing source snapshot. + // This field is REQUIRED. Plugin is REQUIRED to support creating + // volume from snapshot if it supports the capability + // CREATE_DELETE_SNAPSHOT. + Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *VolumeContentSource_SnapshotSource) Reset() { *m = VolumeContentSource_SnapshotSource{} } +func (m *VolumeContentSource_SnapshotSource) String() string { return proto.CompactTextString(m) } +func (*VolumeContentSource_SnapshotSource) ProtoMessage() {} +func (*VolumeContentSource_SnapshotSource) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{8, 0} +} +func (m *VolumeContentSource_SnapshotSource) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VolumeContentSource_SnapshotSource.Unmarshal(m, b) +} +func (m *VolumeContentSource_SnapshotSource) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VolumeContentSource_SnapshotSource.Marshal(b, m, deterministic) +} +func (dst *VolumeContentSource_SnapshotSource) XXX_Merge(src proto.Message) { + xxx_messageInfo_VolumeContentSource_SnapshotSource.Merge(dst, src) +} +func (m *VolumeContentSource_SnapshotSource) XXX_Size() int { + return xxx_messageInfo_VolumeContentSource_SnapshotSource.Size(m) +} +func (m *VolumeContentSource_SnapshotSource) XXX_DiscardUnknown() { + xxx_messageInfo_VolumeContentSource_SnapshotSource.DiscardUnknown(m) +} + +var xxx_messageInfo_VolumeContentSource_SnapshotSource proto.InternalMessageInfo + +func (m *VolumeContentSource_SnapshotSource) GetId() string { + if m != nil { + return m.Id + } + return "" +} + type CreateVolumeResponse struct { // Contains all attributes of the newly created volume that are // relevant to the CO along with information required by the Plugin // to uniquely identify the volume. This field is REQUIRED. - Volume *Volume `protobuf:"bytes,1,opt,name=volume" json:"volume,omitempty"` + Volume *Volume `protobuf:"bytes,1,opt,name=volume" json:"volume,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *CreateVolumeResponse) Reset() { *m = CreateVolumeResponse{} } -func (m *CreateVolumeResponse) String() string { return proto.CompactTextString(m) } -func (*CreateVolumeResponse) ProtoMessage() {} -func (*CreateVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (m *CreateVolumeResponse) Reset() { *m = CreateVolumeResponse{} } +func (m *CreateVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*CreateVolumeResponse) ProtoMessage() {} +func (*CreateVolumeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{9} +} +func (m *CreateVolumeResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CreateVolumeResponse.Unmarshal(m, b) +} +func (m *CreateVolumeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CreateVolumeResponse.Marshal(b, m, deterministic) +} +func (dst *CreateVolumeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_CreateVolumeResponse.Merge(dst, src) +} +func (m *CreateVolumeResponse) XXX_Size() int { + return xxx_messageInfo_CreateVolumeResponse.Size(m) +} +func (m *CreateVolumeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_CreateVolumeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_CreateVolumeResponse proto.InternalMessageInfo func (m *CreateVolumeResponse) GetVolume() *Volume { if m != nil { @@ -522,13 +956,35 @@ type VolumeCapability struct { // *VolumeCapability_Mount AccessType isVolumeCapability_AccessType `protobuf_oneof:"access_type"` // This is a REQUIRED field. - AccessMode *VolumeCapability_AccessMode `protobuf:"bytes,3,opt,name=access_mode,json=accessMode" json:"access_mode,omitempty"` + AccessMode *VolumeCapability_AccessMode `protobuf:"bytes,3,opt,name=access_mode,json=accessMode" json:"access_mode,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *VolumeCapability) Reset() { *m = VolumeCapability{} } -func (m *VolumeCapability) String() string { return proto.CompactTextString(m) } -func (*VolumeCapability) ProtoMessage() {} -func (*VolumeCapability) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (m *VolumeCapability) Reset() { *m = VolumeCapability{} } +func (m *VolumeCapability) String() string { return proto.CompactTextString(m) } +func (*VolumeCapability) ProtoMessage() {} +func (*VolumeCapability) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{10} +} +func (m *VolumeCapability) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VolumeCapability.Unmarshal(m, b) +} +func (m *VolumeCapability) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VolumeCapability.Marshal(b, m, deterministic) +} +func (dst *VolumeCapability) XXX_Merge(src proto.Message) { + xxx_messageInfo_VolumeCapability.Merge(dst, src) +} +func (m *VolumeCapability) XXX_Size() int { + return xxx_messageInfo_VolumeCapability.Size(m) +} +func (m *VolumeCapability) XXX_DiscardUnknown() { + xxx_messageInfo_VolumeCapability.DiscardUnknown(m) +} + +var xxx_messageInfo_VolumeCapability proto.InternalMessageInfo type isVolumeCapability_AccessType interface { isVolumeCapability_AccessType() @@ -631,12 +1087,12 @@ func _VolumeCapability_OneofSizer(msg proto.Message) (n int) { switch x := m.AccessType.(type) { case *VolumeCapability_Block: s := proto.Size(x.Block) - n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += 1 // tag and wire n += proto.SizeVarint(uint64(s)) n += s case *VolumeCapability_Mount: s := proto.Size(x.Mount) - n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += 1 // tag and wire n += proto.SizeVarint(uint64(s)) n += s case nil: @@ -648,12 +1104,34 @@ func _VolumeCapability_OneofSizer(msg proto.Message) (n int) { // Indicate that the volume will be accessed via the block device API. type VolumeCapability_BlockVolume struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *VolumeCapability_BlockVolume) Reset() { *m = VolumeCapability_BlockVolume{} } -func (m *VolumeCapability_BlockVolume) String() string { return proto.CompactTextString(m) } -func (*VolumeCapability_BlockVolume) ProtoMessage() {} -func (*VolumeCapability_BlockVolume) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9, 0} } +func (m *VolumeCapability_BlockVolume) Reset() { *m = VolumeCapability_BlockVolume{} } +func (m *VolumeCapability_BlockVolume) String() string { return proto.CompactTextString(m) } +func (*VolumeCapability_BlockVolume) ProtoMessage() {} +func (*VolumeCapability_BlockVolume) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{10, 0} +} +func (m *VolumeCapability_BlockVolume) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VolumeCapability_BlockVolume.Unmarshal(m, b) +} +func (m *VolumeCapability_BlockVolume) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VolumeCapability_BlockVolume.Marshal(b, m, deterministic) +} +func (dst *VolumeCapability_BlockVolume) XXX_Merge(src proto.Message) { + xxx_messageInfo_VolumeCapability_BlockVolume.Merge(dst, src) +} +func (m *VolumeCapability_BlockVolume) XXX_Size() int { + return xxx_messageInfo_VolumeCapability_BlockVolume.Size(m) +} +func (m *VolumeCapability_BlockVolume) XXX_DiscardUnknown() { + xxx_messageInfo_VolumeCapability_BlockVolume.DiscardUnknown(m) +} + +var xxx_messageInfo_VolumeCapability_BlockVolume proto.InternalMessageInfo // Indicate that the volume will be accessed via the filesystem API. type VolumeCapability_MountVolume struct { @@ -665,13 +1143,35 @@ type VolumeCapability_MountVolume struct { // Therefore, the CO and the Plugin MUST NOT leak this information // to untrusted entities. The total size of this repeated field // SHALL NOT exceed 4 KiB. - MountFlags []string `protobuf:"bytes,2,rep,name=mount_flags,json=mountFlags" json:"mount_flags,omitempty"` + MountFlags []string `protobuf:"bytes,2,rep,name=mount_flags,json=mountFlags" json:"mount_flags,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *VolumeCapability_MountVolume) Reset() { *m = VolumeCapability_MountVolume{} } -func (m *VolumeCapability_MountVolume) String() string { return proto.CompactTextString(m) } -func (*VolumeCapability_MountVolume) ProtoMessage() {} -func (*VolumeCapability_MountVolume) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9, 1} } +func (m *VolumeCapability_MountVolume) Reset() { *m = VolumeCapability_MountVolume{} } +func (m *VolumeCapability_MountVolume) String() string { return proto.CompactTextString(m) } +func (*VolumeCapability_MountVolume) ProtoMessage() {} +func (*VolumeCapability_MountVolume) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{10, 1} +} +func (m *VolumeCapability_MountVolume) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VolumeCapability_MountVolume.Unmarshal(m, b) +} +func (m *VolumeCapability_MountVolume) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VolumeCapability_MountVolume.Marshal(b, m, deterministic) +} +func (dst *VolumeCapability_MountVolume) XXX_Merge(src proto.Message) { + xxx_messageInfo_VolumeCapability_MountVolume.Merge(dst, src) +} +func (m *VolumeCapability_MountVolume) XXX_Size() int { + return xxx_messageInfo_VolumeCapability_MountVolume.Size(m) +} +func (m *VolumeCapability_MountVolume) XXX_DiscardUnknown() { + xxx_messageInfo_VolumeCapability_MountVolume.DiscardUnknown(m) +} + +var xxx_messageInfo_VolumeCapability_MountVolume proto.InternalMessageInfo func (m *VolumeCapability_MountVolume) GetFsType() string { if m != nil { @@ -690,13 +1190,35 @@ func (m *VolumeCapability_MountVolume) GetMountFlags() []string { // Specify how a volume can be accessed. type VolumeCapability_AccessMode struct { // This field is REQUIRED. - Mode VolumeCapability_AccessMode_Mode `protobuf:"varint,1,opt,name=mode,enum=csi.v0.VolumeCapability_AccessMode_Mode" json:"mode,omitempty"` + Mode VolumeCapability_AccessMode_Mode `protobuf:"varint,1,opt,name=mode,enum=csi.v0.VolumeCapability_AccessMode_Mode" json:"mode,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *VolumeCapability_AccessMode) Reset() { *m = VolumeCapability_AccessMode{} } -func (m *VolumeCapability_AccessMode) String() string { return proto.CompactTextString(m) } -func (*VolumeCapability_AccessMode) ProtoMessage() {} -func (*VolumeCapability_AccessMode) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9, 2} } +func (m *VolumeCapability_AccessMode) Reset() { *m = VolumeCapability_AccessMode{} } +func (m *VolumeCapability_AccessMode) String() string { return proto.CompactTextString(m) } +func (*VolumeCapability_AccessMode) ProtoMessage() {} +func (*VolumeCapability_AccessMode) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{10, 2} +} +func (m *VolumeCapability_AccessMode) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VolumeCapability_AccessMode.Unmarshal(m, b) +} +func (m *VolumeCapability_AccessMode) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VolumeCapability_AccessMode.Marshal(b, m, deterministic) +} +func (dst *VolumeCapability_AccessMode) XXX_Merge(src proto.Message) { + xxx_messageInfo_VolumeCapability_AccessMode.Merge(dst, src) +} +func (m *VolumeCapability_AccessMode) XXX_Size() int { + return xxx_messageInfo_VolumeCapability_AccessMode.Size(m) +} +func (m *VolumeCapability_AccessMode) XXX_DiscardUnknown() { + xxx_messageInfo_VolumeCapability_AccessMode.DiscardUnknown(m) +} + +var xxx_messageInfo_VolumeCapability_AccessMode proto.InternalMessageInfo func (m *VolumeCapability_AccessMode) GetMode() VolumeCapability_AccessMode_Mode { if m != nil { @@ -706,23 +1228,45 @@ func (m *VolumeCapability_AccessMode) GetMode() VolumeCapability_AccessMode_Mode } // The capacity of the storage space in bytes. To specify an exact size, -// `required_bytes` and `limit_bytes` can be set to the same value. At +// `required_bytes` and `limit_bytes` SHALL be set to the same value. At // least one of the these fields MUST be specified. type CapacityRange struct { - // Volume must be at least this big. This field is OPTIONAL. + // Volume MUST be at least this big. This field is OPTIONAL. // A value of 0 is equal to an unspecified field value. // The value of this field MUST NOT be negative. RequiredBytes int64 `protobuf:"varint,1,opt,name=required_bytes,json=requiredBytes" json:"required_bytes,omitempty"` - // Volume must not be bigger than this. This field is OPTIONAL. + // Volume MUST not be bigger than this. This field is OPTIONAL. // A value of 0 is equal to an unspecified field value. // The value of this field MUST NOT be negative. - LimitBytes int64 `protobuf:"varint,2,opt,name=limit_bytes,json=limitBytes" json:"limit_bytes,omitempty"` + LimitBytes int64 `protobuf:"varint,2,opt,name=limit_bytes,json=limitBytes" json:"limit_bytes,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *CapacityRange) Reset() { *m = CapacityRange{} } -func (m *CapacityRange) String() string { return proto.CompactTextString(m) } -func (*CapacityRange) ProtoMessage() {} -func (*CapacityRange) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (m *CapacityRange) Reset() { *m = CapacityRange{} } +func (m *CapacityRange) String() string { return proto.CompactTextString(m) } +func (*CapacityRange) ProtoMessage() {} +func (*CapacityRange) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{11} +} +func (m *CapacityRange) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CapacityRange.Unmarshal(m, b) +} +func (m *CapacityRange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CapacityRange.Marshal(b, m, deterministic) +} +func (dst *CapacityRange) XXX_Merge(src proto.Message) { + xxx_messageInfo_CapacityRange.Merge(dst, src) +} +func (m *CapacityRange) XXX_Size() int { + return xxx_messageInfo_CapacityRange.Size(m) +} +func (m *CapacityRange) XXX_DiscardUnknown() { + xxx_messageInfo_CapacityRange.DiscardUnknown(m) +} + +var xxx_messageInfo_CapacityRange proto.InternalMessageInfo func (m *CapacityRange) GetRequiredBytes() int64 { if m != nil { @@ -758,12 +1302,64 @@ type Volume struct { // the same attributes. This field is OPTIONAL and when present MUST // be passed to volume validation and publishing calls. Attributes map[string]string `protobuf:"bytes,3,rep,name=attributes" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // If specified, indicates that the volume is not empty and is + // pre-populated with data from the specified source. + // This field is OPTIONAL. + ContentSource *VolumeContentSource `protobuf:"bytes,4,opt,name=content_source,json=contentSource" json:"content_source,omitempty"` + // Specifies where (regions, zones, racks, etc.) the provisioned + // volume is accessible from. + // A plugin that returns this field MUST also set the + // ACCESSIBILITY_CONSTRAINTS plugin capability. + // An SP MAY specify multiple topologies to indicate the volume is + // accessible from multiple locations. + // COs MAY use this information along with the topology information + // returned by NodeGetInfo to ensure that a given volume is accessible + // from a given node when scheduling workloads. + // This field is OPTIONAL. If it is not specified, the CO MAY assume + // the volume is equally accessible from all nodes in the cluster and + // may schedule workloads referencing the volume on any available + // node. + // + // Example 1: + // accessible_topology = {"region": "R1", "zone": "Z2"} + // Indicates a volume accessible only from the "region" "R1" and the + // "zone" "Z2". + // + // Example 2: + // accessible_topology = + // {"region": "R1", "zone": "Z2"}, + // {"region": "R1", "zone": "Z3"} + // Indicates a volume accessible from both "zone" "Z2" and "zone" "Z3" + // in the "region" "R1". + AccessibleTopology []*Topology `protobuf:"bytes,5,rep,name=accessible_topology,json=accessibleTopology" json:"accessible_topology,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Volume) Reset() { *m = Volume{} } -func (m *Volume) String() string { return proto.CompactTextString(m) } -func (*Volume) ProtoMessage() {} -func (*Volume) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (m *Volume) Reset() { *m = Volume{} } +func (m *Volume) String() string { return proto.CompactTextString(m) } +func (*Volume) ProtoMessage() {} +func (*Volume) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{12} +} +func (m *Volume) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Volume.Unmarshal(m, b) +} +func (m *Volume) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Volume.Marshal(b, m, deterministic) +} +func (dst *Volume) XXX_Merge(src proto.Message) { + xxx_messageInfo_Volume.Merge(dst, src) +} +func (m *Volume) XXX_Size() int { + return xxx_messageInfo_Volume.Size(m) +} +func (m *Volume) XXX_DiscardUnknown() { + xxx_messageInfo_Volume.DiscardUnknown(m) +} + +var xxx_messageInfo_Volume proto.InternalMessageInfo func (m *Volume) GetCapacityBytes() int64 { if m != nil { @@ -786,34 +1382,291 @@ func (m *Volume) GetAttributes() map[string]string { return nil } +func (m *Volume) GetContentSource() *VolumeContentSource { + if m != nil { + return m.ContentSource + } + return nil +} + +func (m *Volume) GetAccessibleTopology() []*Topology { + if m != nil { + return m.AccessibleTopology + } + return nil +} + +type TopologyRequirement struct { + // Specifies the list of topologies the provisioned volume MUST be + // accessible from. + // This field is OPTIONAL. If TopologyRequirement is specified either + // requisite or preferred or both MUST be specified. + // + // If requisite is specified, the provisioned volume MUST be + // accessible from at least one of the requisite topologies. + // + // Given + // x = number of topologies provisioned volume is accessible from + // n = number of requisite topologies + // The CO MUST ensure n >= 1. The SP MUST ensure x >= 1 + // If x==n, than the SP MUST make the provisioned volume available to + // all topologies from the list of requisite topologies. If it is + // unable to do so, the SP MUST fail the CreateVolume call. + // For example, if a volume should be accessible from a single zone, + // and requisite = + // {"region": "R1", "zone": "Z2"} + // then the provisioned volume MUST be accessible from the "region" + // "R1" and the "zone" "Z2". + // Similarly, if a volume should be accessible from two zones, and + // requisite = + // {"region": "R1", "zone": "Z2"}, + // {"region": "R1", "zone": "Z3"} + // then the provisioned volume MUST be accessible from the "region" + // "R1" and both "zone" "Z2" and "zone" "Z3". + // + // If xn, than the SP MUST make the provisioned volume available from + // all topologies from the list of requisite topologies and MAY choose + // the remaining x-n unique topologies from the list of all possible + // topologies. If it is unable to do so, the SP MUST fail the + // CreateVolume call. + // For example, if a volume should be accessible from two zones, and + // requisite = + // {"region": "R1", "zone": "Z2"} + // then the provisioned volume MUST be accessible from the "region" + // "R1" and the "zone" "Z2" and the SP may select the second zone + // independently, e.g. "R1/Z4". + Requisite []*Topology `protobuf:"bytes,1,rep,name=requisite" json:"requisite,omitempty"` + // Specifies the list of topologies the CO would prefer the volume to + // be provisioned in. + // + // This field is OPTIONAL. If TopologyRequirement is specified either + // requisite or preferred or both MUST be specified. + // + // An SP MUST attempt to make the provisioned volume available using + // the preferred topologies in order from first to last. + // + // If requisite is specified, all topologies in preferred list MUST + // also be present in the list of requisite topologies. + // + // If the SP is unable to to make the provisioned volume available + // from any of the preferred topologies, the SP MAY choose a topology + // from the list of requisite topologies. + // If the list of requisite topologies is not specified, then the SP + // MAY choose from the list of all possible topologies. + // If the list of requisite topologies is specified and the SP is + // unable to to make the provisioned volume available from any of the + // requisite topologies it MUST fail the CreateVolume call. + // + // Example 1: + // Given a volume should be accessible from a single zone, and + // requisite = + // {"region": "R1", "zone": "Z2"}, + // {"region": "R1", "zone": "Z3"} + // preferred = + // {"region": "R1", "zone": "Z3"} + // then the the SP SHOULD first attempt to make the provisioned volume + // available from "zone" "Z3" in the "region" "R1" and fall back to + // "zone" "Z2" in the "region" "R1" if that is not possible. + // + // Example 2: + // Given a volume should be accessible from a single zone, and + // requisite = + // {"region": "R1", "zone": "Z2"}, + // {"region": "R1", "zone": "Z3"}, + // {"region": "R1", "zone": "Z4"}, + // {"region": "R1", "zone": "Z5"} + // preferred = + // {"region": "R1", "zone": "Z4"}, + // {"region": "R1", "zone": "Z2"} + // then the the SP SHOULD first attempt to make the provisioned volume + // accessible from "zone" "Z4" in the "region" "R1" and fall back to + // "zone" "Z2" in the "region" "R1" if that is not possible. If that + // is not possible, the SP may choose between either the "zone" + // "Z3" or "Z5" in the "region" "R1". + // + // Example 3: + // Given a volume should be accessible from TWO zones (because an + // opaque parameter in CreateVolumeRequest, for example, specifies + // the volume is accessible from two zones, aka synchronously + // replicated), and + // requisite = + // {"region": "R1", "zone": "Z2"}, + // {"region": "R1", "zone": "Z3"}, + // {"region": "R1", "zone": "Z4"}, + // {"region": "R1", "zone": "Z5"} + // preferred = + // {"region": "R1", "zone": "Z5"}, + // {"region": "R1", "zone": "Z3"} + // then the the SP SHOULD first attempt to make the provisioned volume + // accessible from the combination of the two "zones" "Z5" and "Z3" in + // the "region" "R1". If that's not possible, it should fall back to + // a combination of "Z5" and other possibilities from the list of + // requisite. If that's not possible, it should fall back to a + // combination of "Z3" and other possibilities from the list of + // requisite. If that's not possible, it should fall back to a + // combination of other possibilities from the list of requisite. + Preferred []*Topology `protobuf:"bytes,2,rep,name=preferred" json:"preferred,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TopologyRequirement) Reset() { *m = TopologyRequirement{} } +func (m *TopologyRequirement) String() string { return proto.CompactTextString(m) } +func (*TopologyRequirement) ProtoMessage() {} +func (*TopologyRequirement) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{13} +} +func (m *TopologyRequirement) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TopologyRequirement.Unmarshal(m, b) +} +func (m *TopologyRequirement) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TopologyRequirement.Marshal(b, m, deterministic) +} +func (dst *TopologyRequirement) XXX_Merge(src proto.Message) { + xxx_messageInfo_TopologyRequirement.Merge(dst, src) +} +func (m *TopologyRequirement) XXX_Size() int { + return xxx_messageInfo_TopologyRequirement.Size(m) +} +func (m *TopologyRequirement) XXX_DiscardUnknown() { + xxx_messageInfo_TopologyRequirement.DiscardUnknown(m) +} + +var xxx_messageInfo_TopologyRequirement proto.InternalMessageInfo + +func (m *TopologyRequirement) GetRequisite() []*Topology { + if m != nil { + return m.Requisite + } + return nil +} + +func (m *TopologyRequirement) GetPreferred() []*Topology { + if m != nil { + return m.Preferred + } + return nil +} + +// Topology is a map of topological domains to topological segments. +// A topological domain is a sub-division of a cluster, like "region", +// "zone", "rack", etc. +// A topological segment is a specific instance of a topological domain, +// like "zone3", "rack3", etc. +// For example {"com.company/zone": "Z1", "com.company/rack": "R3"} +// Valid keys have two segments: an optional prefix and name, separated +// by a slash (/), for example: "com.company.example/zone". +// The key name segment is required. The prefix is optional. +// Both the key name and the prefix MUST each be 63 characters or less, +// begin and end with an alphanumeric character ([a-z0-9A-Z]) and +// contain only dashes (-), underscores (_), dots (.), or alphanumerics +// in between, for example "zone". +// The key prefix MUST follow reverse domain name notation format +// (https://en.wikipedia.org/wiki/Reverse_domain_name_notation). +// The key prefix SHOULD include the plugin's host company name and/or +// the plugin name, to minimize the possibility of collisions with keys +// from other plugins. +// If a key prefix is specified, it MUST be identical across all +// topology keys returned by the SP (across all RPCs). +// Keys MUST be case-insensitive. Meaning the keys "Zone" and "zone" +// MUST not both exist. +// Each value (topological segment) MUST contain 1 or more strings. +// Each string MUST be 63 characters or less and begin and end with an +// alphanumeric character with '-', '_', '.', or alphanumerics in +// between. +type Topology struct { + Segments map[string]string `protobuf:"bytes,1,rep,name=segments" json:"segments,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Topology) Reset() { *m = Topology{} } +func (m *Topology) String() string { return proto.CompactTextString(m) } +func (*Topology) ProtoMessage() {} +func (*Topology) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{14} +} +func (m *Topology) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Topology.Unmarshal(m, b) +} +func (m *Topology) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Topology.Marshal(b, m, deterministic) +} +func (dst *Topology) XXX_Merge(src proto.Message) { + xxx_messageInfo_Topology.Merge(dst, src) +} +func (m *Topology) XXX_Size() int { + return xxx_messageInfo_Topology.Size(m) +} +func (m *Topology) XXX_DiscardUnknown() { + xxx_messageInfo_Topology.DiscardUnknown(m) +} + +var xxx_messageInfo_Topology proto.InternalMessageInfo + +func (m *Topology) GetSegments() map[string]string { + if m != nil { + return m.Segments + } + return nil +} + type DeleteVolumeRequest struct { // The ID of the volume to be deprovisioned. // This field is REQUIRED. VolumeId string `protobuf:"bytes,1,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"` // Secrets required by plugin to complete volume deletion request. - // A secret is a string to string map where the key identifies the - // name of the secret (e.g. "username" or "password"), and the value - // contains the secret data (e.g. "bob" or "abc123"). - // Each key MUST consist of alphanumeric characters, '-', '_' or '.'. - // Each value MUST contain a valid string. An SP MAY choose to accept - // binary (non-string) data by using a binary-to-text encoding scheme, - // like base64. - // An SP SHALL advertise the requirements for required secret keys and - // values in documentation. - // CO SHALL permit passing through the required secrets. - // A CO MAY pass the same secrets to all RPCs, therefore the keys for - // all unique secrets that an SP expects must be unique across all CSI - // operations. - // This information is sensitive and MUST be treated as such (not - // logged, etc.) by the CO. - // This field is OPTIONAL. + // This field is OPTIONAL. Refer to the `Secrets Requirements` + // section on how to use this field. ControllerDeleteSecrets map[string]string `protobuf:"bytes,2,rep,name=controller_delete_secrets,json=controllerDeleteSecrets" json:"controller_delete_secrets,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *DeleteVolumeRequest) Reset() { *m = DeleteVolumeRequest{} } -func (m *DeleteVolumeRequest) String() string { return proto.CompactTextString(m) } -func (*DeleteVolumeRequest) ProtoMessage() {} -func (*DeleteVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (m *DeleteVolumeRequest) Reset() { *m = DeleteVolumeRequest{} } +func (m *DeleteVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteVolumeRequest) ProtoMessage() {} +func (*DeleteVolumeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{15} +} +func (m *DeleteVolumeRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeleteVolumeRequest.Unmarshal(m, b) +} +func (m *DeleteVolumeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeleteVolumeRequest.Marshal(b, m, deterministic) +} +func (dst *DeleteVolumeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeleteVolumeRequest.Merge(dst, src) +} +func (m *DeleteVolumeRequest) XXX_Size() int { + return xxx_messageInfo_DeleteVolumeRequest.Size(m) +} +func (m *DeleteVolumeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_DeleteVolumeRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_DeleteVolumeRequest proto.InternalMessageInfo func (m *DeleteVolumeRequest) GetVolumeId() string { if m != nil { @@ -830,19 +1683,41 @@ func (m *DeleteVolumeRequest) GetControllerDeleteSecrets() map[string]string { } type DeleteVolumeResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *DeleteVolumeResponse) Reset() { *m = DeleteVolumeResponse{} } -func (m *DeleteVolumeResponse) String() string { return proto.CompactTextString(m) } -func (*DeleteVolumeResponse) ProtoMessage() {} -func (*DeleteVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (m *DeleteVolumeResponse) Reset() { *m = DeleteVolumeResponse{} } +func (m *DeleteVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteVolumeResponse) ProtoMessage() {} +func (*DeleteVolumeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{16} +} +func (m *DeleteVolumeResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeleteVolumeResponse.Unmarshal(m, b) +} +func (m *DeleteVolumeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeleteVolumeResponse.Marshal(b, m, deterministic) +} +func (dst *DeleteVolumeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeleteVolumeResponse.Merge(dst, src) +} +func (m *DeleteVolumeResponse) XXX_Size() int { + return xxx_messageInfo_DeleteVolumeResponse.Size(m) +} +func (m *DeleteVolumeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_DeleteVolumeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_DeleteVolumeResponse proto.InternalMessageInfo type ControllerPublishVolumeRequest struct { // The ID of the volume to be used on a node. // This field is REQUIRED. VolumeId string `protobuf:"bytes,1,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"` // The ID of the node. This field is REQUIRED. The CO SHALL set this - // field to match the node ID returned by `NodeGetId`. + // field to match the node ID returned by `NodeGetInfo`. NodeId string `protobuf:"bytes,2,opt,name=node_id,json=nodeId" json:"node_id,omitempty"` // The capability of the volume the CO expects the volume to have. // This is a REQUIRED field. @@ -851,34 +1726,41 @@ type ControllerPublishVolumeRequest struct { // REQUIRED. Readonly bool `protobuf:"varint,4,opt,name=readonly" json:"readonly,omitempty"` // Secrets required by plugin to complete controller publish volume - // request. - // A secret is a string to string map where the key identifies the - // name of the secret (e.g. "username" or "password"), and the value - // contains the secret data (e.g. "bob" or "abc123"). - // Each key MUST consist of alphanumeric characters, '-', '_' or '.'. - // Each value MUST contain a valid string. An SP MAY choose to accept - // binary (non-string) data by using a binary-to-text encoding scheme, - // like base64. - // An SP SHALL advertise the requirements for required secret keys and - // values in documentation. - // CO SHALL permit passing through the required secrets. - // A CO MAY pass the same secrets to all RPCs, therefore the keys for - // all unique secrets that an SP expects must be unique across all CSI - // operations. - // This information is sensitive and MUST be treated as such (not - // logged, etc.) by the CO. - // This field is OPTIONAL. + // request. This field is OPTIONAL. Refer to the + // `Secrets Requirements` section on how to use this field. ControllerPublishSecrets map[string]string `protobuf:"bytes,5,rep,name=controller_publish_secrets,json=controllerPublishSecrets" json:"controller_publish_secrets,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Attributes of the volume to be used on a node. This field is // OPTIONAL and MUST match the attributes of the Volume identified // by `volume_id`. - VolumeAttributes map[string]string `protobuf:"bytes,6,rep,name=volume_attributes,json=volumeAttributes" json:"volume_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + VolumeAttributes map[string]string `protobuf:"bytes,6,rep,name=volume_attributes,json=volumeAttributes" json:"volume_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *ControllerPublishVolumeRequest) Reset() { *m = ControllerPublishVolumeRequest{} } -func (m *ControllerPublishVolumeRequest) String() string { return proto.CompactTextString(m) } -func (*ControllerPublishVolumeRequest) ProtoMessage() {} -func (*ControllerPublishVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (m *ControllerPublishVolumeRequest) Reset() { *m = ControllerPublishVolumeRequest{} } +func (m *ControllerPublishVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*ControllerPublishVolumeRequest) ProtoMessage() {} +func (*ControllerPublishVolumeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{17} +} +func (m *ControllerPublishVolumeRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ControllerPublishVolumeRequest.Unmarshal(m, b) +} +func (m *ControllerPublishVolumeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ControllerPublishVolumeRequest.Marshal(b, m, deterministic) +} +func (dst *ControllerPublishVolumeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ControllerPublishVolumeRequest.Merge(dst, src) +} +func (m *ControllerPublishVolumeRequest) XXX_Size() int { + return xxx_messageInfo_ControllerPublishVolumeRequest.Size(m) +} +func (m *ControllerPublishVolumeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ControllerPublishVolumeRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ControllerPublishVolumeRequest proto.InternalMessageInfo func (m *ControllerPublishVolumeRequest) GetVolumeId() string { if m != nil { @@ -927,15 +1809,35 @@ type ControllerPublishVolumeResponse struct { // the subsequent `NodeStageVolume` or `NodePublishVolume` calls // for the given volume. // This information is opaque to the CO. This field is OPTIONAL. - PublishInfo map[string]string `protobuf:"bytes,1,rep,name=publish_info,json=publishInfo" json:"publish_info,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + PublishInfo map[string]string `protobuf:"bytes,1,rep,name=publish_info,json=publishInfo" json:"publish_info,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ControllerPublishVolumeResponse) Reset() { *m = ControllerPublishVolumeResponse{} } func (m *ControllerPublishVolumeResponse) String() string { return proto.CompactTextString(m) } func (*ControllerPublishVolumeResponse) ProtoMessage() {} func (*ControllerPublishVolumeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{15} + return fileDescriptor_csi_31237507707d37ec, []int{18} } +func (m *ControllerPublishVolumeResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ControllerPublishVolumeResponse.Unmarshal(m, b) +} +func (m *ControllerPublishVolumeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ControllerPublishVolumeResponse.Marshal(b, m, deterministic) +} +func (dst *ControllerPublishVolumeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ControllerPublishVolumeResponse.Merge(dst, src) +} +func (m *ControllerPublishVolumeResponse) XXX_Size() int { + return xxx_messageInfo_ControllerPublishVolumeResponse.Size(m) +} +func (m *ControllerPublishVolumeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ControllerPublishVolumeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ControllerPublishVolumeResponse proto.InternalMessageInfo func (m *ControllerPublishVolumeResponse) GetPublishInfo() map[string]string { if m != nil { @@ -948,40 +1850,45 @@ type ControllerUnpublishVolumeRequest struct { // The ID of the volume. This field is REQUIRED. VolumeId string `protobuf:"bytes,1,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"` // The ID of the node. This field is OPTIONAL. The CO SHOULD set this - // field to match the node ID returned by `NodeGetId` or leave it + // field to match the node ID returned by `NodeGetInfo` or leave it // unset. If the value is set, the SP MUST unpublish the volume from // the specified node. If the value is unset, the SP MUST unpublish // the volume from all nodes it is published to. NodeId string `protobuf:"bytes,2,opt,name=node_id,json=nodeId" json:"node_id,omitempty"` // Secrets required by plugin to complete controller unpublish volume // request. This SHOULD be the same secrets passed to the - // ControllerPublishVolume. - // call for the specified volume. - // A secret is a string to string map where the key identifies the - // name of the secret (e.g. "username" or "password"), and the value - // contains the secret data (e.g. "bob" or "abc123"). - // Each key MUST consist of alphanumeric characters, '-', '_' or '.'. - // Each value MUST contain a valid string. An SP MAY choose to accept - // binary (non-string) data by using a binary-to-text encoding scheme, - // like base64. - // An SP SHALL advertise the requirements for required secret keys and - // values in documentation. - // CO SHALL permit passing through the required secrets. - // A CO MAY pass the same secrets to all RPCs, therefore the keys for - // all unique secrets that an SP expects must be unique across all CSI - // operations. - // This information is sensitive and MUST be treated as such (not - // logged, etc.) by the CO. - // This field is OPTIONAL. + // ControllerPublishVolume call for the specified volume. + // This field is OPTIONAL. Refer to the `Secrets Requirements` + // section on how to use this field. ControllerUnpublishSecrets map[string]string `protobuf:"bytes,3,rep,name=controller_unpublish_secrets,json=controllerUnpublishSecrets" json:"controller_unpublish_secrets,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ControllerUnpublishVolumeRequest) Reset() { *m = ControllerUnpublishVolumeRequest{} } func (m *ControllerUnpublishVolumeRequest) String() string { return proto.CompactTextString(m) } func (*ControllerUnpublishVolumeRequest) ProtoMessage() {} func (*ControllerUnpublishVolumeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{16} + return fileDescriptor_csi_31237507707d37ec, []int{19} } +func (m *ControllerUnpublishVolumeRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ControllerUnpublishVolumeRequest.Unmarshal(m, b) +} +func (m *ControllerUnpublishVolumeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ControllerUnpublishVolumeRequest.Marshal(b, m, deterministic) +} +func (dst *ControllerUnpublishVolumeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ControllerUnpublishVolumeRequest.Merge(dst, src) +} +func (m *ControllerUnpublishVolumeRequest) XXX_Size() int { + return xxx_messageInfo_ControllerUnpublishVolumeRequest.Size(m) +} +func (m *ControllerUnpublishVolumeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ControllerUnpublishVolumeRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ControllerUnpublishVolumeRequest proto.InternalMessageInfo func (m *ControllerUnpublishVolumeRequest) GetVolumeId() string { if m != nil { @@ -1005,14 +1912,34 @@ func (m *ControllerUnpublishVolumeRequest) GetControllerUnpublishSecrets() map[s } type ControllerUnpublishVolumeResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ControllerUnpublishVolumeResponse) Reset() { *m = ControllerUnpublishVolumeResponse{} } func (m *ControllerUnpublishVolumeResponse) String() string { return proto.CompactTextString(m) } func (*ControllerUnpublishVolumeResponse) ProtoMessage() {} func (*ControllerUnpublishVolumeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{17} + return fileDescriptor_csi_31237507707d37ec, []int{20} } +func (m *ControllerUnpublishVolumeResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ControllerUnpublishVolumeResponse.Unmarshal(m, b) +} +func (m *ControllerUnpublishVolumeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ControllerUnpublishVolumeResponse.Marshal(b, m, deterministic) +} +func (dst *ControllerUnpublishVolumeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ControllerUnpublishVolumeResponse.Merge(dst, src) +} +func (m *ControllerUnpublishVolumeResponse) XXX_Size() int { + return xxx_messageInfo_ControllerUnpublishVolumeResponse.Size(m) +} +func (m *ControllerUnpublishVolumeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ControllerUnpublishVolumeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ControllerUnpublishVolumeResponse proto.InternalMessageInfo type ValidateVolumeCapabilitiesRequest struct { // The ID of the volume to check. This field is REQUIRED. @@ -1024,14 +1951,41 @@ type ValidateVolumeCapabilitiesRequest struct { // Attributes of the volume to check. This field is OPTIONAL and MUST // match the attributes of the Volume identified by `volume_id`. VolumeAttributes map[string]string `protobuf:"bytes,3,rep,name=volume_attributes,json=volumeAttributes" json:"volume_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Specifies where (regions, zones, racks, etc.) the caller believes + // the volume is accessible from. + // A caller MAY specify multiple topologies to indicate they believe + // the volume to be accessible from multiple locations. + // This field is OPTIONAL. This field SHALL NOT be set unless the + // plugin advertises the ACCESSIBILITY_CONSTRAINTS capability. + AccessibleTopology []*Topology `protobuf:"bytes,4,rep,name=accessible_topology,json=accessibleTopology" json:"accessible_topology,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ValidateVolumeCapabilitiesRequest) Reset() { *m = ValidateVolumeCapabilitiesRequest{} } func (m *ValidateVolumeCapabilitiesRequest) String() string { return proto.CompactTextString(m) } func (*ValidateVolumeCapabilitiesRequest) ProtoMessage() {} func (*ValidateVolumeCapabilitiesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{18} + return fileDescriptor_csi_31237507707d37ec, []int{21} } +func (m *ValidateVolumeCapabilitiesRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ValidateVolumeCapabilitiesRequest.Unmarshal(m, b) +} +func (m *ValidateVolumeCapabilitiesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ValidateVolumeCapabilitiesRequest.Marshal(b, m, deterministic) +} +func (dst *ValidateVolumeCapabilitiesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ValidateVolumeCapabilitiesRequest.Merge(dst, src) +} +func (m *ValidateVolumeCapabilitiesRequest) XXX_Size() int { + return xxx_messageInfo_ValidateVolumeCapabilitiesRequest.Size(m) +} +func (m *ValidateVolumeCapabilitiesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ValidateVolumeCapabilitiesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ValidateVolumeCapabilitiesRequest proto.InternalMessageInfo func (m *ValidateVolumeCapabilitiesRequest) GetVolumeId() string { if m != nil { @@ -1054,6 +2008,13 @@ func (m *ValidateVolumeCapabilitiesRequest) GetVolumeAttributes() map[string]str return nil } +func (m *ValidateVolumeCapabilitiesRequest) GetAccessibleTopology() []*Topology { + if m != nil { + return m.AccessibleTopology + } + return nil +} + type ValidateVolumeCapabilitiesResponse struct { // True if the Plugin supports the specified capabilities for the // given volume. This field is REQUIRED. @@ -1061,15 +2022,35 @@ type ValidateVolumeCapabilitiesResponse struct { // Message to the CO if `supported` above is false. This field is // OPTIONAL. // An empty string is equal to an unspecified field value. - Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ValidateVolumeCapabilitiesResponse) Reset() { *m = ValidateVolumeCapabilitiesResponse{} } func (m *ValidateVolumeCapabilitiesResponse) String() string { return proto.CompactTextString(m) } func (*ValidateVolumeCapabilitiesResponse) ProtoMessage() {} func (*ValidateVolumeCapabilitiesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{19} + return fileDescriptor_csi_31237507707d37ec, []int{22} } +func (m *ValidateVolumeCapabilitiesResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ValidateVolumeCapabilitiesResponse.Unmarshal(m, b) +} +func (m *ValidateVolumeCapabilitiesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ValidateVolumeCapabilitiesResponse.Marshal(b, m, deterministic) +} +func (dst *ValidateVolumeCapabilitiesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ValidateVolumeCapabilitiesResponse.Merge(dst, src) +} +func (m *ValidateVolumeCapabilitiesResponse) XXX_Size() int { + return xxx_messageInfo_ValidateVolumeCapabilitiesResponse.Size(m) +} +func (m *ValidateVolumeCapabilitiesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ValidateVolumeCapabilitiesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ValidateVolumeCapabilitiesResponse proto.InternalMessageInfo func (m *ValidateVolumeCapabilitiesResponse) GetSupported() bool { if m != nil { @@ -1099,13 +2080,35 @@ type ListVolumesRequest struct { // `next_token` returned by a previous `ListVolumes` call to get the // next page of entries. This field is OPTIONAL. // An empty string is equal to an unspecified field value. - StartingToken string `protobuf:"bytes,2,opt,name=starting_token,json=startingToken" json:"starting_token,omitempty"` + StartingToken string `protobuf:"bytes,2,opt,name=starting_token,json=startingToken" json:"starting_token,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *ListVolumesRequest) Reset() { *m = ListVolumesRequest{} } -func (m *ListVolumesRequest) String() string { return proto.CompactTextString(m) } -func (*ListVolumesRequest) ProtoMessage() {} -func (*ListVolumesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (m *ListVolumesRequest) Reset() { *m = ListVolumesRequest{} } +func (m *ListVolumesRequest) String() string { return proto.CompactTextString(m) } +func (*ListVolumesRequest) ProtoMessage() {} +func (*ListVolumesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{23} +} +func (m *ListVolumesRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListVolumesRequest.Unmarshal(m, b) +} +func (m *ListVolumesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListVolumesRequest.Marshal(b, m, deterministic) +} +func (dst *ListVolumesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListVolumesRequest.Merge(dst, src) +} +func (m *ListVolumesRequest) XXX_Size() int { + return xxx_messageInfo_ListVolumesRequest.Size(m) +} +func (m *ListVolumesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListVolumesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ListVolumesRequest proto.InternalMessageInfo func (m *ListVolumesRequest) GetMaxEntries() int32 { if m != nil { @@ -1129,13 +2132,35 @@ type ListVolumesResponse struct { // `starting_token` field in the next `ListVolumes` request. This // field is OPTIONAL. // An empty string is equal to an unspecified field value. - NextToken string `protobuf:"bytes,2,opt,name=next_token,json=nextToken" json:"next_token,omitempty"` + NextToken string `protobuf:"bytes,2,opt,name=next_token,json=nextToken" json:"next_token,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *ListVolumesResponse) Reset() { *m = ListVolumesResponse{} } -func (m *ListVolumesResponse) String() string { return proto.CompactTextString(m) } -func (*ListVolumesResponse) ProtoMessage() {} -func (*ListVolumesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (m *ListVolumesResponse) Reset() { *m = ListVolumesResponse{} } +func (m *ListVolumesResponse) String() string { return proto.CompactTextString(m) } +func (*ListVolumesResponse) ProtoMessage() {} +func (*ListVolumesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{24} +} +func (m *ListVolumesResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListVolumesResponse.Unmarshal(m, b) +} +func (m *ListVolumesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListVolumesResponse.Marshal(b, m, deterministic) +} +func (dst *ListVolumesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListVolumesResponse.Merge(dst, src) +} +func (m *ListVolumesResponse) XXX_Size() int { + return xxx_messageInfo_ListVolumesResponse.Size(m) +} +func (m *ListVolumesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ListVolumesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ListVolumesResponse proto.InternalMessageInfo func (m *ListVolumesResponse) GetEntries() []*ListVolumesResponse_Entry { if m != nil { @@ -1152,13 +2177,35 @@ func (m *ListVolumesResponse) GetNextToken() string { } type ListVolumesResponse_Entry struct { - Volume *Volume `protobuf:"bytes,1,opt,name=volume" json:"volume,omitempty"` + Volume *Volume `protobuf:"bytes,1,opt,name=volume" json:"volume,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *ListVolumesResponse_Entry) Reset() { *m = ListVolumesResponse_Entry{} } -func (m *ListVolumesResponse_Entry) String() string { return proto.CompactTextString(m) } -func (*ListVolumesResponse_Entry) ProtoMessage() {} -func (*ListVolumesResponse_Entry) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21, 0} } +func (m *ListVolumesResponse_Entry) Reset() { *m = ListVolumesResponse_Entry{} } +func (m *ListVolumesResponse_Entry) String() string { return proto.CompactTextString(m) } +func (*ListVolumesResponse_Entry) ProtoMessage() {} +func (*ListVolumesResponse_Entry) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{24, 0} +} +func (m *ListVolumesResponse_Entry) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListVolumesResponse_Entry.Unmarshal(m, b) +} +func (m *ListVolumesResponse_Entry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListVolumesResponse_Entry.Marshal(b, m, deterministic) +} +func (dst *ListVolumesResponse_Entry) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListVolumesResponse_Entry.Merge(dst, src) +} +func (m *ListVolumesResponse_Entry) XXX_Size() int { + return xxx_messageInfo_ListVolumesResponse_Entry.Size(m) +} +func (m *ListVolumesResponse_Entry) XXX_DiscardUnknown() { + xxx_messageInfo_ListVolumesResponse_Entry.DiscardUnknown(m) +} + +var xxx_messageInfo_ListVolumesResponse_Entry proto.InternalMessageInfo func (m *ListVolumesResponse_Entry) GetVolume() *Volume { if m != nil { @@ -1179,12 +2226,41 @@ type GetCapacityRequest struct { // specific `parameters`. These are the same `parameters` the CO will // use in `CreateVolumeRequest`. This field is OPTIONAL. Parameters map[string]string `protobuf:"bytes,2,rep,name=parameters" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // If specified, the Plugin SHALL report the capacity of the storage + // that can be used to provision volumes that in the specified + // `accessible_topology`. This is the same as the + // `accessible_topology` the CO returns in a `CreateVolumeResponse`. + // This field is OPTIONAL. This field SHALL NOT be set unless the + // plugin advertises the ACCESSIBILITY_CONSTRAINTS capability. + AccessibleTopology *Topology `protobuf:"bytes,3,opt,name=accessible_topology,json=accessibleTopology" json:"accessible_topology,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *GetCapacityRequest) Reset() { *m = GetCapacityRequest{} } -func (m *GetCapacityRequest) String() string { return proto.CompactTextString(m) } -func (*GetCapacityRequest) ProtoMessage() {} -func (*GetCapacityRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } +func (m *GetCapacityRequest) Reset() { *m = GetCapacityRequest{} } +func (m *GetCapacityRequest) String() string { return proto.CompactTextString(m) } +func (*GetCapacityRequest) ProtoMessage() {} +func (*GetCapacityRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{25} +} +func (m *GetCapacityRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetCapacityRequest.Unmarshal(m, b) +} +func (m *GetCapacityRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetCapacityRequest.Marshal(b, m, deterministic) +} +func (dst *GetCapacityRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetCapacityRequest.Merge(dst, src) +} +func (m *GetCapacityRequest) XXX_Size() int { + return xxx_messageInfo_GetCapacityRequest.Size(m) +} +func (m *GetCapacityRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetCapacityRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetCapacityRequest proto.InternalMessageInfo func (m *GetCapacityRequest) GetVolumeCapabilities() []*VolumeCapability { if m != nil { @@ -1200,20 +2276,49 @@ func (m *GetCapacityRequest) GetParameters() map[string]string { return nil } +func (m *GetCapacityRequest) GetAccessibleTopology() *Topology { + if m != nil { + return m.AccessibleTopology + } + return nil +} + type GetCapacityResponse struct { - // The available capacity of the storage that can be used to - // provision volumes. If `volume_capabilities` or `parameters` is + // The available capacity, in bytes, of the storage that can be used + // to provision volumes. If `volume_capabilities` or `parameters` is // specified in the request, the Plugin SHALL take those into // consideration when calculating the available capacity of the // storage. This field is REQUIRED. // The value of this field MUST NOT be negative. - AvailableCapacity int64 `protobuf:"varint,1,opt,name=available_capacity,json=availableCapacity" json:"available_capacity,omitempty"` + AvailableCapacity int64 `protobuf:"varint,1,opt,name=available_capacity,json=availableCapacity" json:"available_capacity,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *GetCapacityResponse) Reset() { *m = GetCapacityResponse{} } -func (m *GetCapacityResponse) String() string { return proto.CompactTextString(m) } -func (*GetCapacityResponse) ProtoMessage() {} -func (*GetCapacityResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } +func (m *GetCapacityResponse) Reset() { *m = GetCapacityResponse{} } +func (m *GetCapacityResponse) String() string { return proto.CompactTextString(m) } +func (*GetCapacityResponse) ProtoMessage() {} +func (*GetCapacityResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{26} +} +func (m *GetCapacityResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetCapacityResponse.Unmarshal(m, b) +} +func (m *GetCapacityResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetCapacityResponse.Marshal(b, m, deterministic) +} +func (dst *GetCapacityResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetCapacityResponse.Merge(dst, src) +} +func (m *GetCapacityResponse) XXX_Size() int { + return xxx_messageInfo_GetCapacityResponse.Size(m) +} +func (m *GetCapacityResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetCapacityResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetCapacityResponse proto.InternalMessageInfo func (m *GetCapacityResponse) GetAvailableCapacity() int64 { if m != nil { @@ -1223,27 +2328,67 @@ func (m *GetCapacityResponse) GetAvailableCapacity() int64 { } type ControllerGetCapabilitiesRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ControllerGetCapabilitiesRequest) Reset() { *m = ControllerGetCapabilitiesRequest{} } func (m *ControllerGetCapabilitiesRequest) String() string { return proto.CompactTextString(m) } func (*ControllerGetCapabilitiesRequest) ProtoMessage() {} func (*ControllerGetCapabilitiesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{24} + return fileDescriptor_csi_31237507707d37ec, []int{27} } +func (m *ControllerGetCapabilitiesRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ControllerGetCapabilitiesRequest.Unmarshal(m, b) +} +func (m *ControllerGetCapabilitiesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ControllerGetCapabilitiesRequest.Marshal(b, m, deterministic) +} +func (dst *ControllerGetCapabilitiesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ControllerGetCapabilitiesRequest.Merge(dst, src) +} +func (m *ControllerGetCapabilitiesRequest) XXX_Size() int { + return xxx_messageInfo_ControllerGetCapabilitiesRequest.Size(m) +} +func (m *ControllerGetCapabilitiesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ControllerGetCapabilitiesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ControllerGetCapabilitiesRequest proto.InternalMessageInfo type ControllerGetCapabilitiesResponse struct { // All the capabilities that the controller service supports. This // field is OPTIONAL. - Capabilities []*ControllerServiceCapability `protobuf:"bytes,2,rep,name=capabilities" json:"capabilities,omitempty"` + Capabilities []*ControllerServiceCapability `protobuf:"bytes,2,rep,name=capabilities" json:"capabilities,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ControllerGetCapabilitiesResponse) Reset() { *m = ControllerGetCapabilitiesResponse{} } func (m *ControllerGetCapabilitiesResponse) String() string { return proto.CompactTextString(m) } func (*ControllerGetCapabilitiesResponse) ProtoMessage() {} func (*ControllerGetCapabilitiesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{25} + return fileDescriptor_csi_31237507707d37ec, []int{28} } +func (m *ControllerGetCapabilitiesResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ControllerGetCapabilitiesResponse.Unmarshal(m, b) +} +func (m *ControllerGetCapabilitiesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ControllerGetCapabilitiesResponse.Marshal(b, m, deterministic) +} +func (dst *ControllerGetCapabilitiesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ControllerGetCapabilitiesResponse.Merge(dst, src) +} +func (m *ControllerGetCapabilitiesResponse) XXX_Size() int { + return xxx_messageInfo_ControllerGetCapabilitiesResponse.Size(m) +} +func (m *ControllerGetCapabilitiesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ControllerGetCapabilitiesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ControllerGetCapabilitiesResponse proto.InternalMessageInfo func (m *ControllerGetCapabilitiesResponse) GetCapabilities() []*ControllerServiceCapability { if m != nil { @@ -1256,13 +2401,35 @@ func (m *ControllerGetCapabilitiesResponse) GetCapabilities() []*ControllerServi type ControllerServiceCapability struct { // Types that are valid to be assigned to Type: // *ControllerServiceCapability_Rpc - Type isControllerServiceCapability_Type `protobuf_oneof:"type"` + Type isControllerServiceCapability_Type `protobuf_oneof:"type"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *ControllerServiceCapability) Reset() { *m = ControllerServiceCapability{} } -func (m *ControllerServiceCapability) String() string { return proto.CompactTextString(m) } -func (*ControllerServiceCapability) ProtoMessage() {} -func (*ControllerServiceCapability) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } +func (m *ControllerServiceCapability) Reset() { *m = ControllerServiceCapability{} } +func (m *ControllerServiceCapability) String() string { return proto.CompactTextString(m) } +func (*ControllerServiceCapability) ProtoMessage() {} +func (*ControllerServiceCapability) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{29} +} +func (m *ControllerServiceCapability) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ControllerServiceCapability.Unmarshal(m, b) +} +func (m *ControllerServiceCapability) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ControllerServiceCapability.Marshal(b, m, deterministic) +} +func (dst *ControllerServiceCapability) XXX_Merge(src proto.Message) { + xxx_messageInfo_ControllerServiceCapability.Merge(dst, src) +} +func (m *ControllerServiceCapability) XXX_Size() int { + return xxx_messageInfo_ControllerServiceCapability.Size(m) +} +func (m *ControllerServiceCapability) XXX_DiscardUnknown() { + xxx_messageInfo_ControllerServiceCapability.DiscardUnknown(m) +} + +var xxx_messageInfo_ControllerServiceCapability proto.InternalMessageInfo type isControllerServiceCapability_Type interface { isControllerServiceCapability_Type() @@ -1333,7 +2500,7 @@ func _ControllerServiceCapability_OneofSizer(msg proto.Message) (n int) { switch x := m.Type.(type) { case *ControllerServiceCapability_Rpc: s := proto.Size(x.Rpc) - n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += 1 // tag and wire n += proto.SizeVarint(uint64(s)) n += s case nil: @@ -1344,15 +2511,35 @@ func _ControllerServiceCapability_OneofSizer(msg proto.Message) (n int) { } type ControllerServiceCapability_RPC struct { - Type ControllerServiceCapability_RPC_Type `protobuf:"varint,1,opt,name=type,enum=csi.v0.ControllerServiceCapability_RPC_Type" json:"type,omitempty"` + Type ControllerServiceCapability_RPC_Type `protobuf:"varint,1,opt,name=type,enum=csi.v0.ControllerServiceCapability_RPC_Type" json:"type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ControllerServiceCapability_RPC) Reset() { *m = ControllerServiceCapability_RPC{} } func (m *ControllerServiceCapability_RPC) String() string { return proto.CompactTextString(m) } func (*ControllerServiceCapability_RPC) ProtoMessage() {} func (*ControllerServiceCapability_RPC) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{26, 0} + return fileDescriptor_csi_31237507707d37ec, []int{29, 0} } +func (m *ControllerServiceCapability_RPC) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ControllerServiceCapability_RPC.Unmarshal(m, b) +} +func (m *ControllerServiceCapability_RPC) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ControllerServiceCapability_RPC.Marshal(b, m, deterministic) +} +func (dst *ControllerServiceCapability_RPC) XXX_Merge(src proto.Message) { + xxx_messageInfo_ControllerServiceCapability_RPC.Merge(dst, src) +} +func (m *ControllerServiceCapability_RPC) XXX_Size() int { + return xxx_messageInfo_ControllerServiceCapability_RPC.Size(m) +} +func (m *ControllerServiceCapability_RPC) XXX_DiscardUnknown() { + xxx_messageInfo_ControllerServiceCapability_RPC.DiscardUnknown(m) +} + +var xxx_messageInfo_ControllerServiceCapability_RPC proto.InternalMessageInfo func (m *ControllerServiceCapability_RPC) GetType() ControllerServiceCapability_RPC_Type { if m != nil { @@ -1361,6 +2548,520 @@ func (m *ControllerServiceCapability_RPC) GetType() ControllerServiceCapability_ return ControllerServiceCapability_RPC_UNKNOWN } +type CreateSnapshotRequest struct { + // The ID of the source volume to be snapshotted. + // This field is REQUIRED. + SourceVolumeId string `protobuf:"bytes,1,opt,name=source_volume_id,json=sourceVolumeId" json:"source_volume_id,omitempty"` + // The suggested name for the snapshot. This field is REQUIRED for + // idempotency. + Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` + // Secrets required by plugin to complete snapshot creation request. + // This field is OPTIONAL. Refer to the `Secrets Requirements` + // section on how to use this field. + CreateSnapshotSecrets map[string]string `protobuf:"bytes,3,rep,name=create_snapshot_secrets,json=createSnapshotSecrets" json:"create_snapshot_secrets,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Plugin specific parameters passed in as opaque key-value pairs. + // This field is OPTIONAL. The Plugin is responsible for parsing and + // validating these parameters. COs will treat these as opaque. + // Use cases for opaque parameters: + // - Specify a policy to automatically clean up the snapshot. + // - Specify an expiration date for the snapshot. + // - Specify whether the snapshot is readonly or read/write. + // - Specify if the snapshot should be replicated to some place. + // - Specify primary or secondary for replication systems that + // support snapshotting only on primary. + Parameters map[string]string `protobuf:"bytes,4,rep,name=parameters" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CreateSnapshotRequest) Reset() { *m = CreateSnapshotRequest{} } +func (m *CreateSnapshotRequest) String() string { return proto.CompactTextString(m) } +func (*CreateSnapshotRequest) ProtoMessage() {} +func (*CreateSnapshotRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{30} +} +func (m *CreateSnapshotRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CreateSnapshotRequest.Unmarshal(m, b) +} +func (m *CreateSnapshotRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CreateSnapshotRequest.Marshal(b, m, deterministic) +} +func (dst *CreateSnapshotRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_CreateSnapshotRequest.Merge(dst, src) +} +func (m *CreateSnapshotRequest) XXX_Size() int { + return xxx_messageInfo_CreateSnapshotRequest.Size(m) +} +func (m *CreateSnapshotRequest) XXX_DiscardUnknown() { + xxx_messageInfo_CreateSnapshotRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_CreateSnapshotRequest proto.InternalMessageInfo + +func (m *CreateSnapshotRequest) GetSourceVolumeId() string { + if m != nil { + return m.SourceVolumeId + } + return "" +} + +func (m *CreateSnapshotRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *CreateSnapshotRequest) GetCreateSnapshotSecrets() map[string]string { + if m != nil { + return m.CreateSnapshotSecrets + } + return nil +} + +func (m *CreateSnapshotRequest) GetParameters() map[string]string { + if m != nil { + return m.Parameters + } + return nil +} + +type CreateSnapshotResponse struct { + // Contains all attributes of the newly created snapshot that are + // relevant to the CO along with information required by the Plugin + // to uniquely identify the snapshot. This field is REQUIRED. + Snapshot *Snapshot `protobuf:"bytes,1,opt,name=snapshot" json:"snapshot,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CreateSnapshotResponse) Reset() { *m = CreateSnapshotResponse{} } +func (m *CreateSnapshotResponse) String() string { return proto.CompactTextString(m) } +func (*CreateSnapshotResponse) ProtoMessage() {} +func (*CreateSnapshotResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{31} +} +func (m *CreateSnapshotResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CreateSnapshotResponse.Unmarshal(m, b) +} +func (m *CreateSnapshotResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CreateSnapshotResponse.Marshal(b, m, deterministic) +} +func (dst *CreateSnapshotResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_CreateSnapshotResponse.Merge(dst, src) +} +func (m *CreateSnapshotResponse) XXX_Size() int { + return xxx_messageInfo_CreateSnapshotResponse.Size(m) +} +func (m *CreateSnapshotResponse) XXX_DiscardUnknown() { + xxx_messageInfo_CreateSnapshotResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_CreateSnapshotResponse proto.InternalMessageInfo + +func (m *CreateSnapshotResponse) GetSnapshot() *Snapshot { + if m != nil { + return m.Snapshot + } + return nil +} + +// The information about a provisioned snapshot. +type Snapshot struct { + // This is the complete size of the snapshot in bytes. The purpose of + // this field is to give CO guidance on how much space is needed to + // create a volume from this snapshot. The size of the volume MUST NOT + // be less than the size of the source snapshot. This field is + // OPTIONAL. If this field is not set, it indicates that this size is + // unknown. The value of this field MUST NOT be negative and a size of + // zero means it is unspecified. + SizeBytes int64 `protobuf:"varint,1,opt,name=size_bytes,json=sizeBytes" json:"size_bytes,omitempty"` + // Uniquely identifies a snapshot and is generated by the plugin. It + // will not change over time. This field is REQUIRED. The identity + // information will be used by the CO in subsequent calls to refer to + // the provisioned snapshot. + Id string `protobuf:"bytes,2,opt,name=id" json:"id,omitempty"` + // Identity information for the source volume. Note that creating a + // snapshot from a snapshot is not supported here so the source has to + // be a volume. This field is REQUIRED. + SourceVolumeId string `protobuf:"bytes,3,opt,name=source_volume_id,json=sourceVolumeId" json:"source_volume_id,omitempty"` + // Timestamp when the point-in-time snapshot is taken on the storage + // system. The format of this field should be a Unix nanoseconds time + // encoded as an int64. On Unix, the command `date +%s%N` returns the + // current time in nanoseconds since 1970-01-01 00:00:00 UTC. This + // field is REQUIRED. + CreatedAt int64 `protobuf:"varint,4,opt,name=created_at,json=createdAt" json:"created_at,omitempty"` + // The status of a snapshot. + Status *SnapshotStatus `protobuf:"bytes,5,opt,name=status" json:"status,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Snapshot) Reset() { *m = Snapshot{} } +func (m *Snapshot) String() string { return proto.CompactTextString(m) } +func (*Snapshot) ProtoMessage() {} +func (*Snapshot) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{32} +} +func (m *Snapshot) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Snapshot.Unmarshal(m, b) +} +func (m *Snapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Snapshot.Marshal(b, m, deterministic) +} +func (dst *Snapshot) XXX_Merge(src proto.Message) { + xxx_messageInfo_Snapshot.Merge(dst, src) +} +func (m *Snapshot) XXX_Size() int { + return xxx_messageInfo_Snapshot.Size(m) +} +func (m *Snapshot) XXX_DiscardUnknown() { + xxx_messageInfo_Snapshot.DiscardUnknown(m) +} + +var xxx_messageInfo_Snapshot proto.InternalMessageInfo + +func (m *Snapshot) GetSizeBytes() int64 { + if m != nil { + return m.SizeBytes + } + return 0 +} + +func (m *Snapshot) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *Snapshot) GetSourceVolumeId() string { + if m != nil { + return m.SourceVolumeId + } + return "" +} + +func (m *Snapshot) GetCreatedAt() int64 { + if m != nil { + return m.CreatedAt + } + return 0 +} + +func (m *Snapshot) GetStatus() *SnapshotStatus { + if m != nil { + return m.Status + } + return nil +} + +// The status of a snapshot. +type SnapshotStatus struct { + // This field is REQUIRED. + Type SnapshotStatus_Type `protobuf:"varint,1,opt,name=type,enum=csi.v0.SnapshotStatus_Type" json:"type,omitempty"` + // Additional information to describe why a snapshot ended up in the + // `ERROR_UPLOADING` status. This field is OPTIONAL. + Details string `protobuf:"bytes,2,opt,name=details" json:"details,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SnapshotStatus) Reset() { *m = SnapshotStatus{} } +func (m *SnapshotStatus) String() string { return proto.CompactTextString(m) } +func (*SnapshotStatus) ProtoMessage() {} +func (*SnapshotStatus) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{33} +} +func (m *SnapshotStatus) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SnapshotStatus.Unmarshal(m, b) +} +func (m *SnapshotStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SnapshotStatus.Marshal(b, m, deterministic) +} +func (dst *SnapshotStatus) XXX_Merge(src proto.Message) { + xxx_messageInfo_SnapshotStatus.Merge(dst, src) +} +func (m *SnapshotStatus) XXX_Size() int { + return xxx_messageInfo_SnapshotStatus.Size(m) +} +func (m *SnapshotStatus) XXX_DiscardUnknown() { + xxx_messageInfo_SnapshotStatus.DiscardUnknown(m) +} + +var xxx_messageInfo_SnapshotStatus proto.InternalMessageInfo + +func (m *SnapshotStatus) GetType() SnapshotStatus_Type { + if m != nil { + return m.Type + } + return SnapshotStatus_UNKNOWN +} + +func (m *SnapshotStatus) GetDetails() string { + if m != nil { + return m.Details + } + return "" +} + +type DeleteSnapshotRequest struct { + // The ID of the snapshot to be deleted. + // This field is REQUIRED. + SnapshotId string `protobuf:"bytes,1,opt,name=snapshot_id,json=snapshotId" json:"snapshot_id,omitempty"` + // Secrets required by plugin to complete snapshot deletion request. + // This field is OPTIONAL. Refer to the `Secrets Requirements` + // section on how to use this field. + DeleteSnapshotSecrets map[string]string `protobuf:"bytes,2,rep,name=delete_snapshot_secrets,json=deleteSnapshotSecrets" json:"delete_snapshot_secrets,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeleteSnapshotRequest) Reset() { *m = DeleteSnapshotRequest{} } +func (m *DeleteSnapshotRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteSnapshotRequest) ProtoMessage() {} +func (*DeleteSnapshotRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{34} +} +func (m *DeleteSnapshotRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeleteSnapshotRequest.Unmarshal(m, b) +} +func (m *DeleteSnapshotRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeleteSnapshotRequest.Marshal(b, m, deterministic) +} +func (dst *DeleteSnapshotRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeleteSnapshotRequest.Merge(dst, src) +} +func (m *DeleteSnapshotRequest) XXX_Size() int { + return xxx_messageInfo_DeleteSnapshotRequest.Size(m) +} +func (m *DeleteSnapshotRequest) XXX_DiscardUnknown() { + xxx_messageInfo_DeleteSnapshotRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_DeleteSnapshotRequest proto.InternalMessageInfo + +func (m *DeleteSnapshotRequest) GetSnapshotId() string { + if m != nil { + return m.SnapshotId + } + return "" +} + +func (m *DeleteSnapshotRequest) GetDeleteSnapshotSecrets() map[string]string { + if m != nil { + return m.DeleteSnapshotSecrets + } + return nil +} + +type DeleteSnapshotResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeleteSnapshotResponse) Reset() { *m = DeleteSnapshotResponse{} } +func (m *DeleteSnapshotResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteSnapshotResponse) ProtoMessage() {} +func (*DeleteSnapshotResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{35} +} +func (m *DeleteSnapshotResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeleteSnapshotResponse.Unmarshal(m, b) +} +func (m *DeleteSnapshotResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeleteSnapshotResponse.Marshal(b, m, deterministic) +} +func (dst *DeleteSnapshotResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeleteSnapshotResponse.Merge(dst, src) +} +func (m *DeleteSnapshotResponse) XXX_Size() int { + return xxx_messageInfo_DeleteSnapshotResponse.Size(m) +} +func (m *DeleteSnapshotResponse) XXX_DiscardUnknown() { + xxx_messageInfo_DeleteSnapshotResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_DeleteSnapshotResponse proto.InternalMessageInfo + +// List all snapshots on the storage system regardless of how they were +// created. +type ListSnapshotsRequest struct { + // If specified (non-zero value), the Plugin MUST NOT return more + // entries than this number in the response. If the actual number of + // entries is more than this number, the Plugin MUST set `next_token` + // in the response which can be used to get the next page of entries + // in the subsequent `ListSnapshots` call. This field is OPTIONAL. If + // not specified (zero value), it means there is no restriction on the + // number of entries that can be returned. + // The value of this field MUST NOT be negative. + MaxEntries int32 `protobuf:"varint,1,opt,name=max_entries,json=maxEntries" json:"max_entries,omitempty"` + // A token to specify where to start paginating. Set this field to + // `next_token` returned by a previous `ListSnapshots` call to get the + // next page of entries. This field is OPTIONAL. + // An empty string is equal to an unspecified field value. + StartingToken string `protobuf:"bytes,2,opt,name=starting_token,json=startingToken" json:"starting_token,omitempty"` + // Identity information for the source volume. This field is OPTIONAL. + // It can be used to list snapshots by volume. + SourceVolumeId string `protobuf:"bytes,3,opt,name=source_volume_id,json=sourceVolumeId" json:"source_volume_id,omitempty"` + // Identity information for a specific snapshot. This field is + // OPTIONAL. It can be used to list only a specific snapshot. + // ListSnapshots will return with current snapshot information + // and will not block if the snapshot is being uploaded. + SnapshotId string `protobuf:"bytes,4,opt,name=snapshot_id,json=snapshotId" json:"snapshot_id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListSnapshotsRequest) Reset() { *m = ListSnapshotsRequest{} } +func (m *ListSnapshotsRequest) String() string { return proto.CompactTextString(m) } +func (*ListSnapshotsRequest) ProtoMessage() {} +func (*ListSnapshotsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{36} +} +func (m *ListSnapshotsRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListSnapshotsRequest.Unmarshal(m, b) +} +func (m *ListSnapshotsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListSnapshotsRequest.Marshal(b, m, deterministic) +} +func (dst *ListSnapshotsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListSnapshotsRequest.Merge(dst, src) +} +func (m *ListSnapshotsRequest) XXX_Size() int { + return xxx_messageInfo_ListSnapshotsRequest.Size(m) +} +func (m *ListSnapshotsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListSnapshotsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ListSnapshotsRequest proto.InternalMessageInfo + +func (m *ListSnapshotsRequest) GetMaxEntries() int32 { + if m != nil { + return m.MaxEntries + } + return 0 +} + +func (m *ListSnapshotsRequest) GetStartingToken() string { + if m != nil { + return m.StartingToken + } + return "" +} + +func (m *ListSnapshotsRequest) GetSourceVolumeId() string { + if m != nil { + return m.SourceVolumeId + } + return "" +} + +func (m *ListSnapshotsRequest) GetSnapshotId() string { + if m != nil { + return m.SnapshotId + } + return "" +} + +type ListSnapshotsResponse struct { + Entries []*ListSnapshotsResponse_Entry `protobuf:"bytes,1,rep,name=entries" json:"entries,omitempty"` + // This token allows you to get the next page of entries for + // `ListSnapshots` request. If the number of entries is larger than + // `max_entries`, use the `next_token` as a value for the + // `starting_token` field in the next `ListSnapshots` request. This + // field is OPTIONAL. + // An empty string is equal to an unspecified field value. + NextToken string `protobuf:"bytes,2,opt,name=next_token,json=nextToken" json:"next_token,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListSnapshotsResponse) Reset() { *m = ListSnapshotsResponse{} } +func (m *ListSnapshotsResponse) String() string { return proto.CompactTextString(m) } +func (*ListSnapshotsResponse) ProtoMessage() {} +func (*ListSnapshotsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{37} +} +func (m *ListSnapshotsResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListSnapshotsResponse.Unmarshal(m, b) +} +func (m *ListSnapshotsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListSnapshotsResponse.Marshal(b, m, deterministic) +} +func (dst *ListSnapshotsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListSnapshotsResponse.Merge(dst, src) +} +func (m *ListSnapshotsResponse) XXX_Size() int { + return xxx_messageInfo_ListSnapshotsResponse.Size(m) +} +func (m *ListSnapshotsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ListSnapshotsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ListSnapshotsResponse proto.InternalMessageInfo + +func (m *ListSnapshotsResponse) GetEntries() []*ListSnapshotsResponse_Entry { + if m != nil { + return m.Entries + } + return nil +} + +func (m *ListSnapshotsResponse) GetNextToken() string { + if m != nil { + return m.NextToken + } + return "" +} + +type ListSnapshotsResponse_Entry struct { + Snapshot *Snapshot `protobuf:"bytes,1,opt,name=snapshot" json:"snapshot,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListSnapshotsResponse_Entry) Reset() { *m = ListSnapshotsResponse_Entry{} } +func (m *ListSnapshotsResponse_Entry) String() string { return proto.CompactTextString(m) } +func (*ListSnapshotsResponse_Entry) ProtoMessage() {} +func (*ListSnapshotsResponse_Entry) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{37, 0} +} +func (m *ListSnapshotsResponse_Entry) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListSnapshotsResponse_Entry.Unmarshal(m, b) +} +func (m *ListSnapshotsResponse_Entry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListSnapshotsResponse_Entry.Marshal(b, m, deterministic) +} +func (dst *ListSnapshotsResponse_Entry) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListSnapshotsResponse_Entry.Merge(dst, src) +} +func (m *ListSnapshotsResponse_Entry) XXX_Size() int { + return xxx_messageInfo_ListSnapshotsResponse_Entry.Size(m) +} +func (m *ListSnapshotsResponse_Entry) XXX_DiscardUnknown() { + xxx_messageInfo_ListSnapshotsResponse_Entry.DiscardUnknown(m) +} + +var xxx_messageInfo_ListSnapshotsResponse_Entry proto.InternalMessageInfo + +func (m *ListSnapshotsResponse_Entry) GetSnapshot() *Snapshot { + if m != nil { + return m.Snapshot + } + return nil +} + type NodeStageVolumeRequest struct { // The ID of the volume to publish. This field is REQUIRED. VolumeId string `protobuf:"bytes,1,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"` @@ -1380,33 +3081,41 @@ type NodeStageVolumeRequest struct { // This is a REQUIRED field. VolumeCapability *VolumeCapability `protobuf:"bytes,4,opt,name=volume_capability,json=volumeCapability" json:"volume_capability,omitempty"` // Secrets required by plugin to complete node stage volume request. - // A secret is a string to string map where the key identifies the - // name of the secret (e.g. "username" or "password"), and the value - // contains the secret data (e.g. "bob" or "abc123"). - // Each key MUST consist of alphanumeric characters, '-', '_' or '.'. - // Each value MUST contain a valid string. An SP MAY choose to accept - // binary (non-string) data by using a binary-to-text encoding scheme, - // like base64. - // An SP SHALL advertise the requirements for required secret keys and - // values in documentation. - // CO SHALL permit passing through the required secrets. - // A CO MAY pass the same secrets to all RPCs, therefore the keys for - // all unique secrets that an SP expects must be unique across all CSI - // operations. - // This information is sensitive and MUST be treated as such (not - // logged, etc.) by the CO. - // This field is OPTIONAL. + // This field is OPTIONAL. Refer to the `Secrets Requirements` + // section on how to use this field. NodeStageSecrets map[string]string `protobuf:"bytes,5,rep,name=node_stage_secrets,json=nodeStageSecrets" json:"node_stage_secrets,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Attributes of the volume to publish. This field is OPTIONAL and - // MUST match the attributes of the VolumeInfo identified by + // MUST match the attributes of the `Volume` identified by // `volume_id`. - VolumeAttributes map[string]string `protobuf:"bytes,6,rep,name=volume_attributes,json=volumeAttributes" json:"volume_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + VolumeAttributes map[string]string `protobuf:"bytes,6,rep,name=volume_attributes,json=volumeAttributes" json:"volume_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeStageVolumeRequest) Reset() { *m = NodeStageVolumeRequest{} } -func (m *NodeStageVolumeRequest) String() string { return proto.CompactTextString(m) } -func (*NodeStageVolumeRequest) ProtoMessage() {} -func (*NodeStageVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } +func (m *NodeStageVolumeRequest) Reset() { *m = NodeStageVolumeRequest{} } +func (m *NodeStageVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*NodeStageVolumeRequest) ProtoMessage() {} +func (*NodeStageVolumeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{38} +} +func (m *NodeStageVolumeRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeStageVolumeRequest.Unmarshal(m, b) +} +func (m *NodeStageVolumeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeStageVolumeRequest.Marshal(b, m, deterministic) +} +func (dst *NodeStageVolumeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeStageVolumeRequest.Merge(dst, src) +} +func (m *NodeStageVolumeRequest) XXX_Size() int { + return xxx_messageInfo_NodeStageVolumeRequest.Size(m) +} +func (m *NodeStageVolumeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NodeStageVolumeRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeStageVolumeRequest proto.InternalMessageInfo func (m *NodeStageVolumeRequest) GetVolumeId() string { if m != nil { @@ -1451,12 +3160,34 @@ func (m *NodeStageVolumeRequest) GetVolumeAttributes() map[string]string { } type NodeStageVolumeResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeStageVolumeResponse) Reset() { *m = NodeStageVolumeResponse{} } -func (m *NodeStageVolumeResponse) String() string { return proto.CompactTextString(m) } -func (*NodeStageVolumeResponse) ProtoMessage() {} -func (*NodeStageVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } +func (m *NodeStageVolumeResponse) Reset() { *m = NodeStageVolumeResponse{} } +func (m *NodeStageVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*NodeStageVolumeResponse) ProtoMessage() {} +func (*NodeStageVolumeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{39} +} +func (m *NodeStageVolumeResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeStageVolumeResponse.Unmarshal(m, b) +} +func (m *NodeStageVolumeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeStageVolumeResponse.Marshal(b, m, deterministic) +} +func (dst *NodeStageVolumeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeStageVolumeResponse.Merge(dst, src) +} +func (m *NodeStageVolumeResponse) XXX_Size() int { + return xxx_messageInfo_NodeStageVolumeResponse.Size(m) +} +func (m *NodeStageVolumeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NodeStageVolumeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeStageVolumeResponse proto.InternalMessageInfo type NodeUnstageVolumeRequest struct { // The ID of the volume. This field is REQUIRED. @@ -1464,13 +3195,35 @@ type NodeUnstageVolumeRequest struct { // The path at which the volume was published. It MUST be an absolute // path in the root filesystem of the process serving this request. // This is a REQUIRED field. - StagingTargetPath string `protobuf:"bytes,2,opt,name=staging_target_path,json=stagingTargetPath" json:"staging_target_path,omitempty"` + StagingTargetPath string `protobuf:"bytes,2,opt,name=staging_target_path,json=stagingTargetPath" json:"staging_target_path,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeUnstageVolumeRequest) Reset() { *m = NodeUnstageVolumeRequest{} } -func (m *NodeUnstageVolumeRequest) String() string { return proto.CompactTextString(m) } -func (*NodeUnstageVolumeRequest) ProtoMessage() {} -func (*NodeUnstageVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } +func (m *NodeUnstageVolumeRequest) Reset() { *m = NodeUnstageVolumeRequest{} } +func (m *NodeUnstageVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*NodeUnstageVolumeRequest) ProtoMessage() {} +func (*NodeUnstageVolumeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{40} +} +func (m *NodeUnstageVolumeRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeUnstageVolumeRequest.Unmarshal(m, b) +} +func (m *NodeUnstageVolumeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeUnstageVolumeRequest.Marshal(b, m, deterministic) +} +func (dst *NodeUnstageVolumeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeUnstageVolumeRequest.Merge(dst, src) +} +func (m *NodeUnstageVolumeRequest) XXX_Size() int { + return xxx_messageInfo_NodeUnstageVolumeRequest.Size(m) +} +func (m *NodeUnstageVolumeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NodeUnstageVolumeRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeUnstageVolumeRequest proto.InternalMessageInfo func (m *NodeUnstageVolumeRequest) GetVolumeId() string { if m != nil { @@ -1487,12 +3240,34 @@ func (m *NodeUnstageVolumeRequest) GetStagingTargetPath() string { } type NodeUnstageVolumeResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeUnstageVolumeResponse) Reset() { *m = NodeUnstageVolumeResponse{} } -func (m *NodeUnstageVolumeResponse) String() string { return proto.CompactTextString(m) } -func (*NodeUnstageVolumeResponse) ProtoMessage() {} -func (*NodeUnstageVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } +func (m *NodeUnstageVolumeResponse) Reset() { *m = NodeUnstageVolumeResponse{} } +func (m *NodeUnstageVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*NodeUnstageVolumeResponse) ProtoMessage() {} +func (*NodeUnstageVolumeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{41} +} +func (m *NodeUnstageVolumeResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeUnstageVolumeResponse.Unmarshal(m, b) +} +func (m *NodeUnstageVolumeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeUnstageVolumeResponse.Marshal(b, m, deterministic) +} +func (dst *NodeUnstageVolumeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeUnstageVolumeResponse.Merge(dst, src) +} +func (m *NodeUnstageVolumeResponse) XXX_Size() int { + return xxx_messageInfo_NodeUnstageVolumeResponse.Size(m) +} +func (m *NodeUnstageVolumeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NodeUnstageVolumeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeUnstageVolumeResponse proto.InternalMessageInfo type NodePublishVolumeRequest struct { // The ID of the volume to publish. This field is REQUIRED. @@ -1524,33 +3299,41 @@ type NodePublishVolumeRequest struct { // REQUIRED. Readonly bool `protobuf:"varint,6,opt,name=readonly" json:"readonly,omitempty"` // Secrets required by plugin to complete node publish volume request. - // A secret is a string to string map where the key identifies the - // name of the secret (e.g. "username" or "password"), and the value - // contains the secret data (e.g. "bob" or "abc123"). - // Each key MUST consist of alphanumeric characters, '-', '_' or '.'. - // Each value MUST contain a valid string. An SP MAY choose to accept - // binary (non-string) data by using a binary-to-text encoding scheme, - // like base64. - // An SP SHALL advertise the requirements for required secret keys and - // values in documentation. - // CO SHALL permit passing through the required secrets. - // A CO MAY pass the same secrets to all RPCs, therefore the keys for - // all unique secrets that an SP expects must be unique across all CSI - // operations. - // This information is sensitive and MUST be treated as such (not - // logged, etc.) by the CO. - // This field is OPTIONAL. + // This field is OPTIONAL. Refer to the `Secrets Requirements` + // section on how to use this field. NodePublishSecrets map[string]string `protobuf:"bytes,7,rep,name=node_publish_secrets,json=nodePublishSecrets" json:"node_publish_secrets,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Attributes of the volume to publish. This field is OPTIONAL and // MUST match the attributes of the Volume identified by // `volume_id`. - VolumeAttributes map[string]string `protobuf:"bytes,8,rep,name=volume_attributes,json=volumeAttributes" json:"volume_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + VolumeAttributes map[string]string `protobuf:"bytes,8,rep,name=volume_attributes,json=volumeAttributes" json:"volume_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodePublishVolumeRequest) Reset() { *m = NodePublishVolumeRequest{} } -func (m *NodePublishVolumeRequest) String() string { return proto.CompactTextString(m) } -func (*NodePublishVolumeRequest) ProtoMessage() {} -func (*NodePublishVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } +func (m *NodePublishVolumeRequest) Reset() { *m = NodePublishVolumeRequest{} } +func (m *NodePublishVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*NodePublishVolumeRequest) ProtoMessage() {} +func (*NodePublishVolumeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{42} +} +func (m *NodePublishVolumeRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodePublishVolumeRequest.Unmarshal(m, b) +} +func (m *NodePublishVolumeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodePublishVolumeRequest.Marshal(b, m, deterministic) +} +func (dst *NodePublishVolumeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodePublishVolumeRequest.Merge(dst, src) +} +func (m *NodePublishVolumeRequest) XXX_Size() int { + return xxx_messageInfo_NodePublishVolumeRequest.Size(m) +} +func (m *NodePublishVolumeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NodePublishVolumeRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NodePublishVolumeRequest proto.InternalMessageInfo func (m *NodePublishVolumeRequest) GetVolumeId() string { if m != nil { @@ -1609,12 +3392,34 @@ func (m *NodePublishVolumeRequest) GetVolumeAttributes() map[string]string { } type NodePublishVolumeResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodePublishVolumeResponse) Reset() { *m = NodePublishVolumeResponse{} } -func (m *NodePublishVolumeResponse) String() string { return proto.CompactTextString(m) } -func (*NodePublishVolumeResponse) ProtoMessage() {} -func (*NodePublishVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{32} } +func (m *NodePublishVolumeResponse) Reset() { *m = NodePublishVolumeResponse{} } +func (m *NodePublishVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*NodePublishVolumeResponse) ProtoMessage() {} +func (*NodePublishVolumeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{43} +} +func (m *NodePublishVolumeResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodePublishVolumeResponse.Unmarshal(m, b) +} +func (m *NodePublishVolumeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodePublishVolumeResponse.Marshal(b, m, deterministic) +} +func (dst *NodePublishVolumeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodePublishVolumeResponse.Merge(dst, src) +} +func (m *NodePublishVolumeResponse) XXX_Size() int { + return xxx_messageInfo_NodePublishVolumeResponse.Size(m) +} +func (m *NodePublishVolumeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NodePublishVolumeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NodePublishVolumeResponse proto.InternalMessageInfo type NodeUnpublishVolumeRequest struct { // The ID of the volume. This field is REQUIRED. @@ -1622,13 +3427,35 @@ type NodeUnpublishVolumeRequest struct { // The path at which the volume was published. It MUST be an absolute // path in the root filesystem of the process serving this request. // This is a REQUIRED field. - TargetPath string `protobuf:"bytes,2,opt,name=target_path,json=targetPath" json:"target_path,omitempty"` + TargetPath string `protobuf:"bytes,2,opt,name=target_path,json=targetPath" json:"target_path,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeUnpublishVolumeRequest) Reset() { *m = NodeUnpublishVolumeRequest{} } -func (m *NodeUnpublishVolumeRequest) String() string { return proto.CompactTextString(m) } -func (*NodeUnpublishVolumeRequest) ProtoMessage() {} -func (*NodeUnpublishVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} } +func (m *NodeUnpublishVolumeRequest) Reset() { *m = NodeUnpublishVolumeRequest{} } +func (m *NodeUnpublishVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*NodeUnpublishVolumeRequest) ProtoMessage() {} +func (*NodeUnpublishVolumeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{44} +} +func (m *NodeUnpublishVolumeRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeUnpublishVolumeRequest.Unmarshal(m, b) +} +func (m *NodeUnpublishVolumeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeUnpublishVolumeRequest.Marshal(b, m, deterministic) +} +func (dst *NodeUnpublishVolumeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeUnpublishVolumeRequest.Merge(dst, src) +} +func (m *NodeUnpublishVolumeRequest) XXX_Size() int { + return xxx_messageInfo_NodeUnpublishVolumeRequest.Size(m) +} +func (m *NodeUnpublishVolumeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NodeUnpublishVolumeRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeUnpublishVolumeRequest proto.InternalMessageInfo func (m *NodeUnpublishVolumeRequest) GetVolumeId() string { if m != nil { @@ -1645,32 +3472,98 @@ func (m *NodeUnpublishVolumeRequest) GetTargetPath() string { } type NodeUnpublishVolumeResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeUnpublishVolumeResponse) Reset() { *m = NodeUnpublishVolumeResponse{} } -func (m *NodeUnpublishVolumeResponse) String() string { return proto.CompactTextString(m) } -func (*NodeUnpublishVolumeResponse) ProtoMessage() {} -func (*NodeUnpublishVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} } +func (m *NodeUnpublishVolumeResponse) Reset() { *m = NodeUnpublishVolumeResponse{} } +func (m *NodeUnpublishVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*NodeUnpublishVolumeResponse) ProtoMessage() {} +func (*NodeUnpublishVolumeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{45} +} +func (m *NodeUnpublishVolumeResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeUnpublishVolumeResponse.Unmarshal(m, b) +} +func (m *NodeUnpublishVolumeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeUnpublishVolumeResponse.Marshal(b, m, deterministic) +} +func (dst *NodeUnpublishVolumeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeUnpublishVolumeResponse.Merge(dst, src) +} +func (m *NodeUnpublishVolumeResponse) XXX_Size() int { + return xxx_messageInfo_NodeUnpublishVolumeResponse.Size(m) +} +func (m *NodeUnpublishVolumeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NodeUnpublishVolumeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeUnpublishVolumeResponse proto.InternalMessageInfo type NodeGetIdRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeGetIdRequest) Reset() { *m = NodeGetIdRequest{} } -func (m *NodeGetIdRequest) String() string { return proto.CompactTextString(m) } -func (*NodeGetIdRequest) ProtoMessage() {} -func (*NodeGetIdRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{35} } +func (m *NodeGetIdRequest) Reset() { *m = NodeGetIdRequest{} } +func (m *NodeGetIdRequest) String() string { return proto.CompactTextString(m) } +func (*NodeGetIdRequest) ProtoMessage() {} +func (*NodeGetIdRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{46} +} +func (m *NodeGetIdRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeGetIdRequest.Unmarshal(m, b) +} +func (m *NodeGetIdRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeGetIdRequest.Marshal(b, m, deterministic) +} +func (dst *NodeGetIdRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeGetIdRequest.Merge(dst, src) +} +func (m *NodeGetIdRequest) XXX_Size() int { + return xxx_messageInfo_NodeGetIdRequest.Size(m) +} +func (m *NodeGetIdRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NodeGetIdRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeGetIdRequest proto.InternalMessageInfo type NodeGetIdResponse struct { // The ID of the node as understood by the SP which SHALL be used by // CO in subsequent `ControllerPublishVolume`. // This is a REQUIRED field. - NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId" json:"node_id,omitempty"` + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId" json:"node_id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeGetIdResponse) Reset() { *m = NodeGetIdResponse{} } -func (m *NodeGetIdResponse) String() string { return proto.CompactTextString(m) } -func (*NodeGetIdResponse) ProtoMessage() {} -func (*NodeGetIdResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{36} } +func (m *NodeGetIdResponse) Reset() { *m = NodeGetIdResponse{} } +func (m *NodeGetIdResponse) String() string { return proto.CompactTextString(m) } +func (*NodeGetIdResponse) ProtoMessage() {} +func (*NodeGetIdResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{47} +} +func (m *NodeGetIdResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeGetIdResponse.Unmarshal(m, b) +} +func (m *NodeGetIdResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeGetIdResponse.Marshal(b, m, deterministic) +} +func (dst *NodeGetIdResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeGetIdResponse.Merge(dst, src) +} +func (m *NodeGetIdResponse) XXX_Size() int { + return xxx_messageInfo_NodeGetIdResponse.Size(m) +} +func (m *NodeGetIdResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NodeGetIdResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeGetIdResponse proto.InternalMessageInfo func (m *NodeGetIdResponse) GetNodeId() string { if m != nil { @@ -1680,23 +3573,67 @@ func (m *NodeGetIdResponse) GetNodeId() string { } type NodeGetCapabilitiesRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeGetCapabilitiesRequest) Reset() { *m = NodeGetCapabilitiesRequest{} } -func (m *NodeGetCapabilitiesRequest) String() string { return proto.CompactTextString(m) } -func (*NodeGetCapabilitiesRequest) ProtoMessage() {} -func (*NodeGetCapabilitiesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} } +func (m *NodeGetCapabilitiesRequest) Reset() { *m = NodeGetCapabilitiesRequest{} } +func (m *NodeGetCapabilitiesRequest) String() string { return proto.CompactTextString(m) } +func (*NodeGetCapabilitiesRequest) ProtoMessage() {} +func (*NodeGetCapabilitiesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{48} +} +func (m *NodeGetCapabilitiesRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeGetCapabilitiesRequest.Unmarshal(m, b) +} +func (m *NodeGetCapabilitiesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeGetCapabilitiesRequest.Marshal(b, m, deterministic) +} +func (dst *NodeGetCapabilitiesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeGetCapabilitiesRequest.Merge(dst, src) +} +func (m *NodeGetCapabilitiesRequest) XXX_Size() int { + return xxx_messageInfo_NodeGetCapabilitiesRequest.Size(m) +} +func (m *NodeGetCapabilitiesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NodeGetCapabilitiesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeGetCapabilitiesRequest proto.InternalMessageInfo type NodeGetCapabilitiesResponse struct { // All the capabilities that the node service supports. This field // is OPTIONAL. - Capabilities []*NodeServiceCapability `protobuf:"bytes,1,rep,name=capabilities" json:"capabilities,omitempty"` + Capabilities []*NodeServiceCapability `protobuf:"bytes,1,rep,name=capabilities" json:"capabilities,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeGetCapabilitiesResponse) Reset() { *m = NodeGetCapabilitiesResponse{} } -func (m *NodeGetCapabilitiesResponse) String() string { return proto.CompactTextString(m) } -func (*NodeGetCapabilitiesResponse) ProtoMessage() {} -func (*NodeGetCapabilitiesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{38} } +func (m *NodeGetCapabilitiesResponse) Reset() { *m = NodeGetCapabilitiesResponse{} } +func (m *NodeGetCapabilitiesResponse) String() string { return proto.CompactTextString(m) } +func (*NodeGetCapabilitiesResponse) ProtoMessage() {} +func (*NodeGetCapabilitiesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{49} +} +func (m *NodeGetCapabilitiesResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeGetCapabilitiesResponse.Unmarshal(m, b) +} +func (m *NodeGetCapabilitiesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeGetCapabilitiesResponse.Marshal(b, m, deterministic) +} +func (dst *NodeGetCapabilitiesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeGetCapabilitiesResponse.Merge(dst, src) +} +func (m *NodeGetCapabilitiesResponse) XXX_Size() int { + return xxx_messageInfo_NodeGetCapabilitiesResponse.Size(m) +} +func (m *NodeGetCapabilitiesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NodeGetCapabilitiesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeGetCapabilitiesResponse proto.InternalMessageInfo func (m *NodeGetCapabilitiesResponse) GetCapabilities() []*NodeServiceCapability { if m != nil { @@ -1709,13 +3646,35 @@ func (m *NodeGetCapabilitiesResponse) GetCapabilities() []*NodeServiceCapability type NodeServiceCapability struct { // Types that are valid to be assigned to Type: // *NodeServiceCapability_Rpc - Type isNodeServiceCapability_Type `protobuf_oneof:"type"` + Type isNodeServiceCapability_Type `protobuf_oneof:"type"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeServiceCapability) Reset() { *m = NodeServiceCapability{} } -func (m *NodeServiceCapability) String() string { return proto.CompactTextString(m) } -func (*NodeServiceCapability) ProtoMessage() {} -func (*NodeServiceCapability) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39} } +func (m *NodeServiceCapability) Reset() { *m = NodeServiceCapability{} } +func (m *NodeServiceCapability) String() string { return proto.CompactTextString(m) } +func (*NodeServiceCapability) ProtoMessage() {} +func (*NodeServiceCapability) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{50} +} +func (m *NodeServiceCapability) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeServiceCapability.Unmarshal(m, b) +} +func (m *NodeServiceCapability) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeServiceCapability.Marshal(b, m, deterministic) +} +func (dst *NodeServiceCapability) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeServiceCapability.Merge(dst, src) +} +func (m *NodeServiceCapability) XXX_Size() int { + return xxx_messageInfo_NodeServiceCapability.Size(m) +} +func (m *NodeServiceCapability) XXX_DiscardUnknown() { + xxx_messageInfo_NodeServiceCapability.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeServiceCapability proto.InternalMessageInfo type isNodeServiceCapability_Type interface { isNodeServiceCapability_Type() @@ -1786,7 +3745,7 @@ func _NodeServiceCapability_OneofSizer(msg proto.Message) (n int) { switch x := m.Type.(type) { case *NodeServiceCapability_Rpc: s := proto.Size(x.Rpc) - n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += 1 // tag and wire n += proto.SizeVarint(uint64(s)) n += s case nil: @@ -1797,13 +3756,35 @@ func _NodeServiceCapability_OneofSizer(msg proto.Message) (n int) { } type NodeServiceCapability_RPC struct { - Type NodeServiceCapability_RPC_Type `protobuf:"varint,1,opt,name=type,enum=csi.v0.NodeServiceCapability_RPC_Type" json:"type,omitempty"` + Type NodeServiceCapability_RPC_Type `protobuf:"varint,1,opt,name=type,enum=csi.v0.NodeServiceCapability_RPC_Type" json:"type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *NodeServiceCapability_RPC) Reset() { *m = NodeServiceCapability_RPC{} } -func (m *NodeServiceCapability_RPC) String() string { return proto.CompactTextString(m) } -func (*NodeServiceCapability_RPC) ProtoMessage() {} -func (*NodeServiceCapability_RPC) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39, 0} } +func (m *NodeServiceCapability_RPC) Reset() { *m = NodeServiceCapability_RPC{} } +func (m *NodeServiceCapability_RPC) String() string { return proto.CompactTextString(m) } +func (*NodeServiceCapability_RPC) ProtoMessage() {} +func (*NodeServiceCapability_RPC) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{50, 0} +} +func (m *NodeServiceCapability_RPC) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeServiceCapability_RPC.Unmarshal(m, b) +} +func (m *NodeServiceCapability_RPC) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeServiceCapability_RPC.Marshal(b, m, deterministic) +} +func (dst *NodeServiceCapability_RPC) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeServiceCapability_RPC.Merge(dst, src) +} +func (m *NodeServiceCapability_RPC) XXX_Size() int { + return xxx_messageInfo_NodeServiceCapability_RPC.Size(m) +} +func (m *NodeServiceCapability_RPC) XXX_DiscardUnknown() { + xxx_messageInfo_NodeServiceCapability_RPC.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeServiceCapability_RPC proto.InternalMessageInfo func (m *NodeServiceCapability_RPC) GetType() NodeServiceCapability_RPC_Type { if m != nil { @@ -1812,9 +3793,119 @@ func (m *NodeServiceCapability_RPC) GetType() NodeServiceCapability_RPC_Type { return NodeServiceCapability_RPC_UNKNOWN } +type NodeGetInfoRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NodeGetInfoRequest) Reset() { *m = NodeGetInfoRequest{} } +func (m *NodeGetInfoRequest) String() string { return proto.CompactTextString(m) } +func (*NodeGetInfoRequest) ProtoMessage() {} +func (*NodeGetInfoRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{51} +} +func (m *NodeGetInfoRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeGetInfoRequest.Unmarshal(m, b) +} +func (m *NodeGetInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeGetInfoRequest.Marshal(b, m, deterministic) +} +func (dst *NodeGetInfoRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeGetInfoRequest.Merge(dst, src) +} +func (m *NodeGetInfoRequest) XXX_Size() int { + return xxx_messageInfo_NodeGetInfoRequest.Size(m) +} +func (m *NodeGetInfoRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NodeGetInfoRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeGetInfoRequest proto.InternalMessageInfo + +type NodeGetInfoResponse struct { + // The ID of the node as understood by the SP which SHALL be used by + // CO in subsequent calls to `ControllerPublishVolume`. + // This is a REQUIRED field. + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId" json:"node_id,omitempty"` + // Maximum number of volumes that controller can publish to the node. + // If value is not set or zero CO SHALL decide how many volumes of + // this type can be published by the controller to the node. The + // plugin MUST NOT set negative values here. + // This field is OPTIONAL. + MaxVolumesPerNode int64 `protobuf:"varint,2,opt,name=max_volumes_per_node,json=maxVolumesPerNode" json:"max_volumes_per_node,omitempty"` + // Specifies where (regions, zones, racks, etc.) the node is + // accessible from. + // A plugin that returns this field MUST also set the + // ACCESSIBILITY_CONSTRAINTS plugin capability. + // COs MAY use this information along with the topology information + // returned in CreateVolumeResponse to ensure that a given volume is + // accessible from a given node when scheduling workloads. + // This field is OPTIONAL. If it is not specified, the CO MAY assume + // the node is not subject to any topological constraint, and MAY + // schedule workloads that reference any volume V, such that there are + // no topological constraints declared for V. + // + // Example 1: + // accessible_topology = + // {"region": "R1", "zone": "R2"} + // Indicates the node exists within the "region" "R1" and the "zone" + // "Z2". + AccessibleTopology *Topology `protobuf:"bytes,3,opt,name=accessible_topology,json=accessibleTopology" json:"accessible_topology,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NodeGetInfoResponse) Reset() { *m = NodeGetInfoResponse{} } +func (m *NodeGetInfoResponse) String() string { return proto.CompactTextString(m) } +func (*NodeGetInfoResponse) ProtoMessage() {} +func (*NodeGetInfoResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_csi_31237507707d37ec, []int{52} +} +func (m *NodeGetInfoResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeGetInfoResponse.Unmarshal(m, b) +} +func (m *NodeGetInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeGetInfoResponse.Marshal(b, m, deterministic) +} +func (dst *NodeGetInfoResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeGetInfoResponse.Merge(dst, src) +} +func (m *NodeGetInfoResponse) XXX_Size() int { + return xxx_messageInfo_NodeGetInfoResponse.Size(m) +} +func (m *NodeGetInfoResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NodeGetInfoResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeGetInfoResponse proto.InternalMessageInfo + +func (m *NodeGetInfoResponse) GetNodeId() string { + if m != nil { + return m.NodeId + } + return "" +} + +func (m *NodeGetInfoResponse) GetMaxVolumesPerNode() int64 { + if m != nil { + return m.MaxVolumesPerNode + } + return 0 +} + +func (m *NodeGetInfoResponse) GetAccessibleTopology() *Topology { + if m != nil { + return m.AccessibleTopology + } + return nil +} + func init() { proto.RegisterType((*GetPluginInfoRequest)(nil), "csi.v0.GetPluginInfoRequest") proto.RegisterType((*GetPluginInfoResponse)(nil), "csi.v0.GetPluginInfoResponse") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.GetPluginInfoResponse.ManifestEntry") proto.RegisterType((*GetPluginCapabilitiesRequest)(nil), "csi.v0.GetPluginCapabilitiesRequest") proto.RegisterType((*GetPluginCapabilitiesResponse)(nil), "csi.v0.GetPluginCapabilitiesResponse") proto.RegisterType((*PluginCapability)(nil), "csi.v0.PluginCapability") @@ -1822,6 +3913,10 @@ func init() { proto.RegisterType((*ProbeRequest)(nil), "csi.v0.ProbeRequest") proto.RegisterType((*ProbeResponse)(nil), "csi.v0.ProbeResponse") proto.RegisterType((*CreateVolumeRequest)(nil), "csi.v0.CreateVolumeRequest") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.CreateVolumeRequest.ControllerCreateSecretsEntry") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.CreateVolumeRequest.ParametersEntry") + proto.RegisterType((*VolumeContentSource)(nil), "csi.v0.VolumeContentSource") + proto.RegisterType((*VolumeContentSource_SnapshotSource)(nil), "csi.v0.VolumeContentSource.SnapshotSource") proto.RegisterType((*CreateVolumeResponse)(nil), "csi.v0.CreateVolumeResponse") proto.RegisterType((*VolumeCapability)(nil), "csi.v0.VolumeCapability") proto.RegisterType((*VolumeCapability_BlockVolume)(nil), "csi.v0.VolumeCapability.BlockVolume") @@ -1829,28 +3924,57 @@ func init() { proto.RegisterType((*VolumeCapability_AccessMode)(nil), "csi.v0.VolumeCapability.AccessMode") proto.RegisterType((*CapacityRange)(nil), "csi.v0.CapacityRange") proto.RegisterType((*Volume)(nil), "csi.v0.Volume") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.Volume.AttributesEntry") + proto.RegisterType((*TopologyRequirement)(nil), "csi.v0.TopologyRequirement") + proto.RegisterType((*Topology)(nil), "csi.v0.Topology") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.Topology.SegmentsEntry") proto.RegisterType((*DeleteVolumeRequest)(nil), "csi.v0.DeleteVolumeRequest") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.DeleteVolumeRequest.ControllerDeleteSecretsEntry") proto.RegisterType((*DeleteVolumeResponse)(nil), "csi.v0.DeleteVolumeResponse") proto.RegisterType((*ControllerPublishVolumeRequest)(nil), "csi.v0.ControllerPublishVolumeRequest") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.ControllerPublishVolumeRequest.ControllerPublishSecretsEntry") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.ControllerPublishVolumeRequest.VolumeAttributesEntry") proto.RegisterType((*ControllerPublishVolumeResponse)(nil), "csi.v0.ControllerPublishVolumeResponse") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.ControllerPublishVolumeResponse.PublishInfoEntry") proto.RegisterType((*ControllerUnpublishVolumeRequest)(nil), "csi.v0.ControllerUnpublishVolumeRequest") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.ControllerUnpublishVolumeRequest.ControllerUnpublishSecretsEntry") proto.RegisterType((*ControllerUnpublishVolumeResponse)(nil), "csi.v0.ControllerUnpublishVolumeResponse") proto.RegisterType((*ValidateVolumeCapabilitiesRequest)(nil), "csi.v0.ValidateVolumeCapabilitiesRequest") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.ValidateVolumeCapabilitiesRequest.VolumeAttributesEntry") proto.RegisterType((*ValidateVolumeCapabilitiesResponse)(nil), "csi.v0.ValidateVolumeCapabilitiesResponse") proto.RegisterType((*ListVolumesRequest)(nil), "csi.v0.ListVolumesRequest") proto.RegisterType((*ListVolumesResponse)(nil), "csi.v0.ListVolumesResponse") proto.RegisterType((*ListVolumesResponse_Entry)(nil), "csi.v0.ListVolumesResponse.Entry") proto.RegisterType((*GetCapacityRequest)(nil), "csi.v0.GetCapacityRequest") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.GetCapacityRequest.ParametersEntry") proto.RegisterType((*GetCapacityResponse)(nil), "csi.v0.GetCapacityResponse") proto.RegisterType((*ControllerGetCapabilitiesRequest)(nil), "csi.v0.ControllerGetCapabilitiesRequest") proto.RegisterType((*ControllerGetCapabilitiesResponse)(nil), "csi.v0.ControllerGetCapabilitiesResponse") proto.RegisterType((*ControllerServiceCapability)(nil), "csi.v0.ControllerServiceCapability") proto.RegisterType((*ControllerServiceCapability_RPC)(nil), "csi.v0.ControllerServiceCapability.RPC") + proto.RegisterType((*CreateSnapshotRequest)(nil), "csi.v0.CreateSnapshotRequest") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.CreateSnapshotRequest.CreateSnapshotSecretsEntry") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.CreateSnapshotRequest.ParametersEntry") + proto.RegisterType((*CreateSnapshotResponse)(nil), "csi.v0.CreateSnapshotResponse") + proto.RegisterType((*Snapshot)(nil), "csi.v0.Snapshot") + proto.RegisterType((*SnapshotStatus)(nil), "csi.v0.SnapshotStatus") + proto.RegisterType((*DeleteSnapshotRequest)(nil), "csi.v0.DeleteSnapshotRequest") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.DeleteSnapshotRequest.DeleteSnapshotSecretsEntry") + proto.RegisterType((*DeleteSnapshotResponse)(nil), "csi.v0.DeleteSnapshotResponse") + proto.RegisterType((*ListSnapshotsRequest)(nil), "csi.v0.ListSnapshotsRequest") + proto.RegisterType((*ListSnapshotsResponse)(nil), "csi.v0.ListSnapshotsResponse") + proto.RegisterType((*ListSnapshotsResponse_Entry)(nil), "csi.v0.ListSnapshotsResponse.Entry") proto.RegisterType((*NodeStageVolumeRequest)(nil), "csi.v0.NodeStageVolumeRequest") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.NodeStageVolumeRequest.NodeStageSecretsEntry") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.NodeStageVolumeRequest.PublishInfoEntry") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.NodeStageVolumeRequest.VolumeAttributesEntry") proto.RegisterType((*NodeStageVolumeResponse)(nil), "csi.v0.NodeStageVolumeResponse") proto.RegisterType((*NodeUnstageVolumeRequest)(nil), "csi.v0.NodeUnstageVolumeRequest") proto.RegisterType((*NodeUnstageVolumeResponse)(nil), "csi.v0.NodeUnstageVolumeResponse") proto.RegisterType((*NodePublishVolumeRequest)(nil), "csi.v0.NodePublishVolumeRequest") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.NodePublishVolumeRequest.NodePublishSecretsEntry") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.NodePublishVolumeRequest.PublishInfoEntry") + proto.RegisterMapType((map[string]string)(nil), "csi.v0.NodePublishVolumeRequest.VolumeAttributesEntry") proto.RegisterType((*NodePublishVolumeResponse)(nil), "csi.v0.NodePublishVolumeResponse") proto.RegisterType((*NodeUnpublishVolumeRequest)(nil), "csi.v0.NodeUnpublishVolumeRequest") proto.RegisterType((*NodeUnpublishVolumeResponse)(nil), "csi.v0.NodeUnpublishVolumeResponse") @@ -1860,9 +3984,12 @@ func init() { proto.RegisterType((*NodeGetCapabilitiesResponse)(nil), "csi.v0.NodeGetCapabilitiesResponse") proto.RegisterType((*NodeServiceCapability)(nil), "csi.v0.NodeServiceCapability") proto.RegisterType((*NodeServiceCapability_RPC)(nil), "csi.v0.NodeServiceCapability.RPC") + proto.RegisterType((*NodeGetInfoRequest)(nil), "csi.v0.NodeGetInfoRequest") + proto.RegisterType((*NodeGetInfoResponse)(nil), "csi.v0.NodeGetInfoResponse") proto.RegisterEnum("csi.v0.PluginCapability_Service_Type", PluginCapability_Service_Type_name, PluginCapability_Service_Type_value) proto.RegisterEnum("csi.v0.VolumeCapability_AccessMode_Mode", VolumeCapability_AccessMode_Mode_name, VolumeCapability_AccessMode_Mode_value) proto.RegisterEnum("csi.v0.ControllerServiceCapability_RPC_Type", ControllerServiceCapability_RPC_Type_name, ControllerServiceCapability_RPC_Type_value) + proto.RegisterEnum("csi.v0.SnapshotStatus_Type", SnapshotStatus_Type_name, SnapshotStatus_Type_value) proto.RegisterEnum("csi.v0.NodeServiceCapability_RPC_Type", NodeServiceCapability_RPC_Type_name, NodeServiceCapability_RPC_Type_value) } @@ -2015,6 +4142,9 @@ type ControllerClient interface { ListVolumes(ctx context.Context, in *ListVolumesRequest, opts ...grpc.CallOption) (*ListVolumesResponse, error) GetCapacity(ctx context.Context, in *GetCapacityRequest, opts ...grpc.CallOption) (*GetCapacityResponse, error) ControllerGetCapabilities(ctx context.Context, in *ControllerGetCapabilitiesRequest, opts ...grpc.CallOption) (*ControllerGetCapabilitiesResponse, error) + CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*CreateSnapshotResponse, error) + DeleteSnapshot(ctx context.Context, in *DeleteSnapshotRequest, opts ...grpc.CallOption) (*DeleteSnapshotResponse, error) + ListSnapshots(ctx context.Context, in *ListSnapshotsRequest, opts ...grpc.CallOption) (*ListSnapshotsResponse, error) } type controllerClient struct { @@ -2097,6 +4227,33 @@ func (c *controllerClient) ControllerGetCapabilities(ctx context.Context, in *Co return out, nil } +func (c *controllerClient) CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*CreateSnapshotResponse, error) { + out := new(CreateSnapshotResponse) + err := grpc.Invoke(ctx, "/csi.v0.Controller/CreateSnapshot", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controllerClient) DeleteSnapshot(ctx context.Context, in *DeleteSnapshotRequest, opts ...grpc.CallOption) (*DeleteSnapshotResponse, error) { + out := new(DeleteSnapshotResponse) + err := grpc.Invoke(ctx, "/csi.v0.Controller/DeleteSnapshot", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controllerClient) ListSnapshots(ctx context.Context, in *ListSnapshotsRequest, opts ...grpc.CallOption) (*ListSnapshotsResponse, error) { + out := new(ListSnapshotsResponse) + err := grpc.Invoke(ctx, "/csi.v0.Controller/ListSnapshots", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Controller service type ControllerServer interface { @@ -2108,6 +4265,9 @@ type ControllerServer interface { ListVolumes(context.Context, *ListVolumesRequest) (*ListVolumesResponse, error) GetCapacity(context.Context, *GetCapacityRequest) (*GetCapacityResponse, error) ControllerGetCapabilities(context.Context, *ControllerGetCapabilitiesRequest) (*ControllerGetCapabilitiesResponse, error) + CreateSnapshot(context.Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error) + DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*DeleteSnapshotResponse, error) + ListSnapshots(context.Context, *ListSnapshotsRequest) (*ListSnapshotsResponse, error) } func RegisterControllerServer(s *grpc.Server, srv ControllerServer) { @@ -2258,6 +4418,60 @@ func _Controller_ControllerGetCapabilities_Handler(srv interface{}, ctx context. return interceptor(ctx, in, info, handler) } +func _Controller_CreateSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateSnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).CreateSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.v0.Controller/CreateSnapshot", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).CreateSnapshot(ctx, req.(*CreateSnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Controller_DeleteSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteSnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).DeleteSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.v0.Controller/DeleteSnapshot", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).DeleteSnapshot(ctx, req.(*DeleteSnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Controller_ListSnapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListSnapshotsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).ListSnapshots(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.v0.Controller/ListSnapshots", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).ListSnapshots(ctx, req.(*ListSnapshotsRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Controller_serviceDesc = grpc.ServiceDesc{ ServiceName: "csi.v0.Controller", HandlerType: (*ControllerServer)(nil), @@ -2294,6 +4508,18 @@ var _Controller_serviceDesc = grpc.ServiceDesc{ MethodName: "ControllerGetCapabilities", Handler: _Controller_ControllerGetCapabilities_Handler, }, + { + MethodName: "CreateSnapshot", + Handler: _Controller_CreateSnapshot_Handler, + }, + { + MethodName: "DeleteSnapshot", + Handler: _Controller_DeleteSnapshot_Handler, + }, + { + MethodName: "ListSnapshots", + Handler: _Controller_ListSnapshots_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "csi.proto", @@ -2306,8 +4532,15 @@ type NodeClient interface { NodeUnstageVolume(ctx context.Context, in *NodeUnstageVolumeRequest, opts ...grpc.CallOption) (*NodeUnstageVolumeResponse, error) NodePublishVolume(ctx context.Context, in *NodePublishVolumeRequest, opts ...grpc.CallOption) (*NodePublishVolumeResponse, error) NodeUnpublishVolume(ctx context.Context, in *NodeUnpublishVolumeRequest, opts ...grpc.CallOption) (*NodeUnpublishVolumeResponse, error) + // NodeGetId is being deprecated in favor of NodeGetInfo and will be + // removed in CSI 1.0. Existing drivers, however, may depend on this + // RPC call and hence this RPC call MUST be implemented by the CSI + // plugin prior to v1.0. NodeGetId(ctx context.Context, in *NodeGetIdRequest, opts ...grpc.CallOption) (*NodeGetIdResponse, error) NodeGetCapabilities(ctx context.Context, in *NodeGetCapabilitiesRequest, opts ...grpc.CallOption) (*NodeGetCapabilitiesResponse, error) + // Prior to CSI 1.0 - CSI plugins MUST implement both NodeGetId and + // NodeGetInfo RPC calls. + NodeGetInfo(ctx context.Context, in *NodeGetInfoRequest, opts ...grpc.CallOption) (*NodeGetInfoResponse, error) } type nodeClient struct { @@ -2354,6 +4587,7 @@ func (c *nodeClient) NodeUnpublishVolume(ctx context.Context, in *NodeUnpublishV return out, nil } +// Deprecated: Do not use. func (c *nodeClient) NodeGetId(ctx context.Context, in *NodeGetIdRequest, opts ...grpc.CallOption) (*NodeGetIdResponse, error) { out := new(NodeGetIdResponse) err := grpc.Invoke(ctx, "/csi.v0.Node/NodeGetId", in, out, c.cc, opts...) @@ -2372,6 +4606,15 @@ func (c *nodeClient) NodeGetCapabilities(ctx context.Context, in *NodeGetCapabil return out, nil } +func (c *nodeClient) NodeGetInfo(ctx context.Context, in *NodeGetInfoRequest, opts ...grpc.CallOption) (*NodeGetInfoResponse, error) { + out := new(NodeGetInfoResponse) + err := grpc.Invoke(ctx, "/csi.v0.Node/NodeGetInfo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Node service type NodeServer interface { @@ -2379,8 +4622,15 @@ type NodeServer interface { NodeUnstageVolume(context.Context, *NodeUnstageVolumeRequest) (*NodeUnstageVolumeResponse, error) NodePublishVolume(context.Context, *NodePublishVolumeRequest) (*NodePublishVolumeResponse, error) NodeUnpublishVolume(context.Context, *NodeUnpublishVolumeRequest) (*NodeUnpublishVolumeResponse, error) + // NodeGetId is being deprecated in favor of NodeGetInfo and will be + // removed in CSI 1.0. Existing drivers, however, may depend on this + // RPC call and hence this RPC call MUST be implemented by the CSI + // plugin prior to v1.0. NodeGetId(context.Context, *NodeGetIdRequest) (*NodeGetIdResponse, error) NodeGetCapabilities(context.Context, *NodeGetCapabilitiesRequest) (*NodeGetCapabilitiesResponse, error) + // Prior to CSI 1.0 - CSI plugins MUST implement both NodeGetId and + // NodeGetInfo RPC calls. + NodeGetInfo(context.Context, *NodeGetInfoRequest) (*NodeGetInfoResponse, error) } func RegisterNodeServer(s *grpc.Server, srv NodeServer) { @@ -2495,6 +4745,24 @@ func _Node_NodeGetCapabilities_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Node_NodeGetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NodeGetInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServer).NodeGetInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.v0.Node/NodeGetInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServer).NodeGetInfo(ctx, req.(*NodeGetInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Node_serviceDesc = grpc.ServiceDesc{ ServiceName: "csi.v0.Node", HandlerType: (*NodeServer)(nil), @@ -2523,149 +4791,201 @@ var _Node_serviceDesc = grpc.ServiceDesc{ MethodName: "NodeGetCapabilities", Handler: _Node_NodeGetCapabilities_Handler, }, + { + MethodName: "NodeGetInfo", + Handler: _Node_NodeGetInfo_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "csi.proto", } -func init() { proto.RegisterFile("csi.proto", fileDescriptor0) } +func init() { proto.RegisterFile("csi.proto", fileDescriptor_csi_31237507707d37ec) } -var fileDescriptor0 = []byte{ - // 2173 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x1a, 0x4d, 0x53, 0xe3, 0xc8, - 0x15, 0xf9, 0x0b, 0x78, 0x06, 0xd6, 0xd3, 0x30, 0x83, 0x11, 0x30, 0x03, 0x62, 0x67, 0x96, 0xfd, - 0xf2, 0x26, 0x24, 0xd9, 0xda, 0xec, 0x90, 0x49, 0xc0, 0x28, 0xe0, 0xc5, 0x18, 0x4a, 0x18, 0xa6, - 0x76, 0xb2, 0x29, 0xad, 0xb0, 0x1b, 0x46, 0x19, 0x23, 0x79, 0x24, 0x99, 0x1a, 0x6e, 0xa9, 0x5c, - 0x52, 0x95, 0x5b, 0xee, 0x49, 0xa5, 0x2a, 0xc7, 0x9c, 0x73, 0x48, 0x55, 0xaa, 0xe6, 0x9c, 0xaa, - 0xfc, 0x81, 0x9c, 0xf2, 0x03, 0x52, 0x39, 0xe6, 0x94, 0x53, 0x4a, 0xdd, 0x2d, 0xb9, 0x25, 0xb7, - 0x64, 0x7b, 0x67, 0x6a, 0x2b, 0x27, 0xac, 0xf7, 0xdd, 0xaf, 0xdf, 0x7b, 0xfd, 0x5e, 0x37, 0x30, - 0xdd, 0x72, 0xcd, 0x4a, 0xd7, 0xb1, 0x3d, 0x1b, 0x15, 0xfc, 0x9f, 0x37, 0xdf, 0x51, 0xee, 0xc1, - 0xc2, 0x3e, 0xf6, 0x4e, 0x3a, 0xbd, 0x2b, 0xd3, 0xaa, 0x59, 0x97, 0xb6, 0x86, 0x5f, 0xf6, 0xb0, - 0xeb, 0x29, 0xff, 0x90, 0xe0, 0x6e, 0x0c, 0xe1, 0x76, 0x6d, 0xcb, 0xc5, 0x08, 0x41, 0xce, 0x32, - 0xae, 0x71, 0x59, 0x5a, 0x93, 0x36, 0xa7, 0x35, 0xf2, 0x1b, 0x3d, 0x84, 0xb9, 0x1b, 0x6c, 0xb5, - 0x6d, 0x47, 0xbf, 0xc1, 0x8e, 0x6b, 0xda, 0x56, 0x39, 0x43, 0xb0, 0xb3, 0x14, 0x7a, 0x4e, 0x81, - 0x68, 0x1f, 0xa6, 0xae, 0x0d, 0xcb, 0xbc, 0xc4, 0xae, 0x57, 0xce, 0xae, 0x65, 0x37, 0x8b, 0x5b, - 0x1f, 0x56, 0xa8, 0x1d, 0x15, 0xa1, 0xae, 0xca, 0x11, 0xa3, 0x56, 0x2d, 0xcf, 0xb9, 0xd5, 0x42, - 0x66, 0xf9, 0x31, 0xcc, 0x46, 0x50, 0xa8, 0x04, 0xd9, 0x17, 0xf8, 0x96, 0xd9, 0xe4, 0xff, 0x44, - 0x0b, 0x90, 0xbf, 0x31, 0x3a, 0x3d, 0xcc, 0x2c, 0xa1, 0x1f, 0x9f, 0x67, 0x3e, 0x93, 0x94, 0xfb, - 0xb0, 0x12, 0x6a, 0xab, 0x1a, 0x5d, 0xe3, 0xc2, 0xec, 0x98, 0x9e, 0x89, 0xdd, 0x60, 0xe9, 0x3f, - 0x87, 0xd5, 0x04, 0x3c, 0xf3, 0xc0, 0x36, 0xcc, 0xb4, 0x38, 0x78, 0x39, 0x43, 0x96, 0x52, 0x0e, - 0x96, 0x12, 0xe3, 0xbc, 0xd5, 0x22, 0xd4, 0xca, 0xdf, 0x25, 0x28, 0xc5, 0x49, 0xd0, 0x36, 0x4c, - 0xba, 0xd8, 0xb9, 0x31, 0x5b, 0xd4, 0xaf, 0xc5, 0xad, 0xb5, 0x24, 0x69, 0x95, 0x53, 0x4a, 0x77, - 0x30, 0xa1, 0x05, 0x2c, 0xf2, 0x4b, 0x98, 0x64, 0x50, 0xf4, 0x43, 0xc8, 0x79, 0xb7, 0x5d, 0x2a, - 0x65, 0x6e, 0xeb, 0xe1, 0x30, 0x29, 0x95, 0xe6, 0x6d, 0x17, 0x6b, 0x84, 0x45, 0xf9, 0x10, 0x72, - 0xfe, 0x17, 0x2a, 0xc2, 0xe4, 0x59, 0xe3, 0xb0, 0x71, 0xfc, 0xb4, 0x51, 0x9a, 0x40, 0xf7, 0x00, - 0x55, 0x8f, 0x1b, 0x4d, 0xed, 0xb8, 0x5e, 0x57, 0x35, 0xfd, 0x54, 0xd5, 0xce, 0x6b, 0x55, 0xb5, - 0x24, 0xed, 0x16, 0xa8, 0x1e, 0x65, 0x0e, 0x66, 0x4e, 0x1c, 0xfb, 0x02, 0x07, 0xce, 0x7b, 0x07, - 0x66, 0xd9, 0x37, 0x75, 0x96, 0xf2, 0xcb, 0x1c, 0xcc, 0x57, 0x1d, 0x6c, 0x78, 0xf8, 0xdc, 0xee, - 0xf4, 0xae, 0x03, 0x42, 0x61, 0x18, 0x6d, 0xc3, 0x9c, 0xef, 0xaa, 0x96, 0xe9, 0xdd, 0xea, 0x8e, - 0x61, 0x5d, 0xd1, 0xcd, 0x2b, 0x6e, 0xdd, 0x0d, 0x96, 0x51, 0x65, 0x58, 0xcd, 0x47, 0x6a, 0xb3, - 0x2d, 0xfe, 0x13, 0xd5, 0x60, 0xfe, 0x86, 0xa8, 0xd0, 0x23, 0xbb, 0x93, 0x8d, 0xee, 0x0e, 0xb5, - 0x82, 0xdb, 0x1d, 0x74, 0x13, 0x85, 0x98, 0xd8, 0x45, 0x87, 0x00, 0x5d, 0xc3, 0x31, 0xae, 0xb1, - 0x87, 0x1d, 0xb7, 0x9c, 0x8b, 0x86, 0xaa, 0x60, 0x35, 0x95, 0x93, 0x90, 0x9a, 0x86, 0x2a, 0xc7, - 0x8e, 0x3c, 0x58, 0x6a, 0xd9, 0x96, 0xe7, 0xd8, 0x9d, 0x0e, 0x76, 0xf4, 0x16, 0xe1, 0xd6, 0x5d, - 0xdc, 0x72, 0xb0, 0xe7, 0x96, 0xf3, 0x44, 0xf6, 0x67, 0x69, 0xb2, 0xab, 0x21, 0x33, 0xc5, 0x9e, - 0x52, 0x56, 0xaa, 0x68, 0xb1, 0x25, 0xc6, 0xca, 0x3f, 0x82, 0x77, 0x62, 0x46, 0x8d, 0x93, 0x24, - 0xf2, 0x17, 0xb0, 0x92, 0xa6, 0x77, 0xac, 0x84, 0x7b, 0x02, 0x0b, 0xd1, 0x75, 0xb1, 0x3c, 0x7a, - 0x04, 0x05, 0xea, 0x7b, 0x16, 0xf3, 0x73, 0xd1, 0x3d, 0xd2, 0x18, 0x56, 0xf9, 0x53, 0x0e, 0x4a, - 0xf1, 0x6d, 0x43, 0xdb, 0x90, 0xbf, 0xe8, 0xd8, 0xad, 0x17, 0x8c, 0xf7, 0xdd, 0xa4, 0xfd, 0xad, - 0xec, 0xfa, 0x54, 0x14, 0x7a, 0x30, 0xa1, 0x51, 0x26, 0x9f, 0xfb, 0xda, 0xee, 0x59, 0x1e, 0x0b, - 0xb0, 0x64, 0xee, 0x23, 0x9f, 0xaa, 0xcf, 0x4d, 0x98, 0xd0, 0x1e, 0x14, 0x8d, 0x56, 0x0b, 0xbb, - 0xae, 0x7e, 0x6d, 0xb7, 0x71, 0x39, 0x4b, 0x64, 0x6c, 0x24, 0xca, 0xd8, 0x21, 0xb4, 0x47, 0x76, - 0x1b, 0x6b, 0x60, 0x84, 0xbf, 0xe5, 0x59, 0x28, 0x72, 0xb6, 0xc9, 0xfb, 0x50, 0xe4, 0x94, 0xa1, - 0x45, 0x98, 0xbc, 0x74, 0xf5, 0x30, 0x97, 0xa7, 0xb5, 0xc2, 0xa5, 0x4b, 0xd2, 0xf3, 0x01, 0x14, - 0x89, 0x15, 0xfa, 0x65, 0xc7, 0xb8, 0xa2, 0xc5, 0x67, 0x5a, 0x03, 0x02, 0xfa, 0xa9, 0x0f, 0x91, - 0xff, 0x2d, 0x01, 0xf4, 0x55, 0xa2, 0x6d, 0xc8, 0x11, 0x2b, 0x69, 0x45, 0xd8, 0x1c, 0xc1, 0xca, - 0x0a, 0x31, 0x95, 0x70, 0x29, 0x7f, 0x90, 0x20, 0x47, 0xc4, 0xc4, 0xab, 0xc2, 0x69, 0xad, 0xb1, - 0x5f, 0x57, 0xf5, 0xc6, 0xf1, 0x9e, 0xaa, 0x3f, 0xd5, 0x6a, 0x4d, 0x55, 0x2b, 0x49, 0x68, 0x19, - 0x16, 0x79, 0xb8, 0xa6, 0xee, 0xec, 0xa9, 0x9a, 0x7e, 0xdc, 0xa8, 0x7f, 0x59, 0xca, 0x20, 0x19, - 0xee, 0x1d, 0x9d, 0xd5, 0x9b, 0xb5, 0x41, 0x5c, 0x16, 0xad, 0x40, 0x99, 0xc3, 0x31, 0x19, 0x4c, - 0x6c, 0xce, 0x17, 0xcb, 0x61, 0xe9, 0x4f, 0x86, 0xcc, 0xef, 0xce, 0x86, 0x9b, 0x41, 0x0a, 0xd2, - 0x53, 0x98, 0x8d, 0x54, 0x09, 0xff, 0x6c, 0x72, 0xf0, 0xcb, 0x9e, 0xe9, 0xe0, 0xb6, 0x7e, 0x71, - 0xeb, 0x61, 0x97, 0x78, 0x22, 0xab, 0xcd, 0x06, 0xd0, 0x5d, 0x1f, 0xe8, 0xbb, 0xb5, 0x63, 0x5e, - 0x9b, 0x1e, 0xa3, 0xc9, 0x10, 0x1a, 0x20, 0x20, 0x42, 0xa0, 0xbc, 0x96, 0xa0, 0xc0, 0xf6, 0xe6, - 0x21, 0x57, 0xa7, 0x22, 0x22, 0x03, 0x28, 0x15, 0x39, 0x07, 0x19, 0xb3, 0xcd, 0xd2, 0x21, 0x63, - 0xb6, 0xd1, 0x13, 0x00, 0xc3, 0xf3, 0x1c, 0xf3, 0xa2, 0xe7, 0x85, 0x75, 0xe9, 0x7e, 0x74, 0x3f, - 0x2a, 0x3b, 0x21, 0x01, 0x2b, 0x24, 0x7d, 0x0e, 0x3f, 0xa5, 0x63, 0xe8, 0xb1, 0xd2, 0xf0, 0x3f, - 0x12, 0xcc, 0xef, 0xe1, 0x0e, 0x8e, 0x57, 0xe2, 0x65, 0x98, 0x66, 0x75, 0xd3, 0x6c, 0x33, 0x49, - 0x53, 0x14, 0x50, 0x6b, 0xc7, 0x8a, 0x57, 0x9b, 0xb0, 0x87, 0xc5, 0x2b, 0x13, 0x2d, 0x5e, 0x02, - 0xe1, 0x5c, 0xf1, 0xa2, 0xd8, 0xa4, 0xe2, 0x15, 0xc1, 0x46, 0xab, 0xcf, 0x20, 0xe3, 0x58, 0xcb, - 0xbe, 0x07, 0x0b, 0x51, 0xc3, 0xd8, 0xc1, 0xf4, 0xd7, 0x1c, 0xdc, 0xef, 0x2b, 0x39, 0xe9, 0x5d, - 0x74, 0x4c, 0xf7, 0xf9, 0x18, 0x9e, 0x59, 0x84, 0x49, 0xcb, 0x6e, 0x13, 0x14, 0xd5, 0x59, 0xf0, - 0x3f, 0x6b, 0x6d, 0xa4, 0xc2, 0x9d, 0xf8, 0x39, 0x74, 0xcb, 0x6a, 0x44, 0xf2, 0x29, 0x54, 0xba, - 0x89, 0x17, 0x38, 0x19, 0xa6, 0x1c, 0x6c, 0xb4, 0x6d, 0xab, 0x73, 0x5b, 0xce, 0xad, 0x49, 0x9b, - 0x53, 0x5a, 0xf8, 0x8d, 0x7e, 0x25, 0x81, 0xcc, 0x6d, 0x4b, 0x97, 0x1a, 0x1f, 0x3b, 0x54, 0xf6, - 0xc2, 0x43, 0x25, 0x75, 0x95, 0x83, 0xe8, 0xc8, 0x1e, 0x95, 0x5b, 0x09, 0x68, 0x64, 0x86, 0xeb, - 0xe4, 0xa2, 0xba, 0x40, 0x54, 0x6f, 0x8f, 0xa8, 0x9a, 0x7e, 0xc5, 0x63, 0x9e, 0xf9, 0xa2, 0x0f, - 0x96, 0x0f, 0x61, 0x35, 0xd5, 0xca, 0xb1, 0x8e, 0xb6, 0x2a, 0xdc, 0x15, 0xea, 0x1d, 0x2b, 0xaa, - 0x5e, 0x4b, 0xf0, 0x20, 0x71, 0x71, 0xec, 0x7c, 0xfb, 0x19, 0xcc, 0x04, 0x3b, 0x63, 0x5a, 0x97, - 0x76, 0x59, 0x8a, 0x9d, 0xf5, 0xe9, 0xec, 0x15, 0x06, 0xf5, 0x1b, 0x62, 0xea, 0x97, 0x62, 0xb7, - 0x0f, 0x91, 0x9f, 0x40, 0x29, 0x4e, 0x30, 0xd6, 0x02, 0xfe, 0x9c, 0x81, 0xb5, 0xbe, 0x05, 0x67, - 0x56, 0xf7, 0xed, 0x25, 0xc0, 0x6f, 0x24, 0x58, 0xe1, 0xa2, 0xb3, 0x67, 0xc5, 0xe3, 0x93, 0x96, - 0xbe, 0x83, 0x41, 0x47, 0x88, 0xcd, 0x10, 0x11, 0x44, 0x62, 0x94, 0xcb, 0x85, 0x38, 0x81, 0x7c, - 0xc4, 0xef, 0x93, 0x90, 0x7d, 0x2c, 0xb7, 0x6d, 0xc0, 0x7a, 0x8a, 0xb9, 0xac, 0xb4, 0xbc, 0xce, - 0xc0, 0xfa, 0xb9, 0xd1, 0x31, 0xdb, 0x61, 0xcf, 0x23, 0x98, 0x33, 0xd2, 0x9d, 0x9b, 0xd0, 0xcc, - 0x66, 0xbe, 0x41, 0x33, 0xdb, 0x11, 0xe5, 0x29, 0xdd, 0x82, 0x1f, 0x87, 0x82, 0x86, 0x59, 0x3b, - 0x72, 0xaa, 0xbe, 0x95, 0xec, 0xfa, 0x0a, 0x94, 0x34, 0x8b, 0x58, 0x7e, 0xad, 0xc0, 0xb4, 0xdb, - 0xeb, 0x76, 0x6d, 0xc7, 0xc3, 0xd4, 0x81, 0x53, 0x5a, 0x1f, 0x80, 0xca, 0x30, 0x79, 0x8d, 0x5d, - 0xd7, 0xb8, 0x0a, 0xe4, 0x07, 0x9f, 0xca, 0x57, 0x80, 0xea, 0xa6, 0xcb, 0x1a, 0xad, 0x70, 0x3b, - 0xfc, 0xbe, 0xca, 0x78, 0xa5, 0x63, 0xcb, 0x73, 0x4c, 0x76, 0xa2, 0xe7, 0x35, 0xb8, 0x36, 0x5e, - 0xa9, 0x14, 0xe2, 0x9f, 0xfa, 0xae, 0x67, 0x38, 0x9e, 0x69, 0x5d, 0xe9, 0x9e, 0xfd, 0x02, 0x87, - 0x43, 0x6e, 0x00, 0x6d, 0xfa, 0x40, 0xe5, 0x8f, 0x12, 0xcc, 0x47, 0xc4, 0x33, 0x6b, 0x1f, 0xc3, - 0x64, 0x5f, 0xb6, 0xef, 0xfc, 0xf5, 0xc0, 0xf9, 0x02, 0xea, 0x0a, 0x75, 0x6f, 0xc0, 0x81, 0x56, - 0x01, 0x2c, 0xfc, 0xca, 0x8b, 0xe8, 0x9d, 0xf6, 0x21, 0x44, 0xa7, 0xfc, 0x09, 0xe4, 0xa9, 0x93, - 0x47, 0x6d, 0xa9, 0xff, 0x25, 0x01, 0xda, 0xc7, 0x5e, 0xd8, 0x29, 0x31, 0x1f, 0x24, 0x44, 0x9d, - 0xf4, 0x0d, 0xa2, 0xee, 0x8b, 0xc8, 0x08, 0x45, 0xe3, 0xf6, 0x03, 0x6e, 0xda, 0x8f, 0xa9, 0x4e, - 0x9b, 0xa0, 0xde, 0x70, 0x96, 0x51, 0xf6, 0x60, 0x3e, 0xa2, 0x90, 0x6d, 0xc8, 0xc7, 0x80, 0x8c, - 0x1b, 0xc3, 0xec, 0x18, 0x17, 0x1d, 0xba, 0x5e, 0x1f, 0xcb, 0x3a, 0xb9, 0x3b, 0x21, 0x26, 0x60, - 0x53, 0x14, 0xbe, 0x5e, 0x32, 0x79, 0xf1, 0xab, 0x83, 0x0e, 0x5f, 0x1d, 0x06, 0x68, 0x98, 0xde, - 0x7d, 0xe1, 0xf5, 0xc1, 0xc6, 0x60, 0x35, 0x64, 0x33, 0x7a, 0xe2, 0x4d, 0xc2, 0xef, 0x33, 0xb0, - 0x9c, 0x42, 0x8d, 0x1e, 0x43, 0xd6, 0xe9, 0xb6, 0x58, 0x24, 0xbc, 0x37, 0x82, 0xfc, 0x8a, 0x76, - 0x52, 0x3d, 0x98, 0xd0, 0x7c, 0x2e, 0xf9, 0x2f, 0x12, 0x64, 0xb5, 0x93, 0x2a, 0xfa, 0x49, 0xe4, - 0x42, 0xe1, 0xa3, 0x11, 0xa5, 0xf0, 0xf7, 0x0a, 0xb6, 0xe8, 0x5e, 0xa1, 0x0c, 0x0b, 0x55, 0x4d, - 0xdd, 0x69, 0xaa, 0xfa, 0x9e, 0x5a, 0x57, 0x9b, 0xaa, 0x7e, 0x7e, 0x5c, 0x3f, 0x3b, 0x52, 0x4b, - 0x92, 0x3f, 0x0a, 0x9c, 0x9c, 0xed, 0xd6, 0x6b, 0xa7, 0x07, 0xfa, 0x59, 0x23, 0xf8, 0xc5, 0xb0, - 0x19, 0x54, 0x82, 0x99, 0x7a, 0xed, 0xb4, 0xc9, 0x00, 0xa7, 0xa5, 0xac, 0x0f, 0xd9, 0x57, 0x9b, - 0x7a, 0x75, 0xe7, 0x64, 0xa7, 0x5a, 0x6b, 0x7e, 0x59, 0xca, 0x85, 0x77, 0x13, 0xbf, 0xcd, 0xc3, - 0xbd, 0x86, 0xdd, 0xc6, 0xa7, 0x9e, 0x71, 0x35, 0x4e, 0xcf, 0xab, 0xc5, 0xce, 0x6d, 0xba, 0x41, - 0x9f, 0x04, 0x4b, 0x17, 0x8b, 0x4c, 0x3f, 0xae, 0x51, 0x05, 0xe6, 0x5d, 0xcf, 0xb8, 0x22, 0xb5, - 0xc3, 0x70, 0xae, 0xb0, 0xa7, 0x77, 0x0d, 0xef, 0x39, 0x69, 0x0b, 0xa7, 0xb5, 0x3b, 0x0c, 0xd5, - 0x24, 0x98, 0x13, 0xc3, 0x7b, 0x2e, 0x6e, 0x22, 0x73, 0x63, 0x37, 0x91, 0x17, 0x80, 0xc8, 0x19, - 0xed, 0x2b, 0x88, 0x5f, 0x3a, 0x7c, 0x7f, 0xc8, 0x82, 0x42, 0x70, 0xe4, 0xac, 0x2d, 0x59, 0x31, - 0x30, 0x32, 0x92, 0xfb, 0xc0, 0x61, 0x2a, 0x46, 0x3d, 0x54, 0xde, 0xb0, 0xd9, 0xf1, 0x0f, 0x25, - 0xe1, 0x6a, 0xbe, 0xfd, 0xbe, 0x71, 0x09, 0x16, 0x07, 0x7c, 0xc1, 0xba, 0x86, 0x2b, 0x28, 0xfb, - 0xa8, 0x33, 0xcb, 0x1d, 0x33, 0x5e, 0x13, 0x62, 0x2b, 0x93, 0x10, 0x5b, 0xca, 0x32, 0x2c, 0x09, - 0x14, 0x31, 0x2b, 0xfe, 0x99, 0xa7, 0x66, 0x8c, 0x3f, 0x10, 0x35, 0x85, 0x69, 0xf3, 0x5d, 0x3e, - 0x04, 0x84, 0x43, 0xc0, 0xdb, 0x4d, 0x9c, 0x07, 0x50, 0xe4, 0xe9, 0x72, 0x84, 0x0e, 0xbc, 0x21, - 0x99, 0x95, 0x7f, 0xa3, 0xf1, 0xac, 0x10, 0x1b, 0xcf, 0x7e, 0x01, 0x0b, 0x24, 0xeb, 0xe2, 0x7d, - 0xef, 0x64, 0x74, 0x00, 0x48, 0xf4, 0x08, 0x87, 0x88, 0xe4, 0x1e, 0xc9, 0xe5, 0xd8, 0x14, 0xd6, - 0x12, 0x65, 0xdf, 0x14, 0x51, 0xf4, 0xe9, 0x50, 0x45, 0xdf, 0x56, 0xfe, 0xa9, 0x34, 0xea, 0xff, - 0x2f, 0x26, 0x37, 0x16, 0xfd, 0xc2, 0x99, 0x4b, 0x79, 0x06, 0x32, 0x4d, 0x8d, 0xf1, 0xc7, 0xa1, - 0x58, 0xe0, 0x65, 0xe2, 0x81, 0xa7, 0xac, 0xc2, 0xb2, 0x50, 0x36, 0x53, 0x8d, 0xa0, 0xe4, 0xa3, - 0xf7, 0xb1, 0x57, 0x6b, 0x07, 0xfd, 0xc4, 0x47, 0x70, 0x87, 0x83, 0xb1, 0xfe, 0x81, 0x9b, 0xbb, - 0x24, 0x7e, 0xee, 0x52, 0x56, 0xa8, 0xf1, 0x09, 0xbd, 0xc9, 0xd7, 0x54, 0x7d, 0x52, 0x57, 0xb2, - 0x13, 0xeb, 0x4a, 0x68, 0xcf, 0xb7, 0x1a, 0x29, 0xe0, 0x43, 0xfa, 0x91, 0xbf, 0x49, 0xac, 0xcc, - 0x0e, 0x74, 0x22, 0x3f, 0xe0, 0x3b, 0x91, 0xf5, 0x54, 0x99, 0x7c, 0x0f, 0xd2, 0xa5, 0x2d, 0xc8, - 0xe7, 0x91, 0x16, 0xe4, 0xd1, 0x50, 0x76, 0xbe, 0xf9, 0xf8, 0x38, 0xa1, 0xf9, 0x38, 0x6d, 0xee, - 0xec, 0xab, 0xfa, 0x59, 0x83, 0xfe, 0x0d, 0x9a, 0x8f, 0xa0, 0x75, 0xd8, 0xfa, 0xaf, 0x04, 0x53, - 0xb5, 0x36, 0xb6, 0x3c, 0xdf, 0xfa, 0x06, 0xcc, 0x46, 0x9e, 0xa7, 0xd0, 0x4a, 0xc2, 0xab, 0x15, - 0x71, 0xb4, 0xbc, 0x9a, 0xfa, 0xa6, 0xa5, 0x4c, 0xa0, 0x4b, 0xee, 0x69, 0x2d, 0xd2, 0x33, 0xbf, - 0x3b, 0xc0, 0x29, 0xd8, 0x48, 0xf9, 0xe1, 0x10, 0xaa, 0x50, 0xcf, 0xa7, 0x90, 0x27, 0x6f, 0x31, - 0x68, 0x21, 0x7c, 0x06, 0xe2, 0x9e, 0x6a, 0xe4, 0xbb, 0x31, 0x68, 0xc0, 0xb7, 0xf5, 0xeb, 0x02, - 0x40, 0xbf, 0xbf, 0x43, 0x87, 0x30, 0xc3, 0x5f, 0xdf, 0xa3, 0xe5, 0x94, 0xc7, 0x0a, 0x79, 0x45, - 0x8c, 0x0c, 0x6d, 0x3a, 0x84, 0x19, 0xfe, 0x36, 0xae, 0x2f, 0x4c, 0x70, 0x79, 0xd8, 0x17, 0x26, - 0xbc, 0xc0, 0x9b, 0x40, 0x1d, 0x58, 0x4c, 0xb8, 0x44, 0x41, 0x8f, 0x46, 0xbb, 0x81, 0x92, 0xdf, - 0x1b, 0xf1, 0x36, 0x46, 0x99, 0x40, 0x0e, 0x2c, 0x25, 0x8e, 0xfe, 0x68, 0x73, 0xd4, 0xcb, 0x0c, - 0xf9, 0xfd, 0x11, 0x28, 0x43, 0x9d, 0x3d, 0x90, 0x93, 0x07, 0x61, 0xf4, 0xfe, 0xc8, 0xe3, 0xbb, - 0xfc, 0xc1, 0x28, 0xa4, 0xa1, 0xda, 0x03, 0x28, 0x72, 0x43, 0x29, 0x92, 0x85, 0x93, 0x2a, 0x15, - 0xbc, 0x9c, 0x32, 0xc5, 0x52, 0x49, 0xdc, 0xec, 0xd5, 0x97, 0x34, 0x38, 0x01, 0xf6, 0x25, 0x09, - 0x86, 0xb5, 0xb8, 0xfb, 0x63, 0x55, 0x4c, 0xe4, 0x7e, 0x71, 0x19, 0x14, 0xb9, 0x3f, 0xa1, 0x24, - 0x2a, 0x13, 0x5b, 0xbf, 0xcb, 0x41, 0xce, 0x2f, 0x33, 0xa8, 0x09, 0xef, 0xc4, 0xda, 0x36, 0x74, - 0x3f, 0xbd, 0xb7, 0x95, 0x1f, 0x24, 0xe2, 0xc3, 0x25, 0x3d, 0xa3, 0xe5, 0x3d, 0xd2, 0x88, 0xa1, - 0x35, 0x9e, 0x4f, 0xd4, 0x0c, 0xca, 0xeb, 0x29, 0x14, 0x71, 0xd9, 0xd1, 0xac, 0x58, 0x1b, 0xd6, - 0x11, 0x44, 0x65, 0x27, 0x65, 0xc2, 0xd7, 0x30, 0x2f, 0x38, 0xc9, 0x90, 0x12, 0xb5, 0x4b, 0x18, - 0xfd, 0x1b, 0xa9, 0x34, 0xa1, 0x86, 0x5d, 0x98, 0x0e, 0x0f, 0x3e, 0x54, 0xe6, 0x79, 0xf8, 0xf3, - 0x51, 0x5e, 0x12, 0x60, 0xe2, 0x56, 0xc6, 0x43, 0x45, 0x89, 0xf1, 0x88, 0x82, 0x64, 0x23, 0x95, - 0x26, 0xd0, 0xb0, 0x9b, 0x7f, 0x96, 0x6d, 0xb9, 0xe6, 0x45, 0x81, 0xfc, 0x4b, 0xc5, 0xf7, 0xfe, - 0x17, 0x00, 0x00, 0xff, 0xff, 0x69, 0xaa, 0xdb, 0x41, 0x5f, 0x21, 0x00, 0x00, +var fileDescriptor_csi_31237507707d37ec = []byte{ + // 2932 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x1a, 0x4d, 0x73, 0x23, 0x47, + 0xd5, 0xa3, 0x0f, 0xdb, 0x7a, 0x5e, 0x3b, 0xda, 0xf6, 0x97, 0x3c, 0xb6, 0x77, 0xbd, 0xb3, 0xd9, + 0x64, 0x13, 0x12, 0x6d, 0x30, 0x24, 0x15, 0x92, 0x4d, 0x40, 0x96, 0x15, 0x5b, 0x59, 0x5b, 0x36, + 0x23, 0xd9, 0xa9, 0x5d, 0x42, 0x4d, 0xc6, 0x52, 0x5b, 0x3b, 0xac, 0x3c, 0xa3, 0xcc, 0x8c, 0xcc, + 0x9a, 0x1b, 0x70, 0x01, 0x4e, 0xf0, 0x0b, 0x52, 0x95, 0x1b, 0x14, 0xb9, 0x50, 0xdc, 0xa8, 0xe2, + 0x46, 0x15, 0x27, 0xce, 0x9c, 0xb8, 0xa7, 0xe0, 0xc8, 0x89, 0x2a, 0xaa, 0xa8, 0x9e, 0xee, 0x19, + 0x4d, 0xb7, 0x7a, 0xf4, 0x91, 0xdd, 0x4a, 0x71, 0x92, 0xe6, 0x7d, 0xf5, 0xeb, 0xd7, 0xef, 0xbd, + 0x7e, 0xef, 0xcd, 0x40, 0xae, 0xe9, 0x59, 0xc5, 0xae, 0xeb, 0xf8, 0x0e, 0x9a, 0x26, 0x7f, 0x2f, + 0xdf, 0x50, 0x6f, 0xb4, 0x1d, 0xa7, 0xdd, 0xc1, 0xf7, 0x02, 0xe8, 0x59, 0xef, 0xfc, 0xde, 0x8f, + 0x5d, 0xb3, 0xdb, 0xc5, 0xae, 0x47, 0xe9, 0xb4, 0x15, 0x58, 0xda, 0xc3, 0xfe, 0x71, 0xa7, 0xd7, + 0xb6, 0xec, 0xaa, 0x7d, 0xee, 0xe8, 0xf8, 0xd3, 0x1e, 0xf6, 0x7c, 0xed, 0xef, 0x0a, 0x2c, 0x0b, + 0x08, 0xaf, 0xeb, 0xd8, 0x1e, 0x46, 0x08, 0x32, 0xb6, 0x79, 0x81, 0x0b, 0xca, 0x96, 0x72, 0x37, + 0xa7, 0x07, 0xff, 0xd1, 0x1d, 0x58, 0xb8, 0xc4, 0x76, 0xcb, 0x71, 0x8d, 0x4b, 0xec, 0x7a, 0x96, + 0x63, 0x17, 0x52, 0x01, 0x76, 0x9e, 0x42, 0x4f, 0x29, 0x10, 0xed, 0xc1, 0xec, 0x85, 0x69, 0x5b, + 0xe7, 0xd8, 0xf3, 0x0b, 0xe9, 0xad, 0xf4, 0xdd, 0xb9, 0xed, 0x6f, 0x14, 0xa9, 0x9e, 0x45, 0xe9, + 0x5a, 0xc5, 0x43, 0x46, 0x5d, 0xb1, 0x7d, 0xf7, 0x4a, 0x8f, 0x98, 0xd5, 0x77, 0x61, 0x9e, 0x43, + 0xa1, 0x3c, 0xa4, 0x9f, 0xe0, 0x2b, 0xa6, 0x13, 0xf9, 0x8b, 0x96, 0x20, 0x7b, 0x69, 0x76, 0x7a, + 0x98, 0x69, 0x42, 0x1f, 0xde, 0x49, 0xbd, 0xad, 0x68, 0x37, 0x60, 0x23, 0x5a, 0xad, 0x6c, 0x76, + 0xcd, 0x33, 0xab, 0x63, 0xf9, 0x16, 0xf6, 0xc2, 0xad, 0xff, 0x10, 0x36, 0x13, 0xf0, 0xcc, 0x02, + 0xf7, 0xe1, 0x5a, 0x33, 0x06, 0x2f, 0xa4, 0x82, 0xad, 0x14, 0xc2, 0xad, 0x08, 0x9c, 0x57, 0x3a, + 0x47, 0xad, 0xfd, 0x53, 0x81, 0xbc, 0x48, 0x82, 0xee, 0xc3, 0x8c, 0x87, 0xdd, 0x4b, 0xab, 0x49, + 0xed, 0x3a, 0xb7, 0xbd, 0x95, 0x24, 0xad, 0x58, 0xa7, 0x74, 0xfb, 0x53, 0x7a, 0xc8, 0xa2, 0xfe, + 0x5a, 0x81, 0x19, 0x06, 0x46, 0xdf, 0x81, 0x8c, 0x7f, 0xd5, 0xa5, 0x62, 0x16, 0xb6, 0xef, 0x8c, + 0x12, 0x53, 0x6c, 0x5c, 0x75, 0xb1, 0x1e, 0xb0, 0x68, 0x1f, 0x42, 0x86, 0x3c, 0xa1, 0x39, 0x98, + 0x39, 0xa9, 0x3d, 0xa8, 0x1d, 0x7d, 0x54, 0xcb, 0x4f, 0xa1, 0x15, 0x40, 0xe5, 0xa3, 0x5a, 0x43, + 0x3f, 0x3a, 0x38, 0xa8, 0xe8, 0x46, 0xbd, 0xa2, 0x9f, 0x56, 0xcb, 0x95, 0xbc, 0x82, 0x36, 0x61, + 0xad, 0x54, 0x2e, 0x57, 0xea, 0xf5, 0xea, 0x4e, 0xf5, 0xa0, 0xda, 0x78, 0x68, 0x94, 0x8f, 0x6a, + 0xf5, 0x86, 0x5e, 0xaa, 0xd6, 0x1a, 0xf5, 0x7c, 0x6a, 0x67, 0x9a, 0xaa, 0xa1, 0x2d, 0xc0, 0xb5, + 0x63, 0xd7, 0x39, 0xc3, 0xa1, 0x71, 0x4b, 0x30, 0xcf, 0x9e, 0x99, 0x31, 0xdf, 0x80, 0xac, 0x8b, + 0xcd, 0xd6, 0x15, 0xdb, 0xb7, 0x5a, 0xa4, 0x0e, 0x5b, 0x0c, 0x1d, 0xb6, 0xb8, 0xe3, 0x38, 0x9d, + 0x53, 0x72, 0x78, 0x3a, 0x25, 0xd4, 0xbe, 0xc8, 0xc2, 0x62, 0xd9, 0xc5, 0xa6, 0x8f, 0x4f, 0x9d, + 0x4e, 0xef, 0x22, 0x14, 0x2d, 0x75, 0xcc, 0xfb, 0xb0, 0x40, 0x8c, 0xdf, 0xb4, 0xfc, 0x2b, 0xc3, + 0x35, 0xed, 0x36, 0x75, 0x87, 0xb9, 0xed, 0xe5, 0xd0, 0x2e, 0x65, 0x86, 0xd5, 0x09, 0x52, 0x9f, + 0x6f, 0xc6, 0x1f, 0x51, 0x15, 0x16, 0x2f, 0x83, 0x25, 0x0c, 0xee, 0xbc, 0xd3, 0xfc, 0x79, 0x53, + 0x2d, 0x62, 0xe7, 0x8d, 0x2e, 0x79, 0x88, 0x85, 0x3d, 0xf4, 0x00, 0xa0, 0x6b, 0xba, 0xe6, 0x05, + 0xf6, 0xb1, 0xeb, 0x15, 0x32, 0xbc, 0xf3, 0x4b, 0x76, 0x53, 0x3c, 0x8e, 0xa8, 0xa9, 0xf3, 0xc7, + 0xd8, 0x91, 0x0f, 0x6b, 0x4d, 0xc7, 0xf6, 0x5d, 0xa7, 0xd3, 0xc1, 0xae, 0xd1, 0x0c, 0xb8, 0x0d, + 0x0f, 0x37, 0x5d, 0xec, 0x7b, 0x85, 0x6c, 0x20, 0xfb, 0xed, 0x61, 0xb2, 0xcb, 0x11, 0x33, 0xc5, + 0xd6, 0x29, 0x2b, 0x5d, 0x68, 0xb5, 0x29, 0xc7, 0xa2, 0x23, 0x58, 0x0e, 0xad, 0xe1, 0xd8, 0x3e, + 0xb6, 0x7d, 0xc3, 0x73, 0x7a, 0x6e, 0x13, 0x17, 0xa6, 0x03, 0x93, 0xae, 0x0b, 0xf6, 0xa0, 0x34, + 0xf5, 0x80, 0x44, 0x67, 0x76, 0xe4, 0x80, 0xe8, 0x11, 0xa8, 0x66, 0xb3, 0x89, 0x3d, 0xcf, 0xa2, + 0x86, 0x33, 0x5c, 0xfc, 0x69, 0xcf, 0x72, 0xf1, 0x05, 0xb6, 0x7d, 0xaf, 0x30, 0xc3, 0x4b, 0x6d, + 0x38, 0x5d, 0xa7, 0xe3, 0xb4, 0xaf, 0xf4, 0x3e, 0x8d, 0xbe, 0xc6, 0xb1, 0xc7, 0x30, 0x9e, 0xfa, + 0x1e, 0xbc, 0x20, 0x58, 0x70, 0x92, 0x1c, 0xa1, 0x7e, 0x08, 0x1b, 0xc3, 0x8c, 0x34, 0x51, 0xbe, + 0xf9, 0xa5, 0x02, 0x8b, 0x12, 0x9b, 0xa0, 0x7d, 0x98, 0xf5, 0x6c, 0xb3, 0xeb, 0x3d, 0x76, 0x7c, + 0xe6, 0xfc, 0xaf, 0x0e, 0x31, 0x61, 0xb1, 0xce, 0x68, 0xe9, 0xe3, 0xfe, 0x94, 0x1e, 0x71, 0xab, + 0x5b, 0xb0, 0xc0, 0x63, 0xd1, 0x02, 0xa4, 0xac, 0x16, 0x53, 0x2f, 0x65, 0xb5, 0xa2, 0x70, 0x7c, + 0x1f, 0x96, 0x78, 0x87, 0x60, 0x51, 0xf8, 0x12, 0x4c, 0xd3, 0x13, 0x62, 0x9a, 0x2c, 0xf0, 0x9a, + 0xe8, 0x0c, 0xab, 0xfd, 0x2e, 0x03, 0x79, 0xd1, 0xdf, 0xd1, 0x7d, 0xc8, 0x9e, 0x75, 0x9c, 0xe6, + 0x13, 0xc6, 0xfb, 0x62, 0x52, 0x60, 0x14, 0x77, 0x08, 0x15, 0x85, 0xee, 0x4f, 0xe9, 0x94, 0x89, + 0x70, 0x5f, 0x38, 0x3d, 0xdb, 0x67, 0x91, 0x99, 0xcc, 0x7d, 0x48, 0xa8, 0xfa, 0xdc, 0x01, 0x13, + 0xda, 0x85, 0x39, 0xea, 0x04, 0xc6, 0x85, 0xd3, 0xc2, 0x85, 0x74, 0x20, 0xe3, 0x76, 0xa2, 0x8c, + 0x52, 0x40, 0x7b, 0xe8, 0xb4, 0xb0, 0x0e, 0x66, 0xf4, 0x5f, 0x9d, 0x87, 0xb9, 0x98, 0x6e, 0xea, + 0x1e, 0xcc, 0xc5, 0x16, 0x43, 0xab, 0x30, 0x73, 0xee, 0x19, 0x51, 0x56, 0xcd, 0xe9, 0xd3, 0xe7, + 0x5e, 0x90, 0x28, 0x6f, 0xc2, 0x5c, 0xa0, 0x85, 0x71, 0xde, 0x31, 0xdb, 0xf4, 0x1e, 0xc8, 0xe9, + 0x10, 0x80, 0x3e, 0x20, 0x10, 0xf5, 0x5f, 0x0a, 0x40, 0x7f, 0x49, 0x74, 0x1f, 0x32, 0x81, 0x96, + 0x34, 0x37, 0xdf, 0x1d, 0x43, 0xcb, 0x62, 0xa0, 0x6a, 0xc0, 0xa5, 0x7d, 0xa6, 0x40, 0x26, 0x10, + 0x23, 0xe6, 0xe7, 0x7a, 0xb5, 0xb6, 0x77, 0x50, 0x31, 0x6a, 0x47, 0xbb, 0x15, 0xe3, 0x23, 0xbd, + 0xda, 0xa8, 0xe8, 0x79, 0x05, 0xad, 0xc3, 0x6a, 0x1c, 0xae, 0x57, 0x4a, 0xbb, 0x15, 0xdd, 0x38, + 0xaa, 0x1d, 0x3c, 0xcc, 0xa7, 0x90, 0x0a, 0x2b, 0x87, 0x27, 0x07, 0x8d, 0xea, 0x20, 0x2e, 0x8d, + 0x36, 0xa0, 0x10, 0xc3, 0x31, 0x19, 0x4c, 0x6c, 0x86, 0x88, 0x8d, 0x61, 0xe9, 0x5f, 0x86, 0xcc, + 0xee, 0xcc, 0x47, 0x87, 0x11, 0x38, 0xdb, 0x47, 0x30, 0xcf, 0xa5, 0x57, 0x52, 0x26, 0xb0, 0x10, + 0x6f, 0x19, 0x67, 0x57, 0x3e, 0xf6, 0x02, 0x4b, 0xa4, 0xf5, 0xf9, 0x10, 0xba, 0x43, 0x80, 0xc4, + 0xac, 0x1d, 0xeb, 0xc2, 0xf2, 0x19, 0x4d, 0x2a, 0xa0, 0x81, 0x00, 0x14, 0x10, 0x68, 0x7f, 0x49, + 0xc1, 0x34, 0x3b, 0x9b, 0x3b, 0xb1, 0x04, 0xcf, 0x89, 0x0c, 0xa1, 0x54, 0x24, 0x8d, 0x87, 0x54, + 0x18, 0x0f, 0xe8, 0x7d, 0x00, 0xd3, 0xf7, 0x5d, 0xeb, 0xac, 0xe7, 0x47, 0x09, 0xfd, 0x06, 0x7f, + 0x1e, 0xc5, 0x52, 0x44, 0xc0, 0x32, 0x70, 0x9f, 0x03, 0xed, 0xc0, 0x82, 0x90, 0x04, 0x33, 0xa3, + 0x93, 0xe0, 0x7c, 0x93, 0x8b, 0xff, 0x12, 0x2c, 0x86, 0xf9, 0xab, 0x83, 0x0d, 0x9f, 0xe5, 0x37, + 0x96, 0xbf, 0xf3, 0x03, 0x79, 0x0f, 0xf5, 0x89, 0x43, 0x18, 0xc9, 0x72, 0x82, 0x96, 0x13, 0x65, + 0xa6, 0x1e, 0x2c, 0x4a, 0xd2, 0x2a, 0x2a, 0x42, 0x2e, 0x38, 0x10, 0xcf, 0xf2, 0x89, 0xaf, 0xca, + 0xd5, 0xe9, 0x93, 0x10, 0xfa, 0xae, 0x8b, 0xcf, 0xb1, 0xeb, 0xe2, 0x16, 0x2b, 0x86, 0x24, 0xf4, + 0x11, 0x89, 0xf6, 0x73, 0x05, 0x66, 0x43, 0x38, 0x7a, 0x07, 0x66, 0x3d, 0xdc, 0xa6, 0x29, 0x5f, + 0xe1, 0xcf, 0x21, 0xa4, 0x29, 0xd6, 0x19, 0x01, 0x2b, 0x03, 0x43, 0x7a, 0x52, 0x06, 0x72, 0xa8, + 0x89, 0x36, 0xff, 0x6f, 0x05, 0x16, 0x77, 0x71, 0x07, 0x8b, 0x65, 0xc4, 0x3a, 0xe4, 0xd8, 0x35, + 0x17, 0x65, 0xd0, 0x59, 0x0a, 0xa8, 0xb6, 0x84, 0x9b, 0xb7, 0x15, 0xb0, 0x47, 0x37, 0x6f, 0x8a, + 0xbf, 0x79, 0x25, 0xc2, 0x63, 0x37, 0x2f, 0xc5, 0x26, 0xdd, 0xbc, 0x1c, 0x96, 0xbf, 0x8d, 0x06, + 0x19, 0x27, 0xda, 0xf6, 0x0a, 0x2c, 0xf1, 0x8a, 0xd1, 0x1b, 0x40, 0xfb, 0x53, 0x06, 0x6e, 0xf4, + 0x17, 0x39, 0xee, 0x9d, 0x75, 0x2c, 0xef, 0xf1, 0x04, 0x96, 0x59, 0x85, 0x19, 0xdb, 0x69, 0x05, + 0x28, 0xba, 0xe6, 0x34, 0x79, 0xac, 0xb6, 0x50, 0x05, 0xae, 0x8b, 0x45, 0xd4, 0x15, 0xcb, 0xd3, + 0xc9, 0x25, 0x54, 0xfe, 0x52, 0xbc, 0x64, 0x54, 0x98, 0x25, 0xe5, 0x9f, 0x63, 0x77, 0xae, 0x82, + 0x58, 0x9b, 0xd5, 0xa3, 0x67, 0xf4, 0x33, 0x05, 0xd4, 0xd8, 0xb1, 0x74, 0xa9, 0xf2, 0x42, 0x45, + 0xb4, 0x1b, 0x55, 0x44, 0x43, 0x77, 0x39, 0x88, 0xe6, 0xce, 0xa8, 0xd0, 0x4c, 0x40, 0x23, 0x2b, + 0xda, 0x67, 0x2c, 0xb3, 0x4c, 0x07, 0x4b, 0xdf, 0x1f, 0x73, 0x69, 0xfa, 0x24, 0xe6, 0x1d, 0x66, + 0x8b, 0x3e, 0x58, 0x7d, 0x00, 0x9b, 0x43, 0xb5, 0x9c, 0xa8, 0xd4, 0x29, 0xc3, 0xb2, 0x74, 0xdd, + 0x89, 0xbc, 0xea, 0xcf, 0x0a, 0xdc, 0x4c, 0xdc, 0x1c, 0xab, 0x31, 0x7e, 0x00, 0xd7, 0xc2, 0x93, + 0xb1, 0xec, 0x73, 0x87, 0x45, 0xfb, 0xdb, 0x23, 0x6d, 0xc3, 0x7a, 0x41, 0x06, 0x25, 0xfd, 0x21, + 0xb5, 0xcb, 0x5c, 0xb7, 0x0f, 0x51, 0xdf, 0x87, 0xbc, 0x48, 0x30, 0xd1, 0x06, 0xfe, 0x98, 0x82, + 0xad, 0xbe, 0x06, 0x27, 0x76, 0xf7, 0xf9, 0x05, 0xc0, 0xaf, 0x14, 0xd8, 0x88, 0x79, 0x67, 0xcf, + 0x16, 0xfd, 0x93, 0x5e, 0x3f, 0xfb, 0x83, 0x86, 0x90, 0xab, 0x21, 0x23, 0xe0, 0x7c, 0x34, 0x16, + 0x0b, 0x22, 0x81, 0x7a, 0x18, 0x3f, 0x27, 0x29, 0xfb, 0x44, 0x66, 0xbb, 0x0d, 0xb7, 0x86, 0xa8, + 0xcb, 0x52, 0xcb, 0x4f, 0xd3, 0x70, 0xeb, 0xd4, 0xec, 0x58, 0xad, 0xa8, 0xee, 0x94, 0xb4, 0xdd, + 0xc3, 0x8d, 0x9b, 0xd0, 0x89, 0xa5, 0xbe, 0x42, 0x27, 0xd6, 0x91, 0xc5, 0x29, 0x3d, 0x82, 0xef, + 0x46, 0x82, 0x46, 0x69, 0x3b, 0x6e, 0xa8, 0x26, 0x5d, 0xf2, 0x99, 0x09, 0x2e, 0xf9, 0xe7, 0x12, + 0xa0, 0x1f, 0x83, 0x36, 0x6c, 0x53, 0x2c, 0x44, 0x37, 0x20, 0xe7, 0xf5, 0xba, 0x5d, 0xc7, 0xf5, + 0x31, 0x3d, 0x83, 0x59, 0xbd, 0x0f, 0x40, 0x05, 0x98, 0xb9, 0xc0, 0x9e, 0x67, 0xb6, 0x43, 0xf9, + 0xe1, 0xa3, 0xf6, 0x31, 0xa0, 0x03, 0xcb, 0x63, 0xf5, 0x72, 0x74, 0xa2, 0xa4, 0x3c, 0x36, 0x9f, + 0x1a, 0xd8, 0xf6, 0x5d, 0x8b, 0x15, 0x66, 0x59, 0x1d, 0x2e, 0xcc, 0xa7, 0x15, 0x0a, 0x21, 0xc5, + 0x9b, 0xe7, 0x9b, 0xae, 0x6f, 0xd9, 0x6d, 0xc3, 0x77, 0x9e, 0xe0, 0x68, 0x6c, 0x14, 0x42, 0x1b, + 0x04, 0xa8, 0x7d, 0xae, 0xc0, 0x22, 0x27, 0x9e, 0x69, 0xfb, 0x2e, 0xcc, 0xf4, 0x65, 0x13, 0x7b, + 0xde, 0x0a, 0xed, 0x29, 0xa1, 0x2e, 0xd2, 0x13, 0x0a, 0x39, 0xd0, 0x26, 0x80, 0x8d, 0x9f, 0xfa, + 0xdc, 0xba, 0x39, 0x02, 0x09, 0xd6, 0x54, 0xef, 0x41, 0x96, 0x1a, 0x79, 0xdc, 0xce, 0xe8, 0x8b, + 0x14, 0xa0, 0x3d, 0xec, 0x47, 0x05, 0x2f, 0xb3, 0x41, 0x82, 0xe3, 0x2a, 0x5f, 0xc1, 0x71, 0x3f, + 0xe4, 0x46, 0x08, 0xd4, 0xf5, 0x5f, 0x8d, 0xcd, 0xcf, 0x84, 0xa5, 0x87, 0x4e, 0x10, 0x12, 0xdc, + 0x92, 0x5e, 0xcb, 0x63, 0xd7, 0x9e, 0xcf, 0xd0, 0x61, 0x6b, 0xbb, 0xb0, 0xc8, 0xe9, 0xcc, 0xce, + 0xf4, 0x75, 0x40, 0xe6, 0xa5, 0x69, 0x75, 0x4c, 0xa2, 0x57, 0x58, 0xc3, 0xb3, 0x9a, 0xfe, 0x7a, + 0x84, 0x09, 0xd9, 0x34, 0x2d, 0x9e, 0xb5, 0x99, 0x3c, 0x71, 0x9e, 0xd7, 0x89, 0xe7, 0xa8, 0x01, + 0x1a, 0xb6, 0xee, 0x9e, 0x74, 0xa6, 0x77, 0x7b, 0x30, 0x27, 0xb3, 0xb9, 0x59, 0xe2, 0x78, 0xef, + 0x6f, 0x29, 0x58, 0x1f, 0x42, 0x8d, 0xde, 0x85, 0xb4, 0xdb, 0x6d, 0x32, 0x67, 0x7a, 0x79, 0x0c, + 0xf9, 0x45, 0xfd, 0xb8, 0xbc, 0x3f, 0xa5, 0x13, 0x2e, 0xf5, 0x4b, 0x05, 0xd2, 0xfa, 0x71, 0x19, + 0x7d, 0x8f, 0x1b, 0xf2, 0xbd, 0x36, 0xa6, 0x94, 0xf8, 0xac, 0x8f, 0x34, 0x93, 0x83, 0xc3, 0xbe, + 0x02, 0x2c, 0x95, 0xf5, 0x4a, 0xa9, 0x51, 0x31, 0x76, 0x2b, 0x07, 0x95, 0x46, 0xc5, 0x38, 0x3d, + 0x3a, 0x38, 0x39, 0xac, 0xe4, 0x15, 0xd2, 0x15, 0x1e, 0x9f, 0xec, 0x1c, 0x54, 0xeb, 0xfb, 0xc6, + 0x49, 0x2d, 0xfc, 0xc7, 0xb0, 0x29, 0x94, 0x87, 0x6b, 0x07, 0xd5, 0x7a, 0x83, 0x01, 0xea, 0xf9, + 0x34, 0x81, 0xec, 0x55, 0x1a, 0x46, 0xb9, 0x74, 0x5c, 0x2a, 0x57, 0x1b, 0x0f, 0xf3, 0x19, 0xd2, + 0x73, 0xf2, 0xb2, 0xeb, 0xb5, 0xd2, 0x71, 0x7d, 0xff, 0xa8, 0x91, 0xcf, 0x22, 0x04, 0x0b, 0x01, + 0x7f, 0x08, 0xaa, 0xe7, 0xa7, 0xa3, 0x91, 0xc5, 0x67, 0x69, 0x58, 0x66, 0x13, 0x18, 0x36, 0xe3, + 0x08, 0x63, 0xeb, 0x2e, 0xe4, 0x69, 0xf3, 0x65, 0x88, 0x17, 0xc7, 0x02, 0x85, 0x9f, 0x86, 0xd7, + 0x47, 0x38, 0x1a, 0x4c, 0xc5, 0x46, 0x83, 0x5d, 0x58, 0x0d, 0x27, 0x67, 0x4c, 0xae, 0x70, 0x21, + 0x0b, 0x23, 0x34, 0x61, 0x75, 0x01, 0xca, 0x5d, 0xc0, 0xcb, 0x4d, 0x19, 0x0e, 0x1d, 0x4a, 0x66, + 0x80, 0xaf, 0x0f, 0x5f, 0x64, 0x48, 0x0c, 0xab, 0xfb, 0xa0, 0x26, 0xeb, 0x30, 0x51, 0x09, 0xf8, + 0x8c, 0xa1, 0xfc, 0x01, 0xac, 0x88, 0xda, 0xb3, 0xa8, 0x7a, 0x6d, 0x60, 0xc4, 0x15, 0xe5, 0x96, + 0x88, 0x36, 0xa2, 0xd0, 0xfe, 0xa0, 0xc0, 0x6c, 0x08, 0x26, 0xf9, 0xd9, 0xb3, 0x7e, 0x82, 0xb9, + 0xa6, 0x3e, 0x47, 0x20, 0xf2, 0x86, 0x5e, 0xe6, 0x0b, 0x69, 0xa9, 0x2f, 0x6c, 0x02, 0xd0, 0xe3, + 0x69, 0x19, 0xa6, 0x1f, 0xb4, 0x12, 0x69, 0x3d, 0xc7, 0x20, 0x25, 0xd2, 0xfc, 0x4e, 0x7b, 0xbe, + 0xe9, 0xf7, 0x48, 0xdb, 0x40, 0x14, 0x5e, 0x11, 0x15, 0xae, 0x07, 0x58, 0x9d, 0x51, 0x91, 0x40, + 0x5a, 0xe0, 0x51, 0xe8, 0x1e, 0x17, 0x9d, 0xeb, 0x72, 0x01, 0xb1, 0x60, 0x24, 0x17, 0x6b, 0x0b, + 0xfb, 0xa6, 0xd5, 0xf1, 0xc2, 0x8b, 0x95, 0x3d, 0x6a, 0x3b, 0xb2, 0x28, 0xcd, 0x41, 0x56, 0xaf, + 0x94, 0x76, 0x1f, 0xe6, 0x15, 0x34, 0x0f, 0xb9, 0x93, 0xe3, 0x83, 0xa3, 0xd2, 0x6e, 0xb5, 0xb6, + 0x97, 0x4f, 0xa1, 0x45, 0x78, 0xa1, 0xa2, 0xeb, 0x47, 0xba, 0xd1, 0x07, 0xa6, 0x49, 0xa3, 0xbb, + 0xcc, 0x9a, 0x46, 0x21, 0x80, 0x6e, 0xc2, 0x5c, 0xe4, 0xfb, 0x51, 0xec, 0x40, 0x08, 0xaa, 0xb6, + 0x48, 0x8c, 0x84, 0x3d, 0xae, 0x18, 0x23, 0xd2, 0x66, 0x57, 0x74, 0x5f, 0x1e, 0xca, 0xc7, 0x48, + 0x4b, 0x86, 0x23, 0x4e, 0x9d, 0xcc, 0x34, 0x91, 0x57, 0x16, 0x60, 0x45, 0x54, 0x8a, 0xd5, 0xa3, + 0xbf, 0x55, 0x60, 0x89, 0x54, 0x08, 0x21, 0xe2, 0x79, 0x17, 0x2c, 0x13, 0x38, 0xa3, 0x70, 0x02, + 0x19, 0xf1, 0x04, 0xb4, 0xdf, 0x2b, 0xb0, 0x2c, 0xe8, 0xca, 0x62, 0xeb, 0x3d, 0xb1, 0xfa, 0xb9, + 0x1d, 0xaf, 0x7e, 0x06, 0xe8, 0x27, 0xac, 0x7f, 0xde, 0x0c, 0xeb, 0x9f, 0xc9, 0x42, 0xf8, 0x37, + 0x59, 0x58, 0xa9, 0x39, 0x2d, 0x5c, 0xf7, 0xcd, 0xf6, 0x24, 0x73, 0x15, 0x5d, 0xe8, 0x0d, 0xa9, + 0x77, 0xdd, 0x0b, 0x57, 0x92, 0x8b, 0x1c, 0xde, 0x12, 0xa2, 0x22, 0x2c, 0x7a, 0xbe, 0xd9, 0x0e, + 0xce, 0xca, 0x74, 0xdb, 0xd8, 0x37, 0xba, 0xa6, 0xff, 0x98, 0x1d, 0xc4, 0x75, 0x86, 0x6a, 0x04, + 0x98, 0x63, 0xd3, 0x7f, 0x2c, 0x1f, 0x54, 0x64, 0x26, 0x1e, 0x54, 0x9c, 0x01, 0x0a, 0xfa, 0x40, + 0xb2, 0x80, 0xf8, 0x56, 0xe6, 0xdb, 0x23, 0x36, 0x14, 0x81, 0xb9, 0x50, 0xc9, 0xdb, 0x02, 0x18, + 0x99, 0xc9, 0xb3, 0x86, 0x51, 0x4b, 0x8c, 0x3b, 0x63, 0x78, 0xc6, 0x86, 0x9a, 0x74, 0x2d, 0xd2, + 0xdd, 0x7c, 0xfd, 0xb3, 0x89, 0x35, 0x58, 0x1d, 0xb0, 0x05, 0xcb, 0x04, 0x6d, 0x28, 0x10, 0xd4, + 0x89, 0xed, 0x4d, 0xe8, 0xaf, 0x09, 0xbe, 0x95, 0x4a, 0xf0, 0x2d, 0x6d, 0x1d, 0xd6, 0x24, 0x0b, + 0x31, 0x2d, 0xfe, 0x91, 0xa5, 0x6a, 0x4c, 0x3e, 0x74, 0x6b, 0x48, 0xc3, 0xe6, 0x9b, 0x71, 0x17, + 0x90, 0x0e, 0x9a, 0x9e, 0x6f, 0xe0, 0xdc, 0x84, 0xb9, 0x38, 0x1d, 0x4b, 0x62, 0xfe, 0x88, 0xc8, + 0xca, 0x3e, 0xd3, 0x08, 0x70, 0x5a, 0x18, 0x01, 0xfe, 0x08, 0x96, 0x82, 0xa8, 0x13, 0x67, 0x2b, + 0x33, 0xfc, 0x35, 0x95, 0x68, 0x91, 0x18, 0x82, 0x8b, 0xbd, 0x20, 0x96, 0x85, 0x49, 0x5f, 0x53, + 0x16, 0x7d, 0xb3, 0xc1, 0x42, 0x6f, 0x8d, 0x5c, 0xe8, 0xeb, 0x8a, 0xbf, 0x0a, 0xf5, 0xfa, 0xff, + 0x8b, 0xe9, 0x20, 0xf3, 0x7e, 0xe9, 0x5c, 0x4f, 0x7b, 0x04, 0x2a, 0x0d, 0x8d, 0xc9, 0x47, 0x6e, + 0x82, 0xe3, 0xa5, 0x44, 0xc7, 0xd3, 0x36, 0x61, 0x5d, 0x2a, 0x9b, 0x2d, 0x8d, 0x20, 0x4f, 0xd0, + 0x7b, 0xd8, 0xaf, 0xb6, 0xc2, 0x6e, 0xf1, 0x35, 0xb8, 0x1e, 0x83, 0xb1, 0xbb, 0x36, 0x36, 0xdb, + 0x53, 0xe2, 0xb3, 0x3d, 0x6d, 0x83, 0x2a, 0x9f, 0xd0, 0x79, 0x7e, 0x42, 0x97, 0x4f, 0xea, 0x39, + 0x4b, 0x42, 0xcf, 0x49, 0xaf, 0xf1, 0x4d, 0x2e, 0x81, 0x8f, 0xe8, 0x36, 0xff, 0xaa, 0xb0, 0x34, + 0x3b, 0xd0, 0x67, 0xbe, 0x19, 0xef, 0x33, 0x6f, 0x0d, 0x95, 0x19, 0xef, 0x30, 0xbb, 0xb4, 0xc1, + 0x7c, 0x87, 0x2b, 0x61, 0x5f, 0x1a, 0xc9, 0x1e, 0x6f, 0x2d, 0x5f, 0x4f, 0xe8, 0x2c, 0xeb, 0x8d, + 0xd2, 0x5e, 0xc5, 0x38, 0xa9, 0xd1, 0xdf, 0xb0, 0xb3, 0x8c, 0xfa, 0xbc, 0x25, 0x40, 0xa1, 0xe1, + 0x63, 0xdf, 0x21, 0x7d, 0xae, 0xc0, 0x22, 0x07, 0x1e, 0x71, 0x22, 0xe8, 0x1e, 0x2c, 0x91, 0x1a, + 0x8e, 0xfa, 0x88, 0x67, 0x74, 0xb1, 0x6b, 0x10, 0x0c, 0x7b, 0x8b, 0x78, 0xfd, 0xc2, 0x7c, 0xca, + 0x06, 0x43, 0xc7, 0xd8, 0x25, 0x82, 0x9f, 0xc3, 0x28, 0x64, 0xfb, 0x3f, 0x0a, 0xcc, 0x56, 0x5b, + 0xd8, 0xf6, 0x89, 0xe1, 0x6b, 0x30, 0xcf, 0x7d, 0xcc, 0x84, 0x36, 0x12, 0xbe, 0x71, 0x0a, 0x36, + 0xa8, 0x6e, 0x0e, 0xfd, 0x02, 0x4a, 0x9b, 0x42, 0xe7, 0xb1, 0x0f, 0xb1, 0xb8, 0x79, 0xd0, 0x8b, + 0x03, 0x9c, 0x12, 0x1f, 0x54, 0xef, 0x8c, 0xa0, 0x8a, 0xd6, 0x79, 0x0b, 0xb2, 0xc1, 0x97, 0x39, + 0x68, 0x29, 0xfa, 0x66, 0x28, 0xf6, 0xe1, 0x8e, 0xba, 0x2c, 0x40, 0x43, 0xbe, 0xed, 0xff, 0xce, + 0x00, 0xf4, 0x07, 0x0f, 0xe8, 0x01, 0x5c, 0x8b, 0x7f, 0x61, 0x80, 0xd6, 0x87, 0x7c, 0x88, 0xa2, + 0x6e, 0xc8, 0x91, 0x91, 0x4e, 0x0f, 0xe0, 0x5a, 0xfc, 0x65, 0x55, 0x5f, 0x98, 0xe4, 0xdd, 0x5a, + 0x5f, 0x98, 0xf4, 0xfd, 0xd6, 0x14, 0xea, 0xc0, 0x6a, 0xc2, 0x3b, 0x06, 0xf4, 0xd2, 0x78, 0x2f, + 0x68, 0xd4, 0x97, 0xc7, 0x7c, 0x59, 0xa1, 0x4d, 0x21, 0x17, 0xd6, 0x12, 0x27, 0xe3, 0xe8, 0xee, + 0xb8, 0xb3, 0x7e, 0xf5, 0x95, 0x31, 0x28, 0xa3, 0x35, 0x7b, 0xa0, 0x26, 0x0f, 0x79, 0xd1, 0x2b, + 0x63, 0x4f, 0xb7, 0xd5, 0x57, 0xc7, 0x21, 0x8d, 0x96, 0xdd, 0x87, 0xb9, 0xd8, 0xc0, 0x15, 0xa9, + 0xd2, 0x29, 0x2c, 0x15, 0xbc, 0x3e, 0x64, 0x42, 0x4b, 0x25, 0xc5, 0x86, 0x82, 0x7d, 0x49, 0x83, + 0xd3, 0xcd, 0xbe, 0x24, 0xc9, 0x14, 0x51, 0x34, 0xbf, 0x90, 0x80, 0x65, 0xe6, 0x97, 0x67, 0x70, + 0x99, 0xf9, 0x13, 0xb2, 0xb9, 0x36, 0x85, 0xbe, 0x0f, 0x0b, 0xfc, 0x1c, 0x04, 0x6d, 0x0e, 0x9d, + 0xee, 0xa8, 0x37, 0x92, 0xd0, 0x71, 0x91, 0x7c, 0x13, 0xdb, 0x17, 0x29, 0xed, 0xb8, 0xfb, 0x22, + 0x13, 0x7a, 0xdf, 0x29, 0x92, 0x9f, 0xb8, 0x06, 0xb1, 0x9f, 0x9f, 0x64, 0x3d, 0x71, 0x3f, 0x3f, + 0x49, 0xbb, 0x4a, 0x6d, 0x6a, 0xfb, 0xcb, 0x0c, 0x64, 0x82, 0x44, 0xda, 0x80, 0x17, 0x84, 0x3a, + 0x1b, 0xdd, 0x18, 0xde, 0x8c, 0xa8, 0x37, 0x13, 0xf1, 0x91, 0xba, 0x8f, 0xe8, 0x7d, 0xcc, 0x55, + 0xce, 0x68, 0x2b, 0xce, 0x27, 0xab, 0xde, 0xd5, 0x5b, 0x43, 0x28, 0x44, 0xd9, 0x7c, 0x2e, 0xd8, + 0x1a, 0x55, 0xc2, 0xf1, 0xb2, 0x93, 0xe2, 0xff, 0x13, 0x7a, 0x6f, 0x89, 0x91, 0xaf, 0xf1, 0x7a, + 0x49, 0x63, 0xfe, 0xf6, 0x50, 0x9a, 0x68, 0x85, 0x0a, 0xe4, 0xa2, 0x4a, 0x05, 0x15, 0xe2, 0x3c, + 0xf1, 0x82, 0x46, 0x5d, 0x93, 0x60, 0x98, 0x8c, 0xf4, 0x2f, 0x52, 0x4a, 0xa8, 0xa8, 0x18, 0x23, + 0x9a, 0xc0, 0x26, 0x8b, 0x8e, 0xdb, 0x43, 0x69, 0xe2, 0x51, 0x1d, 0xbb, 0xc2, 0xfb, 0x51, 0x3d, + 0x78, 0xdd, 0xf7, 0xa3, 0x5a, 0x72, 0xe7, 0x6b, 0x53, 0x3b, 0xd9, 0x47, 0xe9, 0xa6, 0x67, 0x9d, + 0x4d, 0x07, 0x1f, 0x87, 0x7e, 0xeb, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x9c, 0x3b, 0x5a, 0x51, + 0xf0, 0x2c, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/api/services/containers/v1/BUILD b/vendor/github.com/containerd/containerd/api/services/containers/v1/BUILD index 4e6ff097d72..c6ce0a6387d 100644 --- a/vendor/github.com/containerd/containerd/api/services/containers/v1/BUILD +++ b/vendor/github.com/containerd/containerd/api/services/containers/v1/BUILD @@ -12,11 +12,9 @@ go_library( importpath = "github.com/containerd/containerd/api/services/containers/v1", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library", "//vendor/github.com/gogo/protobuf/proto:go_default_library", "//vendor/github.com/gogo/protobuf/sortkeys:go_default_library", "//vendor/github.com/gogo/protobuf/types:go_default_library", - "//vendor/github.com/golang/protobuf/ptypes/empty:go_default_library", "//vendor/golang.org/x/net/context:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", ], diff --git a/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.pb.go b/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.pb.go index 90d30990317..17cd36d36ef 100644 --- a/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.pb.go +++ b/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-gogo. +// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: github.com/containerd/containerd/api/services/containers/v1/containers.proto -// DO NOT EDIT! /* Package containers is a generated protocol buffer package. @@ -25,9 +24,10 @@ package containers import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" -import _ "github.com/gogo/protobuf/gogoproto" + +// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto" import google_protobuf1 "github.com/gogo/protobuf/types" -import google_protobuf2 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf2 "github.com/gogo/protobuf/types" import google_protobuf3 "github.com/gogo/protobuf/types" import _ "github.com/gogo/protobuf/types" @@ -844,24 +844,6 @@ func (m *DeleteContainerRequest) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func encodeFixed64Containers(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Containers(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} func encodeVarintContainers(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -1270,51 +1252,14 @@ func (m *Container) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowContainers - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowContainers - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthContainers - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey if m.Labels == nil { m.Labels = make(map[string]string) } - if iNdEx < postIndex { - var valuekey uint64 + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowContainers @@ -1324,41 +1269,80 @@ func (m *Container) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift + wire |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowContainers + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowContainers + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } - if iNdEx >= l { + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthContainers + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { return io.ErrUnexpectedEOF } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowContainers + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthContainers + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipContainers(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthContainers + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthContainers - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - m.Labels[mapkey] = mapvalue - } else { - var mapvalue string - m.Labels[mapkey] = mapvalue } + m.Labels[mapkey] = mapvalue iNdEx = postIndex case 3: if wireType != 2 { @@ -1599,51 +1583,14 @@ func (m *Container) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowContainers - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowContainers - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthContainers - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey if m.Extensions == nil { m.Extensions = make(map[string]google_protobuf1.Any) } - if iNdEx < postIndex { - var valuekey uint64 + var mapkey string + mapvalue := &google_protobuf1.Any{} + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowContainers @@ -1653,46 +1600,85 @@ func (m *Container) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift + wire |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - var mapmsglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowContainers + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowContainers + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } - if iNdEx >= l { + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthContainers + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { return io.ErrUnexpectedEOF } - b := dAtA[iNdEx] - iNdEx++ - mapmsglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowContainers + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } } + if mapmsglen < 0 { + return ErrInvalidLengthContainers + } + postmsgIndex := iNdEx + mapmsglen + if mapmsglen < 0 { + return ErrInvalidLengthContainers + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = &google_protobuf1.Any{} + if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := skipContainers(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthContainers + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy } - if mapmsglen < 0 { - return ErrInvalidLengthContainers - } - postmsgIndex := iNdEx + mapmsglen - if mapmsglen < 0 { - return ErrInvalidLengthContainers - } - if postmsgIndex > l { - return io.ErrUnexpectedEOF - } - mapvalue := &google_protobuf1.Any{} - if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil { - return err - } - iNdEx = postmsgIndex - m.Extensions[mapkey] = *mapvalue - } else { - var mapvalue google_protobuf1.Any - m.Extensions[mapkey] = mapvalue } + m.Extensions[mapkey] = *mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -2689,53 +2675,53 @@ func init() { var fileDescriptorContainers = []byte{ // 776 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcd, 0x72, 0x12, 0x5b, - 0x10, 0xce, 0x00, 0x81, 0xd0, 0xdc, 0xaa, 0x7b, 0xeb, 0x5c, 0x2e, 0x77, 0x1c, 0xab, 0x80, 0xb0, - 0xa2, 0x2c, 0x1d, 0x0c, 0x5a, 0x9a, 0x1f, 0x37, 0x21, 0x7f, 0x65, 0x99, 0x58, 0xa9, 0x51, 0x37, - 0xba, 0x88, 0x03, 0x74, 0xc8, 0xc8, 0xfc, 0x39, 0xe7, 0x40, 0x49, 0xb9, 0xd0, 0x47, 0x70, 0xe7, - 0x23, 0xf8, 0x2a, 0x59, 0xba, 0x74, 0x15, 0x13, 0x9e, 0xc4, 0x9a, 0x33, 0x33, 0xcc, 0x04, 0x06, - 0x85, 0x68, 0x76, 0xa7, 0x39, 0xfd, 0x7d, 0xfd, 0xf1, 0x75, 0xf7, 0x01, 0xd8, 0xef, 0x68, 0xec, - 0xa4, 0xd7, 0x94, 0x5b, 0x96, 0x51, 0x6b, 0x59, 0x26, 0x53, 0x35, 0x13, 0x9d, 0x76, 0xf4, 0xa8, - 0xda, 0x5a, 0x8d, 0xa2, 0xd3, 0xd7, 0x5a, 0x48, 0xc3, 0xcf, 0x69, 0xad, 0xbf, 0x12, 0x89, 0x64, - 0xdb, 0xb1, 0x98, 0x45, 0x96, 0x43, 0x9c, 0x1c, 0x60, 0xe4, 0x48, 0x56, 0x7f, 0x45, 0xca, 0x77, - 0xac, 0x8e, 0xc5, 0xb3, 0x6b, 0xee, 0xc9, 0x03, 0x4a, 0x37, 0x3a, 0x96, 0xd5, 0xd1, 0xb1, 0xc6, - 0xa3, 0x66, 0xef, 0xb8, 0xa6, 0x9a, 0x03, 0xff, 0xea, 0xe6, 0xf8, 0x15, 0x1a, 0x36, 0x0b, 0x2e, - 0xcb, 0xe3, 0x97, 0xc7, 0x1a, 0xea, 0xed, 0x23, 0x43, 0xa5, 0x5d, 0x3f, 0xa3, 0x34, 0x9e, 0xc1, - 0x34, 0x03, 0x29, 0x53, 0x0d, 0xdb, 0x4b, 0xa8, 0x7c, 0x4e, 0x43, 0x76, 0x2b, 0x90, 0x48, 0x0a, - 0x90, 0xd0, 0xda, 0xa2, 0x50, 0x16, 0xaa, 0xd9, 0x46, 0x7a, 0x78, 0x56, 0x4a, 0x3c, 0xde, 0x56, - 0x12, 0x5a, 0x9b, 0x1c, 0x42, 0x5a, 0x57, 0x9b, 0xa8, 0x53, 0x31, 0x51, 0x4e, 0x56, 0x73, 0xf5, - 0x55, 0xf9, 0x97, 0x5f, 0x55, 0x1e, 0xb1, 0xca, 0xfb, 0x1c, 0xba, 0x63, 0x32, 0x67, 0xa0, 0xf8, - 0x3c, 0x24, 0x0f, 0x8b, 0x9a, 0xa1, 0x76, 0x50, 0x4c, 0xba, 0xc5, 0x14, 0x2f, 0x20, 0x4f, 0x21, - 0xe3, 0xf4, 0x4c, 0x57, 0xa3, 0x98, 0x2a, 0x0b, 0xd5, 0x5c, 0xfd, 0xfe, 0x5c, 0x85, 0x14, 0x0f, - 0xab, 0x04, 0x24, 0xa4, 0x0a, 0x29, 0x6a, 0x63, 0x4b, 0x5c, 0xe4, 0x64, 0x79, 0xd9, 0x73, 0x43, - 0x0e, 0xdc, 0x90, 0x37, 0xcd, 0x81, 0xc2, 0x33, 0x48, 0x19, 0x72, 0xd4, 0x54, 0x6d, 0x7a, 0x62, - 0x31, 0x86, 0x8e, 0x98, 0xe6, 0xaa, 0xa2, 0x1f, 0x91, 0x65, 0xf8, 0x2b, 0x08, 0x8f, 0xba, 0x38, - 0x10, 0x33, 0x97, 0x53, 0x9e, 0xe0, 0x80, 0x6c, 0x01, 0xb4, 0x1c, 0x54, 0x19, 0xb6, 0x8f, 0x54, - 0x26, 0x2e, 0xf1, 0xa2, 0xd2, 0x44, 0xd1, 0xe7, 0x41, 0x0b, 0x1a, 0x4b, 0xa7, 0x67, 0xa5, 0x85, - 0x4f, 0xdf, 0x4b, 0x82, 0x92, 0xf5, 0x71, 0x9b, 0xcc, 0x25, 0xe9, 0xd9, 0xed, 0x80, 0x24, 0x3b, - 0x0f, 0x89, 0x8f, 0xdb, 0x64, 0xa4, 0x09, 0x80, 0xef, 0x18, 0x9a, 0x54, 0xb3, 0x4c, 0x2a, 0x02, - 0x6f, 0xda, 0xa3, 0xb9, 0xbc, 0xdc, 0x19, 0xc1, 0x79, 0xe3, 0x1a, 0x29, 0xb7, 0x8c, 0x12, 0x61, - 0x95, 0xd6, 0x20, 0x17, 0xe9, 0x2c, 0xf9, 0x07, 0x92, 0xae, 0x2d, 0x7c, 0x78, 0x14, 0xf7, 0xe8, - 0xf6, 0xb8, 0xaf, 0xea, 0x3d, 0x14, 0x13, 0x5e, 0x8f, 0x79, 0xb0, 0x9e, 0x58, 0x15, 0xa4, 0x03, - 0xc8, 0xf8, 0xbd, 0x22, 0x04, 0x52, 0xa6, 0x6a, 0xa0, 0x8f, 0xe3, 0x67, 0x22, 0x43, 0xc6, 0xb2, - 0x19, 0x97, 0x9e, 0xf8, 0x49, 0xe7, 0x82, 0x24, 0xe9, 0x19, 0xfc, 0x3d, 0x26, 0x37, 0x46, 0xcd, - 0xad, 0xa8, 0x9a, 0x69, 0x94, 0xa1, 0xc6, 0xca, 0x1d, 0xf8, 0x77, 0x0f, 0xd9, 0xc8, 0x10, 0x05, - 0xdf, 0xf6, 0x90, 0xb2, 0x69, 0x2b, 0x52, 0x39, 0x81, 0xfc, 0xe5, 0x74, 0x6a, 0x5b, 0x26, 0x45, - 0x72, 0x08, 0xd9, 0x91, 0xc5, 0x1c, 0x96, 0xab, 0xdf, 0x9e, 0xa7, 0x11, 0xbe, 0xf1, 0x21, 0x49, - 0x65, 0x05, 0xfe, 0xdb, 0xd7, 0x68, 0x58, 0x8a, 0x06, 0xd2, 0x44, 0xc8, 0x1c, 0x6b, 0x3a, 0x43, - 0x87, 0x8a, 0x42, 0x39, 0x59, 0xcd, 0x2a, 0x41, 0x58, 0xd1, 0xa1, 0x30, 0x0e, 0xf1, 0xe5, 0x29, - 0x00, 0x61, 0x61, 0x0e, 0xbb, 0x9a, 0xbe, 0x08, 0x4b, 0xe5, 0x0d, 0x14, 0xb6, 0xf8, 0x38, 0x4f, - 0x98, 0xf7, 0xe7, 0xcd, 0xe8, 0xc2, 0xff, 0x13, 0xb5, 0xae, 0xcd, 0xf9, 0x2f, 0x02, 0x14, 0x5e, - 0xf0, 0x1d, 0xbb, 0xfe, 0x6f, 0x46, 0x36, 0x20, 0xe7, 0xed, 0x33, 0x7f, 0xcf, 0xfd, 0xa9, 0x9d, - 0x7c, 0x08, 0x76, 0xdd, 0x27, 0xff, 0x40, 0xa5, 0x5d, 0xc5, 0x7f, 0x36, 0xdc, 0xb3, 0x6b, 0xcb, - 0x84, 0xd0, 0x6b, 0xb3, 0xe5, 0x2e, 0x14, 0xb6, 0x51, 0xc7, 0x18, 0x57, 0xa6, 0x2c, 0x4b, 0xfd, - 0x3c, 0x05, 0x10, 0x0e, 0x23, 0xe9, 0x43, 0x72, 0x0f, 0x19, 0x79, 0x30, 0x83, 0x8c, 0x98, 0x95, - 0x94, 0x1e, 0xce, 0x8d, 0xf3, 0xad, 0x78, 0x0f, 0x29, 0x77, 0x2d, 0xc8, 0x2c, 0x3f, 0x67, 0xb1, - 0x2b, 0x27, 0xad, 0x5d, 0x01, 0xe9, 0x17, 0xff, 0x00, 0x69, 0x6f, 0x72, 0xc9, 0x2c, 0x24, 0xf1, - 0x0b, 0x25, 0xad, 0x5f, 0x05, 0x1a, 0x0a, 0xf0, 0x66, 0x64, 0x26, 0x01, 0xf1, 0x73, 0x3f, 0x93, - 0x80, 0x69, 0x93, 0xf8, 0x0a, 0xd2, 0xde, 0xdc, 0xcc, 0x24, 0x20, 0x7e, 0xc4, 0xa4, 0xc2, 0xc4, - 0x46, 0xec, 0xb8, 0xff, 0x90, 0x1a, 0xaf, 0x4f, 0x2f, 0x8a, 0x0b, 0xdf, 0x2e, 0x8a, 0x0b, 0x1f, - 0x87, 0x45, 0xe1, 0x74, 0x58, 0x14, 0xbe, 0x0e, 0x8b, 0xc2, 0xf9, 0xb0, 0x28, 0xbc, 0xdc, 0xfd, - 0x8d, 0x3f, 0x7d, 0x1b, 0x61, 0xd4, 0x4c, 0xf3, 0x8a, 0xf7, 0x7e, 0x04, 0x00, 0x00, 0xff, 0xff, - 0x17, 0x73, 0xba, 0x43, 0x45, 0x0a, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcd, 0x72, 0xd2, 0x50, + 0x14, 0x26, 0x81, 0x86, 0x72, 0x70, 0x46, 0xe7, 0x8a, 0x18, 0xe3, 0x0c, 0x50, 0x56, 0x8c, 0xa3, + 0xc1, 0xa2, 0xa3, 0xfd, 0x71, 0x53, 0xfa, 0x37, 0x8e, 0xad, 0xd3, 0x89, 0x3a, 0xe3, 0xe8, 0xa2, + 0x06, 0xb8, 0xa5, 0x91, 0xfc, 0x99, 0x7b, 0x61, 0x64, 0x5c, 0xe8, 0x23, 0xb8, 0xf3, 0x11, 0x7c, + 0x95, 0x2e, 0x5d, 0xba, 0xaa, 0x2d, 0x4f, 0xe2, 0xe4, 0x26, 0x21, 0x29, 0x04, 0x85, 0x2a, 0xbb, + 0x7b, 0xb8, 0xe7, 0xfb, 0xce, 0xc7, 0x77, 0xce, 0xb9, 0x00, 0x7b, 0x6d, 0x8d, 0x1e, 0x77, 0x1b, + 0x72, 0xd3, 0x32, 0xaa, 0x4d, 0xcb, 0xa4, 0xaa, 0x66, 0x62, 0xa7, 0x15, 0x3d, 0xaa, 0xb6, 0x56, + 0x25, 0xd8, 0xe9, 0x69, 0x4d, 0x4c, 0xc2, 0xcf, 0x49, 0xb5, 0xb7, 0x1c, 0x89, 0x64, 0xdb, 0xb1, + 0xa8, 0x85, 0x96, 0x42, 0x9c, 0x1c, 0x60, 0xe4, 0x48, 0x56, 0x6f, 0x59, 0xca, 0xb5, 0xad, 0xb6, + 0xc5, 0xb2, 0xab, 0xee, 0xc9, 0x03, 0x4a, 0xb7, 0xda, 0x96, 0xd5, 0xd6, 0x71, 0x95, 0x45, 0x8d, + 0xee, 0x51, 0x55, 0x35, 0xfb, 0xfe, 0xd5, 0xed, 0xd1, 0x2b, 0x6c, 0xd8, 0x34, 0xb8, 0x2c, 0x8d, + 0x5e, 0x1e, 0x69, 0x58, 0x6f, 0x1d, 0x1a, 0x2a, 0xe9, 0xf8, 0x19, 0xc5, 0xd1, 0x0c, 0xaa, 0x19, + 0x98, 0x50, 0xd5, 0xb0, 0xbd, 0x84, 0xf2, 0x37, 0x01, 0x32, 0x9b, 0x81, 0x44, 0x94, 0x07, 0x5e, + 0x6b, 0x89, 0x5c, 0x89, 0xab, 0x64, 0xea, 0xc2, 0xe0, 0xb4, 0xc8, 0x3f, 0xdd, 0x52, 0x78, 0xad, + 0x85, 0x0e, 0x40, 0xd0, 0xd5, 0x06, 0xd6, 0x89, 0xc8, 0x97, 0x92, 0x95, 0x6c, 0x6d, 0x45, 0xfe, + 0xeb, 0x57, 0x95, 0x87, 0xac, 0xf2, 0x1e, 0x83, 0x6e, 0x9b, 0xd4, 0xe9, 0x2b, 0x3e, 0x0f, 0xca, + 0xc1, 0x82, 0x66, 0xa8, 0x6d, 0x2c, 0x26, 0xdd, 0x62, 0x8a, 0x17, 0xa0, 0xe7, 0x90, 0x76, 0xba, + 0xa6, 0xab, 0x51, 0x4c, 0x95, 0xb8, 0x4a, 0xb6, 0xf6, 0x70, 0xa6, 0x42, 0x8a, 0x87, 0x55, 0x02, + 0x12, 0x54, 0x81, 0x14, 0xb1, 0x71, 0x53, 0x5c, 0x60, 0x64, 0x39, 0xd9, 0x73, 0x43, 0x0e, 0xdc, + 0x90, 0x37, 0xcc, 0xbe, 0xc2, 0x32, 0x50, 0x09, 0xb2, 0xc4, 0x54, 0x6d, 0x72, 0x6c, 0x51, 0x8a, + 0x1d, 0x51, 0x60, 0xaa, 0xa2, 0x1f, 0xa1, 0x25, 0xb8, 0x12, 0x84, 0x87, 0x1d, 0xdc, 0x17, 0xd3, + 0x17, 0x53, 0x9e, 0xe1, 0x3e, 0xda, 0x04, 0x68, 0x3a, 0x58, 0xa5, 0xb8, 0x75, 0xa8, 0x52, 0x71, + 0x91, 0x15, 0x95, 0xc6, 0x8a, 0xbe, 0x0c, 0x5a, 0x50, 0x5f, 0x3c, 0x39, 0x2d, 0x26, 0xbe, 0xfe, + 0x2a, 0x72, 0x4a, 0xc6, 0xc7, 0x6d, 0x50, 0x97, 0xa4, 0x6b, 0xb7, 0x02, 0x92, 0xcc, 0x2c, 0x24, + 0x3e, 0x6e, 0x83, 0xa2, 0x06, 0x00, 0xfe, 0x48, 0xb1, 0x49, 0x34, 0xcb, 0x24, 0x22, 0xb0, 0xa6, + 0x3d, 0x99, 0xc9, 0xcb, 0xed, 0x21, 0x9c, 0x35, 0xae, 0x9e, 0x72, 0xcb, 0x28, 0x11, 0x56, 0x69, + 0x15, 0xb2, 0x91, 0xce, 0xa2, 0x6b, 0x90, 0x74, 0x6d, 0x61, 0xc3, 0xa3, 0xb8, 0x47, 0xb7, 0xc7, + 0x3d, 0x55, 0xef, 0x62, 0x91, 0xf7, 0x7a, 0xcc, 0x82, 0x35, 0x7e, 0x85, 0x93, 0xf6, 0x21, 0xed, + 0xf7, 0x0a, 0x21, 0x48, 0x99, 0xaa, 0x81, 0x7d, 0x1c, 0x3b, 0x23, 0x19, 0xd2, 0x96, 0x4d, 0x99, + 0x74, 0xfe, 0x0f, 0x9d, 0x0b, 0x92, 0xa4, 0x17, 0x70, 0x75, 0x44, 0x6e, 0x8c, 0x9a, 0x3b, 0x51, + 0x35, 0x93, 0x28, 0x43, 0x8d, 0xe5, 0x7b, 0x70, 0x7d, 0x17, 0xd3, 0xa1, 0x21, 0x0a, 0xfe, 0xd0, + 0xc5, 0x84, 0x4e, 0x5a, 0x91, 0xf2, 0x31, 0xe4, 0x2e, 0xa6, 0x13, 0xdb, 0x32, 0x09, 0x46, 0x07, + 0x90, 0x19, 0x5a, 0xcc, 0x60, 0xd9, 0xda, 0xdd, 0x59, 0x1a, 0xe1, 0x1b, 0x1f, 0x92, 0x94, 0x97, + 0xe1, 0xc6, 0x9e, 0x46, 0xc2, 0x52, 0x24, 0x90, 0x26, 0x42, 0xfa, 0x48, 0xd3, 0x29, 0x76, 0x88, + 0xc8, 0x95, 0x92, 0x95, 0x8c, 0x12, 0x84, 0x65, 0x1d, 0xf2, 0xa3, 0x10, 0x5f, 0x9e, 0x02, 0x10, + 0x16, 0x66, 0xb0, 0xcb, 0xe9, 0x8b, 0xb0, 0x94, 0xdf, 0x43, 0x7e, 0x93, 0x8d, 0xf3, 0x98, 0x79, + 0xff, 0xdf, 0x8c, 0x0e, 0xdc, 0x1c, 0xab, 0x35, 0x37, 0xe7, 0xbf, 0x73, 0x90, 0x7f, 0xc5, 0x76, + 0x6c, 0xfe, 0xdf, 0x0c, 0xad, 0x43, 0xd6, 0xdb, 0x67, 0xf6, 0x9e, 0xfb, 0x53, 0x3b, 0xfe, 0x10, + 0xec, 0xb8, 0x4f, 0xfe, 0xbe, 0x4a, 0x3a, 0x8a, 0xff, 0x6c, 0xb8, 0x67, 0xd7, 0x96, 0x31, 0xa1, + 0x73, 0xb3, 0xe5, 0x3e, 0xe4, 0xb7, 0xb0, 0x8e, 0x63, 0x5c, 0x99, 0xb0, 0x2c, 0xb5, 0xb3, 0x14, + 0x40, 0x38, 0x8c, 0xa8, 0x07, 0xc9, 0x5d, 0x4c, 0xd1, 0xa3, 0x29, 0x64, 0xc4, 0xac, 0xa4, 0xf4, + 0x78, 0x66, 0x9c, 0x6f, 0xc5, 0x27, 0x48, 0xb9, 0x6b, 0x81, 0xa6, 0xf9, 0x39, 0x8b, 0x5d, 0x39, + 0x69, 0xf5, 0x12, 0x48, 0xbf, 0xf8, 0x67, 0x10, 0xbc, 0xc9, 0x45, 0xd3, 0x90, 0xc4, 0x2f, 0x94, + 0xb4, 0x76, 0x19, 0x68, 0x28, 0xc0, 0x9b, 0x91, 0xa9, 0x04, 0xc4, 0xcf, 0xfd, 0x54, 0x02, 0x26, + 0x4d, 0xe2, 0x5b, 0x10, 0xbc, 0xb9, 0x99, 0x4a, 0x40, 0xfc, 0x88, 0x49, 0xf9, 0xb1, 0x8d, 0xd8, + 0x76, 0xff, 0x21, 0xd5, 0xdf, 0x9d, 0x9c, 0x17, 0x12, 0x3f, 0xcf, 0x0b, 0x89, 0x2f, 0x83, 0x02, + 0x77, 0x32, 0x28, 0x70, 0x3f, 0x06, 0x05, 0xee, 0x6c, 0x50, 0xe0, 0xde, 0xec, 0xfc, 0xc3, 0x9f, + 0xbe, 0xf5, 0x30, 0x7a, 0x9d, 0x68, 0x08, 0xac, 0xe6, 0x83, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, + 0x95, 0x94, 0x84, 0xf2, 0x47, 0x0a, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.proto b/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.proto index 0a2311c4c47..b7b32d949ab 100644 --- a/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.proto +++ b/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package containerd.services.containers.v1; -import "gogoproto/gogo.proto"; +import weak "gogoproto/gogo.proto"; import "google/protobuf/any.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/field_mask.proto"; diff --git a/vendor/github.com/containerd/containerd/api/services/tasks/v1/BUILD b/vendor/github.com/containerd/containerd/api/services/tasks/v1/BUILD index 916c3ed1968..6be5c321be4 100644 --- a/vendor/github.com/containerd/containerd/api/services/tasks/v1/BUILD +++ b/vendor/github.com/containerd/containerd/api/services/tasks/v1/BUILD @@ -14,10 +14,8 @@ go_library( deps = [ "//vendor/github.com/containerd/containerd/api/types:go_default_library", "//vendor/github.com/containerd/containerd/api/types/task:go_default_library", - "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library", "//vendor/github.com/gogo/protobuf/proto:go_default_library", "//vendor/github.com/gogo/protobuf/types:go_default_library", - "//vendor/github.com/golang/protobuf/ptypes/empty:go_default_library", "//vendor/github.com/opencontainers/go-digest:go_default_library", "//vendor/golang.org/x/net/context:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", diff --git a/vendor/github.com/containerd/containerd/api/services/tasks/v1/tasks.pb.go b/vendor/github.com/containerd/containerd/api/services/tasks/v1/tasks.pb.go index 0f587685b94..83c18f68aa7 100644 --- a/vendor/github.com/containerd/containerd/api/services/tasks/v1/tasks.pb.go +++ b/vendor/github.com/containerd/containerd/api/services/tasks/v1/tasks.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-gogo. +// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: github.com/containerd/containerd/api/services/tasks/v1/tasks.proto -// DO NOT EDIT! /* Package tasks is a generated protocol buffer package. @@ -42,9 +41,10 @@ package tasks import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" -import google_protobuf "github.com/golang/protobuf/ptypes/empty" +import google_protobuf "github.com/gogo/protobuf/types" import google_protobuf1 "github.com/gogo/protobuf/types" -import _ "github.com/gogo/protobuf/gogoproto" + +// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto" import containerd_types "github.com/containerd/containerd/api/types" import containerd_types1 "github.com/containerd/containerd/api/types" import containerd_types2 "github.com/containerd/containerd/api/types" @@ -1890,24 +1890,6 @@ func (m *WaitResponse) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func encodeFixed64Tasks(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Tasks(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} func encodeVarintTasks(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -5725,88 +5707,88 @@ func init() { } var fileDescriptorTasks = []byte{ - // 1317 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x5b, 0x6f, 0x1b, 0x45, - 0x1b, 0xee, 0xfa, 0xec, 0xd7, 0x49, 0x9b, 0xec, 0x97, 0xe6, 0x33, 0x4b, 0x15, 0x87, 0xe5, 0xc6, - 0x04, 0xba, 0x4b, 0x5d, 0x54, 0x21, 0x5a, 0x21, 0x35, 0x07, 0x22, 0x0b, 0xaa, 0xa6, 0xdb, 0x72, - 0x50, 0x25, 0x14, 0xb6, 0xbb, 0x13, 0x67, 0x14, 0x7b, 0x67, 0xbb, 0x33, 0x4e, 0x1b, 0xb8, 0x80, - 0x9f, 0xd0, 0x5b, 0x6e, 0xf8, 0x3d, 0xb9, 0xe4, 0x12, 0xa1, 0x2a, 0x50, 0xff, 0x0b, 0xee, 0xd0, - 0x1c, 0x76, 0xb3, 0xb1, 0x63, 0xaf, 0x93, 0x34, 0xdc, 0xb4, 0x33, 0xb3, 0xef, 0x69, 0x9e, 0x79, - 0x0f, 0x8f, 0x03, 0xab, 0x1d, 0xcc, 0x76, 0xfb, 0xcf, 0x2c, 0x8f, 0xf4, 0x6c, 0x8f, 0x04, 0xcc, - 0xc5, 0x01, 0x8a, 0xfc, 0xf4, 0xd2, 0x0d, 0xb1, 0x4d, 0x51, 0xb4, 0x8f, 0x3d, 0x44, 0x6d, 0xe6, - 0xd2, 0x3d, 0x6a, 0xef, 0xdf, 0x92, 0x0b, 0x2b, 0x8c, 0x08, 0x23, 0xfa, 0x8d, 0x63, 0x69, 0x2b, - 0x96, 0xb4, 0xa4, 0xc0, 0xfe, 0x2d, 0xe3, 0xdd, 0x0e, 0x21, 0x9d, 0x2e, 0xb2, 0x85, 0xec, 0xb3, - 0xfe, 0x8e, 0x8d, 0x7a, 0x21, 0x3b, 0x90, 0xaa, 0xc6, 0x3b, 0xc3, 0x1f, 0xdd, 0x20, 0xfe, 0xb4, - 0xd0, 0x21, 0x1d, 0x22, 0x96, 0x36, 0x5f, 0xa9, 0xd3, 0x3b, 0x53, 0xc5, 0xcb, 0x0e, 0x42, 0x44, - 0xed, 0x1e, 0xe9, 0x07, 0x4c, 0xe9, 0x7d, 0x7a, 0x16, 0x3d, 0xc4, 0x22, 0xec, 0xa9, 0xdb, 0x19, - 0x77, 0xcf, 0xa0, 0xe9, 0x23, 0xea, 0x45, 0x38, 0x64, 0x24, 0x52, 0xca, 0x9f, 0x9d, 0x41, 0x99, - 0x23, 0x26, 0xfe, 0x51, 0xba, 0x8d, 0x61, 0x6c, 0x18, 0xee, 0x21, 0xca, 0xdc, 0x5e, 0x28, 0x05, - 0xcc, 0xc3, 0x1c, 0xcc, 0xaf, 0x45, 0xc8, 0x65, 0xe8, 0x89, 0x4b, 0xf7, 0x1c, 0xf4, 0xbc, 0x8f, - 0x28, 0xd3, 0x5b, 0x30, 0x93, 0x98, 0xdf, 0xc6, 0x7e, 0x5d, 0x5b, 0xd6, 0x9a, 0xd5, 0xd5, 0x6b, - 0x83, 0xa3, 0x46, 0x6d, 0x2d, 0x3e, 0x6f, 0xaf, 0x3b, 0xb5, 0x44, 0xa8, 0xed, 0xeb, 0x36, 0x94, - 0x22, 0x42, 0xd8, 0x0e, 0xad, 0xe7, 0x97, 0xf3, 0xcd, 0x5a, 0xeb, 0xff, 0x56, 0xea, 0x49, 0x45, - 0x74, 0xd6, 0x03, 0x0e, 0xa6, 0xa3, 0xc4, 0xf4, 0x05, 0x28, 0x52, 0xe6, 0xe3, 0xa0, 0x5e, 0xe0, - 0xd6, 0x1d, 0xb9, 0xd1, 0x17, 0xa1, 0x44, 0x99, 0x4f, 0xfa, 0xac, 0x5e, 0x14, 0xc7, 0x6a, 0xa7, - 0xce, 0x51, 0x14, 0xd5, 0x4b, 0xc9, 0x39, 0x8a, 0x22, 0xdd, 0x80, 0x0a, 0x43, 0x51, 0x0f, 0x07, - 0x6e, 0xb7, 0x5e, 0x5e, 0xd6, 0x9a, 0x15, 0x27, 0xd9, 0xeb, 0xf7, 0x00, 0xbc, 0x5d, 0xe4, 0xed, - 0x85, 0x04, 0x07, 0xac, 0x5e, 0x59, 0xd6, 0x9a, 0xb5, 0xd6, 0x8d, 0xd1, 0xb0, 0xd6, 0x13, 0xc4, - 0x9d, 0x94, 0xbc, 0x6e, 0x41, 0x99, 0x84, 0x0c, 0x93, 0x80, 0xd6, 0xab, 0x42, 0x75, 0xc1, 0x92, - 0x68, 0x5a, 0x31, 0x9a, 0xd6, 0xfd, 0xe0, 0xc0, 0x89, 0x85, 0xcc, 0xa7, 0xa0, 0xa7, 0x91, 0xa4, - 0x21, 0x09, 0x28, 0x3a, 0x17, 0x94, 0x73, 0x90, 0x0f, 0xb1, 0x5f, 0xcf, 0x2d, 0x6b, 0xcd, 0x59, - 0x87, 0x2f, 0xcd, 0x0e, 0xcc, 0x3c, 0x66, 0x6e, 0xc4, 0x2e, 0xf2, 0x40, 0xef, 0x43, 0x19, 0xbd, - 0x44, 0xde, 0xb6, 0xb2, 0x5c, 0x5d, 0x85, 0xc1, 0x51, 0xa3, 0xb4, 0xf1, 0x12, 0x79, 0xed, 0x75, - 0xa7, 0xc4, 0x3f, 0xb5, 0x7d, 0xf3, 0x3d, 0x98, 0x55, 0x8e, 0x54, 0xfc, 0x2a, 0x16, 0xed, 0x38, - 0x96, 0x4d, 0x98, 0x5f, 0x47, 0x5d, 0x74, 0xe1, 0x8c, 0x31, 0x7f, 0xd3, 0xe0, 0xaa, 0xb4, 0x94, - 0x78, 0x5b, 0x84, 0x5c, 0xa2, 0x5c, 0x1a, 0x1c, 0x35, 0x72, 0xed, 0x75, 0x27, 0x87, 0x4f, 0x41, - 0x44, 0x6f, 0x40, 0x0d, 0xbd, 0xc4, 0x6c, 0x9b, 0x32, 0x97, 0xf5, 0x79, 0xce, 0xf1, 0x2f, 0xc0, - 0x8f, 0x1e, 0x8b, 0x13, 0xfd, 0x3e, 0x54, 0xf9, 0x0e, 0xf9, 0xdb, 0x2e, 0x13, 0x29, 0x56, 0x6b, - 0x19, 0x23, 0x0f, 0xf8, 0x24, 0x2e, 0x87, 0xd5, 0xca, 0xe1, 0x51, 0xe3, 0xca, 0xab, 0xbf, 0x1a, - 0x9a, 0x53, 0x91, 0x6a, 0xf7, 0x99, 0x49, 0x60, 0x41, 0xc6, 0xb7, 0x15, 0x11, 0x0f, 0x51, 0x7a, - 0xe9, 0xe8, 0x23, 0x80, 0x4d, 0x74, 0xf9, 0x8f, 0xbc, 0x01, 0x35, 0xe1, 0x46, 0x81, 0x7e, 0x07, - 0xca, 0xa1, 0xbc, 0xa0, 0x70, 0x31, 0x54, 0x23, 0xfb, 0xb7, 0x54, 0x99, 0xc4, 0x20, 0xc4, 0xc2, - 0xe6, 0x0a, 0xcc, 0x7d, 0x85, 0x29, 0xe3, 0x69, 0x90, 0x40, 0xb3, 0x08, 0xa5, 0x1d, 0xdc, 0x65, - 0x28, 0x92, 0xd1, 0x3a, 0x6a, 0xc7, 0x93, 0x26, 0x25, 0x9b, 0xd4, 0x46, 0x51, 0xb4, 0xf8, 0xba, - 0x26, 0x3a, 0xc6, 0x64, 0xb7, 0x52, 0xd4, 0x7c, 0xa5, 0x41, 0xed, 0x4b, 0xdc, 0xed, 0x5e, 0x36, - 0x48, 0xa2, 0xe1, 0xe0, 0x0e, 0x6f, 0x2b, 0x32, 0xb7, 0xd4, 0x8e, 0xa7, 0xa2, 0xdb, 0xed, 0x8a, - 0x8c, 0xaa, 0x38, 0x7c, 0x69, 0xfe, 0xa3, 0x81, 0xce, 0x95, 0xdf, 0x42, 0x96, 0x24, 0x3d, 0x31, - 0x77, 0x7a, 0x4f, 0xcc, 0x8f, 0xe9, 0x89, 0x85, 0xb1, 0x3d, 0xb1, 0x38, 0xd4, 0x13, 0x9b, 0x50, - 0xa0, 0x21, 0xf2, 0x44, 0x17, 0x1d, 0xd7, 0xd2, 0x84, 0x44, 0x1a, 0xa5, 0xf2, 0xd8, 0x54, 0xba, - 0x0e, 0xff, 0x3b, 0x71, 0x75, 0xf9, 0xb2, 0xe6, 0xaf, 0x1a, 0xcc, 0x39, 0x88, 0xe2, 0x1f, 0xd1, - 0x16, 0x3b, 0xb8, 0xf4, 0xa7, 0x5a, 0x80, 0xe2, 0x0b, 0xec, 0xb3, 0x5d, 0xf5, 0x52, 0x72, 0xc3, - 0xd1, 0xd9, 0x45, 0xb8, 0xb3, 0x2b, 0xab, 0x7f, 0xd6, 0x51, 0x3b, 0xf3, 0x67, 0xb8, 0xba, 0xd6, - 0x25, 0x14, 0xb5, 0x1f, 0xfe, 0x17, 0x81, 0xc9, 0xe7, 0xcc, 0x8b, 0x57, 0x90, 0x1b, 0xf3, 0x0b, - 0x98, 0xdb, 0x72, 0xfb, 0xf4, 0xc2, 0xfd, 0x73, 0x13, 0xe6, 0x1d, 0x44, 0xfb, 0xbd, 0x0b, 0x1b, - 0xda, 0x80, 0x6b, 0xbc, 0x38, 0xb7, 0xb0, 0x7f, 0x91, 0xe4, 0x35, 0x1d, 0xd9, 0x0f, 0xa4, 0x19, - 0x55, 0xe2, 0x9f, 0x43, 0x55, 0xb5, 0x0b, 0x14, 0x97, 0xf9, 0xf2, 0xa4, 0x32, 0x6f, 0x07, 0x3b, - 0xc4, 0x39, 0x56, 0x31, 0x5f, 0x6b, 0x70, 0x7d, 0x2d, 0x99, 0xc9, 0x17, 0xe5, 0x28, 0xdb, 0x30, - 0x1f, 0xba, 0x11, 0x0a, 0xd8, 0x76, 0x8a, 0x17, 0xc8, 0xe7, 0x6b, 0xf1, 0xfe, 0xff, 0xe7, 0x51, - 0x63, 0x25, 0xc5, 0xb6, 0x48, 0x88, 0x82, 0x44, 0x9d, 0xda, 0x1d, 0x72, 0xd3, 0xc7, 0x1d, 0x44, - 0x99, 0xb5, 0x2e, 0xfe, 0x73, 0xe6, 0xa4, 0xb1, 0xb5, 0x53, 0x39, 0x43, 0x7e, 0x1a, 0xce, 0xf0, - 0x1d, 0x2c, 0x0e, 0xdf, 0x2e, 0x01, 0xae, 0x76, 0xcc, 0x04, 0x4f, 0xed, 0x90, 0x23, 0xe4, 0x25, - 0xad, 0x60, 0xfe, 0x04, 0xf3, 0x5f, 0x87, 0xfe, 0x5b, 0xe0, 0x75, 0x2d, 0xa8, 0x46, 0x88, 0x92, - 0x7e, 0xe4, 0x21, 0x2a, 0xb0, 0x1a, 0x77, 0xa9, 0x63, 0x31, 0x73, 0x05, 0xae, 0x3e, 0x90, 0x04, - 0x38, 0xf6, 0x5c, 0x87, 0xb2, 0x9c, 0x04, 0xf2, 0x2a, 0x55, 0x27, 0xde, 0xf2, 0xe4, 0x4b, 0x64, - 0x93, 0xb9, 0x50, 0x56, 0xfc, 0x59, 0xdd, 0xbb, 0x7e, 0x0a, 0x97, 0x14, 0x02, 0x4e, 0x2c, 0x68, - 0xee, 0x40, 0xed, 0x5b, 0x17, 0x5f, 0xfe, 0xec, 0x8c, 0x60, 0x46, 0xfa, 0x51, 0xb1, 0x0e, 0xf1, - 0x10, 0x6d, 0x32, 0x0f, 0xc9, 0x9d, 0x87, 0x87, 0xb4, 0x5e, 0xcf, 0x40, 0x51, 0x4c, 0x4e, 0x7d, - 0x0f, 0x4a, 0x92, 0x63, 0xea, 0xb6, 0x35, 0xe9, 0x17, 0x93, 0x35, 0xc2, 0xe9, 0x8d, 0x8f, 0xa7, - 0x57, 0x50, 0x57, 0xfb, 0x01, 0x8a, 0x82, 0x0b, 0xea, 0x2b, 0x93, 0x55, 0xd3, 0xcc, 0xd4, 0xf8, - 0x70, 0x2a, 0x59, 0xe5, 0xa1, 0x03, 0x25, 0x49, 0xb0, 0xb2, 0xae, 0x33, 0x42, 0x38, 0x8d, 0x8f, - 0xa6, 0x51, 0x48, 0x1c, 0x3d, 0x87, 0xd9, 0x13, 0x4c, 0x4e, 0x6f, 0x4d, 0xa3, 0x7e, 0x72, 0xa0, - 0x9f, 0xd1, 0xe5, 0x53, 0xc8, 0x6f, 0x22, 0xa6, 0x37, 0x27, 0x2b, 0x1d, 0xd3, 0x3d, 0xe3, 0x83, - 0x29, 0x24, 0x13, 0xdc, 0x0a, 0xbc, 0xd3, 0xea, 0xd6, 0x64, 0x95, 0x61, 0x76, 0x66, 0xd8, 0x53, - 0xcb, 0x2b, 0x47, 0x6d, 0x28, 0x70, 0xb2, 0xa5, 0x67, 0xc4, 0x96, 0x22, 0x64, 0xc6, 0xe2, 0x48, - 0x72, 0x6f, 0xf0, 0x1f, 0xeb, 0xfa, 0x16, 0x14, 0x78, 0x29, 0xe9, 0x19, 0x79, 0x38, 0x4a, 0xa4, - 0xc6, 0x5a, 0x7c, 0x0c, 0xd5, 0x84, 0x63, 0x64, 0x41, 0x31, 0x4c, 0x46, 0xc6, 0x1a, 0x7d, 0x08, - 0x65, 0xc5, 0x0e, 0xf4, 0x8c, 0xf7, 0x3e, 0x49, 0x22, 0x26, 0x18, 0x2c, 0x8a, 0x69, 0x9f, 0x15, - 0xe1, 0x30, 0x25, 0x18, 0x6b, 0xf0, 0x11, 0x94, 0xe4, 0xd8, 0xcf, 0x2a, 0x9a, 0x11, 0x72, 0x30, - 0xd6, 0x24, 0x86, 0x4a, 0x3c, 0xb9, 0xf5, 0x9b, 0xd9, 0x39, 0x92, 0x22, 0x0a, 0x86, 0x35, 0xad, - 0xb8, 0xca, 0xa8, 0x17, 0x00, 0xa9, 0x79, 0x79, 0x3b, 0x03, 0xe2, 0xd3, 0x26, 0xbf, 0xf1, 0xc9, - 0xd9, 0x94, 0x94, 0xe3, 0x47, 0x50, 0x92, 0x03, 0x31, 0x0b, 0xb6, 0x91, 0xb1, 0x39, 0x16, 0xb6, - 0x1d, 0x28, 0xab, 0xd1, 0x95, 0x95, 0x2b, 0x27, 0xa7, 0xa1, 0x71, 0x73, 0x4a, 0x69, 0x15, 0xfa, - 0xf7, 0x50, 0xe0, 0x33, 0x27, 0xab, 0x0a, 0x53, 0xf3, 0xcf, 0x58, 0x99, 0x46, 0x54, 0x9a, 0x5f, - 0xfd, 0xe6, 0xf0, 0xcd, 0xd2, 0x95, 0x3f, 0xde, 0x2c, 0x5d, 0xf9, 0x65, 0xb0, 0xa4, 0x1d, 0x0e, - 0x96, 0xb4, 0xdf, 0x07, 0x4b, 0xda, 0xdf, 0x83, 0x25, 0xed, 0xe9, 0xbd, 0xf3, 0xfd, 0x65, 0xef, - 0xae, 0x58, 0x3c, 0x2b, 0x09, 0xb8, 0x6e, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x67, 0xc5, 0x63, - 0x32, 0x20, 0x14, 0x00, 0x00, + // 1318 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4b, 0x6f, 0x1b, 0x45, + 0x1c, 0xef, 0xfa, 0xed, 0xbf, 0x93, 0x36, 0x59, 0xd2, 0x60, 0x96, 0x2a, 0x0e, 0xcb, 0xc5, 0x04, + 0xba, 0x4b, 0x5d, 0x54, 0x21, 0x5a, 0x21, 0x35, 0x0f, 0x22, 0x0b, 0xaa, 0xa6, 0xdb, 0x02, 0x55, + 0x25, 0x14, 0xb6, 0xbb, 0x13, 0x67, 0x14, 0x7b, 0x67, 0xbb, 0x33, 0x4e, 0x1b, 0x38, 0xc0, 0x47, + 0xe8, 0x95, 0x0b, 0x9f, 0x27, 0x47, 0x8e, 0x08, 0x55, 0x81, 0xfa, 0x5b, 0x70, 0x43, 0xf3, 0xd8, + 0xcd, 0xc6, 0x8e, 0xbd, 0x4e, 0xd3, 0x70, 0x69, 0x67, 0x66, 0xff, 0xaf, 0xf9, 0xcd, 0xff, 0xf1, + 0x73, 0x60, 0xb5, 0x83, 0xd9, 0x6e, 0xff, 0xa9, 0xe5, 0x91, 0x9e, 0xed, 0x91, 0x80, 0xb9, 0x38, + 0x40, 0x91, 0x9f, 0x5e, 0xba, 0x21, 0xb6, 0x29, 0x8a, 0xf6, 0xb1, 0x87, 0xa8, 0xcd, 0x5c, 0xba, + 0x47, 0xed, 0xfd, 0x1b, 0x72, 0x61, 0x85, 0x11, 0x61, 0x44, 0xbf, 0x76, 0x2c, 0x6d, 0xc5, 0x92, + 0x96, 0x14, 0xd8, 0xbf, 0x61, 0xbc, 0xdf, 0x21, 0xa4, 0xd3, 0x45, 0xb6, 0x90, 0x7d, 0xda, 0xdf, + 0xb1, 0x51, 0x2f, 0x64, 0x07, 0x52, 0xd5, 0x78, 0x6f, 0xf8, 0xa3, 0x1b, 0xc4, 0x9f, 0x16, 0x3a, + 0xa4, 0x43, 0xc4, 0xd2, 0xe6, 0x2b, 0x75, 0x7a, 0x6b, 0xaa, 0x78, 0xd9, 0x41, 0x88, 0xa8, 0xdd, + 0x23, 0xfd, 0x80, 0x29, 0xbd, 0xcf, 0xcf, 0xa2, 0x87, 0x58, 0x84, 0x3d, 0x75, 0x3b, 0xe3, 0xf6, + 0x19, 0x34, 0x7d, 0x44, 0xbd, 0x08, 0x87, 0x8c, 0x44, 0x4a, 0xf9, 0x8b, 0x33, 0x28, 0x73, 0xc4, + 0xc4, 0x3f, 0x4a, 0xb7, 0x31, 0x8c, 0x0d, 0xc3, 0x3d, 0x44, 0x99, 0xdb, 0x0b, 0xa5, 0x80, 0x79, + 0x98, 0x83, 0xf9, 0xb5, 0x08, 0xb9, 0x0c, 0x3d, 0x72, 0xe9, 0x9e, 0x83, 0x9e, 0xf5, 0x11, 0x65, + 0x7a, 0x0b, 0x66, 0x12, 0xf3, 0xdb, 0xd8, 0xaf, 0x6b, 0xcb, 0x5a, 0xb3, 0xba, 0x7a, 0x65, 0x70, + 0xd4, 0xa8, 0xad, 0xc5, 0xe7, 0xed, 0x75, 0xa7, 0x96, 0x08, 0xb5, 0x7d, 0xdd, 0x86, 0x52, 0x44, + 0x08, 0xdb, 0xa1, 0xf5, 0xfc, 0x72, 0xbe, 0x59, 0x6b, 0xbd, 0x6b, 0xa5, 0x9e, 0x54, 0x44, 0x67, + 0xdd, 0xe3, 0x60, 0x3a, 0x4a, 0x4c, 0x5f, 0x80, 0x22, 0x65, 0x3e, 0x0e, 0xea, 0x05, 0x6e, 0xdd, + 0x91, 0x1b, 0x7d, 0x11, 0x4a, 0x94, 0xf9, 0xa4, 0xcf, 0xea, 0x45, 0x71, 0xac, 0x76, 0xea, 0x1c, + 0x45, 0x51, 0xbd, 0x94, 0x9c, 0xa3, 0x28, 0xd2, 0x0d, 0xa8, 0x30, 0x14, 0xf5, 0x70, 0xe0, 0x76, + 0xeb, 0xe5, 0x65, 0xad, 0x59, 0x71, 0x92, 0xbd, 0x7e, 0x07, 0xc0, 0xdb, 0x45, 0xde, 0x5e, 0x48, + 0x70, 0xc0, 0xea, 0x95, 0x65, 0xad, 0x59, 0x6b, 0x5d, 0x1b, 0x0d, 0x6b, 0x3d, 0x41, 0xdc, 0x49, + 0xc9, 0xeb, 0x16, 0x94, 0x49, 0xc8, 0x30, 0x09, 0x68, 0xbd, 0x2a, 0x54, 0x17, 0x2c, 0x89, 0xa6, + 0x15, 0xa3, 0x69, 0xdd, 0x0d, 0x0e, 0x9c, 0x58, 0xc8, 0x7c, 0x02, 0x7a, 0x1a, 0x49, 0x1a, 0x92, + 0x80, 0xa2, 0x37, 0x82, 0x72, 0x0e, 0xf2, 0x21, 0xf6, 0xeb, 0xb9, 0x65, 0xad, 0x39, 0xeb, 0xf0, + 0xa5, 0xd9, 0x81, 0x99, 0x87, 0xcc, 0x8d, 0xd8, 0x79, 0x1e, 0xe8, 0x43, 0x28, 0xa3, 0x17, 0xc8, + 0xdb, 0x56, 0x96, 0xab, 0xab, 0x30, 0x38, 0x6a, 0x94, 0x36, 0x5e, 0x20, 0xaf, 0xbd, 0xee, 0x94, + 0xf8, 0xa7, 0xb6, 0x6f, 0x7e, 0x00, 0xb3, 0xca, 0x91, 0x8a, 0x5f, 0xc5, 0xa2, 0x1d, 0xc7, 0xb2, + 0x09, 0xf3, 0xeb, 0xa8, 0x8b, 0xce, 0x9d, 0x31, 0xe6, 0xef, 0x1a, 0x5c, 0x96, 0x96, 0x12, 0x6f, + 0x8b, 0x90, 0x4b, 0x94, 0x4b, 0x83, 0xa3, 0x46, 0xae, 0xbd, 0xee, 0xe4, 0xf0, 0x29, 0x88, 0xe8, + 0x0d, 0xa8, 0xa1, 0x17, 0x98, 0x6d, 0x53, 0xe6, 0xb2, 0x3e, 0xcf, 0x39, 0xfe, 0x05, 0xf8, 0xd1, + 0x43, 0x71, 0xa2, 0xdf, 0x85, 0x2a, 0xdf, 0x21, 0x7f, 0xdb, 0x65, 0x22, 0xc5, 0x6a, 0x2d, 0x63, + 0xe4, 0x01, 0x1f, 0xc5, 0xe5, 0xb0, 0x5a, 0x39, 0x3c, 0x6a, 0x5c, 0x7a, 0xf9, 0x77, 0x43, 0x73, + 0x2a, 0x52, 0xed, 0x2e, 0x33, 0x09, 0x2c, 0xc8, 0xf8, 0xb6, 0x22, 0xe2, 0x21, 0x4a, 0x2f, 0x1c, + 0x7d, 0x04, 0xb0, 0x89, 0x2e, 0xfe, 0x91, 0x37, 0xa0, 0x26, 0xdc, 0x28, 0xd0, 0x6f, 0x41, 0x39, + 0x94, 0x17, 0x14, 0x2e, 0x86, 0x6a, 0x64, 0xff, 0x86, 0x2a, 0x93, 0x18, 0x84, 0x58, 0xd8, 0x5c, + 0x81, 0xb9, 0x6f, 0x30, 0x65, 0x3c, 0x0d, 0x12, 0x68, 0x16, 0xa1, 0xb4, 0x83, 0xbb, 0x0c, 0x45, + 0x32, 0x5a, 0x47, 0xed, 0x78, 0xd2, 0xa4, 0x64, 0x93, 0xda, 0x28, 0x8a, 0x16, 0x5f, 0xd7, 0x44, + 0xc7, 0x98, 0xec, 0x56, 0x8a, 0x9a, 0x2f, 0x35, 0xa8, 0x7d, 0x8d, 0xbb, 0xdd, 0x8b, 0x06, 0x49, + 0x34, 0x1c, 0xdc, 0xe1, 0x6d, 0x45, 0xe6, 0x96, 0xda, 0xf1, 0x54, 0x74, 0xbb, 0x5d, 0x91, 0x51, + 0x15, 0x87, 0x2f, 0xcd, 0x7f, 0x35, 0xd0, 0xb9, 0xf2, 0x5b, 0xc8, 0x92, 0xa4, 0x27, 0xe6, 0x4e, + 0xef, 0x89, 0xf9, 0x31, 0x3d, 0xb1, 0x30, 0xb6, 0x27, 0x16, 0x87, 0x7a, 0x62, 0x13, 0x0a, 0x34, + 0x44, 0x9e, 0xe8, 0xa2, 0xe3, 0x5a, 0x9a, 0x90, 0x48, 0xa3, 0x54, 0x1e, 0x9b, 0x4a, 0x57, 0xe1, + 0x9d, 0x13, 0x57, 0x97, 0x2f, 0x6b, 0xfe, 0xa6, 0xc1, 0x9c, 0x83, 0x28, 0xfe, 0x09, 0x6d, 0xb1, + 0x83, 0x0b, 0x7f, 0xaa, 0x05, 0x28, 0x3e, 0xc7, 0x3e, 0xdb, 0x55, 0x2f, 0x25, 0x37, 0x1c, 0x9d, + 0x5d, 0x84, 0x3b, 0xbb, 0xb2, 0xfa, 0x67, 0x1d, 0xb5, 0x33, 0x7f, 0x81, 0xcb, 0x6b, 0x5d, 0x42, + 0x51, 0xfb, 0xfe, 0xff, 0x11, 0x98, 0x7c, 0xce, 0xbc, 0x78, 0x05, 0xb9, 0x31, 0xbf, 0x82, 0xb9, + 0x2d, 0xb7, 0x4f, 0xcf, 0xdd, 0x3f, 0x37, 0x61, 0xde, 0x41, 0xb4, 0xdf, 0x3b, 0xb7, 0xa1, 0x0d, + 0xb8, 0xc2, 0x8b, 0x73, 0x0b, 0xfb, 0xe7, 0x49, 0x5e, 0xd3, 0x91, 0xfd, 0x40, 0x9a, 0x51, 0x25, + 0xfe, 0x25, 0x54, 0x55, 0xbb, 0x40, 0x71, 0x99, 0x2f, 0x4f, 0x2a, 0xf3, 0x76, 0xb0, 0x43, 0x9c, + 0x63, 0x15, 0xf3, 0x95, 0x06, 0x57, 0xd7, 0x92, 0x99, 0x7c, 0x5e, 0x8e, 0xb2, 0x0d, 0xf3, 0xa1, + 0x1b, 0xa1, 0x80, 0x6d, 0xa7, 0x78, 0x81, 0x7c, 0xbe, 0x16, 0xef, 0xff, 0x7f, 0x1d, 0x35, 0x56, + 0x52, 0x6c, 0x8b, 0x84, 0x28, 0x48, 0xd4, 0xa9, 0xdd, 0x21, 0xd7, 0x7d, 0xdc, 0x41, 0x94, 0x59, + 0xeb, 0xe2, 0x3f, 0x67, 0x4e, 0x1a, 0x5b, 0x3b, 0x95, 0x33, 0xe4, 0xa7, 0xe1, 0x0c, 0x8f, 0x61, + 0x71, 0xf8, 0x76, 0x09, 0x70, 0xb5, 0x63, 0x26, 0x78, 0x6a, 0x87, 0x1c, 0x21, 0x2f, 0x69, 0x05, + 0xf3, 0x67, 0x98, 0xff, 0x36, 0xf4, 0xdf, 0x02, 0xaf, 0x6b, 0x41, 0x35, 0x42, 0x94, 0xf4, 0x23, + 0x0f, 0x51, 0x81, 0xd5, 0xb8, 0x4b, 0x1d, 0x8b, 0x99, 0x2b, 0x70, 0xf9, 0x9e, 0x24, 0xc0, 0xb1, + 0xe7, 0x3a, 0x94, 0xe5, 0x24, 0x90, 0x57, 0xa9, 0x3a, 0xf1, 0x96, 0x27, 0x5f, 0x22, 0x9b, 0xcc, + 0x85, 0xb2, 0xe2, 0xcf, 0xea, 0xde, 0xf5, 0x53, 0xb8, 0xa4, 0x10, 0x70, 0x62, 0x41, 0x73, 0x07, + 0x6a, 0xdf, 0xbb, 0xf8, 0xe2, 0x67, 0x67, 0x04, 0x33, 0xd2, 0x8f, 0x8a, 0x75, 0x88, 0x87, 0x68, + 0x93, 0x79, 0x48, 0xee, 0x4d, 0x78, 0x48, 0xeb, 0xd5, 0x0c, 0x14, 0xc5, 0xe4, 0xd4, 0xf7, 0xa0, + 0x24, 0x39, 0xa6, 0x6e, 0x5b, 0x93, 0x7e, 0x31, 0x59, 0x23, 0x9c, 0xde, 0xf8, 0x74, 0x7a, 0x05, + 0x75, 0xb5, 0x1f, 0xa1, 0x28, 0xb8, 0xa0, 0xbe, 0x32, 0x59, 0x35, 0xcd, 0x4c, 0x8d, 0x8f, 0xa7, + 0x92, 0x55, 0x1e, 0x3a, 0x50, 0x92, 0x04, 0x2b, 0xeb, 0x3a, 0x23, 0x84, 0xd3, 0xf8, 0x64, 0x1a, + 0x85, 0xc4, 0xd1, 0x33, 0x98, 0x3d, 0xc1, 0xe4, 0xf4, 0xd6, 0x34, 0xea, 0x27, 0x07, 0xfa, 0x19, + 0x5d, 0x3e, 0x81, 0xfc, 0x26, 0x62, 0x7a, 0x73, 0xb2, 0xd2, 0x31, 0xdd, 0x33, 0x3e, 0x9a, 0x42, + 0x32, 0xc1, 0xad, 0xc0, 0x3b, 0xad, 0x6e, 0x4d, 0x56, 0x19, 0x66, 0x67, 0x86, 0x3d, 0xb5, 0xbc, + 0x72, 0xd4, 0x86, 0x02, 0x27, 0x5b, 0x7a, 0x46, 0x6c, 0x29, 0x42, 0x66, 0x2c, 0x8e, 0x24, 0xf7, + 0x06, 0xff, 0xb1, 0xae, 0x6f, 0x41, 0x81, 0x97, 0x92, 0x9e, 0x91, 0x87, 0xa3, 0x44, 0x6a, 0xac, + 0xc5, 0x87, 0x50, 0x4d, 0x38, 0x46, 0x16, 0x14, 0xc3, 0x64, 0x64, 0xac, 0xd1, 0xfb, 0x50, 0x56, + 0xec, 0x40, 0xcf, 0x78, 0xef, 0x93, 0x24, 0x62, 0x82, 0xc1, 0xa2, 0x98, 0xf6, 0x59, 0x11, 0x0e, + 0x53, 0x82, 0xb1, 0x06, 0x1f, 0x40, 0x49, 0x8e, 0xfd, 0xac, 0xa2, 0x19, 0x21, 0x07, 0x63, 0x4d, + 0x62, 0xa8, 0xc4, 0x93, 0x5b, 0xbf, 0x9e, 0x9d, 0x23, 0x29, 0xa2, 0x60, 0x58, 0xd3, 0x8a, 0xab, + 0x8c, 0x7a, 0x0e, 0x90, 0x9a, 0x97, 0x37, 0x33, 0x20, 0x3e, 0x6d, 0xf2, 0x1b, 0x9f, 0x9d, 0x4d, + 0x49, 0x39, 0x7e, 0x00, 0x25, 0x39, 0x10, 0xb3, 0x60, 0x1b, 0x19, 0x9b, 0x63, 0x61, 0xdb, 0x81, + 0xb2, 0x1a, 0x5d, 0x59, 0xb9, 0x72, 0x72, 0x1a, 0x1a, 0xd7, 0xa7, 0x94, 0x56, 0xa1, 0xff, 0x00, + 0x05, 0x3e, 0x73, 0xb2, 0xaa, 0x30, 0x35, 0xff, 0x8c, 0x95, 0x69, 0x44, 0xa5, 0xf9, 0xd5, 0xef, + 0x0e, 0x5f, 0x2f, 0x5d, 0xfa, 0xf3, 0xf5, 0xd2, 0xa5, 0x5f, 0x07, 0x4b, 0xda, 0xe1, 0x60, 0x49, + 0xfb, 0x63, 0xb0, 0xa4, 0xfd, 0x33, 0x58, 0xd2, 0x9e, 0xdc, 0x79, 0xb3, 0xbf, 0xec, 0xdd, 0x16, + 0x8b, 0xc7, 0xb9, 0xa7, 0x25, 0x01, 0xd8, 0xcd, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x85, 0xa2, + 0x4f, 0xd1, 0x22, 0x14, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/api/services/tasks/v1/tasks.proto b/vendor/github.com/containerd/containerd/api/services/tasks/v1/tasks.proto index eb373185eba..90793cbabad 100644 --- a/vendor/github.com/containerd/containerd/api/services/tasks/v1/tasks.proto +++ b/vendor/github.com/containerd/containerd/api/services/tasks/v1/tasks.proto @@ -4,7 +4,7 @@ package containerd.services.tasks.v1; import "google/protobuf/empty.proto"; import "google/protobuf/any.proto"; -import "gogoproto/gogo.proto"; +import weak "gogoproto/gogo.proto"; import "github.com/containerd/containerd/api/types/mount.proto"; import "github.com/containerd/containerd/api/types/metrics.proto"; import "github.com/containerd/containerd/api/types/descriptor.proto"; diff --git a/vendor/github.com/containerd/containerd/api/services/version/v1/BUILD b/vendor/github.com/containerd/containerd/api/services/version/v1/BUILD index b1f44359310..1bfa4d3fa66 100644 --- a/vendor/github.com/containerd/containerd/api/services/version/v1/BUILD +++ b/vendor/github.com/containerd/containerd/api/services/version/v1/BUILD @@ -12,9 +12,8 @@ go_library( importpath = "github.com/containerd/containerd/api/services/version/v1", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library", "//vendor/github.com/gogo/protobuf/proto:go_default_library", - "//vendor/github.com/golang/protobuf/ptypes/empty:go_default_library", + "//vendor/github.com/gogo/protobuf/types:go_default_library", "//vendor/golang.org/x/net/context:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", ], diff --git a/vendor/github.com/containerd/containerd/api/services/version/v1/version.pb.go b/vendor/github.com/containerd/containerd/api/services/version/v1/version.pb.go index c403c8431be..3f6528a0bb4 100644 --- a/vendor/github.com/containerd/containerd/api/services/version/v1/version.pb.go +++ b/vendor/github.com/containerd/containerd/api/services/version/v1/version.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-gogo. +// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: github.com/containerd/containerd/api/services/version/v1/version.proto -// DO NOT EDIT! /* Package version is a generated protocol buffer package. @@ -16,8 +15,9 @@ package version import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" -import google_protobuf "github.com/golang/protobuf/ptypes/empty" -import _ "github.com/gogo/protobuf/gogoproto" +import google_protobuf "github.com/gogo/protobuf/types" + +// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto" import ( context "golang.org/x/net/context" @@ -155,24 +155,6 @@ func (m *VersionResponse) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func encodeFixed64Version(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Version(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} func encodeVarintVersion(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -446,7 +428,7 @@ func init() { } var fileDescriptorVersion = []byte{ - // 241 bytes of a gzipped FileDescriptorProto + // 243 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x72, 0x4b, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0x4a, 0x41, 0x66, 0x26, 0x16, 0x64, 0xea, 0x17, 0xa7, 0x16, 0x95, 0x65, 0x26, 0xa7, 0x16, 0xeb, @@ -460,7 +442,7 @@ var fileDescriptorVersion = []byte{ 0x76, 0xa8, 0x41, 0x42, 0x41, 0x08, 0xa6, 0x98, 0x1e, 0xc4, 0x49, 0x7a, 0x30, 0x27, 0xe9, 0xb9, 0x82, 0x9c, 0x24, 0xa5, 0xaf, 0x87, 0xdf, 0x2b, 0x7a, 0x68, 0x8e, 0x72, 0x8a, 0x3a, 0xf1, 0x50, 0x8e, 0xe1, 0xc6, 0x43, 0x39, 0x86, 0x86, 0x47, 0x72, 0x8c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, - 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0x63, 0x94, 0x03, 0xb9, 0x81, 0x6b, 0x0d, 0x65, 0x26, 0xb1, - 0x81, 0x1d, 0x67, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xb6, 0x37, 0xd8, 0xc6, 0xa7, 0x01, 0x00, - 0x00, + 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0x63, 0x94, 0x03, 0xb9, 0x81, 0x6b, 0x0d, 0x65, 0x46, 0x30, + 0x26, 0xb1, 0x81, 0x9d, 0x67, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x95, 0x0d, 0x52, 0x23, 0xa9, + 0x01, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/api/services/version/v1/version.proto b/vendor/github.com/containerd/containerd/api/services/version/v1/version.proto index 2398fdcbedb..0e4c3d1e081 100644 --- a/vendor/github.com/containerd/containerd/api/services/version/v1/version.proto +++ b/vendor/github.com/containerd/containerd/api/services/version/v1/version.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package containerd.services.version.v1; import "google/protobuf/empty.proto"; -import "gogoproto/gogo.proto"; +import weak "gogoproto/gogo.proto"; // TODO(stevvooe): Should version service actually be versioned? option go_package = "github.com/containerd/containerd/api/services/version/v1;version"; diff --git a/vendor/github.com/containerd/containerd/api/types/BUILD b/vendor/github.com/containerd/containerd/api/types/BUILD index 8d0bbf57d37..9fdec8b01e0 100644 --- a/vendor/github.com/containerd/containerd/api/types/BUILD +++ b/vendor/github.com/containerd/containerd/api/types/BUILD @@ -23,7 +23,6 @@ go_library( importpath = "github.com/containerd/containerd/api/types", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library", "//vendor/github.com/gogo/protobuf/proto:go_default_library", "//vendor/github.com/gogo/protobuf/types:go_default_library", "//vendor/github.com/opencontainers/go-digest:go_default_library", diff --git a/vendor/github.com/containerd/containerd/api/types/descriptor.pb.go b/vendor/github.com/containerd/containerd/api/types/descriptor.pb.go index 785d0507071..93e88c0dc27 100644 --- a/vendor/github.com/containerd/containerd/api/types/descriptor.pb.go +++ b/vendor/github.com/containerd/containerd/api/types/descriptor.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-gogo. +// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: github.com/containerd/containerd/api/types/descriptor.proto -// DO NOT EDIT! /* Package types is a generated protocol buffer package. @@ -22,7 +21,8 @@ package types import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" -import _ "github.com/gogo/protobuf/gogoproto" + +// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto" import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest" @@ -95,24 +95,6 @@ func (m *Descriptor) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func encodeFixed64Descriptor(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Descriptor(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} func encodeVarintDescriptor(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -409,7 +391,7 @@ func init() { } var fileDescriptorDescriptor = []byte{ - // 232 bytes of a gzipped FileDescriptorProto + // 234 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x4e, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0x4a, 0x41, 0x66, 0x26, 0x16, 0x64, 0xea, 0x97, 0x54, 0x16, 0xa4, 0x16, 0xeb, 0xa7, 0xa4, 0x16, @@ -423,6 +405,6 @@ var fileDescriptorDescriptor = []byte{ 0x4d, 0x10, 0x12, 0xe2, 0x62, 0x29, 0xce, 0xac, 0x4a, 0x95, 0x60, 0x56, 0x60, 0xd4, 0x60, 0x0e, 0x02, 0xb3, 0x9d, 0xbc, 0x4e, 0x3c, 0x94, 0x63, 0xb8, 0xf1, 0x50, 0x8e, 0xa1, 0xe1, 0x91, 0x1c, 0xe3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x18, 0x65, 0x40, - 0x7c, 0x60, 0x58, 0x83, 0xc9, 0x24, 0x36, 0xb0, 0x07, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, - 0x23, 0x14, 0xc9, 0x7c, 0x47, 0x01, 0x00, 0x00, + 0x7c, 0x60, 0x58, 0x83, 0xc9, 0x08, 0x86, 0x24, 0x36, 0xb0, 0x17, 0x8d, 0x01, 0x01, 0x00, 0x00, + 0xff, 0xff, 0xea, 0xac, 0x78, 0x9a, 0x49, 0x01, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/api/types/descriptor.proto b/vendor/github.com/containerd/containerd/api/types/descriptor.proto index 7975ab06d92..5c00dca4f1b 100644 --- a/vendor/github.com/containerd/containerd/api/types/descriptor.proto +++ b/vendor/github.com/containerd/containerd/api/types/descriptor.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package containerd.types; -import "gogoproto/gogo.proto"; +import weak "gogoproto/gogo.proto"; option go_package = "github.com/containerd/containerd/api/types;types"; diff --git a/vendor/github.com/containerd/containerd/api/types/metrics.pb.go b/vendor/github.com/containerd/containerd/api/types/metrics.pb.go index f9aacf941aa..da0467884c8 100644 --- a/vendor/github.com/containerd/containerd/api/types/metrics.pb.go +++ b/vendor/github.com/containerd/containerd/api/types/metrics.pb.go @@ -1,13 +1,13 @@ -// Code generated by protoc-gen-gogo. +// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: github.com/containerd/containerd/api/types/metrics.proto -// DO NOT EDIT! package types import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" -import _ "github.com/gogo/protobuf/gogoproto" + +// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto" import google_protobuf1 "github.com/gogo/protobuf/types" import _ "github.com/gogo/protobuf/types" @@ -81,24 +81,6 @@ func (m *Metric) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func encodeFixed64Metrics(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Metrics(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} func encodeVarintMetrics(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -409,7 +391,7 @@ func init() { } var fileDescriptorMetrics = []byte{ - // 256 bytes of a gzipped FileDescriptorProto + // 258 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x48, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0x4a, 0x41, 0x66, 0x26, 0x16, 0x64, 0xea, 0x97, 0x54, 0x16, 0xa4, 0x16, 0xeb, 0xe7, 0xa6, 0x96, @@ -424,6 +406,7 @@ var fileDescriptorMetrics = []byte{ 0x5d, 0x82, 0x98, 0x32, 0x53, 0x84, 0x34, 0xb8, 0x58, 0x52, 0x12, 0x4b, 0x12, 0x25, 0x98, 0xc1, 0xc6, 0x8a, 0x60, 0x18, 0xeb, 0x98, 0x57, 0x19, 0x04, 0x56, 0xe1, 0xe4, 0x75, 0xe2, 0xa1, 0x1c, 0xc3, 0x8d, 0x87, 0x72, 0x0c, 0x0d, 0x8f, 0xe4, 0x18, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, - 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x28, 0x03, 0xe2, 0x03, 0xd2, 0x1a, 0x4c, 0x26, 0xb1, 0x81, - 0xcd, 0x37, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x51, 0x36, 0x74, 0x83, 0x01, 0x00, 0x00, + 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x28, 0x03, 0xe2, 0x03, 0xd2, 0x1a, 0x4c, 0x46, 0x30, 0x24, + 0xb1, 0x81, 0x6d, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xde, 0x0d, 0x02, 0xfe, 0x85, 0x01, + 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/api/types/metrics.proto b/vendor/github.com/containerd/containerd/api/types/metrics.proto index d1629c7eec4..0e631d2ac35 100644 --- a/vendor/github.com/containerd/containerd/api/types/metrics.proto +++ b/vendor/github.com/containerd/containerd/api/types/metrics.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package containerd.types; -import "gogoproto/gogo.proto"; +import weak "gogoproto/gogo.proto"; import "google/protobuf/any.proto"; import "google/protobuf/timestamp.proto"; diff --git a/vendor/github.com/containerd/containerd/api/types/mount.pb.go b/vendor/github.com/containerd/containerd/api/types/mount.pb.go index cc835140e31..f7a9c3c1fe2 100644 --- a/vendor/github.com/containerd/containerd/api/types/mount.pb.go +++ b/vendor/github.com/containerd/containerd/api/types/mount.pb.go @@ -1,13 +1,13 @@ -// Code generated by protoc-gen-gogo. +// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: github.com/containerd/containerd/api/types/mount.proto -// DO NOT EDIT! package types import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" -import _ "github.com/gogo/protobuf/gogoproto" + +// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto" import strings "strings" import reflect "reflect" @@ -96,24 +96,6 @@ func (m *Mount) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func encodeFixed64Mount(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Mount(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} func encodeVarintMount(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -457,7 +439,7 @@ func init() { } var fileDescriptorMount = []byte{ - // 200 bytes of a gzipped FileDescriptorProto + // 202 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0x4b, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0x4a, 0x41, 0x66, 0x26, 0x16, 0x64, 0xea, 0x97, 0x54, 0x16, 0xa4, 0x16, 0xeb, 0xe7, 0xe6, 0x97, @@ -469,6 +451,6 @@ var fileDescriptorMount = []byte{ 0x82, 0x8b, 0x3d, 0xbf, 0xa0, 0x24, 0x33, 0x3f, 0xaf, 0x58, 0x82, 0x45, 0x81, 0x59, 0x83, 0x33, 0x08, 0xc6, 0x75, 0xf2, 0x3a, 0xf1, 0x50, 0x8e, 0xe1, 0xc6, 0x43, 0x39, 0x86, 0x86, 0x47, 0x72, 0x8c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0x63, 0x94, 0x01, - 0xf1, 0x1e, 0xb4, 0x06, 0x93, 0x49, 0x6c, 0x60, 0x97, 0x1b, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, - 0xe5, 0xc7, 0x07, 0x3f, 0x1b, 0x01, 0x00, 0x00, + 0xf1, 0x1e, 0xb4, 0x06, 0x93, 0x11, 0x0c, 0x49, 0x6c, 0x60, 0xb7, 0x1b, 0x03, 0x02, 0x00, 0x00, + 0xff, 0xff, 0x82, 0x1c, 0x02, 0x18, 0x1d, 0x01, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/api/types/mount.proto b/vendor/github.com/containerd/containerd/api/types/mount.proto index 031e6544247..cd80e44a2c0 100644 --- a/vendor/github.com/containerd/containerd/api/types/mount.proto +++ b/vendor/github.com/containerd/containerd/api/types/mount.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package containerd.types; -import "gogoproto/gogo.proto"; +import weak "gogoproto/gogo.proto"; option go_package = "github.com/containerd/containerd/api/types;types"; diff --git a/vendor/github.com/containerd/containerd/api/types/platform.pb.go b/vendor/github.com/containerd/containerd/api/types/platform.pb.go index 0ca2afc2596..ba9a3bf8817 100644 --- a/vendor/github.com/containerd/containerd/api/types/platform.pb.go +++ b/vendor/github.com/containerd/containerd/api/types/platform.pb.go @@ -1,13 +1,13 @@ -// Code generated by protoc-gen-gogo. +// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: github.com/containerd/containerd/api/types/platform.proto -// DO NOT EDIT! package types import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" -import _ "github.com/gogo/protobuf/gogoproto" + +// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto" import strings "strings" import reflect "reflect" @@ -70,24 +70,6 @@ func (m *Platform) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func encodeFixed64Platform(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Platform(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} func encodeVarintPlatform(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -395,7 +377,7 @@ func init() { } var fileDescriptorPlatform = []byte{ - // 203 bytes of a gzipped FileDescriptorProto + // 205 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x4c, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0x4a, 0x41, 0x66, 0x26, 0x16, 0x64, 0xea, 0x97, 0x54, 0x16, 0xa4, 0x16, 0xeb, 0x17, 0xe4, 0x24, @@ -407,6 +389,6 @@ var fileDescriptorPlatform = []byte{ 0x40, 0x2a, 0x82, 0x50, 0xc4, 0x84, 0x24, 0xb8, 0xd8, 0xcb, 0x12, 0x8b, 0x32, 0x13, 0xf3, 0x4a, 0x24, 0x98, 0xc1, 0xd2, 0x30, 0xae, 0x93, 0xd7, 0x89, 0x87, 0x72, 0x0c, 0x37, 0x1e, 0xca, 0x31, 0x34, 0x3c, 0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, - 0x18, 0xa3, 0x0c, 0x88, 0xf7, 0x9e, 0x35, 0x98, 0x4c, 0x62, 0x03, 0x3b, 0xda, 0x18, 0x10, 0x00, - 0x00, 0xff, 0xff, 0x97, 0xa1, 0x99, 0x56, 0x19, 0x01, 0x00, 0x00, + 0x18, 0xa3, 0x0c, 0x88, 0xf7, 0x9e, 0x35, 0x98, 0x8c, 0x60, 0x48, 0x62, 0x03, 0x3b, 0xdb, 0x18, + 0x10, 0x00, 0x00, 0xff, 0xff, 0x05, 0xaa, 0xda, 0xa1, 0x1b, 0x01, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/api/types/platform.proto b/vendor/github.com/containerd/containerd/api/types/platform.proto index b1dce06233f..4cf9834bdc4 100644 --- a/vendor/github.com/containerd/containerd/api/types/platform.proto +++ b/vendor/github.com/containerd/containerd/api/types/platform.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package containerd.types; -import "gogoproto/gogo.proto"; +import weak "gogoproto/gogo.proto"; option go_package = "github.com/containerd/containerd/api/types;types"; diff --git a/vendor/github.com/containerd/containerd/api/types/task/BUILD b/vendor/github.com/containerd/containerd/api/types/task/BUILD index 01c18dfd684..7cd385c445c 100644 --- a/vendor/github.com/containerd/containerd/api/types/task/BUILD +++ b/vendor/github.com/containerd/containerd/api/types/task/BUILD @@ -6,7 +6,6 @@ go_library( importpath = "github.com/containerd/containerd/api/types/task", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library", "//vendor/github.com/gogo/protobuf/proto:go_default_library", "//vendor/github.com/gogo/protobuf/types:go_default_library", ], diff --git a/vendor/github.com/containerd/containerd/api/types/task/task.pb.go b/vendor/github.com/containerd/containerd/api/types/task/task.pb.go index ccc230ae734..ba34270a372 100644 --- a/vendor/github.com/containerd/containerd/api/types/task/task.pb.go +++ b/vendor/github.com/containerd/containerd/api/types/task/task.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-gogo. +// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: github.com/containerd/containerd/api/types/task/task.proto -// DO NOT EDIT! /* Package task is a generated protocol buffer package. @@ -17,7 +16,8 @@ package task import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" -import _ "github.com/gogo/protobuf/gogoproto" + +// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto" import _ "github.com/gogo/protobuf/types" import google_protobuf2 "github.com/gogo/protobuf/types" @@ -224,24 +224,6 @@ func (m *ProcessInfo) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func encodeFixed64Task(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Task(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} func encodeVarintTask(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -869,39 +851,40 @@ func init() { } var fileDescriptorTask = []byte{ - // 543 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xcf, 0x6e, 0xd3, 0x4c, - 0x14, 0xc5, 0x33, 0x6e, 0xe3, 0x24, 0xe3, 0xb6, 0x9f, 0x3f, 0x13, 0x55, 0xc6, 0x20, 0xdb, 0xea, - 0xca, 0x62, 0x61, 0x8b, 0x74, 0xc7, 0x2e, 0xff, 0x84, 0x2c, 0x24, 0x37, 0x72, 0x12, 0xb1, 0x8c, - 0x9c, 0x78, 0x62, 0x46, 0x6d, 0x66, 0x2c, 0x7b, 0x0c, 0x64, 0xc7, 0x12, 0x75, 0xc5, 0x0b, 0x74, - 0x05, 0x4f, 0xc1, 0x13, 0x64, 0xc9, 0x0a, 0xb1, 0x0a, 0xd4, 0x4f, 0x82, 0xc6, 0x76, 0xd2, 0x08, - 0xd8, 0x8c, 0xee, 0x3d, 0xbf, 0x33, 0x77, 0xee, 0x1c, 0xf8, 0x22, 0xc2, 0xec, 0x4d, 0x36, 0xb7, - 0x17, 0x74, 0xe5, 0x2c, 0x28, 0x61, 0x01, 0x26, 0x28, 0x09, 0x0f, 0xcb, 0x20, 0xc6, 0x0e, 0x5b, - 0xc7, 0x28, 0x75, 0x58, 0x90, 0x5e, 0x17, 0x87, 0x1d, 0x27, 0x94, 0x51, 0xe5, 0xd1, 0x83, 0xcb, - 0x7e, 0xfb, 0xdc, 0x2e, 0x4c, 0x5a, 0x3b, 0xa2, 0x11, 0x2d, 0xb8, 0xc3, 0xab, 0xd2, 0xaa, 0x19, - 0x11, 0xa5, 0xd1, 0x0d, 0x72, 0x8a, 0x6e, 0x9e, 0x2d, 0x1d, 0x86, 0x57, 0x28, 0x65, 0xc1, 0x2a, - 0xae, 0x0c, 0x8f, 0xff, 0x34, 0x04, 0x64, 0x5d, 0xa2, 0x8b, 0x5c, 0x80, 0x8d, 0x51, 0x42, 0x17, - 0x28, 0x4d, 0x95, 0x0e, 0x3c, 0xd9, 0x3f, 0x3a, 0xc3, 0xa1, 0x0a, 0x4c, 0x60, 0xb5, 0x7a, 0xff, - 0xe5, 0x5b, 0x43, 0xea, 0xef, 0x74, 0x77, 0xe0, 0x4b, 0x7b, 0x93, 0x1b, 0x2a, 0xe7, 0x50, 0xc0, - 0xa1, 0x2a, 0x14, 0x4e, 0x31, 0xdf, 0x1a, 0x82, 0x3b, 0xf0, 0x05, 0x1c, 0x2a, 0x32, 0x3c, 0x8a, - 0x71, 0xa8, 0x1e, 0x99, 0xc0, 0x3a, 0xf5, 0x79, 0xa9, 0x5c, 0x42, 0x31, 0x65, 0x01, 0xcb, 0x52, - 0xf5, 0xd8, 0x04, 0xd6, 0x59, 0xe7, 0x89, 0xfd, 0x8f, 0x1f, 0xda, 0xe3, 0xc2, 0xe2, 0x57, 0x56, - 0xa5, 0x0d, 0xeb, 0x29, 0x0b, 0x31, 0x51, 0xeb, 0xfc, 0x05, 0xbf, 0x6c, 0x94, 0x73, 0x3e, 0x2a, - 0xa4, 0x19, 0x53, 0xc5, 0x42, 0xae, 0xba, 0x4a, 0x47, 0x49, 0xa2, 0x36, 0xf6, 0x3a, 0x4a, 0x12, - 0x45, 0x83, 0x4d, 0x86, 0x92, 0x15, 0x26, 0xc1, 0x8d, 0xda, 0x34, 0x81, 0xd5, 0xf4, 0xf7, 0xbd, - 0x62, 0x40, 0x09, 0xbd, 0xc7, 0x6c, 0x56, 0xed, 0xd6, 0x2a, 0x16, 0x86, 0x5c, 0x2a, 0x57, 0x51, - 0xba, 0xb0, 0xc5, 0x3b, 0x14, 0xce, 0x02, 0xa6, 0x42, 0x13, 0x58, 0x52, 0x47, 0xb3, 0xcb, 0x40, - 0xed, 0x5d, 0xa0, 0xf6, 0x64, 0x97, 0x78, 0xaf, 0xb9, 0xd9, 0x1a, 0xb5, 0x4f, 0x3f, 0x0d, 0xe0, - 0x37, 0xcb, 0x6b, 0x5d, 0x76, 0xe1, 0x42, 0xa9, 0xca, 0xd8, 0x25, 0x4b, 0xba, 0xcb, 0x06, 0x3c, - 0x64, 0x63, 0xc1, 0x63, 0x4c, 0x96, 0xb4, 0xc8, 0x51, 0xea, 0xb4, 0xff, 0x1a, 0xdf, 0x25, 0x6b, - 0xbf, 0x70, 0x3c, 0xfb, 0x0e, 0xa0, 0x58, 0x2d, 0xa6, 0xc3, 0xc6, 0xd4, 0x7b, 0xe5, 0x5d, 0xbd, - 0xf6, 0xe4, 0x9a, 0xf6, 0xff, 0xed, 0x9d, 0x79, 0x5a, 0x82, 0x29, 0xb9, 0x26, 0xf4, 0x1d, 0xe1, - 0xbc, 0xef, 0x0f, 0xbb, 0x93, 0xe1, 0x40, 0x06, 0x87, 0xbc, 0x9f, 0xa0, 0x80, 0xa1, 0x90, 0x73, - 0x7f, 0xea, 0x79, 0xae, 0xf7, 0x52, 0x16, 0x0e, 0xb9, 0x9f, 0x11, 0x82, 0x49, 0xc4, 0xf9, 0x78, - 0x72, 0x35, 0x1a, 0x0d, 0x07, 0xf2, 0xd1, 0x21, 0x1f, 0x33, 0x1a, 0xc7, 0x28, 0x54, 0x9e, 0x42, - 0x71, 0xd4, 0x9d, 0x8e, 0x87, 0x03, 0xf9, 0x58, 0x93, 0x6f, 0xef, 0xcc, 0x93, 0x12, 0x8f, 0x82, - 0x2c, 0x2d, 0xa7, 0x73, 0xca, 0xa7, 0xd7, 0x0f, 0x6f, 0x73, 0x8c, 0x49, 0xa4, 0x9d, 0x7d, 0xfc, - 0xac, 0xd7, 0xbe, 0x7e, 0xd1, 0xab, 0xdf, 0xf4, 0xd4, 0xcd, 0xbd, 0x5e, 0xfb, 0x71, 0xaf, 0xd7, - 0x3e, 0xe4, 0x3a, 0xd8, 0xe4, 0x3a, 0xf8, 0x96, 0xeb, 0xe0, 0x57, 0xae, 0x83, 0xb9, 0x58, 0xc4, - 0x70, 0xf9, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x19, 0xf7, 0x5b, 0x8f, 0x4e, 0x03, 0x00, 0x00, + // 545 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x3f, 0x6f, 0xd3, 0x40, + 0x18, 0xc6, 0x7d, 0x6e, 0xeb, 0xa6, 0xe7, 0xb6, 0x18, 0x13, 0x55, 0xc6, 0x20, 0xdb, 0xea, 0x64, + 0x31, 0xd8, 0x22, 0xdd, 0xd8, 0xf2, 0x4f, 0xc8, 0x42, 0x72, 0x23, 0x27, 0x11, 0x6c, 0x91, 0x13, + 0x5f, 0xcc, 0xa9, 0xcd, 0x9d, 0x65, 0x9f, 0x81, 0x6c, 0x8c, 0xa8, 0x13, 0x5f, 0xa0, 0x13, 0x7c, + 0x0a, 0x3e, 0x41, 0x46, 0x26, 0xc4, 0x14, 0xa8, 0x3f, 0x09, 0x3a, 0xdb, 0x49, 0x23, 0x60, 0x39, + 0xbd, 0xef, 0xf3, 0x7b, 0xee, 0xbd, 0xf7, 0x1e, 0xf8, 0x22, 0xc6, 0xec, 0x6d, 0x3e, 0x75, 0x66, + 0x74, 0xe1, 0xce, 0x28, 0x61, 0x21, 0x26, 0x28, 0x8d, 0x76, 0xcb, 0x30, 0xc1, 0x2e, 0x5b, 0x26, + 0x28, 0x73, 0x59, 0x98, 0x5d, 0x95, 0x87, 0x93, 0xa4, 0x94, 0x51, 0xf5, 0xd1, 0xbd, 0xcb, 0x79, + 0xf7, 0xdc, 0x29, 0x4d, 0x7a, 0x33, 0xa6, 0x31, 0x2d, 0xb9, 0xcb, 0xab, 0xca, 0xaa, 0x9b, 0x31, + 0xa5, 0xf1, 0x35, 0x72, 0xcb, 0x6e, 0x9a, 0xcf, 0x5d, 0x86, 0x17, 0x28, 0x63, 0xe1, 0x22, 0xa9, + 0x0d, 0x8f, 0xff, 0x36, 0x84, 0x64, 0x59, 0xa1, 0xf3, 0x42, 0x84, 0x87, 0x83, 0x94, 0xce, 0x50, + 0x96, 0xa9, 0x2d, 0x78, 0xbc, 0x7d, 0x74, 0x82, 0x23, 0x0d, 0x58, 0xc0, 0x3e, 0xea, 0x3c, 0x28, + 0xd6, 0xa6, 0xdc, 0xdd, 0xe8, 0x5e, 0x2f, 0x90, 0xb7, 0x26, 0x2f, 0x52, 0xcf, 0xa0, 0x88, 0x23, + 0x4d, 0x2c, 0x9d, 0x52, 0xb1, 0x36, 0x45, 0xaf, 0x17, 0x88, 0x38, 0x52, 0x15, 0xb8, 0x97, 0xe0, + 0x48, 0xdb, 0xb3, 0x80, 0x7d, 0x12, 0xf0, 0x52, 0xbd, 0x80, 0x52, 0xc6, 0x42, 0x96, 0x67, 0xda, + 0xbe, 0x05, 0xec, 0xd3, 0xd6, 0x13, 0xe7, 0x3f, 0x3f, 0x74, 0x86, 0xa5, 0x25, 0xa8, 0xad, 0x6a, + 0x13, 0x1e, 0x64, 0x2c, 0xc2, 0x44, 0x3b, 0xe0, 0x2f, 0x04, 0x55, 0xa3, 0x9e, 0xf1, 0x51, 0x11, + 0xcd, 0x99, 0x26, 0x95, 0x72, 0xdd, 0xd5, 0x3a, 0x4a, 0x53, 0xed, 0x70, 0xab, 0xa3, 0x34, 0x55, + 0x75, 0xd8, 0x60, 0x28, 0x5d, 0x60, 0x12, 0x5e, 0x6b, 0x0d, 0x0b, 0xd8, 0x8d, 0x60, 0xdb, 0xab, + 0x26, 0x94, 0xd1, 0x07, 0xcc, 0x26, 0xf5, 0x6e, 0x47, 0xe5, 0xc2, 0x90, 0x4b, 0xd5, 0x2a, 0x6a, + 0x1b, 0x1e, 0xf1, 0x0e, 0x45, 0x93, 0x90, 0x69, 0xd0, 0x02, 0xb6, 0xdc, 0xd2, 0x9d, 0x2a, 0x50, + 0x67, 0x13, 0xa8, 0x33, 0xda, 0x24, 0xde, 0x69, 0xac, 0xd6, 0xa6, 0xf0, 0xf9, 0x97, 0x09, 0x82, + 0x46, 0x75, 0xad, 0xcd, 0xce, 0x3d, 0x28, 0xd7, 0x19, 0x7b, 0x64, 0x4e, 0x37, 0xd9, 0x80, 0xfb, + 0x6c, 0x6c, 0xb8, 0x8f, 0xc9, 0x9c, 0x96, 0x39, 0xca, 0xad, 0xe6, 0x3f, 0xe3, 0xdb, 0x64, 0x19, + 0x94, 0x8e, 0x67, 0x3f, 0x00, 0x94, 0xea, 0xc5, 0x0c, 0x78, 0x38, 0xf6, 0x5f, 0xf9, 0x97, 0xaf, + 0x7d, 0x45, 0xd0, 0x1f, 0xde, 0xdc, 0x5a, 0x27, 0x15, 0x18, 0x93, 0x2b, 0x42, 0xdf, 0x13, 0xce, + 0xbb, 0x41, 0xbf, 0x3d, 0xea, 0xf7, 0x14, 0xb0, 0xcb, 0xbb, 0x29, 0x0a, 0x19, 0x8a, 0x38, 0x0f, + 0xc6, 0xbe, 0xef, 0xf9, 0x2f, 0x15, 0x71, 0x97, 0x07, 0x39, 0x21, 0x98, 0xc4, 0x9c, 0x0f, 0x47, + 0x97, 0x83, 0x41, 0xbf, 0xa7, 0xec, 0xed, 0xf2, 0x21, 0xa3, 0x49, 0x82, 0x22, 0xf5, 0x29, 0x94, + 0x06, 0xed, 0xf1, 0xb0, 0xdf, 0x53, 0xf6, 0x75, 0xe5, 0xe6, 0xd6, 0x3a, 0xae, 0xf0, 0x20, 0xcc, + 0xb3, 0x6a, 0x3a, 0xa7, 0x7c, 0xfa, 0xc1, 0xee, 0x6d, 0x8e, 0x31, 0x89, 0xf5, 0xd3, 0x4f, 0x5f, + 0x0c, 0xe1, 0xdb, 0x57, 0xa3, 0xfe, 0x4d, 0x47, 0x5b, 0xdd, 0x19, 0xc2, 0xcf, 0x3b, 0x43, 0xf8, + 0x58, 0x18, 0x60, 0x55, 0x18, 0xe0, 0x7b, 0x61, 0x80, 0xdf, 0x85, 0x01, 0xde, 0x08, 0x53, 0xa9, + 0x0c, 0xe2, 0xe2, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc3, 0x32, 0xd2, 0x86, 0x50, 0x03, 0x00, + 0x00, } diff --git a/vendor/github.com/containerd/containerd/api/types/task/task.proto b/vendor/github.com/containerd/containerd/api/types/task/task.proto index 5845edf292e..da91cb033ef 100644 --- a/vendor/github.com/containerd/containerd/api/types/task/task.proto +++ b/vendor/github.com/containerd/containerd/api/types/task/task.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package containerd.v1.types; -import "gogoproto/gogo.proto"; +import weak "gogoproto/gogo.proto"; import "google/protobuf/timestamp.proto"; import "google/protobuf/any.proto"; diff --git a/vendor/github.com/containerd/containerd/dialer/dialer.go b/vendor/github.com/containerd/containerd/dialer/dialer.go index 65af69f9bca..1ad4ab71830 100644 --- a/vendor/github.com/containerd/containerd/dialer/dialer.go +++ b/vendor/github.com/containerd/containerd/dialer/dialer.go @@ -42,7 +42,7 @@ func Dialer(address string, timeout time.Duration) (net.Conn, error) { close(stopC) go func() { dr := <-synC - if dr != nil { + if dr != nil && dr.c != nil { dr.c.Close() } }() diff --git a/vendor/github.com/containerd/containerd/errdefs/BUILD b/vendor/github.com/containerd/containerd/errdefs/BUILD index e3c03e37b97..2dfcdc5d88a 100644 --- a/vendor/github.com/containerd/containerd/errdefs/BUILD +++ b/vendor/github.com/containerd/containerd/errdefs/BUILD @@ -10,7 +10,6 @@ go_library( visibility = ["//visibility:public"], deps = [ "//vendor/github.com/pkg/errors:go_default_library", - "//vendor/google.golang.org/grpc:go_default_library", "//vendor/google.golang.org/grpc/codes:go_default_library", "//vendor/google.golang.org/grpc/status:go_default_library", ], diff --git a/vendor/github.com/containerd/containerd/errdefs/grpc.go b/vendor/github.com/containerd/containerd/errdefs/grpc.go index 2aa2e11b4bb..6a3bbcaa143 100644 --- a/vendor/github.com/containerd/containerd/errdefs/grpc.go +++ b/vendor/github.com/containerd/containerd/errdefs/grpc.go @@ -4,7 +4,6 @@ import ( "strings" "github.com/pkg/errors" - "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -61,7 +60,7 @@ func FromGRPC(err error) error { var cls error // divide these into error classes, becomes the cause - switch grpc.Code(err) { + switch code(err) { case codes.InvalidArgument: cls = ErrInvalidArgument case codes.AlreadyExists: @@ -94,7 +93,7 @@ func FromGRPC(err error) error { // Effectively, we just remove the string of cls from the end of err if it // appears there. func rebaseMessage(cls error, err error) string { - desc := grpc.ErrorDesc(err) + desc := errDesc(err) clss := cls.Error() if desc == clss { return "" @@ -107,3 +106,17 @@ func isGRPCError(err error) bool { _, ok := status.FromError(err) return ok } + +func code(err error) codes.Code { + if s, ok := status.FromError(err); ok { + return s.Code() + } + return codes.Unknown +} + +func errDesc(err error) string { + if s, ok := status.FromError(err); ok { + return s.Message() + } + return err.Error() +} diff --git a/vendor/github.com/docker/docker/pkg/parsers/BUILD b/vendor/github.com/docker/docker/pkg/parsers/BUILD index 2ff1ce1c226..3c869d18e1d 100644 --- a/vendor/github.com/docker/docker/pkg/parsers/BUILD +++ b/vendor/github.com/docker/docker/pkg/parsers/BUILD @@ -16,7 +16,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//vendor/github.com/docker/docker/pkg/parsers/operatingsystem:all-srcs", + ], tags = ["automanaged"], visibility = ["//visibility:public"], ) diff --git a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/BUILD b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/BUILD new file mode 100644 index 00000000000..6d23f90122f --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/BUILD @@ -0,0 +1,49 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = select({ + "@io_bazel_rules_go//go/platform:darwin": [ + "operatingsystem_unix.go", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "operatingsystem_unix.go", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "operatingsystem_linux.go", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "operatingsystem_solaris.go", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "operatingsystem_windows.go", + ], + "//conditions:default": [], + }), + cgo = True, + importpath = "github.com/docker/docker/pkg/parsers/operatingsystem", + visibility = ["//visibility:public"], + deps = select({ + "@io_bazel_rules_go//go/platform:linux": [ + "//vendor/github.com/mattn/go-shellwords:go_default_library", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "//vendor/golang.org/x/sys/windows:go_default_library", + ], + "//conditions:default": [], + }), +) + +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/docker/docker/pkg/parsers/operatingsystem/operatingsystem_linux.go b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_linux.go new file mode 100644 index 00000000000..e04a3499af9 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_linux.go @@ -0,0 +1,77 @@ +// Package operatingsystem provides helper function to get the operating system +// name for different platforms. +package operatingsystem + +import ( + "bufio" + "bytes" + "fmt" + "io/ioutil" + "os" + "strings" + + "github.com/mattn/go-shellwords" +) + +var ( + // file to use to detect if the daemon is running in a container + proc1Cgroup = "/proc/1/cgroup" + + // file to check to determine Operating System + etcOsRelease = "/etc/os-release" + + // used by stateless systems like Clear Linux + altOsRelease = "/usr/lib/os-release" +) + +// GetOperatingSystem gets the name of the current operating system. +func GetOperatingSystem() (string, error) { + osReleaseFile, err := os.Open(etcOsRelease) + if err != nil { + if !os.IsNotExist(err) { + return "", fmt.Errorf("Error opening %s: %v", etcOsRelease, err) + } + osReleaseFile, err = os.Open(altOsRelease) + if err != nil { + return "", fmt.Errorf("Error opening %s: %v", altOsRelease, err) + } + } + defer osReleaseFile.Close() + + var prettyName string + scanner := bufio.NewScanner(osReleaseFile) + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "PRETTY_NAME=") { + data := strings.SplitN(line, "=", 2) + prettyNames, err := shellwords.Parse(data[1]) + if err != nil { + return "", fmt.Errorf("PRETTY_NAME is invalid: %s", err.Error()) + } + if len(prettyNames) != 1 { + return "", fmt.Errorf("PRETTY_NAME needs to be enclosed by quotes if they have spaces: %s", data[1]) + } + prettyName = prettyNames[0] + } + } + if prettyName != "" { + return prettyName, nil + } + // If not set, defaults to PRETTY_NAME="Linux" + // c.f. http://www.freedesktop.org/software/systemd/man/os-release.html + return "Linux", nil +} + +// IsContainerized returns true if we are running inside a container. +func IsContainerized() (bool, error) { + b, err := ioutil.ReadFile(proc1Cgroup) + if err != nil { + return false, err + } + for _, line := range bytes.Split(b, []byte{'\n'}) { + if len(line) > 0 && !bytes.HasSuffix(line, []byte{'/'}) && !bytes.HasSuffix(line, []byte("init.scope")) { + return true, nil + } + } + return false, nil +} diff --git a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_solaris.go b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_solaris.go new file mode 100644 index 00000000000..d08ad148604 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_solaris.go @@ -0,0 +1,37 @@ +// +build solaris,cgo + +package operatingsystem + +/* +#include +*/ +import "C" + +import ( + "bytes" + "errors" + "io/ioutil" +) + +var etcOsRelease = "/etc/release" + +// GetOperatingSystem gets the name of the current operating system. +func GetOperatingSystem() (string, error) { + b, err := ioutil.ReadFile(etcOsRelease) + if err != nil { + return "", err + } + if i := bytes.Index(b, []byte("\n")); i >= 0 { + b = bytes.Trim(b[:i], " ") + return string(b), nil + } + return "", errors.New("release not found") +} + +// IsContainerized returns true if we are running inside a container. +func IsContainerized() (bool, error) { + if C.getzoneid() != 0 { + return true, nil + } + return false, nil +} diff --git a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_unix.go b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_unix.go new file mode 100644 index 00000000000..bc91c3c5337 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_unix.go @@ -0,0 +1,25 @@ +// +build freebsd darwin + +package operatingsystem + +import ( + "errors" + "os/exec" +) + +// GetOperatingSystem gets the name of the current operating system. +func GetOperatingSystem() (string, error) { + cmd := exec.Command("uname", "-s") + osName, err := cmd.Output() + if err != nil { + return "", err + } + return string(osName), nil +} + +// IsContainerized returns true if we are running inside a container. +// No-op on FreeBSD and Darwin, always returns false. +func IsContainerized() (bool, error) { + // TODO: Implement jail detection for freeBSD + return false, errors.New("Cannot detect if we are in container") +} diff --git a/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_windows.go b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_windows.go new file mode 100644 index 00000000000..5d8b42cc365 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_windows.go @@ -0,0 +1,50 @@ +package operatingsystem + +import ( + "unsafe" + + "golang.org/x/sys/windows" +) + +// See https://code.google.com/p/go/source/browse/src/pkg/mime/type_windows.go?r=d14520ac25bf6940785aabb71f5be453a286f58c +// for a similar sample + +// GetOperatingSystem gets the name of the current operating system. +func GetOperatingSystem() (string, error) { + + var h windows.Handle + + // Default return value + ret := "Unknown Operating System" + + if err := windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, + windows.StringToUTF16Ptr(`SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\`), + 0, + windows.KEY_READ, + &h); err != nil { + return ret, err + } + defer windows.RegCloseKey(h) + + var buf [1 << 10]uint16 + var typ uint32 + n := uint32(len(buf) * 2) // api expects array of bytes, not uint16 + + if err := windows.RegQueryValueEx(h, + windows.StringToUTF16Ptr("ProductName"), + nil, + &typ, + (*byte)(unsafe.Pointer(&buf[0])), + &n); err != nil { + return ret, err + } + ret = windows.UTF16ToString(buf[:]) + + return ret, nil +} + +// IsContainerized returns true if we are running inside a container. +// No-op on Windows, always returns false. +func IsContainerized() (bool, error) { + return false, nil +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go index 110ae138427..ff368f33c54 100644 --- a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go +++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go @@ -56,6 +56,8 @@ import ( stpb "github.com/golang/protobuf/ptypes/struct" ) +const secondInNanos = int64(time.Second / time.Nanosecond) + // Marshaler is a configurable object for converting between // protocol buffer objects and a JSON representation for them. type Marshaler struct { @@ -118,6 +120,14 @@ type JSONPBUnmarshaler interface { // Marshal marshals a protocol buffer into JSON. func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error { + v := reflect.ValueOf(pb) + if pb == nil || (v.Kind() == reflect.Ptr && v.IsNil()) { + return errors.New("Marshal called with nil") + } + // Check for unset required fields first. + if err := checkRequiredFields(pb); err != nil { + return err + } writer := &errWriter{writer: out} return m.marshalObject(writer, pb, "", "") } @@ -190,13 +200,22 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU // Any is a bit more involved. return m.marshalAny(out, v, indent) case "Duration": - // "Generated output always contains 3, 6, or 9 fractional digits, + // "Generated output always contains 0, 3, 6, or 9 fractional digits, // depending on required precision." s, ns := s.Field(0).Int(), s.Field(1).Int() - d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond - x := fmt.Sprintf("%.9f", d.Seconds()) + if ns <= -secondInNanos || ns >= secondInNanos { + return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos) + } + if (s > 0 && ns < 0) || (s < 0 && ns > 0) { + return errors.New("signs of seconds and nanos do not match") + } + if s < 0 { + ns = -ns + } + x := fmt.Sprintf("%d.%09d", s, ns) x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, ".000") out.write(`"`) out.write(x) out.write(`s"`) @@ -207,13 +226,17 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU return m.marshalValue(out, &proto.Properties{}, s.Field(0), indent) case "Timestamp": // "RFC 3339, where generated output will always be Z-normalized - // and uses 3, 6 or 9 fractional digits." + // and uses 0, 3, 6 or 9 fractional digits." s, ns := s.Field(0).Int(), s.Field(1).Int() + if ns < 0 || ns >= secondInNanos { + return fmt.Errorf("ns out of range [0, %v)", secondInNanos) + } t := time.Unix(s, ns).UTC() // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits). x := t.Format("2006-01-02T15:04:05.000000000") x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, ".000") out.write(`"`) out.write(x) out.write(`Z"`) @@ -632,7 +655,10 @@ func (u *Unmarshaler) UnmarshalNext(dec *json.Decoder, pb proto.Message) error { if err := dec.Decode(&inputValue); err != nil { return err } - return u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil) + if err := u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil); err != nil { + return err + } + return checkRequiredFields(pb) } // Unmarshal unmarshals a JSON object stream into a protocol @@ -803,7 +829,7 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe return fmt.Errorf("bad ListValue: %v", err) } - target.Field(0).Set(reflect.ValueOf(make([]*stpb.Value, len(s), len(s)))) + target.Field(0).Set(reflect.ValueOf(make([]*stpb.Value, len(s)))) for i, sv := range s { if err := u.unmarshalValue(target.Field(0).Index(i), sv, prop); err != nil { return err @@ -973,13 +999,6 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe } if mp != nil { target.Set(reflect.MakeMap(targetType)) - var keyprop, valprop *proto.Properties - if prop != nil { - // These could still be nil if the protobuf metadata is broken somehow. - // TODO: This won't work because the fields are unexported. - // We should probably just reparse them. - //keyprop, valprop = prop.mkeyprop, prop.mvalprop - } for ks, raw := range mp { // Unmarshal map key. The core json library already decoded the key into a // string, so we handle that specially. Other types were quoted post-serialization. @@ -988,14 +1007,16 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe k = reflect.ValueOf(ks) } else { k = reflect.New(targetType.Key()).Elem() - if err := u.unmarshalValue(k, json.RawMessage(ks), keyprop); err != nil { + // TODO: pass the correct Properties if needed. + if err := u.unmarshalValue(k, json.RawMessage(ks), nil); err != nil { return err } } // Unmarshal map value. v := reflect.New(targetType.Elem()).Elem() - if err := u.unmarshalValue(v, raw, valprop); err != nil { + // TODO: pass the correct Properties if needed. + if err := u.unmarshalValue(v, raw, nil); err != nil { return err } target.SetMapIndex(k, v) @@ -1081,3 +1102,140 @@ func (s mapKeys) Less(i, j int) bool { } return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface()) } + +// checkRequiredFields returns an error if any required field in the given proto message is not set. +// This function is used by both Marshal and Unmarshal. While required fields only exist in a +// proto2 message, a proto3 message can contain proto2 message(s). +func checkRequiredFields(pb proto.Message) error { + // Most well-known type messages do not contain required fields. The "Any" type may contain + // a message that has required fields. + // + // When an Any message is being marshaled, the code will invoked proto.Unmarshal on Any.Value + // field in order to transform that into JSON, and that should have returned an error if a + // required field is not set in the embedded message. + // + // When an Any message is being unmarshaled, the code will have invoked proto.Marshal on the + // embedded message to store the serialized message in Any.Value field, and that should have + // returned an error if a required field is not set. + if _, ok := pb.(wkt); ok { + return nil + } + + v := reflect.ValueOf(pb) + // Skip message if it is not a struct pointer. + if v.Kind() != reflect.Ptr { + return nil + } + v = v.Elem() + if v.Kind() != reflect.Struct { + return nil + } + + for i := 0; i < v.NumField(); i++ { + field := v.Field(i) + sfield := v.Type().Field(i) + + if sfield.PkgPath != "" { + // blank PkgPath means the field is exported; skip if not exported + continue + } + + if strings.HasPrefix(sfield.Name, "XXX_") { + continue + } + + // Oneof field is an interface implemented by wrapper structs containing the actual oneof + // field, i.e. an interface containing &T{real_value}. + if sfield.Tag.Get("protobuf_oneof") != "" { + if field.Kind() != reflect.Interface { + continue + } + v := field.Elem() + if v.Kind() != reflect.Ptr || v.IsNil() { + continue + } + v = v.Elem() + if v.Kind() != reflect.Struct || v.NumField() < 1 { + continue + } + field = v.Field(0) + sfield = v.Type().Field(0) + } + + protoTag := sfield.Tag.Get("protobuf") + if protoTag == "" { + continue + } + var prop proto.Properties + prop.Init(sfield.Type, sfield.Name, protoTag, &sfield) + + switch field.Kind() { + case reflect.Map: + if field.IsNil() { + continue + } + // Check each map value. + keys := field.MapKeys() + for _, k := range keys { + v := field.MapIndex(k) + if err := checkRequiredFieldsInValue(v); err != nil { + return err + } + } + case reflect.Slice: + // Handle non-repeated type, e.g. bytes. + if !prop.Repeated { + if prop.Required && field.IsNil() { + return fmt.Errorf("required field %q is not set", prop.Name) + } + continue + } + + // Handle repeated type. + if field.IsNil() { + continue + } + // Check each slice item. + for i := 0; i < field.Len(); i++ { + v := field.Index(i) + if err := checkRequiredFieldsInValue(v); err != nil { + return err + } + } + case reflect.Ptr: + if field.IsNil() { + if prop.Required { + return fmt.Errorf("required field %q is not set", prop.Name) + } + continue + } + if err := checkRequiredFieldsInValue(field); err != nil { + return err + } + } + } + + // Handle proto2 extensions. + for _, ext := range proto.RegisteredExtensions(pb) { + if !proto.HasExtension(pb, ext) { + continue + } + ep, err := proto.GetExtension(pb, ext) + if err != nil { + return err + } + err = checkRequiredFieldsInValue(reflect.ValueOf(ep)) + if err != nil { + return err + } + } + + return nil +} + +func checkRequiredFieldsInValue(v reflect.Value) error { + if pm, ok := v.Interface().(proto.Message); ok { + return checkRequiredFields(pm) + } + return nil +} diff --git a/vendor/github.com/golang/protobuf/proto/BUILD b/vendor/github.com/golang/protobuf/proto/BUILD index 2ef1ce53655..1becc3b87da 100644 --- a/vendor/github.com/golang/protobuf/proto/BUILD +++ b/vendor/github.com/golang/protobuf/proto/BUILD @@ -5,6 +5,7 @@ go_library( srcs = [ "clone.go", "decode.go", + "discard.go", "encode.go", "equal.go", "extensions.go", @@ -12,6 +13,9 @@ go_library( "message_set.go", "pointer_unsafe.go", "properties.go", + "table_marshal.go", + "table_merge.go", + "table_unmarshal.go", "text.go", "text_parser.go", ], diff --git a/vendor/github.com/golang/protobuf/proto/Makefile b/vendor/github.com/golang/protobuf/proto/Makefile deleted file mode 100644 index e2e0651a934..00000000000 --- a/vendor/github.com/golang/protobuf/proto/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# Go support for Protocol Buffers - Google's data interchange format -# -# Copyright 2010 The Go Authors. All rights reserved. -# https://github.com/golang/protobuf -# -# 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. - -install: - go install - -test: install generate-test-pbs - go test - - -generate-test-pbs: - make install - make -C testdata - protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto - make diff --git a/vendor/github.com/golang/protobuf/proto/clone.go b/vendor/github.com/golang/protobuf/proto/clone.go index e392575b353..3cd3249f706 100644 --- a/vendor/github.com/golang/protobuf/proto/clone.go +++ b/vendor/github.com/golang/protobuf/proto/clone.go @@ -35,22 +35,39 @@ package proto import ( + "fmt" "log" "reflect" "strings" ) // Clone returns a deep copy of a protocol buffer. -func Clone(pb Message) Message { - in := reflect.ValueOf(pb) +func Clone(src Message) Message { + in := reflect.ValueOf(src) if in.IsNil() { - return pb + return src } - out := reflect.New(in.Type().Elem()) - // out is empty so a merge is a deep copy. - mergeStruct(out.Elem(), in.Elem()) - return out.Interface().(Message) + dst := out.Interface().(Message) + Merge(dst, src) + return dst +} + +// Merger is the interface representing objects that can merge messages of the same type. +type Merger interface { + // Merge merges src into this message. + // Required and optional fields that are set in src will be set to that value in dst. + // Elements of repeated fields will be appended. + // + // Merge may panic if called with a different argument type than the receiver. + Merge(src Message) +} + +// generatedMerger is the custom merge method that generated protos will have. +// We must add this method since a generate Merge method will conflict with +// many existing protos that have a Merge data field already defined. +type generatedMerger interface { + XXX_Merge(src Message) } // Merge merges src into dst. @@ -58,17 +75,24 @@ func Clone(pb Message) Message { // Elements of repeated fields will be appended. // Merge panics if src and dst are not the same type, or if dst is nil. func Merge(dst, src Message) { + if m, ok := dst.(Merger); ok { + m.Merge(src) + return + } + in := reflect.ValueOf(src) out := reflect.ValueOf(dst) if out.IsNil() { panic("proto: nil destination") } if in.Type() != out.Type() { - // Explicit test prior to mergeStruct so that mistyped nils will fail - panic("proto: type mismatch") + panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src)) } if in.IsNil() { - // Merging nil into non-nil is a quiet no-op + return // Merge from nil src is a noop + } + if m, ok := dst.(generatedMerger); ok { + m.XXX_Merge(src) return } mergeStruct(out.Elem(), in.Elem()) @@ -84,7 +108,7 @@ func mergeStruct(out, in reflect.Value) { mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) } - if emIn, ok := extendable(in.Addr().Interface()); ok { + if emIn, err := extendable(in.Addr().Interface()); err == nil { emOut, _ := extendable(out.Addr().Interface()) mIn, muIn := emIn.extensionsRead() if mIn != nil { diff --git a/vendor/github.com/golang/protobuf/proto/decode.go b/vendor/github.com/golang/protobuf/proto/decode.go index aa207298f99..d9aa3c42d66 100644 --- a/vendor/github.com/golang/protobuf/proto/decode.go +++ b/vendor/github.com/golang/protobuf/proto/decode.go @@ -39,8 +39,6 @@ import ( "errors" "fmt" "io" - "os" - "reflect" ) // errOverflow is returned when an integer is too large to be represented. @@ -50,10 +48,6 @@ var errOverflow = errors.New("proto: integer overflow") // wire type is encountered. It does not get returned to user code. var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof") -// The fundamental decoders that interpret bytes on the wire. -// Those that take integer types all return uint64 and are -// therefore of type valueDecoder. - // DecodeVarint reads a varint-encoded integer from the slice. // It returns the integer and the number of bytes consumed, or // zero if there is not enough. @@ -267,9 +261,6 @@ func (p *Buffer) DecodeZigzag32() (x uint64, err error) { return } -// These are not ValueDecoders: they produce an array of bytes or a string. -// bytes, embedded messages - // DecodeRawBytes reads a count-delimited byte buffer from the Buffer. // This is the format used for the bytes protocol buffer // type and for embedded messages. @@ -311,81 +302,29 @@ func (p *Buffer) DecodeStringBytes() (s string, err error) { return string(buf), nil } -// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. -// If the protocol buffer has extensions, and the field matches, add it as an extension. -// Otherwise, if the XXX_unrecognized field exists, append the skipped data there. -func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error { - oi := o.index - - err := o.skip(t, tag, wire) - if err != nil { - return err - } - - if !unrecField.IsValid() { - return nil - } - - ptr := structPointer_Bytes(base, unrecField) - - // Add the skipped field to struct field - obuf := o.buf - - o.buf = *ptr - o.EncodeVarint(uint64(tag<<3 | wire)) - *ptr = append(o.buf, obuf[oi:o.index]...) - - o.buf = obuf - - return nil -} - -// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. -func (o *Buffer) skip(t reflect.Type, tag, wire int) error { - - var u uint64 - var err error - - switch wire { - case WireVarint: - _, err = o.DecodeVarint() - case WireFixed64: - _, err = o.DecodeFixed64() - case WireBytes: - _, err = o.DecodeRawBytes(false) - case WireFixed32: - _, err = o.DecodeFixed32() - case WireStartGroup: - for { - u, err = o.DecodeVarint() - if err != nil { - break - } - fwire := int(u & 0x7) - if fwire == WireEndGroup { - break - } - ftag := int(u >> 3) - err = o.skip(t, ftag, fwire) - if err != nil { - break - } - } - default: - err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t) - } - return err -} - // Unmarshaler is the interface representing objects that can -// unmarshal themselves. The method should reset the receiver before -// decoding starts. The argument points to data that may be +// unmarshal themselves. The argument points to data that may be // overwritten, so implementations should not keep references to the // buffer. +// Unmarshal implementations should not clear the receiver. +// Any unmarshaled data should be merged into the receiver. +// Callers of Unmarshal that do not want to retain existing data +// should Reset the receiver before calling Unmarshal. type Unmarshaler interface { Unmarshal([]byte) error } +// newUnmarshaler is the interface representing objects that can +// unmarshal themselves. The semantics are identical to Unmarshaler. +// +// This exists to support protoc-gen-go generated messages. +// The proto package will stop type-asserting to this interface in the future. +// +// DO NOT DEPEND ON THIS. +type newUnmarshaler interface { + XXX_Unmarshal([]byte) error +} + // Unmarshal parses the protocol buffer representation in buf and places the // decoded result in pb. If the struct underlying pb does not match // the data in buf, the results can be unpredictable. @@ -395,7 +334,13 @@ type Unmarshaler interface { // to preserve and append to existing data. func Unmarshal(buf []byte, pb Message) error { pb.Reset() - return UnmarshalMerge(buf, pb) + if u, ok := pb.(newUnmarshaler); ok { + return u.XXX_Unmarshal(buf) + } + if u, ok := pb.(Unmarshaler); ok { + return u.Unmarshal(buf) + } + return NewBuffer(buf).Unmarshal(pb) } // UnmarshalMerge parses the protocol buffer representation in buf and @@ -405,8 +350,16 @@ func Unmarshal(buf []byte, pb Message) error { // UnmarshalMerge merges into existing data in pb. // Most code should use Unmarshal instead. func UnmarshalMerge(buf []byte, pb Message) error { - // If the object can unmarshal itself, let it. + if u, ok := pb.(newUnmarshaler); ok { + return u.XXX_Unmarshal(buf) + } if u, ok := pb.(Unmarshaler); ok { + // NOTE: The history of proto have unfortunately been inconsistent + // whether Unmarshaler should or should not implicitly clear itself. + // Some implementations do, most do not. + // Thus, calling this here may or may not do what people want. + // + // See https://github.com/golang/protobuf/issues/424 return u.Unmarshal(buf) } return NewBuffer(buf).Unmarshal(pb) @@ -422,12 +375,17 @@ func (p *Buffer) DecodeMessage(pb Message) error { } // DecodeGroup reads a tag-delimited group from the Buffer. +// StartGroup tag is already consumed. This function consumes +// EndGroup tag. func (p *Buffer) DecodeGroup(pb Message) error { - typ, base, err := getbase(pb) - if err != nil { - return err + b := p.buf[p.index:] + x, y := findEndGroup(b) + if x < 0 { + return io.ErrUnexpectedEOF } - return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base) + err := Unmarshal(b[:x], pb) + p.index += y + return err } // Unmarshal parses the protocol buffer representation in the @@ -438,533 +396,33 @@ func (p *Buffer) DecodeGroup(pb Message) error { // Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal. func (p *Buffer) Unmarshal(pb Message) error { // If the object can unmarshal itself, let it. + if u, ok := pb.(newUnmarshaler); ok { + err := u.XXX_Unmarshal(p.buf[p.index:]) + p.index = len(p.buf) + return err + } if u, ok := pb.(Unmarshaler); ok { + // NOTE: The history of proto have unfortunately been inconsistent + // whether Unmarshaler should or should not implicitly clear itself. + // Some implementations do, most do not. + // Thus, calling this here may or may not do what people want. + // + // See https://github.com/golang/protobuf/issues/424 err := u.Unmarshal(p.buf[p.index:]) p.index = len(p.buf) return err } - typ, base, err := getbase(pb) - if err != nil { - return err - } - - err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base) - - if collectStats { - stats.Decode++ - } - - return err -} - -// unmarshalType does the work of unmarshaling a structure. -func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error { - var state errorState - required, reqFields := prop.reqCount, uint64(0) - - var err error - for err == nil && o.index < len(o.buf) { - oi := o.index - var u uint64 - u, err = o.DecodeVarint() - if err != nil { - break - } - wire := int(u & 0x7) - if wire == WireEndGroup { - if is_group { - if required > 0 { - // Not enough information to determine the exact field. - // (See below.) - return &RequiredNotSetError{"{Unknown}"} - } - return nil // input is satisfied - } - return fmt.Errorf("proto: %s: wiretype end group for non-group", st) - } - tag := int(u >> 3) - if tag <= 0 { - return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire) - } - fieldnum, ok := prop.decoderTags.get(tag) - if !ok { - // Maybe it's an extension? - if prop.extendable { - if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) { - if err = o.skip(st, tag, wire); err == nil { - extmap := e.extensionsWrite() - ext := extmap[int32(tag)] // may be missing - ext.enc = append(ext.enc, o.buf[oi:o.index]...) - extmap[int32(tag)] = ext - } - continue - } - } - // Maybe it's a oneof? - if prop.oneofUnmarshaler != nil { - m := structPointer_Interface(base, st).(Message) - // First return value indicates whether tag is a oneof field. - ok, err = prop.oneofUnmarshaler(m, tag, wire, o) - if err == ErrInternalBadWireType { - // Map the error to something more descriptive. - // Do the formatting here to save generated code space. - err = fmt.Errorf("bad wiretype for oneof field in %T", m) - } - if ok { - continue - } - } - err = o.skipAndSave(st, tag, wire, base, prop.unrecField) - continue - } - p := prop.Prop[fieldnum] - - if p.dec == nil { - fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name) - continue - } - dec := p.dec - if wire != WireStartGroup && wire != p.WireType { - if wire == WireBytes && p.packedDec != nil { - // a packable field - dec = p.packedDec - } else { - err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType) - continue - } - } - decErr := dec(o, p, base) - if decErr != nil && !state.shouldContinue(decErr, p) { - err = decErr - } - if err == nil && p.Required { - // Successfully decoded a required field. - if tag <= 64 { - // use bitmap for fields 1-64 to catch field reuse. - var mask uint64 = 1 << uint64(tag-1) - if reqFields&mask == 0 { - // new required field - reqFields |= mask - required-- - } - } else { - // This is imprecise. It can be fooled by a required field - // with a tag > 64 that is encoded twice; that's very rare. - // A fully correct implementation would require allocating - // a data structure, which we would like to avoid. - required-- - } - } - } - if err == nil { - if is_group { - return io.ErrUnexpectedEOF - } - if state.err != nil { - return state.err - } - if required > 0 { - // Not enough information to determine the exact field. If we use extra - // CPU, we could determine the field only if the missing required field - // has a tag <= 64 and we check reqFields. - return &RequiredNotSetError{"{Unknown}"} - } - } - return err -} - -// Individual type decoders -// For each, -// u is the decoded value, -// v is a pointer to the field (pointer) in the struct - -// Sizes of the pools to allocate inside the Buffer. -// The goal is modest amortization and allocation -// on at least 16-byte boundaries. -const ( - boolPoolSize = 16 - uint32PoolSize = 8 - uint64PoolSize = 4 -) - -// Decode a bool. -func (o *Buffer) dec_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - if len(o.bools) == 0 { - o.bools = make([]bool, boolPoolSize) - } - o.bools[0] = u != 0 - *structPointer_Bool(base, p.field) = &o.bools[0] - o.bools = o.bools[1:] - return nil -} - -func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - *structPointer_BoolVal(base, p.field) = u != 0 - return nil -} - -// Decode an int32. -func (o *Buffer) dec_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word32_Set(structPointer_Word32(base, p.field), o, uint32(u)) - return nil -} - -func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u)) - return nil -} - -// Decode an int64. -func (o *Buffer) dec_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word64_Set(structPointer_Word64(base, p.field), o, u) - return nil -} - -func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word64Val_Set(structPointer_Word64Val(base, p.field), o, u) - return nil -} - -// Decode a string. -func (o *Buffer) dec_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - *structPointer_String(base, p.field) = &s - return nil -} - -func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - *structPointer_StringVal(base, p.field) = s - return nil -} - -// Decode a slice of bytes ([]byte). -func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error { - b, err := o.DecodeRawBytes(true) - if err != nil { - return err - } - *structPointer_Bytes(base, p.field) = b - return nil -} - -// Decode a slice of bools ([]bool). -func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - v := structPointer_BoolSlice(base, p.field) - *v = append(*v, u != 0) - return nil -} - -// Decode a slice of bools ([]bool) in packed format. -func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error { - v := structPointer_BoolSlice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded bools - fin := o.index + nb - if fin < o.index { - return errOverflow - } - - y := *v - for o.index < fin { - u, err := p.valDec(o) - if err != nil { - return err - } - y = append(y, u != 0) - } - - *v = y - return nil -} - -// Decode a slice of int32s ([]int32). -func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - structPointer_Word32Slice(base, p.field).Append(uint32(u)) - return nil -} - -// Decode a slice of int32s ([]int32) in packed format. -func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error { - v := structPointer_Word32Slice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded int32s - - fin := o.index + nb - if fin < o.index { - return errOverflow - } - for o.index < fin { - u, err := p.valDec(o) - if err != nil { - return err - } - v.Append(uint32(u)) - } - return nil -} - -// Decode a slice of int64s ([]int64). -func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - - structPointer_Word64Slice(base, p.field).Append(u) - return nil -} - -// Decode a slice of int64s ([]int64) in packed format. -func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error { - v := structPointer_Word64Slice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded int64s - - fin := o.index + nb - if fin < o.index { - return errOverflow - } - for o.index < fin { - u, err := p.valDec(o) - if err != nil { - return err - } - v.Append(u) - } - return nil -} - -// Decode a slice of strings ([]string). -func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - v := structPointer_StringSlice(base, p.field) - *v = append(*v, s) - return nil -} - -// Decode a slice of slice of bytes ([][]byte). -func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error { - b, err := o.DecodeRawBytes(true) - if err != nil { - return err - } - v := structPointer_BytesSlice(base, p.field) - *v = append(*v, b) - return nil -} - -// Decode a map field. -func (o *Buffer) dec_new_map(p *Properties, base structPointer) error { - raw, err := o.DecodeRawBytes(false) - if err != nil { - return err - } - oi := o.index // index at the end of this map entry - o.index -= len(raw) // move buffer back to start of map entry - - mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V - if mptr.Elem().IsNil() { - mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem())) - } - v := mptr.Elem() // map[K]V - - // Prepare addressable doubly-indirect placeholders for the key and value types. - // See enc_new_map for why. - keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K - keybase := toStructPointer(keyptr.Addr()) // **K - - var valbase structPointer - var valptr reflect.Value - switch p.mtype.Elem().Kind() { - case reflect.Slice: - // []byte - var dummy []byte - valptr = reflect.ValueOf(&dummy) // *[]byte - valbase = toStructPointer(valptr) // *[]byte - case reflect.Ptr: - // message; valptr is **Msg; need to allocate the intermediate pointer - valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V - valptr.Set(reflect.New(valptr.Type().Elem())) - valbase = toStructPointer(valptr) - default: - // everything else - valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V - valbase = toStructPointer(valptr.Addr()) // **V - } - - // Decode. - // This parses a restricted wire format, namely the encoding of a message - // with two fields. See enc_new_map for the format. - for o.index < oi { - // tagcode for key and value properties are always a single byte - // because they have tags 1 and 2. - tagcode := o.buf[o.index] - o.index++ - switch tagcode { - case p.mkeyprop.tagcode[0]: - if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil { - return err - } - case p.mvalprop.tagcode[0]: - if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil { - return err - } - default: - // TODO: Should we silently skip this instead? - return fmt.Errorf("proto: bad map data tag %d", raw[0]) - } - } - keyelem, valelem := keyptr.Elem(), valptr.Elem() - if !keyelem.IsValid() { - keyelem = reflect.Zero(p.mtype.Key()) - } - if !valelem.IsValid() { - valelem = reflect.Zero(p.mtype.Elem()) - } - - v.SetMapIndex(keyelem, valelem) - return nil -} - -// Decode a group. -func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error { - bas := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(bas) { - // allocate new nested message - bas = toStructPointer(reflect.New(p.stype)) - structPointer_SetStructPointer(base, p.field, bas) - } - return o.unmarshalType(p.stype, p.sprop, true, bas) -} - -// Decode an embedded message. -func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) { - raw, e := o.DecodeRawBytes(false) - if e != nil { - return e - } - - bas := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(bas) { - // allocate new nested message - bas = toStructPointer(reflect.New(p.stype)) - structPointer_SetStructPointer(base, p.field, bas) - } - - // If the object can unmarshal itself, let it. - if p.isUnmarshaler { - iv := structPointer_Interface(bas, p.stype) - return iv.(Unmarshaler).Unmarshal(raw) - } - - obuf := o.buf - oi := o.index - o.buf = raw - o.index = 0 - - err = o.unmarshalType(p.stype, p.sprop, false, bas) - o.buf = obuf - o.index = oi - - return err -} - -// Decode a slice of embedded messages. -func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error { - return o.dec_slice_struct(p, false, base) -} - -// Decode a slice of embedded groups. -func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error { - return o.dec_slice_struct(p, true, base) -} - -// Decode a slice of structs ([]*struct). -func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error { - v := reflect.New(p.stype) - bas := toStructPointer(v) - structPointer_StructPointerSlice(base, p.field).Append(bas) - - if is_group { - err := o.unmarshalType(p.stype, p.sprop, is_group, bas) - return err - } - - raw, err := o.DecodeRawBytes(false) - if err != nil { - return err - } - - // If the object can unmarshal itself, let it. - if p.isUnmarshaler { - iv := v.Interface() - return iv.(Unmarshaler).Unmarshal(raw) - } - - obuf := o.buf - oi := o.index - o.buf = raw - o.index = 0 - - err = o.unmarshalType(p.stype, p.sprop, is_group, bas) - - o.buf = obuf - o.index = oi - + // Slow workaround for messages that aren't Unmarshalers. + // This includes some hand-coded .pb.go files and + // bootstrap protos. + // TODO: fix all of those and then add Unmarshal to + // the Message interface. Then: + // The cast above and code below can be deleted. + // The old unmarshaler can be deleted. + // Clients can call Unmarshal directly (can already do that, actually). + var info InternalMessageInfo + err := info.Unmarshal(pb, p.buf[p.index:]) + p.index = len(p.buf) return err } diff --git a/vendor/github.com/golang/protobuf/proto/discard.go b/vendor/github.com/golang/protobuf/proto/discard.go new file mode 100644 index 00000000000..dea2617ced3 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/discard.go @@ -0,0 +1,350 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2017 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +import ( + "fmt" + "reflect" + "strings" + "sync" + "sync/atomic" +) + +type generatedDiscarder interface { + XXX_DiscardUnknown() +} + +// DiscardUnknown recursively discards all unknown fields from this message +// and all embedded messages. +// +// When unmarshaling a message with unrecognized fields, the tags and values +// of such fields are preserved in the Message. This allows a later call to +// marshal to be able to produce a message that continues to have those +// unrecognized fields. To avoid this, DiscardUnknown is used to +// explicitly clear the unknown fields after unmarshaling. +// +// For proto2 messages, the unknown fields of message extensions are only +// discarded from messages that have been accessed via GetExtension. +func DiscardUnknown(m Message) { + if m, ok := m.(generatedDiscarder); ok { + m.XXX_DiscardUnknown() + return + } + // TODO: Dynamically populate a InternalMessageInfo for legacy messages, + // but the master branch has no implementation for InternalMessageInfo, + // so it would be more work to replicate that approach. + discardLegacy(m) +} + +// DiscardUnknown recursively discards all unknown fields. +func (a *InternalMessageInfo) DiscardUnknown(m Message) { + di := atomicLoadDiscardInfo(&a.discard) + if di == nil { + di = getDiscardInfo(reflect.TypeOf(m).Elem()) + atomicStoreDiscardInfo(&a.discard, di) + } + di.discard(toPointer(&m)) +} + +type discardInfo struct { + typ reflect.Type + + initialized int32 // 0: only typ is valid, 1: everything is valid + lock sync.Mutex + + fields []discardFieldInfo + unrecognized field +} + +type discardFieldInfo struct { + field field // Offset of field, guaranteed to be valid + discard func(src pointer) +} + +var ( + discardInfoMap = map[reflect.Type]*discardInfo{} + discardInfoLock sync.Mutex +) + +func getDiscardInfo(t reflect.Type) *discardInfo { + discardInfoLock.Lock() + defer discardInfoLock.Unlock() + di := discardInfoMap[t] + if di == nil { + di = &discardInfo{typ: t} + discardInfoMap[t] = di + } + return di +} + +func (di *discardInfo) discard(src pointer) { + if src.isNil() { + return // Nothing to do. + } + + if atomic.LoadInt32(&di.initialized) == 0 { + di.computeDiscardInfo() + } + + for _, fi := range di.fields { + sfp := src.offset(fi.field) + fi.discard(sfp) + } + + // For proto2 messages, only discard unknown fields in message extensions + // that have been accessed via GetExtension. + if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil { + // Ignore lock since DiscardUnknown is not concurrency safe. + emm, _ := em.extensionsRead() + for _, mx := range emm { + if m, ok := mx.value.(Message); ok { + DiscardUnknown(m) + } + } + } + + if di.unrecognized.IsValid() { + *src.offset(di.unrecognized).toBytes() = nil + } +} + +func (di *discardInfo) computeDiscardInfo() { + di.lock.Lock() + defer di.lock.Unlock() + if di.initialized != 0 { + return + } + t := di.typ + n := t.NumField() + + for i := 0; i < n; i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + + dfi := discardFieldInfo{field: toField(&f)} + tf := f.Type + + // Unwrap tf to get its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name)) + } + + switch tf.Kind() { + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name)) + case isSlice: // E.g., []*pb.T + di := getDiscardInfo(tf) + dfi.discard = func(src pointer) { + sps := src.getPointerSlice() + for _, sp := range sps { + if !sp.isNil() { + di.discard(sp) + } + } + } + default: // E.g., *pb.T + di := getDiscardInfo(tf) + dfi.discard = func(src pointer) { + sp := src.getPointer() + if !sp.isNil() { + di.discard(sp) + } + } + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name)) + default: // E.g., map[K]V + if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T) + dfi.discard = func(src pointer) { + sm := src.asPointerTo(tf).Elem() + if sm.Len() == 0 { + return + } + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + DiscardUnknown(val.Interface().(Message)) + } + } + } else { + dfi.discard = func(pointer) {} // Noop + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name)) + default: // E.g., interface{} + // TODO: Make this faster? + dfi.discard = func(src pointer) { + su := src.asPointerTo(tf).Elem() + if !su.IsNil() { + sv := su.Elem().Elem().Field(0) + if sv.Kind() == reflect.Ptr && sv.IsNil() { + return + } + switch sv.Type().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + DiscardUnknown(sv.Interface().(Message)) + } + } + } + } + default: + continue + } + di.fields = append(di.fields, dfi) + } + + di.unrecognized = invalidField + if f, ok := t.FieldByName("XXX_unrecognized"); ok { + if f.Type != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + di.unrecognized = toField(&f) + } + + atomic.StoreInt32(&di.initialized, 1) +} + +func discardLegacy(m Message) { + v := reflect.ValueOf(m) + if v.Kind() != reflect.Ptr || v.IsNil() { + return + } + v = v.Elem() + if v.Kind() != reflect.Struct { + return + } + t := v.Type() + + for i := 0; i < v.NumField(); i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + vf := v.Field(i) + tf := f.Type + + // Unwrap tf to get its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name)) + } + + switch tf.Kind() { + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name)) + case isSlice: // E.g., []*pb.T + for j := 0; j < vf.Len(); j++ { + discardLegacy(vf.Index(j).Interface().(Message)) + } + default: // E.g., *pb.T + discardLegacy(vf.Interface().(Message)) + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name)) + default: // E.g., map[K]V + tv := vf.Type().Elem() + if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T) + for _, key := range vf.MapKeys() { + val := vf.MapIndex(key) + discardLegacy(val.Interface().(Message)) + } + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name)) + default: // E.g., test_proto.isCommunique_Union interface + if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" { + vf = vf.Elem() // E.g., *test_proto.Communique_Msg + if !vf.IsNil() { + vf = vf.Elem() // E.g., test_proto.Communique_Msg + vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value + if vf.Kind() == reflect.Ptr { + discardLegacy(vf.Interface().(Message)) + } + } + } + } + } + } + + if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() { + if vf.Type() != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + vf.Set(reflect.ValueOf([]byte(nil))) + } + + // For proto2 messages, only discard unknown fields in message extensions + // that have been accessed via GetExtension. + if em, err := extendable(m); err == nil { + // Ignore lock since discardLegacy is not concurrency safe. + emm, _ := em.extensionsRead() + for _, mx := range emm { + if m, ok := mx.value.(Message); ok { + discardLegacy(m) + } + } + } +} diff --git a/vendor/github.com/golang/protobuf/proto/encode.go b/vendor/github.com/golang/protobuf/proto/encode.go index 8b84d1b22d4..c27d35f866b 100644 --- a/vendor/github.com/golang/protobuf/proto/encode.go +++ b/vendor/github.com/golang/protobuf/proto/encode.go @@ -39,7 +39,6 @@ import ( "errors" "fmt" "reflect" - "sort" ) // RequiredNotSetError is the error returned if Marshal is called with @@ -82,10 +81,6 @@ var ( const maxVarintBytes = 10 // maximum length of a varint -// maxMarshalSize is the largest allowed size of an encoded protobuf, -// since C++ and Java use signed int32s for the size. -const maxMarshalSize = 1<<31 - 1 - // EncodeVarint returns the varint encoding of x. // This is the format for the // int32, int64, uint32, uint64, bool, and enum @@ -119,18 +114,27 @@ func (p *Buffer) EncodeVarint(x uint64) error { // SizeVarint returns the varint encoding size of an integer. func SizeVarint(x uint64) int { - return sizeVarint(x) -} - -func sizeVarint(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } + switch { + case x < 1<<7: + return 1 + case x < 1<<14: + return 2 + case x < 1<<21: + return 3 + case x < 1<<28: + return 4 + case x < 1<<35: + return 5 + case x < 1<<42: + return 6 + case x < 1<<49: + return 7 + case x < 1<<56: + return 8 + case x < 1<<63: + return 9 } - return n + return 10 } // EncodeFixed64 writes a 64-bit integer to the Buffer. @@ -149,10 +153,6 @@ func (p *Buffer) EncodeFixed64(x uint64) error { return nil } -func sizeFixed64(x uint64) int { - return 8 -} - // EncodeFixed32 writes a 32-bit integer to the Buffer. // This is the format for the // fixed32, sfixed32, and float protocol buffer types. @@ -165,20 +165,12 @@ func (p *Buffer) EncodeFixed32(x uint64) error { return nil } -func sizeFixed32(x uint64) int { - return 4 -} - // EncodeZigzag64 writes a zigzag-encoded 64-bit integer // to the Buffer. // This is the format used for the sint64 protocol buffer type. func (p *Buffer) EncodeZigzag64(x uint64) error { // use signed number to get arithmetic right shift. - return p.EncodeVarint((x << 1) ^ uint64((int64(x) >> 63))) -} - -func sizeZigzag64(x uint64) int { - return sizeVarint((x << 1) ^ uint64((int64(x) >> 63))) + return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } // EncodeZigzag32 writes a zigzag-encoded 32-bit integer @@ -189,10 +181,6 @@ func (p *Buffer) EncodeZigzag32(x uint64) error { return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) } -func sizeZigzag32(x uint64) int { - return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) -} - // EncodeRawBytes writes a count-delimited byte buffer to the Buffer. // This is the format used for the bytes protocol buffer // type and for embedded messages. @@ -202,11 +190,6 @@ func (p *Buffer) EncodeRawBytes(b []byte) error { return nil } -func sizeRawBytes(b []byte) int { - return sizeVarint(uint64(len(b))) + - len(b) -} - // EncodeStringBytes writes an encoded string to the Buffer. // This is the format used for the proto2 string type. func (p *Buffer) EncodeStringBytes(s string) error { @@ -215,319 +198,17 @@ func (p *Buffer) EncodeStringBytes(s string) error { return nil } -func sizeStringBytes(s string) int { - return sizeVarint(uint64(len(s))) + - len(s) -} - // Marshaler is the interface representing objects that can marshal themselves. type Marshaler interface { Marshal() ([]byte, error) } -// Marshal takes the protocol buffer -// and encodes it into the wire format, returning the data. -func Marshal(pb Message) ([]byte, error) { - // Can the object marshal itself? - if m, ok := pb.(Marshaler); ok { - return m.Marshal() - } - p := NewBuffer(nil) - err := p.Marshal(pb) - if p.buf == nil && err == nil { - // Return a non-nil slice on success. - return []byte{}, nil - } - return p.buf, err -} - // EncodeMessage writes the protocol buffer to the Buffer, // prefixed by a varint-encoded length. func (p *Buffer) EncodeMessage(pb Message) error { - t, base, err := getbase(pb) - if structPointer_IsNil(base) { - return ErrNil - } - if err == nil { - var state errorState - err = p.enc_len_struct(GetProperties(t.Elem()), base, &state) - } - return err -} - -// Marshal takes the protocol buffer -// and encodes it into the wire format, writing the result to the -// Buffer. -func (p *Buffer) Marshal(pb Message) error { - // Can the object marshal itself? - if m, ok := pb.(Marshaler); ok { - data, err := m.Marshal() - p.buf = append(p.buf, data...) - return err - } - - t, base, err := getbase(pb) - if structPointer_IsNil(base) { - return ErrNil - } - if err == nil { - err = p.enc_struct(GetProperties(t.Elem()), base) - } - - if collectStats { - (stats).Encode++ // Parens are to work around a goimports bug. - } - - if len(p.buf) > maxMarshalSize { - return ErrTooLarge - } - return err -} - -// Size returns the encoded size of a protocol buffer. -func Size(pb Message) (n int) { - // Can the object marshal itself? If so, Size is slow. - // TODO: add Size to Marshaler, or add a Sizer interface. - if m, ok := pb.(Marshaler); ok { - b, _ := m.Marshal() - return len(b) - } - - t, base, err := getbase(pb) - if structPointer_IsNil(base) { - return 0 - } - if err == nil { - n = size_struct(GetProperties(t.Elem()), base) - } - - if collectStats { - (stats).Size++ // Parens are to work around a goimports bug. - } - - return -} - -// Individual type encoders. - -// Encode a bool. -func (o *Buffer) enc_bool(p *Properties, base structPointer) error { - v := *structPointer_Bool(base, p.field) - if v == nil { - return ErrNil - } - x := 0 - if *v { - x = 1 - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error { - v := *structPointer_BoolVal(base, p.field) - if !v { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, 1) - return nil -} - -func size_bool(p *Properties, base structPointer) int { - v := *structPointer_Bool(base, p.field) - if v == nil { - return 0 - } - return len(p.tagcode) + 1 // each bool takes exactly one byte -} - -func size_proto3_bool(p *Properties, base structPointer) int { - v := *structPointer_BoolVal(base, p.field) - if !v && !p.oneof { - return 0 - } - return len(p.tagcode) + 1 // each bool takes exactly one byte -} - -// Encode an int32. -func (o *Buffer) enc_int32(p *Properties, base structPointer) error { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return ErrNil - } - x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error { - v := structPointer_Word32Val(base, p.field) - x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func size_int32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return 0 - } - x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -func size_proto3_int32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32Val(base, p.field) - x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range - if x == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -// Encode a uint32. -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_uint32(p *Properties, base structPointer) error { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return ErrNil - } - x := word32_Get(v) - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error { - v := structPointer_Word32Val(base, p.field) - x := word32Val_Get(v) - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func size_uint32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return 0 - } - x := word32_Get(v) - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -func size_proto3_uint32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32Val(base, p.field) - x := word32Val_Get(v) - if x == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -// Encode an int64. -func (o *Buffer) enc_int64(p *Properties, base structPointer) error { - v := structPointer_Word64(base, p.field) - if word64_IsNil(v) { - return ErrNil - } - x := word64_Get(v) - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, x) - return nil -} - -func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error { - v := structPointer_Word64Val(base, p.field) - x := word64Val_Get(v) - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, x) - return nil -} - -func size_int64(p *Properties, base structPointer) (n int) { - v := structPointer_Word64(base, p.field) - if word64_IsNil(v) { - return 0 - } - x := word64_Get(v) - n += len(p.tagcode) - n += p.valSize(x) - return -} - -func size_proto3_int64(p *Properties, base structPointer) (n int) { - v := structPointer_Word64Val(base, p.field) - x := word64Val_Get(v) - if x == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += p.valSize(x) - return -} - -// Encode a string. -func (o *Buffer) enc_string(p *Properties, base structPointer) error { - v := *structPointer_String(base, p.field) - if v == nil { - return ErrNil - } - x := *v - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(x) - return nil -} - -func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error { - v := *structPointer_StringVal(base, p.field) - if v == "" { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(v) - return nil -} - -func size_string(p *Properties, base structPointer) (n int) { - v := *structPointer_String(base, p.field) - if v == nil { - return 0 - } - x := *v - n += len(p.tagcode) - n += sizeStringBytes(x) - return -} - -func size_proto3_string(p *Properties, base structPointer) (n int) { - v := *structPointer_StringVal(base, p.field) - if v == "" && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += sizeStringBytes(v) - return + siz := Size(pb) + p.EncodeVarint(uint64(siz)) + return p.Marshal(pb) } // All protocol buffer fields are nillable, but be careful. @@ -538,825 +219,3 @@ func isNil(v reflect.Value) bool { } return false } - -// Encode a message struct. -func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error { - var state errorState - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return ErrNil - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, err := m.Marshal() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - return state.err - } - - o.buf = append(o.buf, p.tagcode...) - return o.enc_len_struct(p.sprop, structp, &state) -} - -func size_struct_message(p *Properties, base structPointer) int { - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return 0 - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, _ := m.Marshal() - n0 := len(p.tagcode) - n1 := sizeRawBytes(data) - return n0 + n1 - } - - n0 := len(p.tagcode) - n1 := size_struct(p.sprop, structp) - n2 := sizeVarint(uint64(n1)) // size of encoded length - return n0 + n1 + n2 -} - -// Encode a group struct. -func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error { - var state errorState - b := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(b) { - return ErrNil - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) - err := o.enc_struct(p.sprop, b) - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) - return state.err -} - -func size_struct_group(p *Properties, base structPointer) (n int) { - b := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(b) { - return 0 - } - - n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup)) - n += size_struct(p.sprop, b) - n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup)) - return -} - -// Encode a slice of bools ([]bool). -func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return ErrNil - } - for _, x := range s { - o.buf = append(o.buf, p.tagcode...) - v := uint64(0) - if x { - v = 1 - } - p.valEnc(o, v) - } - return nil -} - -func size_slice_bool(p *Properties, base structPointer) int { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return 0 - } - return l * (len(p.tagcode) + 1) // each bool takes exactly one byte -} - -// Encode a slice of bools ([]bool) in packed format. -func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(l)) // each bool takes exactly one byte - for _, x := range s { - v := uint64(0) - if x { - v = 1 - } - p.valEnc(o, v) - } - return nil -} - -func size_slice_packed_bool(p *Properties, base structPointer) (n int) { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return 0 - } - n += len(p.tagcode) - n += sizeVarint(uint64(l)) - n += l // each bool takes exactly one byte - return -} - -// Encode a slice of bytes ([]byte). -func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error { - s := *structPointer_Bytes(base, p.field) - if s == nil { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(s) - return nil -} - -func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error { - s := *structPointer_Bytes(base, p.field) - if len(s) == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(s) - return nil -} - -func size_slice_byte(p *Properties, base structPointer) (n int) { - s := *structPointer_Bytes(base, p.field) - if s == nil && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += sizeRawBytes(s) - return -} - -func size_proto3_slice_byte(p *Properties, base structPointer) (n int) { - s := *structPointer_Bytes(base, p.field) - if len(s) == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += sizeRawBytes(s) - return -} - -// Encode a slice of int32s ([]int32). -func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - p.valEnc(o, uint64(x)) - } - return nil -} - -func size_slice_int32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - n += p.valSize(uint64(x)) - } - return -} - -// Encode a slice of int32s ([]int32) in packed format. -func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - p.valEnc(buf, uint64(x)) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_int32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - bufSize += p.valSize(uint64(x)) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of uint32s ([]uint32). -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - x := s.Index(i) - p.valEnc(o, uint64(x)) - } - return nil -} - -func size_slice_uint32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - x := s.Index(i) - n += p.valSize(uint64(x)) - } - return -} - -// Encode a slice of uint32s ([]uint32) in packed format. -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - p.valEnc(buf, uint64(s.Index(i))) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_uint32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - bufSize += p.valSize(uint64(s.Index(i))) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of int64s ([]int64). -func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, s.Index(i)) - } - return nil -} - -func size_slice_int64(p *Properties, base structPointer) (n int) { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - n += p.valSize(s.Index(i)) - } - return -} - -// Encode a slice of int64s ([]int64) in packed format. -func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - p.valEnc(buf, s.Index(i)) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_int64(p *Properties, base structPointer) (n int) { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - bufSize += p.valSize(s.Index(i)) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of slice of bytes ([][]byte). -func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error { - ss := *structPointer_BytesSlice(base, p.field) - l := len(ss) - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(ss[i]) - } - return nil -} - -func size_slice_slice_byte(p *Properties, base structPointer) (n int) { - ss := *structPointer_BytesSlice(base, p.field) - l := len(ss) - if l == 0 { - return 0 - } - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - n += sizeRawBytes(ss[i]) - } - return -} - -// Encode a slice of strings ([]string). -func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error { - ss := *structPointer_StringSlice(base, p.field) - l := len(ss) - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(ss[i]) - } - return nil -} - -func size_slice_string(p *Properties, base structPointer) (n int) { - ss := *structPointer_StringSlice(base, p.field) - l := len(ss) - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - n += sizeStringBytes(ss[i]) - } - return -} - -// Encode a slice of message structs ([]*struct). -func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error { - var state errorState - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - for i := 0; i < l; i++ { - structp := s.Index(i) - if structPointer_IsNil(structp) { - return errRepeatedHasNil - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, err := m.Marshal() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - continue - } - - o.buf = append(o.buf, p.tagcode...) - err := o.enc_len_struct(p.sprop, structp, &state) - if err != nil && !state.shouldContinue(err, nil) { - if err == ErrNil { - return errRepeatedHasNil - } - return err - } - } - return state.err -} - -func size_slice_struct_message(p *Properties, base structPointer) (n int) { - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - structp := s.Index(i) - if structPointer_IsNil(structp) { - return // return the size up to this point - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, _ := m.Marshal() - n += sizeRawBytes(data) - continue - } - - n0 := size_struct(p.sprop, structp) - n1 := sizeVarint(uint64(n0)) // size of encoded length - n += n0 + n1 - } - return -} - -// Encode a slice of group structs ([]*struct). -func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error { - var state errorState - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - for i := 0; i < l; i++ { - b := s.Index(i) - if structPointer_IsNil(b) { - return errRepeatedHasNil - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) - - err := o.enc_struct(p.sprop, b) - - if err != nil && !state.shouldContinue(err, nil) { - if err == ErrNil { - return errRepeatedHasNil - } - return err - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) - } - return state.err -} - -func size_slice_struct_group(p *Properties, base structPointer) (n int) { - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup)) - n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup)) - for i := 0; i < l; i++ { - b := s.Index(i) - if structPointer_IsNil(b) { - return // return size up to this point - } - - n += size_struct(p.sprop, b) - } - return -} - -// Encode an extension map. -func (o *Buffer) enc_map(p *Properties, base structPointer) error { - exts := structPointer_ExtMap(base, p.field) - if err := encodeExtensionsMap(*exts); err != nil { - return err - } - - return o.enc_map_body(*exts) -} - -func (o *Buffer) enc_exts(p *Properties, base structPointer) error { - exts := structPointer_Extensions(base, p.field) - - v, mu := exts.extensionsRead() - if v == nil { - return nil - } - - mu.Lock() - defer mu.Unlock() - if err := encodeExtensionsMap(v); err != nil { - return err - } - - return o.enc_map_body(v) -} - -func (o *Buffer) enc_map_body(v map[int32]Extension) error { - // Fast-path for common cases: zero or one extensions. - if len(v) <= 1 { - for _, e := range v { - o.buf = append(o.buf, e.enc...) - } - return nil - } - - // Sort keys to provide a deterministic encoding. - keys := make([]int, 0, len(v)) - for k := range v { - keys = append(keys, int(k)) - } - sort.Ints(keys) - - for _, k := range keys { - o.buf = append(o.buf, v[int32(k)].enc...) - } - return nil -} - -func size_map(p *Properties, base structPointer) int { - v := structPointer_ExtMap(base, p.field) - return extensionsMapSize(*v) -} - -func size_exts(p *Properties, base structPointer) int { - v := structPointer_Extensions(base, p.field) - return extensionsSize(v) -} - -// Encode a map field. -func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { - var state errorState // XXX: or do we need to plumb this through? - - /* - A map defined as - map map_field = N; - is encoded in the same way as - message MapFieldEntry { - key_type key = 1; - value_type value = 2; - } - repeated MapFieldEntry map_field = N; - */ - - v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V - if v.Len() == 0 { - return nil - } - - keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) - - enc := func() error { - if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil { - return err - } - if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil { - return err - } - return nil - } - - // Don't sort map keys. It is not required by the spec, and C++ doesn't do it. - for _, key := range v.MapKeys() { - val := v.MapIndex(key) - - keycopy.Set(key) - valcopy.Set(val) - - o.buf = append(o.buf, p.tagcode...) - if err := o.enc_len_thing(enc, &state); err != nil { - return err - } - } - return nil -} - -func size_new_map(p *Properties, base structPointer) int { - v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V - - keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) - - n := 0 - for _, key := range v.MapKeys() { - val := v.MapIndex(key) - keycopy.Set(key) - valcopy.Set(val) - - // Tag codes for key and val are the responsibility of the sub-sizer. - keysize := p.mkeyprop.size(p.mkeyprop, keybase) - valsize := p.mvalprop.size(p.mvalprop, valbase) - entry := keysize + valsize - // Add on tag code and length of map entry itself. - n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry - } - return n -} - -// mapEncodeScratch returns a new reflect.Value matching the map's value type, -// and a structPointer suitable for passing to an encoder or sizer. -func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) { - // Prepare addressable doubly-indirect placeholders for the key and value types. - // This is needed because the element-type encoders expect **T, but the map iteration produces T. - - keycopy = reflect.New(mapType.Key()).Elem() // addressable K - keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K - keyptr.Set(keycopy.Addr()) // - keybase = toStructPointer(keyptr.Addr()) // **K - - // Value types are more varied and require special handling. - switch mapType.Elem().Kind() { - case reflect.Slice: - // []byte - var dummy []byte - valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte - valbase = toStructPointer(valcopy.Addr()) - case reflect.Ptr: - // message; the generated field type is map[K]*Msg (so V is *Msg), - // so we only need one level of indirection. - valcopy = reflect.New(mapType.Elem()).Elem() // addressable V - valbase = toStructPointer(valcopy.Addr()) - default: - // everything else - valcopy = reflect.New(mapType.Elem()).Elem() // addressable V - valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V - valptr.Set(valcopy.Addr()) // - valbase = toStructPointer(valptr.Addr()) // **V - } - return -} - -// Encode a struct. -func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { - var state errorState - // Encode fields in tag order so that decoders may use optimizations - // that depend on the ordering. - // https://developers.google.com/protocol-buffers/docs/encoding#order - for _, i := range prop.order { - p := prop.Prop[i] - if p.enc != nil { - err := p.enc(o, p, base) - if err != nil { - if err == ErrNil { - if p.Required && state.err == nil { - state.err = &RequiredNotSetError{p.Name} - } - } else if err == errRepeatedHasNil { - // Give more context to nil values in repeated fields. - return errors.New("repeated field " + p.OrigName + " has nil element") - } else if !state.shouldContinue(err, p) { - return err - } - } - if len(o.buf) > maxMarshalSize { - return ErrTooLarge - } - } - } - - // Do oneof fields. - if prop.oneofMarshaler != nil { - m := structPointer_Interface(base, prop.stype).(Message) - if err := prop.oneofMarshaler(m, o); err == ErrNil { - return errOneofHasNil - } else if err != nil { - return err - } - } - - // Add unrecognized fields at the end. - if prop.unrecField.IsValid() { - v := *structPointer_Bytes(base, prop.unrecField) - if len(o.buf)+len(v) > maxMarshalSize { - return ErrTooLarge - } - if len(v) > 0 { - o.buf = append(o.buf, v...) - } - } - - return state.err -} - -func size_struct(prop *StructProperties, base structPointer) (n int) { - for _, i := range prop.order { - p := prop.Prop[i] - if p.size != nil { - n += p.size(p, base) - } - } - - // Add unrecognized fields at the end. - if prop.unrecField.IsValid() { - v := *structPointer_Bytes(base, prop.unrecField) - n += len(v) - } - - // Factor in any oneof fields. - if prop.oneofSizer != nil { - m := structPointer_Interface(base, prop.stype).(Message) - n += prop.oneofSizer(m) - } - - return -} - -var zeroes [20]byte // longer than any conceivable sizeVarint - -// Encode a struct, preceded by its encoded length (as a varint). -func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error { - return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state) -} - -// Encode something, preceded by its encoded length (as a varint). -func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error { - iLen := len(o.buf) - o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length - iMsg := len(o.buf) - err := enc() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - lMsg := len(o.buf) - iMsg - lLen := sizeVarint(uint64(lMsg)) - switch x := lLen - (iMsg - iLen); { - case x > 0: // actual length is x bytes larger than the space we reserved - // Move msg x bytes right. - o.buf = append(o.buf, zeroes[:x]...) - copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) - case x < 0: // actual length is x bytes smaller than the space we reserved - // Move msg x bytes left. - copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) - o.buf = o.buf[:len(o.buf)+x] // x is negative - } - // Encode the length in the reserved space. - o.buf = o.buf[:iLen] - o.EncodeVarint(uint64(lMsg)) - o.buf = o.buf[:len(o.buf)+lMsg] - return state.err -} - -// errorState maintains the first error that occurs and updates that error -// with additional context. -type errorState struct { - err error -} - -// shouldContinue reports whether encoding should continue upon encountering the -// given error. If the error is RequiredNotSetError, shouldContinue returns true -// and, if this is the first appearance of that error, remembers it for future -// reporting. -// -// If prop is not nil, it may update any error with additional context about the -// field with the error. -func (s *errorState) shouldContinue(err error, prop *Properties) bool { - // Ignore unset required fields. - reqNotSet, ok := err.(*RequiredNotSetError) - if !ok { - return false - } - if s.err == nil { - if prop != nil { - err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field} - } - s.err = err - } - return true -} diff --git a/vendor/github.com/golang/protobuf/proto/equal.go b/vendor/github.com/golang/protobuf/proto/equal.go index 2ed1cf59666..d4db5a1c145 100644 --- a/vendor/github.com/golang/protobuf/proto/equal.go +++ b/vendor/github.com/golang/protobuf/proto/equal.go @@ -109,15 +109,6 @@ func equalStruct(v1, v2 reflect.Value) bool { // set/unset mismatch return false } - b1, ok := f1.Interface().(raw) - if ok { - b2 := f2.Interface().(raw) - // RawMessage - if !bytes.Equal(b1.Bytes(), b2.Bytes()) { - return false - } - continue - } f1, f2 = f1.Elem(), f2.Elem() } if !equalAny(f1, f2, sprop.Prop[i]) { @@ -146,11 +137,7 @@ func equalStruct(v1, v2 reflect.Value) bool { u1 := uf.Bytes() u2 := v2.FieldByName("XXX_unrecognized").Bytes() - if !bytes.Equal(u1, u2) { - return false - } - - return true + return bytes.Equal(u1, u2) } // v1 and v2 are known to have the same type. @@ -261,6 +248,15 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { m1, m2 := e1.value, e2.value + if m1 == nil && m2 == nil { + // Both have only encoded form. + if bytes.Equal(e1.enc, e2.enc) { + continue + } + // The bytes are different, but the extensions might still be + // equal. We need to decode them to compare. + } + if m1 != nil && m2 != nil { // Both are unencoded. if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { @@ -276,8 +272,12 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { desc = m[extNum] } if desc == nil { + // If both have only encoded form and the bytes are the same, + // it is handled above. We get here when the bytes are different. + // We don't know how to decode it, so just compare them as byte + // slices. log.Printf("proto: don't know how to compare extension %d of %v", extNum, base) - continue + return false } var err error if m1 == nil { diff --git a/vendor/github.com/golang/protobuf/proto/extensions.go b/vendor/github.com/golang/protobuf/proto/extensions.go index eaad2183126..816a3b9d6c0 100644 --- a/vendor/github.com/golang/protobuf/proto/extensions.go +++ b/vendor/github.com/golang/protobuf/proto/extensions.go @@ -38,6 +38,7 @@ package proto import ( "errors" "fmt" + "io" "reflect" "strconv" "sync" @@ -91,14 +92,29 @@ func (n notLocker) Unlock() {} // extendable returns the extendableProto interface for the given generated proto message. // If the proto message has the old extension format, it returns a wrapper that implements // the extendableProto interface. -func extendable(p interface{}) (extendableProto, bool) { - if ep, ok := p.(extendableProto); ok { - return ep, ok +func extendable(p interface{}) (extendableProto, error) { + switch p := p.(type) { + case extendableProto: + if isNilPtr(p) { + return nil, fmt.Errorf("proto: nil %T is not extendable", p) + } + return p, nil + case extendableProtoV1: + if isNilPtr(p) { + return nil, fmt.Errorf("proto: nil %T is not extendable", p) + } + return extensionAdapter{p}, nil } - if ep, ok := p.(extendableProtoV1); ok { - return extensionAdapter{ep}, ok - } - return nil, false + // Don't allocate a specific error containing %T: + // this is the hot path for Clone and MarshalText. + return nil, errNotExtendable +} + +var errNotExtendable = errors.New("proto: not an extendable proto.Message") + +func isNilPtr(x interface{}) bool { + v := reflect.ValueOf(x) + return v.Kind() == reflect.Ptr && v.IsNil() } // XXX_InternalExtensions is an internal representation of proto extensions. @@ -143,9 +159,6 @@ func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Loc return e.p.extensionMap, &e.p.mu } -var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem() -var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem() - // ExtensionDesc represents an extension specification. // Used in generated code from the protocol compiler. type ExtensionDesc struct { @@ -179,8 +192,8 @@ type Extension struct { // SetRawExtension is for testing only. func SetRawExtension(base Message, id int32, b []byte) { - epb, ok := extendable(base) - if !ok { + epb, err := extendable(base) + if err != nil { return } extmap := epb.extensionsWrite() @@ -205,7 +218,7 @@ func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error { pbi = ea.extendableProtoV1 } if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b { - return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String()) + return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a) } // Check the range. if !isExtensionField(pb, extension.Field) { @@ -250,85 +263,11 @@ func extensionProperties(ed *ExtensionDesc) *Properties { return prop } -// encode encodes any unmarshaled (unencoded) extensions in e. -func encodeExtensions(e *XXX_InternalExtensions) error { - m, mu := e.extensionsRead() - if m == nil { - return nil // fast path - } - mu.Lock() - defer mu.Unlock() - return encodeExtensionsMap(m) -} - -// encode encodes any unmarshaled (unencoded) extensions in e. -func encodeExtensionsMap(m map[int32]Extension) error { - for k, e := range m { - if e.value == nil || e.desc == nil { - // Extension is only in its encoded form. - continue - } - - // We don't skip extensions that have an encoded form set, - // because the extension value may have been mutated after - // the last time this function was called. - - et := reflect.TypeOf(e.desc.ExtensionType) - props := extensionProperties(e.desc) - - p := NewBuffer(nil) - // If e.value has type T, the encoder expects a *struct{ X T }. - // Pass a *T with a zero field and hope it all works out. - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(e.value)) - if err := props.enc(p, props, toStructPointer(x)); err != nil { - return err - } - e.enc = p.buf - m[k] = e - } - return nil -} - -func extensionsSize(e *XXX_InternalExtensions) (n int) { - m, mu := e.extensionsRead() - if m == nil { - return 0 - } - mu.Lock() - defer mu.Unlock() - return extensionsMapSize(m) -} - -func extensionsMapSize(m map[int32]Extension) (n int) { - for _, e := range m { - if e.value == nil || e.desc == nil { - // Extension is only in its encoded form. - n += len(e.enc) - continue - } - - // We don't skip extensions that have an encoded form set, - // because the extension value may have been mutated after - // the last time this function was called. - - et := reflect.TypeOf(e.desc.ExtensionType) - props := extensionProperties(e.desc) - - // If e.value has type T, the encoder expects a *struct{ X T }. - // Pass a *T with a zero field and hope it all works out. - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(e.value)) - n += props.size(props, toStructPointer(x)) - } - return -} - // HasExtension returns whether the given extension is present in pb. func HasExtension(pb Message, extension *ExtensionDesc) bool { // TODO: Check types, field numbers, etc.? - epb, ok := extendable(pb) - if !ok { + epb, err := extendable(pb) + if err != nil { return false } extmap, mu := epb.extensionsRead() @@ -336,15 +275,15 @@ func HasExtension(pb Message, extension *ExtensionDesc) bool { return false } mu.Lock() - _, ok = extmap[extension.Field] + _, ok := extmap[extension.Field] mu.Unlock() return ok } // ClearExtension removes the given extension from pb. func ClearExtension(pb Message, extension *ExtensionDesc) { - epb, ok := extendable(pb) - if !ok { + epb, err := extendable(pb) + if err != nil { return } // TODO: Check types, field numbers, etc.? @@ -352,16 +291,26 @@ func ClearExtension(pb Message, extension *ExtensionDesc) { delete(extmap, extension.Field) } -// GetExtension parses and returns the given extension of pb. -// If the extension is not present and has no default value it returns ErrMissingExtension. +// GetExtension retrieves a proto2 extended field from pb. +// +// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil), +// then GetExtension parses the encoded field and returns a Go value of the specified type. +// If the field is not present, then the default value is returned (if one is specified), +// otherwise ErrMissingExtension is reported. +// +// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil), +// then GetExtension returns the raw encoded bytes of the field extension. func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { - epb, ok := extendable(pb) - if !ok { - return nil, errors.New("proto: not an extendable proto") + epb, err := extendable(pb) + if err != nil { + return nil, err } - if err := checkExtensionTypes(epb, extension); err != nil { - return nil, err + if extension.ExtendedType != nil { + // can only check type if this is a complete descriptor + if err := checkExtensionTypes(epb, extension); err != nil { + return nil, err + } } emap, mu := epb.extensionsRead() @@ -388,6 +337,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { return e.value, nil } + if extension.ExtensionType == nil { + // incomplete descriptor + return e.enc, nil + } + v, err := decodeExtension(e.enc, extension) if err != nil { return nil, err @@ -405,6 +359,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { // defaultExtensionValue returns the default value for extension. // If no default for an extension is defined ErrMissingExtension is returned. func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) { + if extension.ExtensionType == nil { + // incomplete descriptor, so no default + return nil, ErrMissingExtension + } + t := reflect.TypeOf(extension.ExtensionType) props := extensionProperties(extension) @@ -439,31 +398,28 @@ func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) { // decodeExtension decodes an extension encoded in b. func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { - o := NewBuffer(b) - t := reflect.TypeOf(extension.ExtensionType) - - props := extensionProperties(extension) + unmarshal := typeUnmarshaler(t, extension.Tag) // t is a pointer to a struct, pointer to basic type or a slice. - // Allocate a "field" to store the pointer/slice itself; the - // pointer/slice will be stored here. We pass - // the address of this field to props.dec. - // This passes a zero field and a *t and lets props.dec - // interpret it as a *struct{ x t }. + // Allocate space to store the pointer/slice. value := reflect.New(t).Elem() + var err error for { - // Discard wire type and field number varint. It isn't needed. - if _, err := o.DecodeVarint(); err != nil { + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + wire := int(x) & 7 + + b, err = unmarshal(b, valToPointer(value.Addr()), wire) + if err != nil { return nil, err } - if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil { - return nil, err - } - - if o.index >= len(o.buf) { + if len(b) == 0 { break } } @@ -473,9 +429,9 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { // GetExtensions returns a slice of the extensions present in pb that are also listed in es. // The returned slice has the same length as es; missing extensions will appear as nil elements. func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) { - epb, ok := extendable(pb) - if !ok { - return nil, errors.New("proto: not an extendable proto") + epb, err := extendable(pb) + if err != nil { + return nil, err } extensions = make([]interface{}, len(es)) for i, e := range es { @@ -494,9 +450,9 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e // For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing // just the Field field, which defines the extension's field number. func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) { - epb, ok := extendable(pb) - if !ok { - return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb) + epb, err := extendable(pb) + if err != nil { + return nil, err } registeredExtensions := RegisteredExtensions(pb) @@ -523,9 +479,9 @@ func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) { // SetExtension sets the specified extension of pb to the specified value. func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error { - epb, ok := extendable(pb) - if !ok { - return errors.New("proto: not an extendable proto") + epb, err := extendable(pb) + if err != nil { + return err } if err := checkExtensionTypes(epb, extension); err != nil { return err @@ -550,8 +506,8 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error // ClearAllExtensions clears all extensions from pb. func ClearAllExtensions(pb Message) { - epb, ok := extendable(pb) - if !ok { + epb, err := extendable(pb) + if err != nil { return } m := epb.extensionsWrite() diff --git a/vendor/github.com/golang/protobuf/proto/lib.go b/vendor/github.com/golang/protobuf/proto/lib.go index 1c225504a01..0e2191b8ada 100644 --- a/vendor/github.com/golang/protobuf/proto/lib.go +++ b/vendor/github.com/golang/protobuf/proto/lib.go @@ -265,6 +265,7 @@ package proto import ( "encoding/json" + "errors" "fmt" "log" "reflect" @@ -273,6 +274,8 @@ import ( "sync" ) +var errInvalidUTF8 = errors.New("proto: invalid UTF-8 string") + // Message is implemented by generated protocol buffer messages. type Message interface { Reset() @@ -309,16 +312,7 @@ type Buffer struct { buf []byte // encode/decode byte stream index int // read point - // pools of basic types to amortize allocation. - bools []bool - uint32s []uint32 - uint64s []uint64 - - // extra pools, only used with pointer_reflect.go - int32s []int32 - int64s []int64 - float32s []float32 - float64s []float64 + deterministic bool } // NewBuffer allocates a new Buffer and initializes its internal data to @@ -343,6 +337,30 @@ func (p *Buffer) SetBuf(s []byte) { // Bytes returns the contents of the Buffer. func (p *Buffer) Bytes() []byte { return p.buf } +// SetDeterministic sets whether to use deterministic serialization. +// +// Deterministic serialization guarantees that for a given binary, equal +// messages will always be serialized to the same bytes. This implies: +// +// - Repeated serialization of a message will return the same bytes. +// - Different processes of the same binary (which may be executing on +// different machines) will serialize equal messages to the same bytes. +// +// Note that the deterministic serialization is NOT canonical across +// languages. It is not guaranteed to remain stable over time. It is unstable +// across different builds with schema changes due to unknown fields. +// Users who need canonical serialization (e.g., persistent storage in a +// canonical form, fingerprinting, etc.) should define their own +// canonicalization specification and implement their own serializer rather +// than relying on this API. +// +// If deterministic serialization is requested, map entries will be sorted +// by keys in lexographical order. This is an implementation detail and +// subject to change. +func (p *Buffer) SetDeterministic(deterministic bool) { + p.deterministic = deterministic +} + /* * Helper routines for simplifying the creation of optional fields of basic type. */ @@ -831,22 +849,12 @@ func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMes return sf, false, nil } +// mapKeys returns a sort.Interface to be used for sorting the map keys. // Map fields may have key types of non-float scalars, strings and enums. -// The easiest way to sort them in some deterministic order is to use fmt. -// If this turns out to be inefficient we can always consider other options, -// such as doing a Schwartzian transform. - func mapKeys(vs []reflect.Value) sort.Interface { - s := mapKeySorter{ - vs: vs, - // default Less function: textual comparison - less: func(a, b reflect.Value) bool { - return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface()) - }, - } + s := mapKeySorter{vs: vs} - // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps; - // numeric keys are sorted numerically. + // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps. if len(vs) == 0 { return s } @@ -855,6 +863,12 @@ func mapKeys(vs []reflect.Value) sort.Interface { s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() } case reflect.Uint32, reflect.Uint64: s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() } + case reflect.Bool: + s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true + case reflect.String: + s.less = func(a, b reflect.Value) bool { return a.String() < b.String() } + default: + panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind())) } return s @@ -895,3 +909,13 @@ const ProtoPackageIsVersion2 = true // ProtoPackageIsVersion1 is referenced from generated protocol buffer files // to assert that that code is compatible with this version of the proto package. const ProtoPackageIsVersion1 = true + +// InternalMessageInfo is a type used internally by generated .pb.go files. +// This type is not intended to be used by non-generated code. +// This type is not subject to any compatibility guarantee. +type InternalMessageInfo struct { + marshal *marshalInfo + unmarshal *unmarshalInfo + merge *mergeInfo + discard *discardInfo +} diff --git a/vendor/github.com/golang/protobuf/proto/message_set.go b/vendor/github.com/golang/protobuf/proto/message_set.go index fd982decd66..3b6ca41d5e5 100644 --- a/vendor/github.com/golang/protobuf/proto/message_set.go +++ b/vendor/github.com/golang/protobuf/proto/message_set.go @@ -42,6 +42,7 @@ import ( "fmt" "reflect" "sort" + "sync" ) // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID. @@ -94,10 +95,7 @@ func (ms *messageSet) find(pb Message) *_MessageSet_Item { } func (ms *messageSet) Has(pb Message) bool { - if ms.find(pb) != nil { - return true - } - return false + return ms.find(pb) != nil } func (ms *messageSet) Unmarshal(pb Message) error { @@ -150,46 +148,42 @@ func skipVarint(buf []byte) []byte { // MarshalMessageSet encodes the extension map represented by m in the message set wire format. // It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. func MarshalMessageSet(exts interface{}) ([]byte, error) { - var m map[int32]Extension + return marshalMessageSet(exts, false) +} + +// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal. +func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) { switch exts := exts.(type) { case *XXX_InternalExtensions: - if err := encodeExtensions(exts); err != nil { - return nil, err - } - m, _ = exts.extensionsRead() + var u marshalInfo + siz := u.sizeMessageSet(exts) + b := make([]byte, 0, siz) + return u.appendMessageSet(b, exts, deterministic) + case map[int32]Extension: - if err := encodeExtensionsMap(exts); err != nil { - return nil, err + // This is an old-style extension map. + // Wrap it in a new-style XXX_InternalExtensions. + ie := XXX_InternalExtensions{ + p: &struct { + mu sync.Mutex + extensionMap map[int32]Extension + }{ + extensionMap: exts, + }, } - m = exts + + var u marshalInfo + siz := u.sizeMessageSet(&ie) + b := make([]byte, 0, siz) + return u.appendMessageSet(b, &ie, deterministic) + default: return nil, errors.New("proto: not an extension map") } - - // Sort extension IDs to provide a deterministic encoding. - // See also enc_map in encode.go. - ids := make([]int, 0, len(m)) - for id := range m { - ids = append(ids, int(id)) - } - sort.Ints(ids) - - ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))} - for _, id := range ids { - e := m[int32(id)] - // Remove the wire type and field number varint, as well as the length varint. - msg := skipVarint(skipVarint(e.enc)) - - ms.Item = append(ms.Item, &_MessageSet_Item{ - TypeId: Int32(int32(id)), - Message: msg, - }) - } - return Marshal(ms) } // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. -// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. +// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option. func UnmarshalMessageSet(buf []byte, exts interface{}) error { var m map[int32]Extension switch exts := exts.(type) { @@ -235,7 +229,15 @@ func MarshalMessageSetJSON(exts interface{}) ([]byte, error) { var m map[int32]Extension switch exts := exts.(type) { case *XXX_InternalExtensions: - m, _ = exts.extensionsRead() + var mu sync.Locker + m, mu = exts.extensionsRead() + if m != nil { + // Keep the extensions map locked until we're done marshaling to prevent + // races between marshaling and unmarshaling the lazily-{en,de}coded + // values. + mu.Lock() + defer mu.Unlock() + } case map[int32]Extension: m = exts default: @@ -253,15 +255,16 @@ func MarshalMessageSetJSON(exts interface{}) ([]byte, error) { for i, id := range ids { ext := m[id] - if i > 0 { - b.WriteByte(',') - } - msd, ok := messageSetMap[id] if !ok { // Unknown type; we can't render it, so skip it. continue } + + if i > 0 && b.Len() > 1 { + b.WriteByte(',') + } + fmt.Fprintf(&b, `"[%s]":`, msd.name) x := ext.value diff --git a/vendor/github.com/golang/protobuf/proto/pointer_reflect.go b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go index fb512e2e16d..b6cad90834b 100644 --- a/vendor/github.com/golang/protobuf/proto/pointer_reflect.go +++ b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go @@ -29,7 +29,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +build appengine js +// +build purego appengine js // This file contains an implementation of proto field accesses using package reflect. // It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can @@ -38,32 +38,13 @@ package proto import ( - "math" "reflect" + "sync" ) -// A structPointer is a pointer to a struct. -type structPointer struct { - v reflect.Value -} +const unsafeAllowed = false -// toStructPointer returns a structPointer equivalent to the given reflect value. -// The reflect value must itself be a pointer to a struct. -func toStructPointer(v reflect.Value) structPointer { - return structPointer{v} -} - -// IsNil reports whether p is nil. -func structPointer_IsNil(p structPointer) bool { - return p.v.IsNil() -} - -// Interface returns the struct pointer as an interface value. -func structPointer_Interface(p structPointer, _ reflect.Type) interface{} { - return p.v.Interface() -} - -// A field identifies a field in a struct, accessible from a structPointer. +// A field identifies a field in a struct, accessible from a pointer. // In this implementation, a field is identified by the sequence of field indices // passed to reflect's FieldByIndex. type field []int @@ -76,409 +57,301 @@ func toField(f *reflect.StructField) field { // invalidField is an invalid field identifier. var invalidField = field(nil) +// zeroField is a noop when calling pointer.offset. +var zeroField = field([]int{}) + // IsValid reports whether the field identifier is valid. func (f field) IsValid() bool { return f != nil } -// field returns the given field in the struct as a reflect value. -func structPointer_field(p structPointer, f field) reflect.Value { - // Special case: an extension map entry with a value of type T - // passes a *T to the struct-handling code with a zero field, - // expecting that it will be treated as equivalent to *struct{ X T }, - // which has the same memory layout. We have to handle that case - // specially, because reflect will panic if we call FieldByIndex on a - // non-struct. - if f == nil { - return p.v.Elem() - } - - return p.v.Elem().FieldByIndex(f) -} - -// ifield returns the given field in the struct as an interface value. -func structPointer_ifield(p structPointer, f field) interface{} { - return structPointer_field(p, f).Addr().Interface() -} - -// Bytes returns the address of a []byte field in the struct. -func structPointer_Bytes(p structPointer, f field) *[]byte { - return structPointer_ifield(p, f).(*[]byte) -} - -// BytesSlice returns the address of a [][]byte field in the struct. -func structPointer_BytesSlice(p structPointer, f field) *[][]byte { - return structPointer_ifield(p, f).(*[][]byte) -} - -// Bool returns the address of a *bool field in the struct. -func structPointer_Bool(p structPointer, f field) **bool { - return structPointer_ifield(p, f).(**bool) -} - -// BoolVal returns the address of a bool field in the struct. -func structPointer_BoolVal(p structPointer, f field) *bool { - return structPointer_ifield(p, f).(*bool) -} - -// BoolSlice returns the address of a []bool field in the struct. -func structPointer_BoolSlice(p structPointer, f field) *[]bool { - return structPointer_ifield(p, f).(*[]bool) -} - -// String returns the address of a *string field in the struct. -func structPointer_String(p structPointer, f field) **string { - return structPointer_ifield(p, f).(**string) -} - -// StringVal returns the address of a string field in the struct. -func structPointer_StringVal(p structPointer, f field) *string { - return structPointer_ifield(p, f).(*string) -} - -// StringSlice returns the address of a []string field in the struct. -func structPointer_StringSlice(p structPointer, f field) *[]string { - return structPointer_ifield(p, f).(*[]string) -} - -// Extensions returns the address of an extension map field in the struct. -func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { - return structPointer_ifield(p, f).(*XXX_InternalExtensions) -} - -// ExtMap returns the address of an extension map field in the struct. -func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { - return structPointer_ifield(p, f).(*map[int32]Extension) -} - -// NewAt returns the reflect.Value for a pointer to a field in the struct. -func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { - return structPointer_field(p, f).Addr() -} - -// SetStructPointer writes a *struct field in the struct. -func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { - structPointer_field(p, f).Set(q.v) -} - -// GetStructPointer reads a *struct field in the struct. -func structPointer_GetStructPointer(p structPointer, f field) structPointer { - return structPointer{structPointer_field(p, f)} -} - -// StructPointerSlice the address of a []*struct field in the struct. -func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice { - return structPointerSlice{structPointer_field(p, f)} -} - -// A structPointerSlice represents the address of a slice of pointers to structs -// (themselves messages or groups). That is, v.Type() is *[]*struct{...}. -type structPointerSlice struct { +// The pointer type is for the table-driven decoder. +// The implementation here uses a reflect.Value of pointer type to +// create a generic pointer. In pointer_unsafe.go we use unsafe +// instead of reflect to implement the same (but faster) interface. +type pointer struct { v reflect.Value } -func (p structPointerSlice) Len() int { return p.v.Len() } -func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} } -func (p structPointerSlice) Append(q structPointer) { - p.v.Set(reflect.Append(p.v, q.v)) +// toPointer converts an interface of pointer type to a pointer +// that points to the same target. +func toPointer(i *Message) pointer { + return pointer{v: reflect.ValueOf(*i)} } -var ( - int32Type = reflect.TypeOf(int32(0)) - uint32Type = reflect.TypeOf(uint32(0)) - float32Type = reflect.TypeOf(float32(0)) - int64Type = reflect.TypeOf(int64(0)) - uint64Type = reflect.TypeOf(uint64(0)) - float64Type = reflect.TypeOf(float64(0)) -) - -// A word32 represents a field of type *int32, *uint32, *float32, or *enum. -// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable. -type word32 struct { - v reflect.Value +// toAddrPointer converts an interface to a pointer that points to +// the interface data. +func toAddrPointer(i *interface{}, isptr bool) pointer { + v := reflect.ValueOf(*i) + u := reflect.New(v.Type()) + u.Elem().Set(v) + return pointer{v: u} } -// IsNil reports whether p is nil. -func word32_IsNil(p word32) bool { +// valToPointer converts v to a pointer. v must be of pointer type. +func valToPointer(v reflect.Value) pointer { + return pointer{v: v} +} + +// offset converts from a pointer to a structure to a pointer to +// one of its fields. +func (p pointer) offset(f field) pointer { + return pointer{v: p.v.Elem().FieldByIndex(f).Addr()} +} + +func (p pointer) isNil() bool { return p.v.IsNil() } -// Set sets p to point at a newly allocated word with bits set to x. -func word32_Set(p word32, o *Buffer, x uint32) { - t := p.v.Type().Elem() - switch t { - case int32Type: - if len(o.int32s) == 0 { - o.int32s = make([]int32, uint32PoolSize) - } - o.int32s[0] = int32(x) - p.v.Set(reflect.ValueOf(&o.int32s[0])) - o.int32s = o.int32s[1:] - return - case uint32Type: - if len(o.uint32s) == 0 { - o.uint32s = make([]uint32, uint32PoolSize) - } - o.uint32s[0] = x - p.v.Set(reflect.ValueOf(&o.uint32s[0])) - o.uint32s = o.uint32s[1:] - return - case float32Type: - if len(o.float32s) == 0 { - o.float32s = make([]float32, uint32PoolSize) - } - o.float32s[0] = math.Float32frombits(x) - p.v.Set(reflect.ValueOf(&o.float32s[0])) - o.float32s = o.float32s[1:] - return - } - - // must be enum - p.v.Set(reflect.New(t)) - p.v.Elem().SetInt(int64(int32(x))) -} - -// Get gets the bits pointed at by p, as a uint32. -func word32_Get(p word32) uint32 { - elem := p.v.Elem() - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) - } - panic("unreachable") -} - -// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32(p structPointer, f field) word32 { - return word32{structPointer_field(p, f)} -} - -// A word32Val represents a field of type int32, uint32, float32, or enum. -// That is, v.Type() is int32, uint32, float32, or enum and v is assignable. -type word32Val struct { - v reflect.Value -} - -// Set sets *p to x. -func word32Val_Set(p word32Val, x uint32) { - switch p.v.Type() { - case int32Type: - p.v.SetInt(int64(x)) - return - case uint32Type: - p.v.SetUint(uint64(x)) - return - case float32Type: - p.v.SetFloat(float64(math.Float32frombits(x))) - return - } - - // must be enum - p.v.SetInt(int64(int32(x))) -} - -// Get gets the bits pointed at by p, as a uint32. -func word32Val_Get(p word32Val) uint32 { - elem := p.v - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) - } - panic("unreachable") -} - -// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct. -func structPointer_Word32Val(p structPointer, f field) word32Val { - return word32Val{structPointer_field(p, f)} -} - -// A word32Slice is a slice of 32-bit values. -// That is, v.Type() is []int32, []uint32, []float32, or []enum. -type word32Slice struct { - v reflect.Value -} - -func (p word32Slice) Append(x uint32) { - n, m := p.v.Len(), p.v.Cap() +// grow updates the slice s in place to make it one element longer. +// s must be addressable. +// Returns the (addressable) new element. +func grow(s reflect.Value) reflect.Value { + n, m := s.Len(), s.Cap() if n < m { - p.v.SetLen(n + 1) + s.SetLen(n + 1) } else { - t := p.v.Type().Elem() - p.v.Set(reflect.Append(p.v, reflect.Zero(t))) + s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem()))) } - elem := p.v.Index(n) - switch elem.Kind() { - case reflect.Int32: - elem.SetInt(int64(int32(x))) - case reflect.Uint32: - elem.SetUint(uint64(x)) - case reflect.Float32: - elem.SetFloat(float64(math.Float32frombits(x))) + return s.Index(n) +} + +func (p pointer) toInt64() *int64 { + return p.v.Interface().(*int64) +} +func (p pointer) toInt64Ptr() **int64 { + return p.v.Interface().(**int64) +} +func (p pointer) toInt64Slice() *[]int64 { + return p.v.Interface().(*[]int64) +} + +var int32ptr = reflect.TypeOf((*int32)(nil)) + +func (p pointer) toInt32() *int32 { + return p.v.Convert(int32ptr).Interface().(*int32) +} + +// The toInt32Ptr/Slice methods don't work because of enums. +// Instead, we must use set/get methods for the int32ptr/slice case. +/* + func (p pointer) toInt32Ptr() **int32 { + return p.v.Interface().(**int32) +} + func (p pointer) toInt32Slice() *[]int32 { + return p.v.Interface().(*[]int32) +} +*/ +func (p pointer) getInt32Ptr() *int32 { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + return p.v.Elem().Interface().(*int32) } + // an enum + return p.v.Elem().Convert(int32PtrType).Interface().(*int32) +} +func (p pointer) setInt32Ptr(v int32) { + // Allocate value in a *int32. Possibly convert that to a *enum. + // Then assign it to a **int32 or **enum. + // Note: we can convert *int32 to *enum, but we can't convert + // **int32 to **enum! + p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem())) } -func (p word32Slice) Len() int { - return p.v.Len() -} - -func (p word32Slice) Index(i int) uint32 { - elem := p.v.Index(i) - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) +// getInt32Slice copies []int32 from p as a new slice. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) getInt32Slice() []int32 { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + return p.v.Elem().Interface().([]int32) } - panic("unreachable") + // an enum + // Allocate a []int32, then assign []enum's values into it. + // Note: we can't convert []enum to []int32. + slice := p.v.Elem() + s := make([]int32, slice.Len()) + for i := 0; i < slice.Len(); i++ { + s[i] = int32(slice.Index(i).Int()) + } + return s } -// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct. -func structPointer_Word32Slice(p structPointer, f field) word32Slice { - return word32Slice{structPointer_field(p, f)} -} - -// word64 is like word32 but for 64-bit values. -type word64 struct { - v reflect.Value -} - -func word64_Set(p word64, o *Buffer, x uint64) { - t := p.v.Type().Elem() - switch t { - case int64Type: - if len(o.int64s) == 0 { - o.int64s = make([]int64, uint64PoolSize) - } - o.int64s[0] = int64(x) - p.v.Set(reflect.ValueOf(&o.int64s[0])) - o.int64s = o.int64s[1:] - return - case uint64Type: - if len(o.uint64s) == 0 { - o.uint64s = make([]uint64, uint64PoolSize) - } - o.uint64s[0] = x - p.v.Set(reflect.ValueOf(&o.uint64s[0])) - o.uint64s = o.uint64s[1:] - return - case float64Type: - if len(o.float64s) == 0 { - o.float64s = make([]float64, uint64PoolSize) - } - o.float64s[0] = math.Float64frombits(x) - p.v.Set(reflect.ValueOf(&o.float64s[0])) - o.float64s = o.float64s[1:] +// setInt32Slice copies []int32 into p as a new slice. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) setInt32Slice(v []int32) { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + p.v.Elem().Set(reflect.ValueOf(v)) return } - panic("unreachable") -} - -func word64_IsNil(p word64) bool { - return p.v.IsNil() -} - -func word64_Get(p word64) uint64 { - elem := p.v.Elem() - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return elem.Uint() - case reflect.Float64: - return math.Float64bits(elem.Float()) + // an enum + // Allocate a []enum, then assign []int32's values into it. + // Note: we can't convert []enum to []int32. + slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v)) + for i, x := range v { + slice.Index(i).SetInt(int64(x)) } - panic("unreachable") + p.v.Elem().Set(slice) +} +func (p pointer) appendInt32Slice(v int32) { + grow(p.v.Elem()).SetInt(int64(v)) } -func structPointer_Word64(p structPointer, f field) word64 { - return word64{structPointer_field(p, f)} +func (p pointer) toUint64() *uint64 { + return p.v.Interface().(*uint64) +} +func (p pointer) toUint64Ptr() **uint64 { + return p.v.Interface().(**uint64) +} +func (p pointer) toUint64Slice() *[]uint64 { + return p.v.Interface().(*[]uint64) +} +func (p pointer) toUint32() *uint32 { + return p.v.Interface().(*uint32) +} +func (p pointer) toUint32Ptr() **uint32 { + return p.v.Interface().(**uint32) +} +func (p pointer) toUint32Slice() *[]uint32 { + return p.v.Interface().(*[]uint32) +} +func (p pointer) toBool() *bool { + return p.v.Interface().(*bool) +} +func (p pointer) toBoolPtr() **bool { + return p.v.Interface().(**bool) +} +func (p pointer) toBoolSlice() *[]bool { + return p.v.Interface().(*[]bool) +} +func (p pointer) toFloat64() *float64 { + return p.v.Interface().(*float64) +} +func (p pointer) toFloat64Ptr() **float64 { + return p.v.Interface().(**float64) +} +func (p pointer) toFloat64Slice() *[]float64 { + return p.v.Interface().(*[]float64) +} +func (p pointer) toFloat32() *float32 { + return p.v.Interface().(*float32) +} +func (p pointer) toFloat32Ptr() **float32 { + return p.v.Interface().(**float32) +} +func (p pointer) toFloat32Slice() *[]float32 { + return p.v.Interface().(*[]float32) +} +func (p pointer) toString() *string { + return p.v.Interface().(*string) +} +func (p pointer) toStringPtr() **string { + return p.v.Interface().(**string) +} +func (p pointer) toStringSlice() *[]string { + return p.v.Interface().(*[]string) +} +func (p pointer) toBytes() *[]byte { + return p.v.Interface().(*[]byte) +} +func (p pointer) toBytesSlice() *[][]byte { + return p.v.Interface().(*[][]byte) +} +func (p pointer) toExtensions() *XXX_InternalExtensions { + return p.v.Interface().(*XXX_InternalExtensions) +} +func (p pointer) toOldExtensions() *map[int32]Extension { + return p.v.Interface().(*map[int32]Extension) +} +func (p pointer) getPointer() pointer { + return pointer{v: p.v.Elem()} +} +func (p pointer) setPointer(q pointer) { + p.v.Elem().Set(q.v) +} +func (p pointer) appendPointer(q pointer) { + grow(p.v.Elem()).Set(q.v) } -// word64Val is like word32Val but for 64-bit values. -type word64Val struct { - v reflect.Value +// getPointerSlice copies []*T from p as a new []pointer. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) getPointerSlice() []pointer { + if p.v.IsNil() { + return nil + } + n := p.v.Elem().Len() + s := make([]pointer, n) + for i := 0; i < n; i++ { + s[i] = pointer{v: p.v.Elem().Index(i)} + } + return s } -func word64Val_Set(p word64Val, o *Buffer, x uint64) { - switch p.v.Type() { - case int64Type: - p.v.SetInt(int64(x)) - return - case uint64Type: - p.v.SetUint(x) - return - case float64Type: - p.v.SetFloat(math.Float64frombits(x)) +// setPointerSlice copies []pointer into p as a new []*T. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) setPointerSlice(v []pointer) { + if v == nil { + p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem()) return } - panic("unreachable") -} - -func word64Val_Get(p word64Val) uint64 { - elem := p.v - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return elem.Uint() - case reflect.Float64: - return math.Float64bits(elem.Float()) + s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v)) + for _, p := range v { + s = reflect.Append(s, p.v) } - panic("unreachable") + p.v.Elem().Set(s) } -func structPointer_Word64Val(p structPointer, f field) word64Val { - return word64Val{structPointer_field(p, f)} -} - -type word64Slice struct { - v reflect.Value -} - -func (p word64Slice) Append(x uint64) { - n, m := p.v.Len(), p.v.Cap() - if n < m { - p.v.SetLen(n + 1) - } else { - t := p.v.Type().Elem() - p.v.Set(reflect.Append(p.v, reflect.Zero(t))) - } - elem := p.v.Index(n) - switch elem.Kind() { - case reflect.Int64: - elem.SetInt(int64(int64(x))) - case reflect.Uint64: - elem.SetUint(uint64(x)) - case reflect.Float64: - elem.SetFloat(float64(math.Float64frombits(x))) +// getInterfacePointer returns a pointer that points to the +// interface data of the interface pointed by p. +func (p pointer) getInterfacePointer() pointer { + if p.v.Elem().IsNil() { + return pointer{v: p.v.Elem()} } + return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct } -func (p word64Slice) Len() int { - return p.v.Len() +func (p pointer) asPointerTo(t reflect.Type) reflect.Value { + // TODO: check that p.v.Type().Elem() == t? + return p.v } -func (p word64Slice) Index(i int) uint64 { - elem := p.v.Index(i) - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return uint64(elem.Uint()) - case reflect.Float64: - return math.Float64bits(float64(elem.Float())) - } - panic("unreachable") +func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadDiscardInfo(p **discardInfo) *discardInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v } -func structPointer_Word64Slice(p structPointer, f field) word64Slice { - return word64Slice{structPointer_field(p, f)} -} +var atomicLock sync.Mutex diff --git a/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go index 6b5567d47cd..d55a335d945 100644 --- a/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go +++ b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go @@ -29,7 +29,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +build !appengine,!js +// +build !purego,!appengine,!js // This file contains the implementation of the proto field accesses using package unsafe. @@ -37,38 +37,13 @@ package proto import ( "reflect" + "sync/atomic" "unsafe" ) -// NOTE: These type_Foo functions would more idiomatically be methods, -// but Go does not allow methods on pointer types, and we must preserve -// some pointer type for the garbage collector. We use these -// funcs with clunky names as our poor approximation to methods. -// -// An alternative would be -// type structPointer struct { p unsafe.Pointer } -// but that does not registerize as well. +const unsafeAllowed = true -// A structPointer is a pointer to a struct. -type structPointer unsafe.Pointer - -// toStructPointer returns a structPointer equivalent to the given reflect value. -func toStructPointer(v reflect.Value) structPointer { - return structPointer(unsafe.Pointer(v.Pointer())) -} - -// IsNil reports whether p is nil. -func structPointer_IsNil(p structPointer) bool { - return p == nil -} - -// Interface returns the struct pointer, assumed to have element type t, -// as an interface value. -func structPointer_Interface(p structPointer, t reflect.Type) interface{} { - return reflect.NewAt(t, unsafe.Pointer(p)).Interface() -} - -// A field identifies a field in a struct, accessible from a structPointer. +// A field identifies a field in a struct, accessible from a pointer. // In this implementation, a field is identified by its byte offset from the start of the struct. type field uintptr @@ -80,191 +55,254 @@ func toField(f *reflect.StructField) field { // invalidField is an invalid field identifier. const invalidField = ^field(0) +// zeroField is a noop when calling pointer.offset. +const zeroField = field(0) + // IsValid reports whether the field identifier is valid. func (f field) IsValid() bool { - return f != ^field(0) + return f != invalidField } -// Bytes returns the address of a []byte field in the struct. -func structPointer_Bytes(p structPointer, f field) *[]byte { - return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) +// The pointer type below is for the new table-driven encoder/decoder. +// The implementation here uses unsafe.Pointer to create a generic pointer. +// In pointer_reflect.go we use reflect instead of unsafe to implement +// the same (but slower) interface. +type pointer struct { + p unsafe.Pointer } -// BytesSlice returns the address of a [][]byte field in the struct. -func structPointer_BytesSlice(p structPointer, f field) *[][]byte { - return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) +// size of pointer +var ptrSize = unsafe.Sizeof(uintptr(0)) + +// toPointer converts an interface of pointer type to a pointer +// that points to the same target. +func toPointer(i *Message) pointer { + // Super-tricky - read pointer out of data word of interface value. + // Saves ~25ns over the equivalent: + // return valToPointer(reflect.ValueOf(*i)) + return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} } -// Bool returns the address of a *bool field in the struct. -func structPointer_Bool(p structPointer, f field) **bool { - return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// BoolVal returns the address of a bool field in the struct. -func structPointer_BoolVal(p structPointer, f field) *bool { - return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// BoolSlice returns the address of a []bool field in the struct. -func structPointer_BoolSlice(p structPointer, f field) *[]bool { - return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// String returns the address of a *string field in the struct. -func structPointer_String(p structPointer, f field) **string { - return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StringVal returns the address of a string field in the struct. -func structPointer_StringVal(p structPointer, f field) *string { - return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StringSlice returns the address of a []string field in the struct. -func structPointer_StringSlice(p structPointer, f field) *[]string { - return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// ExtMap returns the address of an extension map field in the struct. -func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { - return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { - return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// NewAt returns the reflect.Value for a pointer to a field in the struct. -func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { - return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f))) -} - -// SetStructPointer writes a *struct field in the struct. -func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { - *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q -} - -// GetStructPointer reads a *struct field in the struct. -func structPointer_GetStructPointer(p structPointer, f field) structPointer { - return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StructPointerSlice the address of a []*struct field in the struct. -func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice { - return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups). -type structPointerSlice []structPointer - -func (v *structPointerSlice) Len() int { return len(*v) } -func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] } -func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) } - -// A word32 is the address of a "pointer to 32-bit value" field. -type word32 **uint32 - -// IsNil reports whether *v is nil. -func word32_IsNil(p word32) bool { - return *p == nil -} - -// Set sets *v to point at a newly allocated word set to x. -func word32_Set(p word32, o *Buffer, x uint32) { - if len(o.uint32s) == 0 { - o.uint32s = make([]uint32, uint32PoolSize) +// toAddrPointer converts an interface to a pointer that points to +// the interface data. +func toAddrPointer(i *interface{}, isptr bool) pointer { + // Super-tricky - read or get the address of data word of interface value. + if isptr { + // The interface is of pointer type, thus it is a direct interface. + // The data word is the pointer data itself. We take its address. + return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)} } - o.uint32s[0] = x - *p = &o.uint32s[0] - o.uint32s = o.uint32s[1:] + // The interface is not of pointer type. The data word is the pointer + // to the data. + return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} } -// Get gets the value pointed at by *v. -func word32_Get(p word32) uint32 { - return **p +// valToPointer converts v to a pointer. v must be of pointer type. +func valToPointer(v reflect.Value) pointer { + return pointer{p: unsafe.Pointer(v.Pointer())} } -// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32(p structPointer, f field) word32 { - return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +// offset converts from a pointer to a structure to a pointer to +// one of its fields. +func (p pointer) offset(f field) pointer { + // For safety, we should panic if !f.IsValid, however calling panic causes + // this to no longer be inlineable, which is a serious performance cost. + /* + if !f.IsValid() { + panic("invalid field") + } + */ + return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))} } -// A word32Val is the address of a 32-bit value field. -type word32Val *uint32 - -// Set sets *p to x. -func word32Val_Set(p word32Val, x uint32) { - *p = x +func (p pointer) isNil() bool { + return p.p == nil } -// Get gets the value pointed at by p. -func word32Val_Get(p word32Val) uint32 { - return *p +func (p pointer) toInt64() *int64 { + return (*int64)(p.p) +} +func (p pointer) toInt64Ptr() **int64 { + return (**int64)(p.p) +} +func (p pointer) toInt64Slice() *[]int64 { + return (*[]int64)(p.p) +} +func (p pointer) toInt32() *int32 { + return (*int32)(p.p) } -// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32Val(p structPointer, f field) word32Val { - return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) -} - -// A word32Slice is a slice of 32-bit values. -type word32Slice []uint32 - -func (v *word32Slice) Append(x uint32) { *v = append(*v, x) } -func (v *word32Slice) Len() int { return len(*v) } -func (v *word32Slice) Index(i int) uint32 { return (*v)[i] } - -// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct. -func structPointer_Word32Slice(p structPointer, f field) *word32Slice { - return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// word64 is like word32 but for 64-bit values. -type word64 **uint64 - -func word64_Set(p word64, o *Buffer, x uint64) { - if len(o.uint64s) == 0 { - o.uint64s = make([]uint64, uint64PoolSize) +// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist. +/* + func (p pointer) toInt32Ptr() **int32 { + return (**int32)(p.p) } - o.uint64s[0] = x - *p = &o.uint64s[0] - o.uint64s = o.uint64s[1:] + func (p pointer) toInt32Slice() *[]int32 { + return (*[]int32)(p.p) + } +*/ +func (p pointer) getInt32Ptr() *int32 { + return *(**int32)(p.p) +} +func (p pointer) setInt32Ptr(v int32) { + *(**int32)(p.p) = &v } -func word64_IsNil(p word64) bool { - return *p == nil +// getInt32Slice loads a []int32 from p. +// The value returned is aliased with the original slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) getInt32Slice() []int32 { + return *(*[]int32)(p.p) } -func word64_Get(p word64) uint64 { - return **p +// setInt32Slice stores a []int32 to p. +// The value set is aliased with the input slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) setInt32Slice(v []int32) { + *(*[]int32)(p.p) = v } -func structPointer_Word64(p structPointer, f field) word64 { - return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead? +func (p pointer) appendInt32Slice(v int32) { + s := (*[]int32)(p.p) + *s = append(*s, v) } -// word64Val is like word32Val but for 64-bit values. -type word64Val *uint64 - -func word64Val_Set(p word64Val, o *Buffer, x uint64) { - *p = x +func (p pointer) toUint64() *uint64 { + return (*uint64)(p.p) +} +func (p pointer) toUint64Ptr() **uint64 { + return (**uint64)(p.p) +} +func (p pointer) toUint64Slice() *[]uint64 { + return (*[]uint64)(p.p) +} +func (p pointer) toUint32() *uint32 { + return (*uint32)(p.p) +} +func (p pointer) toUint32Ptr() **uint32 { + return (**uint32)(p.p) +} +func (p pointer) toUint32Slice() *[]uint32 { + return (*[]uint32)(p.p) +} +func (p pointer) toBool() *bool { + return (*bool)(p.p) +} +func (p pointer) toBoolPtr() **bool { + return (**bool)(p.p) +} +func (p pointer) toBoolSlice() *[]bool { + return (*[]bool)(p.p) +} +func (p pointer) toFloat64() *float64 { + return (*float64)(p.p) +} +func (p pointer) toFloat64Ptr() **float64 { + return (**float64)(p.p) +} +func (p pointer) toFloat64Slice() *[]float64 { + return (*[]float64)(p.p) +} +func (p pointer) toFloat32() *float32 { + return (*float32)(p.p) +} +func (p pointer) toFloat32Ptr() **float32 { + return (**float32)(p.p) +} +func (p pointer) toFloat32Slice() *[]float32 { + return (*[]float32)(p.p) +} +func (p pointer) toString() *string { + return (*string)(p.p) +} +func (p pointer) toStringPtr() **string { + return (**string)(p.p) +} +func (p pointer) toStringSlice() *[]string { + return (*[]string)(p.p) +} +func (p pointer) toBytes() *[]byte { + return (*[]byte)(p.p) +} +func (p pointer) toBytesSlice() *[][]byte { + return (*[][]byte)(p.p) +} +func (p pointer) toExtensions() *XXX_InternalExtensions { + return (*XXX_InternalExtensions)(p.p) +} +func (p pointer) toOldExtensions() *map[int32]Extension { + return (*map[int32]Extension)(p.p) } -func word64Val_Get(p word64Val) uint64 { - return *p +// getPointerSlice loads []*T from p as a []pointer. +// The value returned is aliased with the original slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) getPointerSlice() []pointer { + // Super-tricky - p should point to a []*T where T is a + // message type. We load it as []pointer. + return *(*[]pointer)(p.p) } -func structPointer_Word64Val(p structPointer, f field) word64Val { - return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +// setPointerSlice stores []pointer into p as a []*T. +// The value set is aliased with the input slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) setPointerSlice(v []pointer) { + // Super-tricky - p should point to a []*T where T is a + // message type. We store it as []pointer. + *(*[]pointer)(p.p) = v } -// word64Slice is like word32Slice but for 64-bit values. -type word64Slice []uint64 - -func (v *word64Slice) Append(x uint64) { *v = append(*v, x) } -func (v *word64Slice) Len() int { return len(*v) } -func (v *word64Slice) Index(i int) uint64 { return (*v)[i] } - -func structPointer_Word64Slice(p structPointer, f field) *word64Slice { - return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) +// getPointer loads the pointer at p and returns it. +func (p pointer) getPointer() pointer { + return pointer{p: *(*unsafe.Pointer)(p.p)} +} + +// setPointer stores the pointer q at p. +func (p pointer) setPointer(q pointer) { + *(*unsafe.Pointer)(p.p) = q.p +} + +// append q to the slice pointed to by p. +func (p pointer) appendPointer(q pointer) { + s := (*[]unsafe.Pointer)(p.p) + *s = append(*s, q.p) +} + +// getInterfacePointer returns a pointer that points to the +// interface data of the interface pointed by p. +func (p pointer) getInterfacePointer() pointer { + // Super-tricky - read pointer out of data word of interface value. + return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]} +} + +// asPointerTo returns a reflect.Value that is a pointer to an +// object of type t stored at p. +func (p pointer) asPointerTo(t reflect.Type) reflect.Value { + return reflect.NewAt(t, p.p) +} + +func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo { + return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo { + return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo { + return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadDiscardInfo(p **discardInfo) *discardInfo { + return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) } diff --git a/vendor/github.com/golang/protobuf/proto/properties.go b/vendor/github.com/golang/protobuf/proto/properties.go index ec2289c0058..f710adab092 100644 --- a/vendor/github.com/golang/protobuf/proto/properties.go +++ b/vendor/github.com/golang/protobuf/proto/properties.go @@ -58,42 +58,6 @@ const ( WireFixed32 = 5 ) -const startSize = 10 // initial slice/string sizes - -// Encoders are defined in encode.go -// An encoder outputs the full representation of a field, including its -// tag and encoder type. -type encoder func(p *Buffer, prop *Properties, base structPointer) error - -// A valueEncoder encodes a single integer in a particular encoding. -type valueEncoder func(o *Buffer, x uint64) error - -// Sizers are defined in encode.go -// A sizer returns the encoded size of a field, including its tag and encoder -// type. -type sizer func(prop *Properties, base structPointer) int - -// A valueSizer returns the encoded size of a single integer in a particular -// encoding. -type valueSizer func(x uint64) int - -// Decoders are defined in decode.go -// A decoder creates a value from its wire representation. -// Unrecognized subelements are saved in unrec. -type decoder func(p *Buffer, prop *Properties, base structPointer) error - -// A valueDecoder decodes a single integer in a particular encoding. -type valueDecoder func(o *Buffer) (x uint64, err error) - -// A oneofMarshaler does the marshaling for all oneof fields in a message. -type oneofMarshaler func(Message, *Buffer) error - -// A oneofUnmarshaler does the unmarshaling for a oneof field in a message. -type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error) - -// A oneofSizer does the sizing for all oneof fields in a message. -type oneofSizer func(Message) int - // tagMap is an optimization over map[int]int for typical protocol buffer // use-cases. Encoded protocol buffers are often in tag order with small tag // numbers. @@ -140,13 +104,6 @@ type StructProperties struct { decoderTags tagMap // map from proto tag to struct field number decoderOrigNames map[string]int // map from original name to struct field number order []int // list of struct field numbers in tag order - unrecField field // field id of the XXX_unrecognized []byte field - extendable bool // is this an extendable proto - - oneofMarshaler oneofMarshaler - oneofUnmarshaler oneofUnmarshaler - oneofSizer oneofSizer - stype reflect.Type // OneofTypes contains information about the oneof fields in this message. // It is keyed by the original name of a field. @@ -187,36 +144,19 @@ type Properties struct { Default string // default value HasDefault bool // whether an explicit default was provided - def_uint64 uint64 - enc encoder - valEnc valueEncoder // set for bool and numeric types only - field field - tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType) - tagbuf [8]byte - stype reflect.Type // set for struct types only - sprop *StructProperties // set for struct types only - isMarshaler bool - isUnmarshaler bool + stype reflect.Type // set for struct types only + sprop *StructProperties // set for struct types only mtype reflect.Type // set for map types only mkeyprop *Properties // set for map types only mvalprop *Properties // set for map types only - - size sizer - valSize valueSizer // set for bool and numeric types only - - dec decoder - valDec valueDecoder // set for bool and numeric types only - - // If this is a packable field, this will be the decoder for the packed version of the field. - packedDec decoder } // String formats the properties in the protobuf struct field tag style. func (p *Properties) String() string { s := p.Wire - s = "," + s += "," s += strconv.Itoa(p.Tag) if p.Required { s += ",req" @@ -262,29 +202,14 @@ func (p *Properties) Parse(s string) { switch p.Wire { case "varint": p.WireType = WireVarint - p.valEnc = (*Buffer).EncodeVarint - p.valDec = (*Buffer).DecodeVarint - p.valSize = sizeVarint case "fixed32": p.WireType = WireFixed32 - p.valEnc = (*Buffer).EncodeFixed32 - p.valDec = (*Buffer).DecodeFixed32 - p.valSize = sizeFixed32 case "fixed64": p.WireType = WireFixed64 - p.valEnc = (*Buffer).EncodeFixed64 - p.valDec = (*Buffer).DecodeFixed64 - p.valSize = sizeFixed64 case "zigzag32": p.WireType = WireVarint - p.valEnc = (*Buffer).EncodeZigzag32 - p.valDec = (*Buffer).DecodeZigzag32 - p.valSize = sizeZigzag32 case "zigzag64": p.WireType = WireVarint - p.valEnc = (*Buffer).EncodeZigzag64 - p.valDec = (*Buffer).DecodeZigzag64 - p.valSize = sizeZigzag64 case "bytes", "group": p.WireType = WireBytes // no numeric converter for non-numeric types @@ -299,6 +224,7 @@ func (p *Properties) Parse(s string) { return } +outer: for i := 2; i < len(fields); i++ { f := fields[i] switch { @@ -326,229 +252,28 @@ func (p *Properties) Parse(s string) { if i+1 < len(fields) { // Commas aren't escaped, and def is always last. p.Default += "," + strings.Join(fields[i+1:], ",") - break + break outer } } } } -func logNoSliceEnc(t1, t2 reflect.Type) { - fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2) -} - var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem() -// Initialize the fields for encoding and decoding. -func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { - p.enc = nil - p.dec = nil - p.size = nil - +// setFieldProps initializes the field properties for submessages and maps. +func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { switch t1 := typ; t1.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1) - - // proto3 scalar types - - case reflect.Bool: - p.enc = (*Buffer).enc_proto3_bool - p.dec = (*Buffer).dec_proto3_bool - p.size = size_proto3_bool - case reflect.Int32: - p.enc = (*Buffer).enc_proto3_int32 - p.dec = (*Buffer).dec_proto3_int32 - p.size = size_proto3_int32 - case reflect.Uint32: - p.enc = (*Buffer).enc_proto3_uint32 - p.dec = (*Buffer).dec_proto3_int32 // can reuse - p.size = size_proto3_uint32 - case reflect.Int64, reflect.Uint64: - p.enc = (*Buffer).enc_proto3_int64 - p.dec = (*Buffer).dec_proto3_int64 - p.size = size_proto3_int64 - case reflect.Float32: - p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits - p.dec = (*Buffer).dec_proto3_int32 - p.size = size_proto3_uint32 - case reflect.Float64: - p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits - p.dec = (*Buffer).dec_proto3_int64 - p.size = size_proto3_int64 - case reflect.String: - p.enc = (*Buffer).enc_proto3_string - p.dec = (*Buffer).dec_proto3_string - p.size = size_proto3_string - case reflect.Ptr: - switch t2 := t1.Elem(); t2.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2) - break - case reflect.Bool: - p.enc = (*Buffer).enc_bool - p.dec = (*Buffer).dec_bool - p.size = size_bool - case reflect.Int32: - p.enc = (*Buffer).enc_int32 - p.dec = (*Buffer).dec_int32 - p.size = size_int32 - case reflect.Uint32: - p.enc = (*Buffer).enc_uint32 - p.dec = (*Buffer).dec_int32 // can reuse - p.size = size_uint32 - case reflect.Int64, reflect.Uint64: - p.enc = (*Buffer).enc_int64 - p.dec = (*Buffer).dec_int64 - p.size = size_int64 - case reflect.Float32: - p.enc = (*Buffer).enc_uint32 // can just treat them as bits - p.dec = (*Buffer).dec_int32 - p.size = size_uint32 - case reflect.Float64: - p.enc = (*Buffer).enc_int64 // can just treat them as bits - p.dec = (*Buffer).dec_int64 - p.size = size_int64 - case reflect.String: - p.enc = (*Buffer).enc_string - p.dec = (*Buffer).dec_string - p.size = size_string - case reflect.Struct: + if t1.Elem().Kind() == reflect.Struct { p.stype = t1.Elem() - p.isMarshaler = isMarshaler(t1) - p.isUnmarshaler = isUnmarshaler(t1) - if p.Wire == "bytes" { - p.enc = (*Buffer).enc_struct_message - p.dec = (*Buffer).dec_struct_message - p.size = size_struct_message - } else { - p.enc = (*Buffer).enc_struct_group - p.dec = (*Buffer).dec_struct_group - p.size = size_struct_group - } } case reflect.Slice: - switch t2 := t1.Elem(); t2.Kind() { - default: - logNoSliceEnc(t1, t2) - break - case reflect.Bool: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_bool - p.size = size_slice_packed_bool - } else { - p.enc = (*Buffer).enc_slice_bool - p.size = size_slice_bool - } - p.dec = (*Buffer).dec_slice_bool - p.packedDec = (*Buffer).dec_slice_packed_bool - case reflect.Int32: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int32 - p.size = size_slice_packed_int32 - } else { - p.enc = (*Buffer).enc_slice_int32 - p.size = size_slice_int32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case reflect.Uint32: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_uint32 - p.size = size_slice_packed_uint32 - } else { - p.enc = (*Buffer).enc_slice_uint32 - p.size = size_slice_uint32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case reflect.Int64, reflect.Uint64: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int64 - p.size = size_slice_packed_int64 - } else { - p.enc = (*Buffer).enc_slice_int64 - p.size = size_slice_int64 - } - p.dec = (*Buffer).dec_slice_int64 - p.packedDec = (*Buffer).dec_slice_packed_int64 - case reflect.Uint8: - p.dec = (*Buffer).dec_slice_byte - if p.proto3 { - p.enc = (*Buffer).enc_proto3_slice_byte - p.size = size_proto3_slice_byte - } else { - p.enc = (*Buffer).enc_slice_byte - p.size = size_slice_byte - } - case reflect.Float32, reflect.Float64: - switch t2.Bits() { - case 32: - // can just treat them as bits - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_uint32 - p.size = size_slice_packed_uint32 - } else { - p.enc = (*Buffer).enc_slice_uint32 - p.size = size_slice_uint32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case 64: - // can just treat them as bits - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int64 - p.size = size_slice_packed_int64 - } else { - p.enc = (*Buffer).enc_slice_int64 - p.size = size_slice_int64 - } - p.dec = (*Buffer).dec_slice_int64 - p.packedDec = (*Buffer).dec_slice_packed_int64 - default: - logNoSliceEnc(t1, t2) - break - } - case reflect.String: - p.enc = (*Buffer).enc_slice_string - p.dec = (*Buffer).dec_slice_string - p.size = size_slice_string - case reflect.Ptr: - switch t3 := t2.Elem(); t3.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3) - break - case reflect.Struct: - p.stype = t2.Elem() - p.isMarshaler = isMarshaler(t2) - p.isUnmarshaler = isUnmarshaler(t2) - if p.Wire == "bytes" { - p.enc = (*Buffer).enc_slice_struct_message - p.dec = (*Buffer).dec_slice_struct_message - p.size = size_slice_struct_message - } else { - p.enc = (*Buffer).enc_slice_struct_group - p.dec = (*Buffer).dec_slice_struct_group - p.size = size_slice_struct_group - } - } - case reflect.Slice: - switch t2.Elem().Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem()) - break - case reflect.Uint8: - p.enc = (*Buffer).enc_slice_slice_byte - p.dec = (*Buffer).dec_slice_slice_byte - p.size = size_slice_slice_byte - } + if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct { + p.stype = t2.Elem() } case reflect.Map: - p.enc = (*Buffer).enc_new_map - p.dec = (*Buffer).dec_new_map - p.size = size_new_map - p.mtype = t1 p.mkeyprop = &Properties{} p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) @@ -562,20 +287,6 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) } - // precalculate tag code - wire := p.WireType - if p.Packed { - wire = WireBytes - } - x := uint32(p.Tag)<<3 | uint32(wire) - i := 0 - for i = 0; x > 127; i++ { - p.tagbuf[i] = 0x80 | uint8(x&0x7F) - x >>= 7 - } - p.tagbuf[i] = uint8(x) - p.tagcode = p.tagbuf[0 : i+1] - if p.stype != nil { if lockGetProp { p.sprop = GetProperties(p.stype) @@ -586,32 +297,9 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock } var ( - marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() - unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() + marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() ) -// isMarshaler reports whether type t implements Marshaler. -func isMarshaler(t reflect.Type) bool { - // We're checking for (likely) pointer-receiver methods - // so if t is not a pointer, something is very wrong. - // The calls above only invoke isMarshaler on pointer types. - if t.Kind() != reflect.Ptr { - panic("proto: misuse of isMarshaler") - } - return t.Implements(marshalerType) -} - -// isUnmarshaler reports whether type t implements Unmarshaler. -func isUnmarshaler(t reflect.Type) bool { - // We're checking for (likely) pointer-receiver methods - // so if t is not a pointer, something is very wrong. - // The calls above only invoke isUnmarshaler on pointer types. - if t.Kind() != reflect.Ptr { - panic("proto: misuse of isUnmarshaler") - } - return t.Implements(unmarshalerType) -} - // Init populates the properties from a protocol buffer struct tag. func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) { p.init(typ, name, tag, f, true) @@ -621,14 +309,11 @@ func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructF // "bytes,49,opt,def=hello!" p.Name = name p.OrigName = name - if f != nil { - p.field = toField(f) - } if tag == "" { return } p.Parse(tag) - p.setEncAndDec(typ, f, lockGetProp) + p.setFieldProps(typ, f, lockGetProp) } var ( @@ -678,9 +363,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { propertiesMap[t] = prop // build properties - prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) || - reflect.PtrTo(t).Implements(extendableProtoV1Type) - prop.unrecField = invalidField prop.Prop = make([]*Properties, t.NumField()) prop.order = make([]int, t.NumField()) @@ -690,17 +372,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { name := f.Name p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) - if f.Name == "XXX_InternalExtensions" { // special case - p.enc = (*Buffer).enc_exts - p.dec = nil // not needed - p.size = size_exts - } else if f.Name == "XXX_extensions" { // special case - p.enc = (*Buffer).enc_map - p.dec = nil // not needed - p.size = size_map - } else if f.Name == "XXX_unrecognized" { // special case - prop.unrecField = toField(&f) - } oneof := f.Tag.Get("protobuf_oneof") // special case if oneof != "" { // Oneof fields don't use the traditional protobuf tag. @@ -715,9 +386,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { } print("\n") } - if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" { - fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") - } } // Re-order prop.order. @@ -728,8 +396,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { } if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { var oots []interface{} - prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs() - prop.stype = t + _, _, _, oots = om.XXX_OneofFuncs() // Interpret oneof metadata. prop.OneofTypes = make(map[string]*OneofProperties) @@ -779,30 +446,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { return prop } -// Return the Properties object for the x[0]'th field of the structure. -func propByIndex(t reflect.Type, x []int) *Properties { - if len(x) != 1 { - fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t) - return nil - } - prop := GetProperties(t) - return prop.Prop[x[0]] -} - -// Get the address and type of a pointer to a struct from an interface. -func getbase(pb Message) (t reflect.Type, b structPointer, err error) { - if pb == nil { - err = ErrNil - return - } - // get the reflect type of the pointer to the struct. - t = reflect.TypeOf(pb) - // get the address of the struct. - value := reflect.ValueOf(pb) - b = toStructPointer(value) - return -} - // A global registry of enum types. // The generated code will register the generated maps by calling RegisterEnum. @@ -826,20 +469,42 @@ func EnumValueMap(enumType string) map[string]int32 { // A registry of all linked message types. // The string is a fully-qualified proto name ("pkg.Message"). var ( - protoTypes = make(map[string]reflect.Type) - revProtoTypes = make(map[reflect.Type]string) + protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers + protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types + revProtoTypes = make(map[reflect.Type]string) ) // RegisterType is called from generated code and maps from the fully qualified // proto name to the type (pointer to struct) of the protocol buffer. func RegisterType(x Message, name string) { - if _, ok := protoTypes[name]; ok { + if _, ok := protoTypedNils[name]; ok { // TODO: Some day, make this a panic. log.Printf("proto: duplicate proto type registered: %s", name) return } t := reflect.TypeOf(x) - protoTypes[name] = t + if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 { + // Generated code always calls RegisterType with nil x. + // This check is just for extra safety. + protoTypedNils[name] = x + } else { + protoTypedNils[name] = reflect.Zero(t).Interface().(Message) + } + revProtoTypes[t] = name +} + +// RegisterMapType is called from generated code and maps from the fully qualified +// proto name to the native map type of the proto map definition. +func RegisterMapType(x interface{}, name string) { + if reflect.TypeOf(x).Kind() != reflect.Map { + panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name)) + } + if _, ok := protoMapTypes[name]; ok { + log.Printf("proto: duplicate proto type registered: %s", name) + return + } + t := reflect.TypeOf(x) + protoMapTypes[name] = t revProtoTypes[t] = name } @@ -855,7 +520,14 @@ func MessageName(x Message) string { } // MessageType returns the message type (pointer to struct) for a named message. -func MessageType(name string) reflect.Type { return protoTypes[name] } +// The type is not guaranteed to implement proto.Message if the name refers to a +// map entry. +func MessageType(name string) reflect.Type { + if t, ok := protoTypedNils[name]; ok { + return reflect.TypeOf(t) + } + return protoMapTypes[name] +} // A registry of all linked proto files. var ( diff --git a/vendor/github.com/golang/protobuf/proto/table_marshal.go b/vendor/github.com/golang/protobuf/proto/table_marshal.go new file mode 100644 index 00000000000..0f212b3029d --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/table_marshal.go @@ -0,0 +1,2681 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +import ( + "errors" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "strings" + "sync" + "sync/atomic" + "unicode/utf8" +) + +// a sizer takes a pointer to a field and the size of its tag, computes the size of +// the encoded data. +type sizer func(pointer, int) int + +// a marshaler takes a byte slice, a pointer to a field, and its tag (in wire format), +// marshals the field to the end of the slice, returns the slice and error (if any). +type marshaler func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) + +// marshalInfo is the information used for marshaling a message. +type marshalInfo struct { + typ reflect.Type + fields []*marshalFieldInfo + unrecognized field // offset of XXX_unrecognized + extensions field // offset of XXX_InternalExtensions + v1extensions field // offset of XXX_extensions + sizecache field // offset of XXX_sizecache + initialized int32 // 0 -- only typ is set, 1 -- fully initialized + messageset bool // uses message set wire format + hasmarshaler bool // has custom marshaler + sync.RWMutex // protect extElems map, also for initialization + extElems map[int32]*marshalElemInfo // info of extension elements +} + +// marshalFieldInfo is the information used for marshaling a field of a message. +type marshalFieldInfo struct { + field field + wiretag uint64 // tag in wire format + tagsize int // size of tag in wire format + sizer sizer + marshaler marshaler + isPointer bool + required bool // field is required + name string // name of the field, for error reporting + oneofElems map[reflect.Type]*marshalElemInfo // info of oneof elements +} + +// marshalElemInfo is the information used for marshaling an extension or oneof element. +type marshalElemInfo struct { + wiretag uint64 // tag in wire format + tagsize int // size of tag in wire format + sizer sizer + marshaler marshaler + isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only) +} + +var ( + marshalInfoMap = map[reflect.Type]*marshalInfo{} + marshalInfoLock sync.Mutex +) + +// getMarshalInfo returns the information to marshal a given type of message. +// The info it returns may not necessarily initialized. +// t is the type of the message (NOT the pointer to it). +func getMarshalInfo(t reflect.Type) *marshalInfo { + marshalInfoLock.Lock() + u, ok := marshalInfoMap[t] + if !ok { + u = &marshalInfo{typ: t} + marshalInfoMap[t] = u + } + marshalInfoLock.Unlock() + return u +} + +// Size is the entry point from generated code, +// and should be ONLY called by generated code. +// It computes the size of encoded data of msg. +// a is a pointer to a place to store cached marshal info. +func (a *InternalMessageInfo) Size(msg Message) int { + u := getMessageMarshalInfo(msg, a) + ptr := toPointer(&msg) + if ptr.isNil() { + // We get here if msg is a typed nil ((*SomeMessage)(nil)), + // so it satisfies the interface, and msg == nil wouldn't + // catch it. We don't want crash in this case. + return 0 + } + return u.size(ptr) +} + +// Marshal is the entry point from generated code, +// and should be ONLY called by generated code. +// It marshals msg to the end of b. +// a is a pointer to a place to store cached marshal info. +func (a *InternalMessageInfo) Marshal(b []byte, msg Message, deterministic bool) ([]byte, error) { + u := getMessageMarshalInfo(msg, a) + ptr := toPointer(&msg) + if ptr.isNil() { + // We get here if msg is a typed nil ((*SomeMessage)(nil)), + // so it satisfies the interface, and msg == nil wouldn't + // catch it. We don't want crash in this case. + return b, ErrNil + } + return u.marshal(b, ptr, deterministic) +} + +func getMessageMarshalInfo(msg interface{}, a *InternalMessageInfo) *marshalInfo { + // u := a.marshal, but atomically. + // We use an atomic here to ensure memory consistency. + u := atomicLoadMarshalInfo(&a.marshal) + if u == nil { + // Get marshal information from type of message. + t := reflect.ValueOf(msg).Type() + if t.Kind() != reflect.Ptr { + panic(fmt.Sprintf("cannot handle non-pointer message type %v", t)) + } + u = getMarshalInfo(t.Elem()) + // Store it in the cache for later users. + // a.marshal = u, but atomically. + atomicStoreMarshalInfo(&a.marshal, u) + } + return u +} + +// size is the main function to compute the size of the encoded data of a message. +// ptr is the pointer to the message. +func (u *marshalInfo) size(ptr pointer) int { + if atomic.LoadInt32(&u.initialized) == 0 { + u.computeMarshalInfo() + } + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if u.hasmarshaler { + m := ptr.asPointerTo(u.typ).Interface().(Marshaler) + b, _ := m.Marshal() + return len(b) + } + + n := 0 + for _, f := range u.fields { + if f.isPointer && ptr.offset(f.field).getPointer().isNil() { + // nil pointer always marshals to nothing + continue + } + n += f.sizer(ptr.offset(f.field), f.tagsize) + } + if u.extensions.IsValid() { + e := ptr.offset(u.extensions).toExtensions() + if u.messageset { + n += u.sizeMessageSet(e) + } else { + n += u.sizeExtensions(e) + } + } + if u.v1extensions.IsValid() { + m := *ptr.offset(u.v1extensions).toOldExtensions() + n += u.sizeV1Extensions(m) + } + if u.unrecognized.IsValid() { + s := *ptr.offset(u.unrecognized).toBytes() + n += len(s) + } + // cache the result for use in marshal + if u.sizecache.IsValid() { + atomic.StoreInt32(ptr.offset(u.sizecache).toInt32(), int32(n)) + } + return n +} + +// cachedsize gets the size from cache. If there is no cache (i.e. message is not generated), +// fall back to compute the size. +func (u *marshalInfo) cachedsize(ptr pointer) int { + if u.sizecache.IsValid() { + return int(atomic.LoadInt32(ptr.offset(u.sizecache).toInt32())) + } + return u.size(ptr) +} + +// marshal is the main function to marshal a message. It takes a byte slice and appends +// the encoded data to the end of the slice, returns the slice and error (if any). +// ptr is the pointer to the message. +// If deterministic is true, map is marshaled in deterministic order. +func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte, error) { + if atomic.LoadInt32(&u.initialized) == 0 { + u.computeMarshalInfo() + } + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if u.hasmarshaler { + m := ptr.asPointerTo(u.typ).Interface().(Marshaler) + b1, err := m.Marshal() + b = append(b, b1...) + return b, err + } + + var err, errreq error + // The old marshaler encodes extensions at beginning. + if u.extensions.IsValid() { + e := ptr.offset(u.extensions).toExtensions() + if u.messageset { + b, err = u.appendMessageSet(b, e, deterministic) + } else { + b, err = u.appendExtensions(b, e, deterministic) + } + if err != nil { + return b, err + } + } + if u.v1extensions.IsValid() { + m := *ptr.offset(u.v1extensions).toOldExtensions() + b, err = u.appendV1Extensions(b, m, deterministic) + if err != nil { + return b, err + } + } + for _, f := range u.fields { + if f.required && errreq == nil { + if ptr.offset(f.field).getPointer().isNil() { + // Required field is not set. + // We record the error but keep going, to give a complete marshaling. + errreq = &RequiredNotSetError{f.name} + continue + } + } + if f.isPointer && ptr.offset(f.field).getPointer().isNil() { + // nil pointer always marshals to nothing + continue + } + b, err = f.marshaler(b, ptr.offset(f.field), f.wiretag, deterministic) + if err != nil { + if err1, ok := err.(*RequiredNotSetError); ok { + // Required field in submessage is not set. + // We record the error but keep going, to give a complete marshaling. + if errreq == nil { + errreq = &RequiredNotSetError{f.name + "." + err1.field} + } + continue + } + if err == errRepeatedHasNil { + err = errors.New("proto: repeated field " + f.name + " has nil element") + } + return b, err + } + } + if u.unrecognized.IsValid() { + s := *ptr.offset(u.unrecognized).toBytes() + b = append(b, s...) + } + return b, errreq +} + +// computeMarshalInfo initializes the marshal info. +func (u *marshalInfo) computeMarshalInfo() { + u.Lock() + defer u.Unlock() + if u.initialized != 0 { // non-atomic read is ok as it is protected by the lock + return + } + + t := u.typ + u.unrecognized = invalidField + u.extensions = invalidField + u.v1extensions = invalidField + u.sizecache = invalidField + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if reflect.PtrTo(t).Implements(marshalerType) { + u.hasmarshaler = true + atomic.StoreInt32(&u.initialized, 1) + return + } + + // get oneof implementers + var oneofImplementers []interface{} + if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { + _, _, _, oneofImplementers = m.XXX_OneofFuncs() + } + + n := t.NumField() + + // deal with XXX fields first + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if !strings.HasPrefix(f.Name, "XXX_") { + continue + } + switch f.Name { + case "XXX_sizecache": + u.sizecache = toField(&f) + case "XXX_unrecognized": + u.unrecognized = toField(&f) + case "XXX_InternalExtensions": + u.extensions = toField(&f) + u.messageset = f.Tag.Get("protobuf_messageset") == "1" + case "XXX_extensions": + u.v1extensions = toField(&f) + case "XXX_NoUnkeyedLiteral": + // nothing to do + default: + panic("unknown XXX field: " + f.Name) + } + n-- + } + + // normal fields + fields := make([]marshalFieldInfo, n) // batch allocation + u.fields = make([]*marshalFieldInfo, 0, n) + for i, j := 0, 0; i < t.NumField(); i++ { + f := t.Field(i) + + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + field := &fields[j] + j++ + field.name = f.Name + u.fields = append(u.fields, field) + if f.Tag.Get("protobuf_oneof") != "" { + field.computeOneofFieldInfo(&f, oneofImplementers) + continue + } + if f.Tag.Get("protobuf") == "" { + // field has no tag (not in generated message), ignore it + u.fields = u.fields[:len(u.fields)-1] + j-- + continue + } + field.computeMarshalFieldInfo(&f) + } + + // fields are marshaled in tag order on the wire. + sort.Sort(byTag(u.fields)) + + atomic.StoreInt32(&u.initialized, 1) +} + +// helper for sorting fields by tag +type byTag []*marshalFieldInfo + +func (a byTag) Len() int { return len(a) } +func (a byTag) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byTag) Less(i, j int) bool { return a[i].wiretag < a[j].wiretag } + +// getExtElemInfo returns the information to marshal an extension element. +// The info it returns is initialized. +func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo { + // get from cache first + u.RLock() + e, ok := u.extElems[desc.Field] + u.RUnlock() + if ok { + return e + } + + t := reflect.TypeOf(desc.ExtensionType) // pointer or slice to basic type or struct + tags := strings.Split(desc.Tag, ",") + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + sizer, marshaler := typeMarshaler(t, tags, false, false) + e = &marshalElemInfo{ + wiretag: uint64(tag)<<3 | wt, + tagsize: SizeVarint(uint64(tag) << 3), + sizer: sizer, + marshaler: marshaler, + isptr: t.Kind() == reflect.Ptr, + } + + // update cache + u.Lock() + if u.extElems == nil { + u.extElems = make(map[int32]*marshalElemInfo) + } + u.extElems[desc.Field] = e + u.Unlock() + return e +} + +// computeMarshalFieldInfo fills up the information to marshal a field. +func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) { + // parse protobuf tag of the field. + // tag has format of "bytes,49,opt,name=foo,def=hello!" + tags := strings.Split(f.Tag.Get("protobuf"), ",") + if tags[0] == "" { + return + } + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + if tags[2] == "req" { + fi.required = true + } + fi.setTag(f, tag, wt) + fi.setMarshaler(f, tags) +} + +func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) { + fi.field = toField(f) + fi.wiretag = 1<<31 - 1 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire. + fi.isPointer = true + fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f) + fi.oneofElems = make(map[reflect.Type]*marshalElemInfo) + + ityp := f.Type // interface type + for _, o := range oneofImplementers { + t := reflect.TypeOf(o) + if !t.Implements(ityp) { + continue + } + sf := t.Elem().Field(0) // oneof implementer is a struct with a single field + tags := strings.Split(sf.Tag.Get("protobuf"), ",") + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + sizer, marshaler := typeMarshaler(sf.Type, tags, false, true) // oneof should not omit any zero value + fi.oneofElems[t.Elem()] = &marshalElemInfo{ + wiretag: uint64(tag)<<3 | wt, + tagsize: SizeVarint(uint64(tag) << 3), + sizer: sizer, + marshaler: marshaler, + } + } +} + +type oneofMessage interface { + XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) +} + +// wiretype returns the wire encoding of the type. +func wiretype(encoding string) uint64 { + switch encoding { + case "fixed32": + return WireFixed32 + case "fixed64": + return WireFixed64 + case "varint", "zigzag32", "zigzag64": + return WireVarint + case "bytes": + return WireBytes + case "group": + return WireStartGroup + } + panic("unknown wire type " + encoding) +} + +// setTag fills up the tag (in wire format) and its size in the info of a field. +func (fi *marshalFieldInfo) setTag(f *reflect.StructField, tag int, wt uint64) { + fi.field = toField(f) + fi.wiretag = uint64(tag)<<3 | wt + fi.tagsize = SizeVarint(uint64(tag) << 3) +} + +// setMarshaler fills up the sizer and marshaler in the info of a field. +func (fi *marshalFieldInfo) setMarshaler(f *reflect.StructField, tags []string) { + switch f.Type.Kind() { + case reflect.Map: + // map field + fi.isPointer = true + fi.sizer, fi.marshaler = makeMapMarshaler(f) + return + case reflect.Ptr, reflect.Slice: + fi.isPointer = true + } + fi.sizer, fi.marshaler = typeMarshaler(f.Type, tags, true, false) +} + +// typeMarshaler returns the sizer and marshaler of a given field. +// t is the type of the field. +// tags is the generated "protobuf" tag of the field. +// If nozero is true, zero value is not marshaled to the wire. +// If oneof is true, it is a oneof field. +func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, marshaler) { + encoding := tags[0] + + pointer := false + slice := false + if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { + slice = true + t = t.Elem() + } + if t.Kind() == reflect.Ptr { + pointer = true + t = t.Elem() + } + + packed := false + proto3 := false + for i := 2; i < len(tags); i++ { + if tags[i] == "packed" { + packed = true + } + if tags[i] == "proto3" { + proto3 = true + } + } + + switch t.Kind() { + case reflect.Bool: + if pointer { + return sizeBoolPtr, appendBoolPtr + } + if slice { + if packed { + return sizeBoolPackedSlice, appendBoolPackedSlice + } + return sizeBoolSlice, appendBoolSlice + } + if nozero { + return sizeBoolValueNoZero, appendBoolValueNoZero + } + return sizeBoolValue, appendBoolValue + case reflect.Uint32: + switch encoding { + case "fixed32": + if pointer { + return sizeFixed32Ptr, appendFixed32Ptr + } + if slice { + if packed { + return sizeFixed32PackedSlice, appendFixed32PackedSlice + } + return sizeFixed32Slice, appendFixed32Slice + } + if nozero { + return sizeFixed32ValueNoZero, appendFixed32ValueNoZero + } + return sizeFixed32Value, appendFixed32Value + case "varint": + if pointer { + return sizeVarint32Ptr, appendVarint32Ptr + } + if slice { + if packed { + return sizeVarint32PackedSlice, appendVarint32PackedSlice + } + return sizeVarint32Slice, appendVarint32Slice + } + if nozero { + return sizeVarint32ValueNoZero, appendVarint32ValueNoZero + } + return sizeVarint32Value, appendVarint32Value + } + case reflect.Int32: + switch encoding { + case "fixed32": + if pointer { + return sizeFixedS32Ptr, appendFixedS32Ptr + } + if slice { + if packed { + return sizeFixedS32PackedSlice, appendFixedS32PackedSlice + } + return sizeFixedS32Slice, appendFixedS32Slice + } + if nozero { + return sizeFixedS32ValueNoZero, appendFixedS32ValueNoZero + } + return sizeFixedS32Value, appendFixedS32Value + case "varint": + if pointer { + return sizeVarintS32Ptr, appendVarintS32Ptr + } + if slice { + if packed { + return sizeVarintS32PackedSlice, appendVarintS32PackedSlice + } + return sizeVarintS32Slice, appendVarintS32Slice + } + if nozero { + return sizeVarintS32ValueNoZero, appendVarintS32ValueNoZero + } + return sizeVarintS32Value, appendVarintS32Value + case "zigzag32": + if pointer { + return sizeZigzag32Ptr, appendZigzag32Ptr + } + if slice { + if packed { + return sizeZigzag32PackedSlice, appendZigzag32PackedSlice + } + return sizeZigzag32Slice, appendZigzag32Slice + } + if nozero { + return sizeZigzag32ValueNoZero, appendZigzag32ValueNoZero + } + return sizeZigzag32Value, appendZigzag32Value + } + case reflect.Uint64: + switch encoding { + case "fixed64": + if pointer { + return sizeFixed64Ptr, appendFixed64Ptr + } + if slice { + if packed { + return sizeFixed64PackedSlice, appendFixed64PackedSlice + } + return sizeFixed64Slice, appendFixed64Slice + } + if nozero { + return sizeFixed64ValueNoZero, appendFixed64ValueNoZero + } + return sizeFixed64Value, appendFixed64Value + case "varint": + if pointer { + return sizeVarint64Ptr, appendVarint64Ptr + } + if slice { + if packed { + return sizeVarint64PackedSlice, appendVarint64PackedSlice + } + return sizeVarint64Slice, appendVarint64Slice + } + if nozero { + return sizeVarint64ValueNoZero, appendVarint64ValueNoZero + } + return sizeVarint64Value, appendVarint64Value + } + case reflect.Int64: + switch encoding { + case "fixed64": + if pointer { + return sizeFixedS64Ptr, appendFixedS64Ptr + } + if slice { + if packed { + return sizeFixedS64PackedSlice, appendFixedS64PackedSlice + } + return sizeFixedS64Slice, appendFixedS64Slice + } + if nozero { + return sizeFixedS64ValueNoZero, appendFixedS64ValueNoZero + } + return sizeFixedS64Value, appendFixedS64Value + case "varint": + if pointer { + return sizeVarintS64Ptr, appendVarintS64Ptr + } + if slice { + if packed { + return sizeVarintS64PackedSlice, appendVarintS64PackedSlice + } + return sizeVarintS64Slice, appendVarintS64Slice + } + if nozero { + return sizeVarintS64ValueNoZero, appendVarintS64ValueNoZero + } + return sizeVarintS64Value, appendVarintS64Value + case "zigzag64": + if pointer { + return sizeZigzag64Ptr, appendZigzag64Ptr + } + if slice { + if packed { + return sizeZigzag64PackedSlice, appendZigzag64PackedSlice + } + return sizeZigzag64Slice, appendZigzag64Slice + } + if nozero { + return sizeZigzag64ValueNoZero, appendZigzag64ValueNoZero + } + return sizeZigzag64Value, appendZigzag64Value + } + case reflect.Float32: + if pointer { + return sizeFloat32Ptr, appendFloat32Ptr + } + if slice { + if packed { + return sizeFloat32PackedSlice, appendFloat32PackedSlice + } + return sizeFloat32Slice, appendFloat32Slice + } + if nozero { + return sizeFloat32ValueNoZero, appendFloat32ValueNoZero + } + return sizeFloat32Value, appendFloat32Value + case reflect.Float64: + if pointer { + return sizeFloat64Ptr, appendFloat64Ptr + } + if slice { + if packed { + return sizeFloat64PackedSlice, appendFloat64PackedSlice + } + return sizeFloat64Slice, appendFloat64Slice + } + if nozero { + return sizeFloat64ValueNoZero, appendFloat64ValueNoZero + } + return sizeFloat64Value, appendFloat64Value + case reflect.String: + if pointer { + return sizeStringPtr, appendStringPtr + } + if slice { + return sizeStringSlice, appendStringSlice + } + if nozero { + return sizeStringValueNoZero, appendStringValueNoZero + } + return sizeStringValue, appendStringValue + case reflect.Slice: + if slice { + return sizeBytesSlice, appendBytesSlice + } + if oneof { + // Oneof bytes field may also have "proto3" tag. + // We want to marshal it as a oneof field. Do this + // check before the proto3 check. + return sizeBytesOneof, appendBytesOneof + } + if proto3 { + return sizeBytes3, appendBytes3 + } + return sizeBytes, appendBytes + case reflect.Struct: + switch encoding { + case "group": + if slice { + return makeGroupSliceMarshaler(getMarshalInfo(t)) + } + return makeGroupMarshaler(getMarshalInfo(t)) + case "bytes": + if slice { + return makeMessageSliceMarshaler(getMarshalInfo(t)) + } + return makeMessageMarshaler(getMarshalInfo(t)) + } + } + panic(fmt.Sprintf("unknown or mismatched type: type: %v, wire type: %v", t, encoding)) +} + +// Below are functions to size/marshal a specific type of a field. +// They are stored in the field's info, and called by function pointers. +// They have type sizer or marshaler. + +func sizeFixed32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFixed32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFixed32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFixed32Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + return (4 + tagsize) * len(s) +} +func sizeFixed32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFixedS32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFixedS32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFixedS32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFixedS32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + return (4 + tagsize) * len(s) +} +func sizeFixedS32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFloat32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFloat32ValueNoZero(ptr pointer, tagsize int) int { + v := math.Float32bits(*ptr.toFloat32()) + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFloat32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toFloat32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFloat32Slice(ptr pointer, tagsize int) int { + s := *ptr.toFloat32Slice() + return (4 + tagsize) * len(s) +} +func sizeFloat32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toFloat32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFixed64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFixed64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFixed64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFixed64Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + return (8 + tagsize) * len(s) +} +func sizeFixed64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeFixedS64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFixedS64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFixedS64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFixedS64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + return (8 + tagsize) * len(s) +} +func sizeFixedS64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeFloat64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFloat64ValueNoZero(ptr pointer, tagsize int) int { + v := math.Float64bits(*ptr.toFloat64()) + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFloat64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toFloat64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFloat64Slice(ptr pointer, tagsize int) int { + s := *ptr.toFloat64Slice() + return (8 + tagsize) * len(s) +} +func sizeFloat64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toFloat64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeVarint32Value(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarint32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarint32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint32Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarint32Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarint32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarintS32Value(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarintS32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarintS32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarint64Value(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + return SizeVarint(v) + tagsize +} +func sizeVarint64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + if v == 0 { + return 0 + } + return SizeVarint(v) + tagsize +} +func sizeVarint64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint64Ptr() + if p == nil { + return 0 + } + return SizeVarint(*p) + tagsize +} +func sizeVarint64Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(v) + tagsize + } + return n +} +func sizeVarint64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(v) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarintS64Value(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarintS64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarintS64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeZigzag32Value(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + v := *p + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize + } + return n +} +func sizeZigzag32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31)))) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeZigzag64Value(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + v := *p + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize + } + return n +} +func sizeZigzag64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63))) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeBoolValue(_ pointer, tagsize int) int { + return 1 + tagsize +} +func sizeBoolValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toBool() + if !v { + return 0 + } + return 1 + tagsize +} +func sizeBoolPtr(ptr pointer, tagsize int) int { + p := *ptr.toBoolPtr() + if p == nil { + return 0 + } + return 1 + tagsize +} +func sizeBoolSlice(ptr pointer, tagsize int) int { + s := *ptr.toBoolSlice() + return (1 + tagsize) * len(s) +} +func sizeBoolPackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toBoolSlice() + if len(s) == 0 { + return 0 + } + return len(s) + SizeVarint(uint64(len(s))) + tagsize +} +func sizeStringValue(ptr pointer, tagsize int) int { + v := *ptr.toString() + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toString() + if v == "" { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringPtr(ptr pointer, tagsize int) int { + p := *ptr.toStringPtr() + if p == nil { + return 0 + } + v := *p + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringSlice(ptr pointer, tagsize int) int { + s := *ptr.toStringSlice() + n := 0 + for _, v := range s { + n += len(v) + SizeVarint(uint64(len(v))) + tagsize + } + return n +} +func sizeBytes(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + if v == nil { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytes3(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + if len(v) == 0 { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytesOneof(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytesSlice(ptr pointer, tagsize int) int { + s := *ptr.toBytesSlice() + n := 0 + for _, v := range s { + n += len(v) + SizeVarint(uint64(len(v))) + tagsize + } + return n +} + +// appendFixed32 appends an encoded fixed32 to b. +func appendFixed32(b []byte, v uint32) []byte { + b = append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24)) + return b +} + +// appendFixed64 appends an encoded fixed64 to b. +func appendFixed64(b []byte, v uint64) []byte { + b = append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24), + byte(v>>32), + byte(v>>40), + byte(v>>48), + byte(v>>56)) + return b +} + +// appendVarint appends an encoded varint to b. +func appendVarint(b []byte, v uint64) []byte { + // TODO: make 1-byte (maybe 2-byte) case inline-able, once we + // have non-leaf inliner. + switch { + case v < 1<<7: + b = append(b, byte(v)) + case v < 1<<14: + b = append(b, + byte(v&0x7f|0x80), + byte(v>>7)) + case v < 1<<21: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte(v>>14)) + case v < 1<<28: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte(v>>21)) + case v < 1<<35: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte(v>>28)) + case v < 1<<42: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte(v>>35)) + case v < 1<<49: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte(v>>42)) + case v < 1<<56: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte(v>>49)) + case v < 1<<63: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte(v>>56)) + default: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte((v>>56)&0x7f|0x80), + 1) + } + return b +} + +func appendFixed32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFixed32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFixed32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, *p) + return b, nil +} +func appendFixed32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + } + return b, nil +} +func appendFixed32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, v) + } + return b, nil +} +func appendFixedS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + return b, nil +} +func appendFixedS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + return b, nil +} +func appendFixedS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(*p)) + return b, nil +} +func appendFixedS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + } + return b, nil +} +func appendFixedS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, uint32(v)) + } + return b, nil +} +func appendFloat32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float32bits(*ptr.toFloat32()) + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFloat32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float32bits(*ptr.toFloat32()) + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFloat32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toFloat32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, math.Float32bits(*p)) + return b, nil +} +func appendFloat32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, math.Float32bits(v)) + } + return b, nil +} +func appendFloat32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, math.Float32bits(v)) + } + return b, nil +} +func appendFixed64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFixed64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFixed64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, *p) + return b, nil +} +func appendFixed64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + } + return b, nil +} +func appendFixed64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, v) + } + return b, nil +} +func appendFixedS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + return b, nil +} +func appendFixedS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + return b, nil +} +func appendFixedS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(*p)) + return b, nil +} +func appendFixedS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + } + return b, nil +} +func appendFixedS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, uint64(v)) + } + return b, nil +} +func appendFloat64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float64bits(*ptr.toFloat64()) + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFloat64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float64bits(*ptr.toFloat64()) + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFloat64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toFloat64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, math.Float64bits(*p)) + return b, nil +} +func appendFloat64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, math.Float64bits(v)) + } + return b, nil +} +func appendFloat64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, math.Float64bits(v)) + } + return b, nil +} +func appendVarint32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarint32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarint32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarint32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarint32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarintS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarint64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + return b, nil +} +func appendVarint64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + return b, nil +} +func appendVarint64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, *p) + return b, nil +} +func appendVarint64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + } + return b, nil +} +func appendVarint64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(v) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, v) + } + return b, nil +} +func appendVarintS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarintS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendZigzag32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + v := *p + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + } + return b, nil +} +func appendZigzag32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31)))) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + } + return b, nil +} +func appendZigzag64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + v := *p + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + } + return b, nil +} +func appendZigzag64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63))) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + } + return b, nil +} +func appendBoolValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBool() + b = appendVarint(b, wiretag) + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + return b, nil +} +func appendBoolValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBool() + if !v { + return b, nil + } + b = appendVarint(b, wiretag) + b = append(b, 1) + return b, nil +} + +func appendBoolPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toBoolPtr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + if *p { + b = append(b, 1) + } else { + b = append(b, 0) + } + return b, nil +} +func appendBoolSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBoolSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + } + return b, nil +} +func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBoolSlice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(len(s))) + for _, v := range s { + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + } + return b, nil +} +func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toString() + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toString() + if v == "" { + return b, nil + } + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toStringPtr() + if p == nil { + return b, nil + } + v := *p + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toStringSlice() + for _, v := range s { + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + return b, nil +} +func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + if v == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytes3(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + if len(v) == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytesOneof(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytesSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBytesSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + return b, nil +} + +// makeGroupMarshaler returns the sizer and marshaler for a group. +// u is the marshal info of the underlying message. +func makeGroupMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + p := ptr.getPointer() + if p.isNil() { + return 0 + } + return u.size(p) + 2*tagsize + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + p := ptr.getPointer() + if p.isNil() { + return b, nil + } + var err error + b = appendVarint(b, wiretag) // start group + b, err = u.marshal(b, p, deterministic) + b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group + return b, err + } +} + +// makeGroupSliceMarshaler returns the sizer and marshaler for a group slice. +// u is the marshal info of the underlying message. +func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getPointerSlice() + n := 0 + for _, v := range s { + if v.isNil() { + continue + } + n += u.size(v) + 2*tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getPointerSlice() + var err, errreq error + for _, v := range s { + if v.isNil() { + return b, errRepeatedHasNil + } + b = appendVarint(b, wiretag) // start group + b, err = u.marshal(b, v, deterministic) + b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group + if err != nil { + if _, ok := err.(*RequiredNotSetError); ok { + // Required field in submessage is not set. + // We record the error but keep going, to give a complete marshaling. + if errreq == nil { + errreq = err + } + continue + } + if err == ErrNil { + err = errRepeatedHasNil + } + return b, err + } + } + return b, errreq + } +} + +// makeMessageMarshaler returns the sizer and marshaler for a message field. +// u is the marshal info of the message. +func makeMessageMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + p := ptr.getPointer() + if p.isNil() { + return 0 + } + siz := u.size(p) + return siz + SizeVarint(uint64(siz)) + tagsize + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + p := ptr.getPointer() + if p.isNil() { + return b, nil + } + b = appendVarint(b, wiretag) + siz := u.cachedsize(p) + b = appendVarint(b, uint64(siz)) + return u.marshal(b, p, deterministic) + } +} + +// makeMessageSliceMarshaler returns the sizer and marshaler for a message slice. +// u is the marshal info of the message. +func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getPointerSlice() + n := 0 + for _, v := range s { + if v.isNil() { + continue + } + siz := u.size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getPointerSlice() + var err, errreq error + for _, v := range s { + if v.isNil() { + return b, errRepeatedHasNil + } + b = appendVarint(b, wiretag) + siz := u.cachedsize(v) + b = appendVarint(b, uint64(siz)) + b, err = u.marshal(b, v, deterministic) + + if err != nil { + if _, ok := err.(*RequiredNotSetError); ok { + // Required field in submessage is not set. + // We record the error but keep going, to give a complete marshaling. + if errreq == nil { + errreq = err + } + continue + } + if err == ErrNil { + err = errRepeatedHasNil + } + return b, err + } + } + return b, errreq + } +} + +// makeMapMarshaler returns the sizer and marshaler for a map field. +// f is the pointer to the reflect data structure of the field. +func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) { + // figure out key and value type + t := f.Type + keyType := t.Key() + valType := t.Elem() + keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",") + valTags := strings.Split(f.Tag.Get("protobuf_val"), ",") + keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map + valSizer, valMarshaler := typeMarshaler(valType, valTags, false, false) // don't omit zero value in map + keyWireTag := 1<<3 | wiretype(keyTags[0]) + valWireTag := 2<<3 | wiretype(valTags[0]) + + // We create an interface to get the addresses of the map key and value. + // If value is pointer-typed, the interface is a direct interface, the + // idata itself is the value. Otherwise, the idata is the pointer to the + // value. + // Key cannot be pointer-typed. + valIsPtr := valType.Kind() == reflect.Ptr + return func(ptr pointer, tagsize int) int { + m := ptr.asPointerTo(t).Elem() // the map + n := 0 + for _, k := range m.MapKeys() { + ki := k.Interface() + vi := m.MapIndex(k).Interface() + kaddr := toAddrPointer(&ki, false) // pointer to key + vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value + siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, tag uint64, deterministic bool) ([]byte, error) { + m := ptr.asPointerTo(t).Elem() // the map + var err error + keys := m.MapKeys() + if len(keys) > 1 && deterministic { + sort.Sort(mapKeys(keys)) + } + for _, k := range keys { + ki := k.Interface() + vi := m.MapIndex(k).Interface() + kaddr := toAddrPointer(&ki, false) // pointer to key + vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value + b = appendVarint(b, tag) + siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) + b = appendVarint(b, uint64(siz)) + b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic) + if err != nil { + return b, err + } + b, err = valMarshaler(b, vaddr, valWireTag, deterministic) + if err != nil && err != ErrNil { // allow nil value in map + return b, err + } + } + return b, nil + } +} + +// makeOneOfMarshaler returns the sizer and marshaler for a oneof field. +// fi is the marshal info of the field. +// f is the pointer to the reflect data structure of the field. +func makeOneOfMarshaler(fi *marshalFieldInfo, f *reflect.StructField) (sizer, marshaler) { + // Oneof field is an interface. We need to get the actual data type on the fly. + t := f.Type + return func(ptr pointer, _ int) int { + p := ptr.getInterfacePointer() + if p.isNil() { + return 0 + } + v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct + telem := v.Type() + e := fi.oneofElems[telem] + return e.sizer(p, e.tagsize) + }, + func(b []byte, ptr pointer, _ uint64, deterministic bool) ([]byte, error) { + p := ptr.getInterfacePointer() + if p.isNil() { + return b, nil + } + v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct + telem := v.Type() + if telem.Field(0).Type.Kind() == reflect.Ptr && p.getPointer().isNil() { + return b, errOneofHasNil + } + e := fi.oneofElems[telem] + return e.marshaler(b, p, e.wiretag, deterministic) + } +} + +// sizeExtensions computes the size of encoded data for a XXX_InternalExtensions field. +func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int { + m, mu := ext.extensionsRead() + if m == nil { + return 0 + } + mu.Lock() + + n := 0 + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + n += len(e.enc) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, ei.tagsize) + } + mu.Unlock() + return n +} + +// appendExtensions marshals a XXX_InternalExtensions field to the end of byte slice b. +func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) { + m, mu := ext.extensionsRead() + if m == nil { + return b, nil + } + mu.Lock() + defer mu.Unlock() + + var err error + + // Fast-path for common cases: zero or one extensions. + // Don't bother sorting the keys. + if len(m) <= 1 { + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if err != nil { + return b, err + } + } + return b, nil + } + + // Sort the keys to provide a deterministic encoding. + // Not sure this is required, but the old code does it. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, k := range keys { + e := m[int32(k)] + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if err != nil { + return b, err + } + } + return b, nil +} + +// message set format is: +// message MessageSet { +// repeated group Item = 1 { +// required int32 type_id = 2; +// required string message = 3; +// }; +// } + +// sizeMessageSet computes the size of encoded data for a XXX_InternalExtensions field +// in message set format (above). +func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int { + m, mu := ext.extensionsRead() + if m == nil { + return 0 + } + mu.Lock() + + n := 0 + for id, e := range m { + n += 2 // start group, end group. tag = 1 (size=1) + n += SizeVarint(uint64(id)) + 1 // type_id, tag = 2 (size=1) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + siz := len(msgWithLen) + n += siz + 1 // message, tag = 3 (size=1) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, 1) // message, tag = 3 (size=1) + } + mu.Unlock() + return n +} + +// appendMessageSet marshals a XXX_InternalExtensions field in message set format (above) +// to the end of byte slice b. +func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) { + m, mu := ext.extensionsRead() + if m == nil { + return b, nil + } + mu.Lock() + defer mu.Unlock() + + var err error + + // Fast-path for common cases: zero or one extensions. + // Don't bother sorting the keys. + if len(m) <= 1 { + for id, e := range m { + b = append(b, 1<<3|WireStartGroup) + b = append(b, 2<<3|WireVarint) + b = appendVarint(b, uint64(id)) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + b = append(b, 3<<3|WireBytes) + b = append(b, msgWithLen...) + b = append(b, 1<<3|WireEndGroup) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) + if err != nil { + return b, err + } + b = append(b, 1<<3|WireEndGroup) + } + return b, nil + } + + // Sort the keys to provide a deterministic encoding. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, id := range keys { + e := m[int32(id)] + b = append(b, 1<<3|WireStartGroup) + b = append(b, 2<<3|WireVarint) + b = appendVarint(b, uint64(id)) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + b = append(b, 3<<3|WireBytes) + b = append(b, msgWithLen...) + b = append(b, 1<<3|WireEndGroup) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) + b = append(b, 1<<3|WireEndGroup) + if err != nil { + return b, err + } + } + return b, nil +} + +// sizeV1Extensions computes the size of encoded data for a V1-API extension field. +func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int { + if m == nil { + return 0 + } + + n := 0 + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + n += len(e.enc) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, ei.tagsize) + } + return n +} + +// appendV1Extensions marshals a V1-API extension field to the end of byte slice b. +func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, deterministic bool) ([]byte, error) { + if m == nil { + return b, nil + } + + // Sort the keys to provide a deterministic encoding. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + var err error + for _, k := range keys { + e := m[int32(k)] + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if err != nil { + return b, err + } + } + return b, nil +} + +// newMarshaler is the interface representing objects that can marshal themselves. +// +// This exists to support protoc-gen-go generated messages. +// The proto package will stop type-asserting to this interface in the future. +// +// DO NOT DEPEND ON THIS. +type newMarshaler interface { + XXX_Size() int + XXX_Marshal(b []byte, deterministic bool) ([]byte, error) +} + +// Size returns the encoded size of a protocol buffer message. +// This is the main entry point. +func Size(pb Message) int { + if m, ok := pb.(newMarshaler); ok { + return m.XXX_Size() + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + b, _ := m.Marshal() + return len(b) + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return 0 + } + var info InternalMessageInfo + return info.Size(pb) +} + +// Marshal takes a protocol buffer message +// and encodes it into the wire format, returning the data. +// This is the main entry point. +func Marshal(pb Message) ([]byte, error) { + if m, ok := pb.(newMarshaler); ok { + siz := m.XXX_Size() + b := make([]byte, 0, siz) + return m.XXX_Marshal(b, false) + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + return m.Marshal() + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return nil, ErrNil + } + var info InternalMessageInfo + siz := info.Size(pb) + b := make([]byte, 0, siz) + return info.Marshal(b, pb, false) +} + +// Marshal takes a protocol buffer message +// and encodes it into the wire format, writing the result to the +// Buffer. +// This is an alternative entry point. It is not necessary to use +// a Buffer for most applications. +func (p *Buffer) Marshal(pb Message) error { + var err error + if m, ok := pb.(newMarshaler); ok { + siz := m.XXX_Size() + p.grow(siz) // make sure buf has enough capacity + p.buf, err = m.XXX_Marshal(p.buf, p.deterministic) + return err + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + b, err := m.Marshal() + p.buf = append(p.buf, b...) + return err + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return ErrNil + } + var info InternalMessageInfo + siz := info.Size(pb) + p.grow(siz) // make sure buf has enough capacity + p.buf, err = info.Marshal(p.buf, pb, p.deterministic) + return err +} + +// grow grows the buffer's capacity, if necessary, to guarantee space for +// another n bytes. After grow(n), at least n bytes can be written to the +// buffer without another allocation. +func (p *Buffer) grow(n int) { + need := len(p.buf) + n + if need <= cap(p.buf) { + return + } + newCap := len(p.buf) * 2 + if newCap < need { + newCap = need + } + p.buf = append(make([]byte, 0, newCap), p.buf...) +} diff --git a/vendor/github.com/golang/protobuf/proto/table_merge.go b/vendor/github.com/golang/protobuf/proto/table_merge.go new file mode 100644 index 00000000000..5525def6a5d --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/table_merge.go @@ -0,0 +1,654 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +import ( + "fmt" + "reflect" + "strings" + "sync" + "sync/atomic" +) + +// Merge merges the src message into dst. +// This assumes that dst and src of the same type and are non-nil. +func (a *InternalMessageInfo) Merge(dst, src Message) { + mi := atomicLoadMergeInfo(&a.merge) + if mi == nil { + mi = getMergeInfo(reflect.TypeOf(dst).Elem()) + atomicStoreMergeInfo(&a.merge, mi) + } + mi.merge(toPointer(&dst), toPointer(&src)) +} + +type mergeInfo struct { + typ reflect.Type + + initialized int32 // 0: only typ is valid, 1: everything is valid + lock sync.Mutex + + fields []mergeFieldInfo + unrecognized field // Offset of XXX_unrecognized +} + +type mergeFieldInfo struct { + field field // Offset of field, guaranteed to be valid + + // isPointer reports whether the value in the field is a pointer. + // This is true for the following situations: + // * Pointer to struct + // * Pointer to basic type (proto2 only) + // * Slice (first value in slice header is a pointer) + // * String (first value in string header is a pointer) + isPointer bool + + // basicWidth reports the width of the field assuming that it is directly + // embedded in the struct (as is the case for basic types in proto3). + // The possible values are: + // 0: invalid + // 1: bool + // 4: int32, uint32, float32 + // 8: int64, uint64, float64 + basicWidth int + + // Where dst and src are pointers to the types being merged. + merge func(dst, src pointer) +} + +var ( + mergeInfoMap = map[reflect.Type]*mergeInfo{} + mergeInfoLock sync.Mutex +) + +func getMergeInfo(t reflect.Type) *mergeInfo { + mergeInfoLock.Lock() + defer mergeInfoLock.Unlock() + mi := mergeInfoMap[t] + if mi == nil { + mi = &mergeInfo{typ: t} + mergeInfoMap[t] = mi + } + return mi +} + +// merge merges src into dst assuming they are both of type *mi.typ. +func (mi *mergeInfo) merge(dst, src pointer) { + if dst.isNil() { + panic("proto: nil destination") + } + if src.isNil() { + return // Nothing to do. + } + + if atomic.LoadInt32(&mi.initialized) == 0 { + mi.computeMergeInfo() + } + + for _, fi := range mi.fields { + sfp := src.offset(fi.field) + + // As an optimization, we can avoid the merge function call cost + // if we know for sure that the source will have no effect + // by checking if it is the zero value. + if unsafeAllowed { + if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string + continue + } + if fi.basicWidth > 0 { + switch { + case fi.basicWidth == 1 && !*sfp.toBool(): + continue + case fi.basicWidth == 4 && *sfp.toUint32() == 0: + continue + case fi.basicWidth == 8 && *sfp.toUint64() == 0: + continue + } + } + } + + dfp := dst.offset(fi.field) + fi.merge(dfp, sfp) + } + + // TODO: Make this faster? + out := dst.asPointerTo(mi.typ).Elem() + in := src.asPointerTo(mi.typ).Elem() + if emIn, err := extendable(in.Addr().Interface()); err == nil { + emOut, _ := extendable(out.Addr().Interface()) + mIn, muIn := emIn.extensionsRead() + if mIn != nil { + mOut := emOut.extensionsWrite() + muIn.Lock() + mergeExtension(mOut, mIn) + muIn.Unlock() + } + } + + if mi.unrecognized.IsValid() { + if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 { + *dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...) + } + } +} + +func (mi *mergeInfo) computeMergeInfo() { + mi.lock.Lock() + defer mi.lock.Unlock() + if mi.initialized != 0 { + return + } + t := mi.typ + n := t.NumField() + + props := GetProperties(t) + for i := 0; i < n; i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + + mfi := mergeFieldInfo{field: toField(&f)} + tf := f.Type + + // As an optimization, we can avoid the merge function call cost + // if we know for sure that the source will have no effect + // by checking if it is the zero value. + if unsafeAllowed { + switch tf.Kind() { + case reflect.Ptr, reflect.Slice, reflect.String: + // As a special case, we assume slices and strings are pointers + // since we know that the first field in the SliceSlice or + // StringHeader is a data pointer. + mfi.isPointer = true + case reflect.Bool: + mfi.basicWidth = 1 + case reflect.Int32, reflect.Uint32, reflect.Float32: + mfi.basicWidth = 4 + case reflect.Int64, reflect.Uint64, reflect.Float64: + mfi.basicWidth = 8 + } + } + + // Unwrap tf to get at its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic("both pointer and slice for basic type in " + tf.Name()) + } + + switch tf.Kind() { + case reflect.Int32: + switch { + case isSlice: // E.g., []int32 + mfi.merge = func(dst, src pointer) { + // NOTE: toInt32Slice is not defined (see pointer_reflect.go). + /* + sfsp := src.toInt32Slice() + if *sfsp != nil { + dfsp := dst.toInt32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []int64{} + } + } + */ + sfs := src.getInt32Slice() + if sfs != nil { + dfs := dst.getInt32Slice() + dfs = append(dfs, sfs...) + if dfs == nil { + dfs = []int32{} + } + dst.setInt32Slice(dfs) + } + } + case isPointer: // E.g., *int32 + mfi.merge = func(dst, src pointer) { + // NOTE: toInt32Ptr is not defined (see pointer_reflect.go). + /* + sfpp := src.toInt32Ptr() + if *sfpp != nil { + dfpp := dst.toInt32Ptr() + if *dfpp == nil { + *dfpp = Int32(**sfpp) + } else { + **dfpp = **sfpp + } + } + */ + sfp := src.getInt32Ptr() + if sfp != nil { + dfp := dst.getInt32Ptr() + if dfp == nil { + dst.setInt32Ptr(*sfp) + } else { + *dfp = *sfp + } + } + } + default: // E.g., int32 + mfi.merge = func(dst, src pointer) { + if v := *src.toInt32(); v != 0 { + *dst.toInt32() = v + } + } + } + case reflect.Int64: + switch { + case isSlice: // E.g., []int64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toInt64Slice() + if *sfsp != nil { + dfsp := dst.toInt64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []int64{} + } + } + } + case isPointer: // E.g., *int64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toInt64Ptr() + if *sfpp != nil { + dfpp := dst.toInt64Ptr() + if *dfpp == nil { + *dfpp = Int64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., int64 + mfi.merge = func(dst, src pointer) { + if v := *src.toInt64(); v != 0 { + *dst.toInt64() = v + } + } + } + case reflect.Uint32: + switch { + case isSlice: // E.g., []uint32 + mfi.merge = func(dst, src pointer) { + sfsp := src.toUint32Slice() + if *sfsp != nil { + dfsp := dst.toUint32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []uint32{} + } + } + } + case isPointer: // E.g., *uint32 + mfi.merge = func(dst, src pointer) { + sfpp := src.toUint32Ptr() + if *sfpp != nil { + dfpp := dst.toUint32Ptr() + if *dfpp == nil { + *dfpp = Uint32(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., uint32 + mfi.merge = func(dst, src pointer) { + if v := *src.toUint32(); v != 0 { + *dst.toUint32() = v + } + } + } + case reflect.Uint64: + switch { + case isSlice: // E.g., []uint64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toUint64Slice() + if *sfsp != nil { + dfsp := dst.toUint64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []uint64{} + } + } + } + case isPointer: // E.g., *uint64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toUint64Ptr() + if *sfpp != nil { + dfpp := dst.toUint64Ptr() + if *dfpp == nil { + *dfpp = Uint64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., uint64 + mfi.merge = func(dst, src pointer) { + if v := *src.toUint64(); v != 0 { + *dst.toUint64() = v + } + } + } + case reflect.Float32: + switch { + case isSlice: // E.g., []float32 + mfi.merge = func(dst, src pointer) { + sfsp := src.toFloat32Slice() + if *sfsp != nil { + dfsp := dst.toFloat32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []float32{} + } + } + } + case isPointer: // E.g., *float32 + mfi.merge = func(dst, src pointer) { + sfpp := src.toFloat32Ptr() + if *sfpp != nil { + dfpp := dst.toFloat32Ptr() + if *dfpp == nil { + *dfpp = Float32(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., float32 + mfi.merge = func(dst, src pointer) { + if v := *src.toFloat32(); v != 0 { + *dst.toFloat32() = v + } + } + } + case reflect.Float64: + switch { + case isSlice: // E.g., []float64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toFloat64Slice() + if *sfsp != nil { + dfsp := dst.toFloat64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []float64{} + } + } + } + case isPointer: // E.g., *float64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toFloat64Ptr() + if *sfpp != nil { + dfpp := dst.toFloat64Ptr() + if *dfpp == nil { + *dfpp = Float64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., float64 + mfi.merge = func(dst, src pointer) { + if v := *src.toFloat64(); v != 0 { + *dst.toFloat64() = v + } + } + } + case reflect.Bool: + switch { + case isSlice: // E.g., []bool + mfi.merge = func(dst, src pointer) { + sfsp := src.toBoolSlice() + if *sfsp != nil { + dfsp := dst.toBoolSlice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []bool{} + } + } + } + case isPointer: // E.g., *bool + mfi.merge = func(dst, src pointer) { + sfpp := src.toBoolPtr() + if *sfpp != nil { + dfpp := dst.toBoolPtr() + if *dfpp == nil { + *dfpp = Bool(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., bool + mfi.merge = func(dst, src pointer) { + if v := *src.toBool(); v { + *dst.toBool() = v + } + } + } + case reflect.String: + switch { + case isSlice: // E.g., []string + mfi.merge = func(dst, src pointer) { + sfsp := src.toStringSlice() + if *sfsp != nil { + dfsp := dst.toStringSlice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []string{} + } + } + } + case isPointer: // E.g., *string + mfi.merge = func(dst, src pointer) { + sfpp := src.toStringPtr() + if *sfpp != nil { + dfpp := dst.toStringPtr() + if *dfpp == nil { + *dfpp = String(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., string + mfi.merge = func(dst, src pointer) { + if v := *src.toString(); v != "" { + *dst.toString() = v + } + } + } + case reflect.Slice: + isProto3 := props.Prop[i].proto3 + switch { + case isPointer: + panic("bad pointer in byte slice case in " + tf.Name()) + case tf.Elem().Kind() != reflect.Uint8: + panic("bad element kind in byte slice case in " + tf.Name()) + case isSlice: // E.g., [][]byte + mfi.merge = func(dst, src pointer) { + sbsp := src.toBytesSlice() + if *sbsp != nil { + dbsp := dst.toBytesSlice() + for _, sb := range *sbsp { + if sb == nil { + *dbsp = append(*dbsp, nil) + } else { + *dbsp = append(*dbsp, append([]byte{}, sb...)) + } + } + if *dbsp == nil { + *dbsp = [][]byte{} + } + } + } + default: // E.g., []byte + mfi.merge = func(dst, src pointer) { + sbp := src.toBytes() + if *sbp != nil { + dbp := dst.toBytes() + if !isProto3 || len(*sbp) > 0 { + *dbp = append([]byte{}, *sbp...) + } + } + } + } + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("message field %s without pointer", tf)) + case isSlice: // E.g., []*pb.T + mi := getMergeInfo(tf) + mfi.merge = func(dst, src pointer) { + sps := src.getPointerSlice() + if sps != nil { + dps := dst.getPointerSlice() + for _, sp := range sps { + var dp pointer + if !sp.isNil() { + dp = valToPointer(reflect.New(tf)) + mi.merge(dp, sp) + } + dps = append(dps, dp) + } + if dps == nil { + dps = []pointer{} + } + dst.setPointerSlice(dps) + } + } + default: // E.g., *pb.T + mi := getMergeInfo(tf) + mfi.merge = func(dst, src pointer) { + sp := src.getPointer() + if !sp.isNil() { + dp := dst.getPointer() + if dp.isNil() { + dp = valToPointer(reflect.New(tf)) + dst.setPointer(dp) + } + mi.merge(dp, sp) + } + } + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic("bad pointer or slice in map case in " + tf.Name()) + default: // E.g., map[K]V + mfi.merge = func(dst, src pointer) { + sm := src.asPointerTo(tf).Elem() + if sm.Len() == 0 { + return + } + dm := dst.asPointerTo(tf).Elem() + if dm.IsNil() { + dm.Set(reflect.MakeMap(tf)) + } + + switch tf.Elem().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + val = reflect.ValueOf(Clone(val.Interface().(Message))) + dm.SetMapIndex(key, val) + } + case reflect.Slice: // E.g. Bytes type (e.g., []byte) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + val = reflect.ValueOf(append([]byte{}, val.Bytes()...)) + dm.SetMapIndex(key, val) + } + default: // Basic type (e.g., string) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + dm.SetMapIndex(key, val) + } + } + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic("bad pointer or slice in interface case in " + tf.Name()) + default: // E.g., interface{} + // TODO: Make this faster? + mfi.merge = func(dst, src pointer) { + su := src.asPointerTo(tf).Elem() + if !su.IsNil() { + du := dst.asPointerTo(tf).Elem() + typ := su.Elem().Type() + if du.IsNil() || du.Elem().Type() != typ { + du.Set(reflect.New(typ.Elem())) // Initialize interface if empty + } + sv := su.Elem().Elem().Field(0) + if sv.Kind() == reflect.Ptr && sv.IsNil() { + return + } + dv := du.Elem().Elem().Field(0) + if dv.Kind() == reflect.Ptr && dv.IsNil() { + dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty + } + switch sv.Type().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + Merge(dv.Interface().(Message), sv.Interface().(Message)) + case reflect.Slice: // E.g. Bytes type (e.g., []byte) + dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...))) + default: // Basic type (e.g., string) + dv.Set(sv) + } + } + } + } + default: + panic(fmt.Sprintf("merger not found for type:%s", tf)) + } + mi.fields = append(mi.fields, mfi) + } + + mi.unrecognized = invalidField + if f, ok := t.FieldByName("XXX_unrecognized"); ok { + if f.Type != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + mi.unrecognized = toField(&f) + } + + atomic.StoreInt32(&mi.initialized, 1) +} diff --git a/vendor/github.com/golang/protobuf/proto/table_unmarshal.go b/vendor/github.com/golang/protobuf/proto/table_unmarshal.go new file mode 100644 index 00000000000..55f0340a3fd --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/table_unmarshal.go @@ -0,0 +1,1967 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +import ( + "errors" + "fmt" + "io" + "math" + "reflect" + "strconv" + "strings" + "sync" + "sync/atomic" + "unicode/utf8" +) + +// Unmarshal is the entry point from the generated .pb.go files. +// This function is not intended to be used by non-generated code. +// This function is not subject to any compatibility guarantee. +// msg contains a pointer to a protocol buffer struct. +// b is the data to be unmarshaled into the protocol buffer. +// a is a pointer to a place to store cached unmarshal information. +func (a *InternalMessageInfo) Unmarshal(msg Message, b []byte) error { + // Load the unmarshal information for this message type. + // The atomic load ensures memory consistency. + u := atomicLoadUnmarshalInfo(&a.unmarshal) + if u == nil { + // Slow path: find unmarshal info for msg, update a with it. + u = getUnmarshalInfo(reflect.TypeOf(msg).Elem()) + atomicStoreUnmarshalInfo(&a.unmarshal, u) + } + // Then do the unmarshaling. + err := u.unmarshal(toPointer(&msg), b) + return err +} + +type unmarshalInfo struct { + typ reflect.Type // type of the protobuf struct + + // 0 = only typ field is initialized + // 1 = completely initialized + initialized int32 + lock sync.Mutex // prevents double initialization + dense []unmarshalFieldInfo // fields indexed by tag # + sparse map[uint64]unmarshalFieldInfo // fields indexed by tag # + reqFields []string // names of required fields + reqMask uint64 // 1< 0 { + // Read tag and wire type. + // Special case 1 and 2 byte varints. + var x uint64 + if b[0] < 128 { + x = uint64(b[0]) + b = b[1:] + } else if len(b) >= 2 && b[1] < 128 { + x = uint64(b[0]&0x7f) + uint64(b[1])<<7 + b = b[2:] + } else { + var n int + x, n = decodeVarint(b) + if n == 0 { + return io.ErrUnexpectedEOF + } + b = b[n:] + } + tag := x >> 3 + wire := int(x) & 7 + + // Dispatch on the tag to one of the unmarshal* functions below. + var f unmarshalFieldInfo + if tag < uint64(len(u.dense)) { + f = u.dense[tag] + } else { + f = u.sparse[tag] + } + if fn := f.unmarshal; fn != nil { + var err error + b, err = fn(b, m.offset(f.field), wire) + if err == nil { + reqMask |= f.reqMask + continue + } + if r, ok := err.(*RequiredNotSetError); ok { + // Remember this error, but keep parsing. We need to produce + // a full parse even if a required field is missing. + rnse = r + reqMask |= f.reqMask + continue + } + if err != errInternalBadWireType { + return err + } + // Fragments with bad wire type are treated as unknown fields. + } + + // Unknown tag. + if !u.unrecognized.IsValid() { + // Don't keep unrecognized data; just skip it. + var err error + b, err = skipField(b, wire) + if err != nil { + return err + } + continue + } + // Keep unrecognized data around. + // maybe in extensions, maybe in the unrecognized field. + z := m.offset(u.unrecognized).toBytes() + var emap map[int32]Extension + var e Extension + for _, r := range u.extensionRanges { + if uint64(r.Start) <= tag && tag <= uint64(r.End) { + if u.extensions.IsValid() { + mp := m.offset(u.extensions).toExtensions() + emap = mp.extensionsWrite() + e = emap[int32(tag)] + z = &e.enc + break + } + if u.oldExtensions.IsValid() { + p := m.offset(u.oldExtensions).toOldExtensions() + emap = *p + if emap == nil { + emap = map[int32]Extension{} + *p = emap + } + e = emap[int32(tag)] + z = &e.enc + break + } + panic("no extensions field available") + } + } + + // Use wire type to skip data. + var err error + b0 := b + b, err = skipField(b, wire) + if err != nil { + return err + } + *z = encodeVarint(*z, tag<<3|uint64(wire)) + *z = append(*z, b0[:len(b0)-len(b)]...) + + if emap != nil { + emap[int32(tag)] = e + } + } + if rnse != nil { + // A required field of a submessage/group is missing. Return that error. + return rnse + } + if reqMask != u.reqMask { + // A required field of this message is missing. + for _, n := range u.reqFields { + if reqMask&1 == 0 { + return &RequiredNotSetError{n} + } + reqMask >>= 1 + } + } + return nil +} + +// computeUnmarshalInfo fills in u with information for use +// in unmarshaling protocol buffers of type u.typ. +func (u *unmarshalInfo) computeUnmarshalInfo() { + u.lock.Lock() + defer u.lock.Unlock() + if u.initialized != 0 { + return + } + t := u.typ + n := t.NumField() + + // Set up the "not found" value for the unrecognized byte buffer. + // This is the default for proto3. + u.unrecognized = invalidField + u.extensions = invalidField + u.oldExtensions = invalidField + + // List of the generated type and offset for each oneof field. + type oneofField struct { + ityp reflect.Type // interface type of oneof field + field field // offset in containing message + } + var oneofFields []oneofField + + for i := 0; i < n; i++ { + f := t.Field(i) + if f.Name == "XXX_unrecognized" { + // The byte slice used to hold unrecognized input is special. + if f.Type != reflect.TypeOf(([]byte)(nil)) { + panic("bad type for XXX_unrecognized field: " + f.Type.Name()) + } + u.unrecognized = toField(&f) + continue + } + if f.Name == "XXX_InternalExtensions" { + // Ditto here. + if f.Type != reflect.TypeOf(XXX_InternalExtensions{}) { + panic("bad type for XXX_InternalExtensions field: " + f.Type.Name()) + } + u.extensions = toField(&f) + if f.Tag.Get("protobuf_messageset") == "1" { + u.isMessageSet = true + } + continue + } + if f.Name == "XXX_extensions" { + // An older form of the extensions field. + if f.Type != reflect.TypeOf((map[int32]Extension)(nil)) { + panic("bad type for XXX_extensions field: " + f.Type.Name()) + } + u.oldExtensions = toField(&f) + continue + } + if f.Name == "XXX_NoUnkeyedLiteral" || f.Name == "XXX_sizecache" { + continue + } + + oneof := f.Tag.Get("protobuf_oneof") + if oneof != "" { + oneofFields = append(oneofFields, oneofField{f.Type, toField(&f)}) + // The rest of oneof processing happens below. + continue + } + + tags := f.Tag.Get("protobuf") + tagArray := strings.Split(tags, ",") + if len(tagArray) < 2 { + panic("protobuf tag not enough fields in " + t.Name() + "." + f.Name + ": " + tags) + } + tag, err := strconv.Atoi(tagArray[1]) + if err != nil { + panic("protobuf tag field not an integer: " + tagArray[1]) + } + + name := "" + for _, tag := range tagArray[3:] { + if strings.HasPrefix(tag, "name=") { + name = tag[5:] + } + } + + // Extract unmarshaling function from the field (its type and tags). + unmarshal := fieldUnmarshaler(&f) + + // Required field? + var reqMask uint64 + if tagArray[2] == "req" { + bit := len(u.reqFields) + u.reqFields = append(u.reqFields, name) + reqMask = uint64(1) << uint(bit) + // TODO: if we have more than 64 required fields, we end up + // not verifying that all required fields are present. + // Fix this, perhaps using a count of required fields? + } + + // Store the info in the correct slot in the message. + u.setTag(tag, toField(&f), unmarshal, reqMask) + } + + // Find any types associated with oneof fields. + // TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it? + fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs") + if fn.IsValid() { + res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{} + for i := res.Len() - 1; i >= 0; i-- { + v := res.Index(i) // interface{} + tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X + typ := tptr.Elem() // Msg_X + + f := typ.Field(0) // oneof implementers have one field + baseUnmarshal := fieldUnmarshaler(&f) + tagstr := strings.Split(f.Tag.Get("protobuf"), ",")[1] + tag, err := strconv.Atoi(tagstr) + if err != nil { + panic("protobuf tag field not an integer: " + tagstr) + } + + // Find the oneof field that this struct implements. + // Might take O(n^2) to process all of the oneofs, but who cares. + for _, of := range oneofFields { + if tptr.Implements(of.ityp) { + // We have found the corresponding interface for this struct. + // That lets us know where this struct should be stored + // when we encounter it during unmarshaling. + unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal) + u.setTag(tag, of.field, unmarshal, 0) + } + } + } + } + + // Get extension ranges, if any. + fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") + if fn.IsValid() { + if !u.extensions.IsValid() && !u.oldExtensions.IsValid() { + panic("a message with extensions, but no extensions field in " + t.Name()) + } + u.extensionRanges = fn.Call(nil)[0].Interface().([]ExtensionRange) + } + + // Explicitly disallow tag 0. This will ensure we flag an error + // when decoding a buffer of all zeros. Without this code, we + // would decode and skip an all-zero buffer of even length. + // [0 0] is [tag=0/wiretype=varint varint-encoded-0]. + u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) { + return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w) + }, 0) + + // Set mask for required field check. + u.reqMask = uint64(1)<= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here? + for len(u.dense) <= tag { + u.dense = append(u.dense, unmarshalFieldInfo{}) + } + u.dense[tag] = i + return + } + if u.sparse == nil { + u.sparse = map[uint64]unmarshalFieldInfo{} + } + u.sparse[uint64(tag)] = i +} + +// fieldUnmarshaler returns an unmarshaler for the given field. +func fieldUnmarshaler(f *reflect.StructField) unmarshaler { + if f.Type.Kind() == reflect.Map { + return makeUnmarshalMap(f) + } + return typeUnmarshaler(f.Type, f.Tag.Get("protobuf")) +} + +// typeUnmarshaler returns an unmarshaler for the given field type / field tag pair. +func typeUnmarshaler(t reflect.Type, tags string) unmarshaler { + tagArray := strings.Split(tags, ",") + encoding := tagArray[0] + name := "unknown" + for _, tag := range tagArray[3:] { + if strings.HasPrefix(tag, "name=") { + name = tag[5:] + } + } + + // Figure out packaging (pointer, slice, or both) + slice := false + pointer := false + if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { + slice = true + t = t.Elem() + } + if t.Kind() == reflect.Ptr { + pointer = true + t = t.Elem() + } + + // We'll never have both pointer and slice for basic types. + if pointer && slice && t.Kind() != reflect.Struct { + panic("both pointer and slice for basic type in " + t.Name()) + } + + switch t.Kind() { + case reflect.Bool: + if pointer { + return unmarshalBoolPtr + } + if slice { + return unmarshalBoolSlice + } + return unmarshalBoolValue + case reflect.Int32: + switch encoding { + case "fixed32": + if pointer { + return unmarshalFixedS32Ptr + } + if slice { + return unmarshalFixedS32Slice + } + return unmarshalFixedS32Value + case "varint": + // this could be int32 or enum + if pointer { + return unmarshalInt32Ptr + } + if slice { + return unmarshalInt32Slice + } + return unmarshalInt32Value + case "zigzag32": + if pointer { + return unmarshalSint32Ptr + } + if slice { + return unmarshalSint32Slice + } + return unmarshalSint32Value + } + case reflect.Int64: + switch encoding { + case "fixed64": + if pointer { + return unmarshalFixedS64Ptr + } + if slice { + return unmarshalFixedS64Slice + } + return unmarshalFixedS64Value + case "varint": + if pointer { + return unmarshalInt64Ptr + } + if slice { + return unmarshalInt64Slice + } + return unmarshalInt64Value + case "zigzag64": + if pointer { + return unmarshalSint64Ptr + } + if slice { + return unmarshalSint64Slice + } + return unmarshalSint64Value + } + case reflect.Uint32: + switch encoding { + case "fixed32": + if pointer { + return unmarshalFixed32Ptr + } + if slice { + return unmarshalFixed32Slice + } + return unmarshalFixed32Value + case "varint": + if pointer { + return unmarshalUint32Ptr + } + if slice { + return unmarshalUint32Slice + } + return unmarshalUint32Value + } + case reflect.Uint64: + switch encoding { + case "fixed64": + if pointer { + return unmarshalFixed64Ptr + } + if slice { + return unmarshalFixed64Slice + } + return unmarshalFixed64Value + case "varint": + if pointer { + return unmarshalUint64Ptr + } + if slice { + return unmarshalUint64Slice + } + return unmarshalUint64Value + } + case reflect.Float32: + if pointer { + return unmarshalFloat32Ptr + } + if slice { + return unmarshalFloat32Slice + } + return unmarshalFloat32Value + case reflect.Float64: + if pointer { + return unmarshalFloat64Ptr + } + if slice { + return unmarshalFloat64Slice + } + return unmarshalFloat64Value + case reflect.Map: + panic("map type in typeUnmarshaler in " + t.Name()) + case reflect.Slice: + if pointer { + panic("bad pointer in slice case in " + t.Name()) + } + if slice { + return unmarshalBytesSlice + } + return unmarshalBytesValue + case reflect.String: + if pointer { + return unmarshalStringPtr + } + if slice { + return unmarshalStringSlice + } + return unmarshalStringValue + case reflect.Struct: + // message or group field + if !pointer { + panic(fmt.Sprintf("message/group field %s:%s without pointer", t, encoding)) + } + switch encoding { + case "bytes": + if slice { + return makeUnmarshalMessageSlicePtr(getUnmarshalInfo(t), name) + } + return makeUnmarshalMessagePtr(getUnmarshalInfo(t), name) + case "group": + if slice { + return makeUnmarshalGroupSlicePtr(getUnmarshalInfo(t), name) + } + return makeUnmarshalGroupPtr(getUnmarshalInfo(t), name) + } + } + panic(fmt.Sprintf("unmarshaler not found type:%s encoding:%s", t, encoding)) +} + +// Below are all the unmarshalers for individual fields of various types. + +func unmarshalInt64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + *f.toInt64() = v + return b, nil +} + +func unmarshalInt64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + *f.toInt64Ptr() = &v + return b, nil +} + +func unmarshalInt64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + s := f.toInt64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + s := f.toInt64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalSint64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + *f.toInt64() = v + return b, nil +} + +func unmarshalSint64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + *f.toInt64Ptr() = &v + return b, nil +} + +func unmarshalSint64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + s := f.toInt64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + s := f.toInt64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalUint64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + *f.toUint64() = v + return b, nil +} + +func unmarshalUint64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + *f.toUint64Ptr() = &v + return b, nil +} + +func unmarshalUint64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + s := f.toUint64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + s := f.toUint64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalInt32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + *f.toInt32() = v + return b, nil +} + +func unmarshalInt32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.setInt32Ptr(v) + return b, nil +} + +func unmarshalInt32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.appendInt32Slice(v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.appendInt32Slice(v) + return b, nil +} + +func unmarshalSint32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + *f.toInt32() = v + return b, nil +} + +func unmarshalSint32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.setInt32Ptr(v) + return b, nil +} + +func unmarshalSint32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.appendInt32Slice(v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.appendInt32Slice(v) + return b, nil +} + +func unmarshalUint32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + *f.toUint32() = v + return b, nil +} + +func unmarshalUint32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + *f.toUint32Ptr() = &v + return b, nil +} + +func unmarshalUint32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + s := f.toUint32Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + s := f.toUint32Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalFixed64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + *f.toUint64() = v + return b[8:], nil +} + +func unmarshalFixed64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + *f.toUint64Ptr() = &v + return b[8:], nil +} + +func unmarshalFixed64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + s := f.toUint64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + s := f.toUint64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFixedS64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + *f.toInt64() = v + return b[8:], nil +} + +func unmarshalFixedS64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + *f.toInt64Ptr() = &v + return b[8:], nil +} + +func unmarshalFixedS64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + s := f.toInt64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + s := f.toInt64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFixed32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + *f.toUint32() = v + return b[4:], nil +} + +func unmarshalFixed32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + *f.toUint32Ptr() = &v + return b[4:], nil +} + +func unmarshalFixed32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + s := f.toUint32Slice() + *s = append(*s, v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + s := f.toUint32Slice() + *s = append(*s, v) + return b[4:], nil +} + +func unmarshalFixedS32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + *f.toInt32() = v + return b[4:], nil +} + +func unmarshalFixedS32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.setInt32Ptr(v) + return b[4:], nil +} + +func unmarshalFixedS32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.appendInt32Slice(v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.appendInt32Slice(v) + return b[4:], nil +} + +func unmarshalBoolValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + // Note: any length varint is allowed, even though any sane + // encoder will use one byte. + // See https://github.com/golang/protobuf/issues/76 + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + // TODO: check if x>1? Tests seem to indicate no. + v := x != 0 + *f.toBool() = v + return b[n:], nil +} + +func unmarshalBoolPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + *f.toBoolPtr() = &v + return b[n:], nil +} + +func unmarshalBoolSlice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + s := f.toBoolSlice() + *s = append(*s, v) + b = b[n:] + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + s := f.toBoolSlice() + *s = append(*s, v) + return b[n:], nil +} + +func unmarshalFloat64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + *f.toFloat64() = v + return b[8:], nil +} + +func unmarshalFloat64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + *f.toFloat64Ptr() = &v + return b[8:], nil +} + +func unmarshalFloat64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + s := f.toFloat64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + s := f.toFloat64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFloat32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + *f.toFloat32() = v + return b[4:], nil +} + +func unmarshalFloat32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + *f.toFloat32Ptr() = &v + return b[4:], nil +} + +func unmarshalFloat32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + s := f.toFloat32Slice() + *s = append(*s, v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + s := f.toFloat32Slice() + *s = append(*s, v) + return b[4:], nil +} + +func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + *f.toString() = v + return b[x:], nil +} + +func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + *f.toStringPtr() = &v + return b[x:], nil +} + +func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + s := f.toStringSlice() + *s = append(*s, v) + return b[x:], nil +} + +var emptyBuf [0]byte + +func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + // The use of append here is a trick which avoids the zeroing + // that would be required if we used a make/copy pair. + // We append to emptyBuf instead of nil because we want + // a non-nil result even when the length is 0. + v := append(emptyBuf[:], b[:x]...) + *f.toBytes() = v + return b[x:], nil +} + +func unmarshalBytesSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := append(emptyBuf[:], b[:x]...) + s := f.toBytesSlice() + *s = append(*s, v) + return b[x:], nil +} + +func makeUnmarshalMessagePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + // First read the message field to see if something is there. + // The semantics of multiple submessages are weird. Instead of + // the last one winning (as it is for all other fields), multiple + // submessages are merged. + v := f.getPointer() + if v.isNil() { + v = valToPointer(reflect.New(sub.typ)) + f.setPointer(v) + } + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + return b[x:], err + } +} + +func makeUnmarshalMessageSlicePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := valToPointer(reflect.New(sub.typ)) + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + f.appendPointer(v) + return b[x:], err + } +} + +func makeUnmarshalGroupPtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireStartGroup { + return b, errInternalBadWireType + } + x, y := findEndGroup(b) + if x < 0 { + return nil, io.ErrUnexpectedEOF + } + v := f.getPointer() + if v.isNil() { + v = valToPointer(reflect.New(sub.typ)) + f.setPointer(v) + } + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + return b[y:], err + } +} + +func makeUnmarshalGroupSlicePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireStartGroup { + return b, errInternalBadWireType + } + x, y := findEndGroup(b) + if x < 0 { + return nil, io.ErrUnexpectedEOF + } + v := valToPointer(reflect.New(sub.typ)) + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + f.appendPointer(v) + return b[y:], err + } +} + +func makeUnmarshalMap(f *reflect.StructField) unmarshaler { + t := f.Type + kt := t.Key() + vt := t.Elem() + unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key")) + unmarshalVal := typeUnmarshaler(vt, f.Tag.Get("protobuf_val")) + return func(b []byte, f pointer, w int) ([]byte, error) { + // The map entry is a submessage. Figure out how big it is. + if w != WireBytes { + return nil, fmt.Errorf("proto: bad wiretype for map field: got %d want %d", w, WireBytes) + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + r := b[x:] // unused data to return + b = b[:x] // data for map entry + + // Note: we could use #keys * #values ~= 200 functions + // to do map decoding without reflection. Probably not worth it. + // Maps will be somewhat slow. Oh well. + + // Read key and value from data. + k := reflect.New(kt) + v := reflect.New(vt) + for len(b) > 0 { + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + wire := int(x) & 7 + b = b[n:] + + var err error + switch x >> 3 { + case 1: + b, err = unmarshalKey(b, valToPointer(k), wire) + case 2: + b, err = unmarshalVal(b, valToPointer(v), wire) + default: + err = errInternalBadWireType // skip unknown tag + } + + if err == nil { + continue + } + if err != errInternalBadWireType { + return nil, err + } + + // Skip past unknown fields. + b, err = skipField(b, wire) + if err != nil { + return nil, err + } + } + + // Get map, allocate if needed. + m := f.asPointerTo(t).Elem() // an addressable map[K]T + if m.IsNil() { + m.Set(reflect.MakeMap(t)) + } + + // Insert into map. + m.SetMapIndex(k.Elem(), v.Elem()) + + return r, nil + } +} + +// makeUnmarshalOneof makes an unmarshaler for oneof fields. +// for: +// message Msg { +// oneof F { +// int64 X = 1; +// float64 Y = 2; +// } +// } +// typ is the type of the concrete entry for a oneof case (e.g. Msg_X). +// ityp is the interface type of the oneof field (e.g. isMsg_F). +// unmarshal is the unmarshaler for the base type of the oneof case (e.g. int64). +// Note that this function will be called once for each case in the oneof. +func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshaler { + sf := typ.Field(0) + field0 := toField(&sf) + return func(b []byte, f pointer, w int) ([]byte, error) { + // Allocate holder for value. + v := reflect.New(typ) + + // Unmarshal data into holder. + // We unmarshal into the first field of the holder object. + var err error + b, err = unmarshal(b, valToPointer(v).offset(field0), w) + if err != nil { + return nil, err + } + + // Write pointer to holder into target field. + f.asPointerTo(ityp).Elem().Set(v) + + return b, nil + } +} + +// Error used by decode internally. +var errInternalBadWireType = errors.New("proto: internal error: bad wiretype") + +// skipField skips past a field of type wire and returns the remaining bytes. +func skipField(b []byte, wire int) ([]byte, error) { + switch wire { + case WireVarint: + _, k := decodeVarint(b) + if k == 0 { + return b, io.ErrUnexpectedEOF + } + b = b[k:] + case WireFixed32: + if len(b) < 4 { + return b, io.ErrUnexpectedEOF + } + b = b[4:] + case WireFixed64: + if len(b) < 8 { + return b, io.ErrUnexpectedEOF + } + b = b[8:] + case WireBytes: + m, k := decodeVarint(b) + if k == 0 || uint64(len(b)-k) < m { + return b, io.ErrUnexpectedEOF + } + b = b[uint64(k)+m:] + case WireStartGroup: + _, i := findEndGroup(b) + if i == -1 { + return b, io.ErrUnexpectedEOF + } + b = b[i:] + default: + return b, fmt.Errorf("proto: can't skip unknown wire type %d", wire) + } + return b, nil +} + +// findEndGroup finds the index of the next EndGroup tag. +// Groups may be nested, so the "next" EndGroup tag is the first +// unpaired EndGroup. +// findEndGroup returns the indexes of the start and end of the EndGroup tag. +// Returns (-1,-1) if it can't find one. +func findEndGroup(b []byte) (int, int) { + depth := 1 + i := 0 + for { + x, n := decodeVarint(b[i:]) + if n == 0 { + return -1, -1 + } + j := i + i += n + switch x & 7 { + case WireVarint: + _, k := decodeVarint(b[i:]) + if k == 0 { + return -1, -1 + } + i += k + case WireFixed32: + if len(b)-4 < i { + return -1, -1 + } + i += 4 + case WireFixed64: + if len(b)-8 < i { + return -1, -1 + } + i += 8 + case WireBytes: + m, k := decodeVarint(b[i:]) + if k == 0 { + return -1, -1 + } + i += k + if uint64(len(b)-i) < m { + return -1, -1 + } + i += int(m) + case WireStartGroup: + depth++ + case WireEndGroup: + depth-- + if depth == 0 { + return j, i + } + default: + return -1, -1 + } + } +} + +// encodeVarint appends a varint-encoded integer to b and returns the result. +func encodeVarint(b []byte, x uint64) []byte { + for x >= 1<<7 { + b = append(b, byte(x&0x7f|0x80)) + x >>= 7 + } + return append(b, byte(x)) +} + +// decodeVarint reads a varint-encoded integer from b. +// Returns the decoded integer and the number of bytes read. +// If there is an error, it returns 0,0. +func decodeVarint(b []byte) (uint64, int) { + var x, y uint64 + if len(b) <= 0 { + goto bad + } + x = uint64(b[0]) + if x < 0x80 { + return x, 1 + } + x -= 0x80 + + if len(b) <= 1 { + goto bad + } + y = uint64(b[1]) + x += y << 7 + if y < 0x80 { + return x, 2 + } + x -= 0x80 << 7 + + if len(b) <= 2 { + goto bad + } + y = uint64(b[2]) + x += y << 14 + if y < 0x80 { + return x, 3 + } + x -= 0x80 << 14 + + if len(b) <= 3 { + goto bad + } + y = uint64(b[3]) + x += y << 21 + if y < 0x80 { + return x, 4 + } + x -= 0x80 << 21 + + if len(b) <= 4 { + goto bad + } + y = uint64(b[4]) + x += y << 28 + if y < 0x80 { + return x, 5 + } + x -= 0x80 << 28 + + if len(b) <= 5 { + goto bad + } + y = uint64(b[5]) + x += y << 35 + if y < 0x80 { + return x, 6 + } + x -= 0x80 << 35 + + if len(b) <= 6 { + goto bad + } + y = uint64(b[6]) + x += y << 42 + if y < 0x80 { + return x, 7 + } + x -= 0x80 << 42 + + if len(b) <= 7 { + goto bad + } + y = uint64(b[7]) + x += y << 49 + if y < 0x80 { + return x, 8 + } + x -= 0x80 << 49 + + if len(b) <= 8 { + goto bad + } + y = uint64(b[8]) + x += y << 56 + if y < 0x80 { + return x, 9 + } + x -= 0x80 << 56 + + if len(b) <= 9 { + goto bad + } + y = uint64(b[9]) + x += y << 63 + if y < 2 { + return x, 10 + } + +bad: + return 0, 0 +} diff --git a/vendor/github.com/golang/protobuf/proto/text.go b/vendor/github.com/golang/protobuf/proto/text.go index 965876bf033..2205fdaadf8 100644 --- a/vendor/github.com/golang/protobuf/proto/text.go +++ b/vendor/github.com/golang/protobuf/proto/text.go @@ -50,7 +50,6 @@ import ( var ( newline = []byte("\n") spaces = []byte(" ") - gtNewline = []byte(">\n") endBraceNewline = []byte("}\n") backslashN = []byte{'\\', 'n'} backslashR = []byte{'\\', 'r'} @@ -170,11 +169,6 @@ func writeName(w *textWriter, props *Properties) error { return nil } -// raw is the interface satisfied by RawMessage. -type raw interface { - Bytes() []byte -} - func requiresQuotes(u string) bool { // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted. for _, ch := range u { @@ -269,6 +263,10 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { props := sprops.Prop[i] name := st.Field(i).Name + if name == "XXX_NoUnkeyedLiteral" { + continue + } + if strings.HasPrefix(name, "XXX_") { // There are two XXX_ fields: // XXX_unrecognized []byte @@ -436,12 +434,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { return err } } - if b, ok := fv.Interface().(raw); ok { - if err := writeRaw(w, b.Bytes()); err != nil { - return err - } - continue - } // Enums have a String method, so writeAny will work fine. if err := tm.writeAny(w, fv, props); err != nil { @@ -455,7 +447,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { // Extensions (the XXX_extensions field). pv := sv.Addr() - if _, ok := extendable(pv.Interface()); ok { + if _, err := extendable(pv.Interface()); err == nil { if err := tm.writeExtensions(w, pv); err != nil { return err } @@ -464,27 +456,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { return nil } -// writeRaw writes an uninterpreted raw message. -func writeRaw(w *textWriter, b []byte) error { - if err := w.WriteByte('<'); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte('\n'); err != nil { - return err - } - } - w.indent() - if err := writeUnknownStruct(w, b); err != nil { - return err - } - w.unindent() - if err := w.WriteByte('>'); err != nil { - return err - } - return nil -} - // writeAny writes an arbitrary field. func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { v = reflect.Indirect(v) @@ -535,6 +506,19 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert } } w.indent() + if v.CanAddr() { + // Calling v.Interface on a struct causes the reflect package to + // copy the entire struct. This is racy with the new Marshaler + // since we atomically update the XXX_sizecache. + // + // Thus, we retrieve a pointer to the struct if possible to avoid + // a race since v.Interface on the pointer doesn't copy the struct. + // + // If v is not addressable, then we are not worried about a race + // since it implies that the binary Marshaler cannot possibly be + // mutating this value. + v = v.Addr() + } if etm, ok := v.Interface().(encoding.TextMarshaler); ok { text, err := etm.MarshalText() if err != nil { @@ -543,8 +527,13 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert if _, err = w.Write(text); err != nil { return err } - } else if err := tm.writeStruct(w, v); err != nil { - return err + } else { + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + if err := tm.writeStruct(w, v); err != nil { + return err + } } w.unindent() if err := w.WriteByte(ket); err != nil { diff --git a/vendor/github.com/golang/protobuf/proto/text_parser.go b/vendor/github.com/golang/protobuf/proto/text_parser.go index 5e14513f28c..0685bae36d5 100644 --- a/vendor/github.com/golang/protobuf/proto/text_parser.go +++ b/vendor/github.com/golang/protobuf/proto/text_parser.go @@ -206,7 +206,6 @@ func (p *textParser) advance() { var ( errBadUTF8 = errors.New("proto: bad UTF-8") - errBadHex = errors.New("proto: bad hexadecimal") ) func unquoteC(s string, quote rune) (string, error) { @@ -277,60 +276,47 @@ func unescape(s string) (ch string, tail string, err error) { return "?", s, nil // trigraph workaround case '\'', '"', '\\': return string(r), s, nil - case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X': + case '0', '1', '2', '3', '4', '5', '6', '7': if len(s) < 2 { return "", "", fmt.Errorf(`\%c requires 2 following digits`, r) } - base := 8 - ss := s[:2] + ss := string(r) + s[:2] s = s[2:] - if r == 'x' || r == 'X' { - base = 16 - } else { - ss = string(r) + ss - } - i, err := strconv.ParseUint(ss, base, 8) + i, err := strconv.ParseUint(ss, 8, 8) if err != nil { - return "", "", err + return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss) } return string([]byte{byte(i)}), s, nil - case 'u', 'U': - n := 4 - if r == 'U' { + case 'x', 'X', 'u', 'U': + var n int + switch r { + case 'x', 'X': + n = 2 + case 'u': + n = 4 + case 'U': n = 8 } if len(s) < n { - return "", "", fmt.Errorf(`\%c requires %d digits`, r, n) - } - - bs := make([]byte, n/2) - for i := 0; i < n; i += 2 { - a, ok1 := unhex(s[i]) - b, ok2 := unhex(s[i+1]) - if !ok1 || !ok2 { - return "", "", errBadHex - } - bs[i/2] = a<<4 | b + return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n) } + ss := s[:n] s = s[n:] - return string(bs), s, nil + i, err := strconv.ParseUint(ss, 16, 64) + if err != nil { + return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss) + } + if r == 'x' || r == 'X' { + return string([]byte{byte(i)}), s, nil + } + if i > utf8.MaxRune { + return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss) + } + return string(i), s, nil } return "", "", fmt.Errorf(`unknown escape \%c`, r) } -// Adapted from src/pkg/strconv/quote.go. -func unhex(b byte) (v byte, ok bool) { - switch { - case '0' <= b && b <= '9': - return b - '0', true - case 'a' <= b && b <= 'f': - return b - 'a' + 10, true - case 'A' <= b && b <= 'F': - return b - 'A' + 10, true - } - return 0, false -} - // Back off the parser by one token. Can only be done between calls to next(). // It makes the next advance() a no-op. func (p *textParser) back() { p.backed = true } @@ -728,6 +714,9 @@ func (p *textParser) consumeExtName() (string, error) { if tok.err != nil { return "", p.errorf("unrecognized type_url or extension name: %s", tok.err) } + if p.done && tok.value != "]" { + return "", p.errorf("unclosed type_url or extension name") + } } return strings.Join(parts, ""), nil } @@ -865,7 +854,7 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error { return p.readStruct(fv, terminator) case reflect.Uint32: if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil { - fv.SetUint(x) + fv.SetUint(uint64(x)) return nil } case reflect.Uint64: @@ -883,13 +872,9 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error { // UnmarshalText returns *RequiredNotSetError. func UnmarshalText(s string, pb Message) error { if um, ok := pb.(encoding.TextUnmarshaler); ok { - err := um.UnmarshalText([]byte(s)) - return err + return um.UnmarshalText([]byte(s)) } pb.Reset() v := reflect.ValueOf(pb) - if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil { - return pe - } - return nil + return newTextParser(s).readStruct(v.Elem(), "") } diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile deleted file mode 100644 index f706871a6fa..00000000000 --- a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# Go support for Protocol Buffers - Google's data interchange format -# -# Copyright 2010 The Go Authors. All rights reserved. -# https://github.com/golang/protobuf -# -# 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. - -# Not stored here, but descriptor.proto is in https://github.com/google/protobuf/ -# at src/google/protobuf/descriptor.proto -regenerate: - @echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION - cp $(HOME)/src/protobuf/include/google/protobuf/descriptor.proto . - protoc --go_out=../../../../.. -I$(HOME)/src/protobuf/include $(HOME)/src/protobuf/include/google/protobuf/descriptor.proto diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go index c6a91bcab9c..9e029e8cb44 100644 --- a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go @@ -1,35 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // source: google/protobuf/descriptor.proto -/* -Package descriptor is a generated protocol buffer package. - -It is generated from these files: - google/protobuf/descriptor.proto - -It has these top-level messages: - FileDescriptorSet - FileDescriptorProto - DescriptorProto - ExtensionRangeOptions - FieldDescriptorProto - OneofDescriptorProto - EnumDescriptorProto - EnumValueDescriptorProto - ServiceDescriptorProto - MethodDescriptorProto - FileOptions - MessageOptions - FieldOptions - OneofOptions - EnumOptions - EnumValueOptions - ServiceOptions - MethodOptions - UninterpretedOption - SourceCodeInfo - GeneratedCodeInfo -*/ package descriptor import proto "github.com/golang/protobuf/proto" @@ -138,7 +109,9 @@ func (x *FieldDescriptorProto_Type) UnmarshalJSON(data []byte) error { *x = FieldDescriptorProto_Type(value) return nil } -func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{4, 0} } +func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{4, 0} +} type FieldDescriptorProto_Label int32 @@ -177,7 +150,7 @@ func (x *FieldDescriptorProto_Label) UnmarshalJSON(data []byte) error { return nil } func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{4, 1} + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{4, 1} } // Generated classes can be optimized for speed or code size. @@ -217,7 +190,9 @@ func (x *FileOptions_OptimizeMode) UnmarshalJSON(data []byte) error { *x = FileOptions_OptimizeMode(value) return nil } -func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{10, 0} } +func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{10, 0} +} type FieldOptions_CType int32 @@ -255,7 +230,9 @@ func (x *FieldOptions_CType) UnmarshalJSON(data []byte) error { *x = FieldOptions_CType(value) return nil } -func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 0} } +func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{12, 0} +} type FieldOptions_JSType int32 @@ -295,7 +272,9 @@ func (x *FieldOptions_JSType) UnmarshalJSON(data []byte) error { *x = FieldOptions_JSType(value) return nil } -func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 1} } +func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{12, 1} +} // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, // or neither? HTTP based RPC implementation may choose GET verb for safe @@ -336,20 +315,41 @@ func (x *MethodOptions_IdempotencyLevel) UnmarshalJSON(data []byte) error { return nil } func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{17, 0} + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{17, 0} } // The protocol compiler can output a FileDescriptorSet containing the .proto // files it parses. type FileDescriptorSet struct { - File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file" json:"file,omitempty"` - XXX_unrecognized []byte `json:"-"` + File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file" json:"file,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *FileDescriptorSet) Reset() { *m = FileDescriptorSet{} } -func (m *FileDescriptorSet) String() string { return proto.CompactTextString(m) } -func (*FileDescriptorSet) ProtoMessage() {} -func (*FileDescriptorSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (m *FileDescriptorSet) Reset() { *m = FileDescriptorSet{} } +func (m *FileDescriptorSet) String() string { return proto.CompactTextString(m) } +func (*FileDescriptorSet) ProtoMessage() {} +func (*FileDescriptorSet) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{0} +} +func (m *FileDescriptorSet) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FileDescriptorSet.Unmarshal(m, b) +} +func (m *FileDescriptorSet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FileDescriptorSet.Marshal(b, m, deterministic) +} +func (dst *FileDescriptorSet) XXX_Merge(src proto.Message) { + xxx_messageInfo_FileDescriptorSet.Merge(dst, src) +} +func (m *FileDescriptorSet) XXX_Size() int { + return xxx_messageInfo_FileDescriptorSet.Size(m) +} +func (m *FileDescriptorSet) XXX_DiscardUnknown() { + xxx_messageInfo_FileDescriptorSet.DiscardUnknown(m) +} + +var xxx_messageInfo_FileDescriptorSet proto.InternalMessageInfo func (m *FileDescriptorSet) GetFile() []*FileDescriptorProto { if m != nil { @@ -382,14 +382,35 @@ type FileDescriptorProto struct { SourceCodeInfo *SourceCodeInfo `protobuf:"bytes,9,opt,name=source_code_info,json=sourceCodeInfo" json:"source_code_info,omitempty"` // The syntax of the proto file. // The supported values are "proto2" and "proto3". - Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"` - XXX_unrecognized []byte `json:"-"` + Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *FileDescriptorProto) Reset() { *m = FileDescriptorProto{} } -func (m *FileDescriptorProto) String() string { return proto.CompactTextString(m) } -func (*FileDescriptorProto) ProtoMessage() {} -func (*FileDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (m *FileDescriptorProto) Reset() { *m = FileDescriptorProto{} } +func (m *FileDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*FileDescriptorProto) ProtoMessage() {} +func (*FileDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{1} +} +func (m *FileDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FileDescriptorProto.Unmarshal(m, b) +} +func (m *FileDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FileDescriptorProto.Marshal(b, m, deterministic) +} +func (dst *FileDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_FileDescriptorProto.Merge(dst, src) +} +func (m *FileDescriptorProto) XXX_Size() int { + return xxx_messageInfo_FileDescriptorProto.Size(m) +} +func (m *FileDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_FileDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_FileDescriptorProto proto.InternalMessageInfo func (m *FileDescriptorProto) GetName() string { if m != nil && m.Name != nil { @@ -488,14 +509,35 @@ type DescriptorProto struct { ReservedRange []*DescriptorProto_ReservedRange `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"` // Reserved field names, which may not be used by fields in the same message. // A given name may only be reserved once. - ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"` - XXX_unrecognized []byte `json:"-"` + ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *DescriptorProto) Reset() { *m = DescriptorProto{} } -func (m *DescriptorProto) String() string { return proto.CompactTextString(m) } -func (*DescriptorProto) ProtoMessage() {} -func (*DescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (m *DescriptorProto) Reset() { *m = DescriptorProto{} } +func (m *DescriptorProto) String() string { return proto.CompactTextString(m) } +func (*DescriptorProto) ProtoMessage() {} +func (*DescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{2} +} +func (m *DescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DescriptorProto.Unmarshal(m, b) +} +func (m *DescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DescriptorProto.Marshal(b, m, deterministic) +} +func (dst *DescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_DescriptorProto.Merge(dst, src) +} +func (m *DescriptorProto) XXX_Size() int { + return xxx_messageInfo_DescriptorProto.Size(m) +} +func (m *DescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_DescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_DescriptorProto proto.InternalMessageInfo func (m *DescriptorProto) GetName() string { if m != nil && m.Name != nil { @@ -568,18 +610,37 @@ func (m *DescriptorProto) GetReservedName() []string { } type DescriptorProto_ExtensionRange struct { - Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` - End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` - Options *ExtensionRangeOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` - XXX_unrecognized []byte `json:"-"` + Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` + End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` + Options *ExtensionRangeOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *DescriptorProto_ExtensionRange) Reset() { *m = DescriptorProto_ExtensionRange{} } func (m *DescriptorProto_ExtensionRange) String() string { return proto.CompactTextString(m) } func (*DescriptorProto_ExtensionRange) ProtoMessage() {} func (*DescriptorProto_ExtensionRange) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{2, 0} + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{2, 0} } +func (m *DescriptorProto_ExtensionRange) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DescriptorProto_ExtensionRange.Unmarshal(m, b) +} +func (m *DescriptorProto_ExtensionRange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DescriptorProto_ExtensionRange.Marshal(b, m, deterministic) +} +func (dst *DescriptorProto_ExtensionRange) XXX_Merge(src proto.Message) { + xxx_messageInfo_DescriptorProto_ExtensionRange.Merge(dst, src) +} +func (m *DescriptorProto_ExtensionRange) XXX_Size() int { + return xxx_messageInfo_DescriptorProto_ExtensionRange.Size(m) +} +func (m *DescriptorProto_ExtensionRange) XXX_DiscardUnknown() { + xxx_messageInfo_DescriptorProto_ExtensionRange.DiscardUnknown(m) +} + +var xxx_messageInfo_DescriptorProto_ExtensionRange proto.InternalMessageInfo func (m *DescriptorProto_ExtensionRange) GetStart() int32 { if m != nil && m.Start != nil { @@ -606,17 +667,36 @@ func (m *DescriptorProto_ExtensionRange) GetOptions() *ExtensionRangeOptions { // fields or extension ranges in the same message. Reserved ranges may // not overlap. type DescriptorProto_ReservedRange struct { - Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` - End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` - XXX_unrecognized []byte `json:"-"` + Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` + End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *DescriptorProto_ReservedRange) Reset() { *m = DescriptorProto_ReservedRange{} } func (m *DescriptorProto_ReservedRange) String() string { return proto.CompactTextString(m) } func (*DescriptorProto_ReservedRange) ProtoMessage() {} func (*DescriptorProto_ReservedRange) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{2, 1} + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{2, 1} } +func (m *DescriptorProto_ReservedRange) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DescriptorProto_ReservedRange.Unmarshal(m, b) +} +func (m *DescriptorProto_ReservedRange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DescriptorProto_ReservedRange.Marshal(b, m, deterministic) +} +func (dst *DescriptorProto_ReservedRange) XXX_Merge(src proto.Message) { + xxx_messageInfo_DescriptorProto_ReservedRange.Merge(dst, src) +} +func (m *DescriptorProto_ReservedRange) XXX_Size() int { + return xxx_messageInfo_DescriptorProto_ReservedRange.Size(m) +} +func (m *DescriptorProto_ReservedRange) XXX_DiscardUnknown() { + xxx_messageInfo_DescriptorProto_ReservedRange.DiscardUnknown(m) +} + +var xxx_messageInfo_DescriptorProto_ReservedRange proto.InternalMessageInfo func (m *DescriptorProto_ReservedRange) GetStart() int32 { if m != nil && m.Start != nil { @@ -635,22 +715,43 @@ func (m *DescriptorProto_ReservedRange) GetEnd() int32 { type ExtensionRangeOptions struct { // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` proto.XXX_InternalExtensions `json:"-"` XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *ExtensionRangeOptions) Reset() { *m = ExtensionRangeOptions{} } -func (m *ExtensionRangeOptions) String() string { return proto.CompactTextString(m) } -func (*ExtensionRangeOptions) ProtoMessage() {} -func (*ExtensionRangeOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (m *ExtensionRangeOptions) Reset() { *m = ExtensionRangeOptions{} } +func (m *ExtensionRangeOptions) String() string { return proto.CompactTextString(m) } +func (*ExtensionRangeOptions) ProtoMessage() {} +func (*ExtensionRangeOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{3} +} var extRange_ExtensionRangeOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*ExtensionRangeOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_ExtensionRangeOptions } +func (m *ExtensionRangeOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ExtensionRangeOptions.Unmarshal(m, b) +} +func (m *ExtensionRangeOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ExtensionRangeOptions.Marshal(b, m, deterministic) +} +func (dst *ExtensionRangeOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtensionRangeOptions.Merge(dst, src) +} +func (m *ExtensionRangeOptions) XXX_Size() int { + return xxx_messageInfo_ExtensionRangeOptions.Size(m) +} +func (m *ExtensionRangeOptions) XXX_DiscardUnknown() { + xxx_messageInfo_ExtensionRangeOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_ExtensionRangeOptions proto.InternalMessageInfo func (m *ExtensionRangeOptions) GetUninterpretedOption() []*UninterpretedOption { if m != nil { @@ -689,15 +790,36 @@ type FieldDescriptorProto struct { // user has set a "json_name" option on this field, that option's value // will be used. Otherwise, it's deduced from the field's name by converting // it to camelCase. - JsonName *string `protobuf:"bytes,10,opt,name=json_name,json=jsonName" json:"json_name,omitempty"` - Options *FieldOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` - XXX_unrecognized []byte `json:"-"` + JsonName *string `protobuf:"bytes,10,opt,name=json_name,json=jsonName" json:"json_name,omitempty"` + Options *FieldOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} } -func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) } -func (*FieldDescriptorProto) ProtoMessage() {} -func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} } +func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*FieldDescriptorProto) ProtoMessage() {} +func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{4} +} +func (m *FieldDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FieldDescriptorProto.Unmarshal(m, b) +} +func (m *FieldDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FieldDescriptorProto.Marshal(b, m, deterministic) +} +func (dst *FieldDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_FieldDescriptorProto.Merge(dst, src) +} +func (m *FieldDescriptorProto) XXX_Size() int { + return xxx_messageInfo_FieldDescriptorProto.Size(m) +} +func (m *FieldDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_FieldDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_FieldDescriptorProto proto.InternalMessageInfo func (m *FieldDescriptorProto) GetName() string { if m != nil && m.Name != nil { @@ -771,15 +893,36 @@ func (m *FieldDescriptorProto) GetOptions() *FieldOptions { // Describes a oneof. type OneofDescriptorProto struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Options *OneofOptions `protobuf:"bytes,2,opt,name=options" json:"options,omitempty"` - XXX_unrecognized []byte `json:"-"` + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Options *OneofOptions `protobuf:"bytes,2,opt,name=options" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} } -func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) } -func (*OneofDescriptorProto) ProtoMessage() {} -func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} } +func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*OneofDescriptorProto) ProtoMessage() {} +func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{5} +} +func (m *OneofDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OneofDescriptorProto.Unmarshal(m, b) +} +func (m *OneofDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OneofDescriptorProto.Marshal(b, m, deterministic) +} +func (dst *OneofDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_OneofDescriptorProto.Merge(dst, src) +} +func (m *OneofDescriptorProto) XXX_Size() int { + return xxx_messageInfo_OneofDescriptorProto.Size(m) +} +func (m *OneofDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_OneofDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_OneofDescriptorProto proto.InternalMessageInfo func (m *OneofDescriptorProto) GetName() string { if m != nil && m.Name != nil { @@ -797,16 +940,44 @@ func (m *OneofDescriptorProto) GetOptions() *OneofOptions { // Describes an enum type. type EnumDescriptorProto struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` - Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` - XXX_unrecognized []byte `json:"-"` + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` + Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + // Range of reserved numeric values. Reserved numeric values may not be used + // by enum values in the same enum declaration. Reserved ranges may not + // overlap. + ReservedRange []*EnumDescriptorProto_EnumReservedRange `protobuf:"bytes,4,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"` + // Reserved enum value names, which may not be reused. A given name may only + // be reserved once. + ReservedName []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} } -func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) } -func (*EnumDescriptorProto) ProtoMessage() {} -func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} } +func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*EnumDescriptorProto) ProtoMessage() {} +func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{6} +} +func (m *EnumDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EnumDescriptorProto.Unmarshal(m, b) +} +func (m *EnumDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EnumDescriptorProto.Marshal(b, m, deterministic) +} +func (dst *EnumDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_EnumDescriptorProto.Merge(dst, src) +} +func (m *EnumDescriptorProto) XXX_Size() int { + return xxx_messageInfo_EnumDescriptorProto.Size(m) +} +func (m *EnumDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_EnumDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_EnumDescriptorProto proto.InternalMessageInfo func (m *EnumDescriptorProto) GetName() string { if m != nil && m.Name != nil { @@ -829,18 +1000,105 @@ func (m *EnumDescriptorProto) GetOptions() *EnumOptions { return nil } -// Describes a value within an enum. -type EnumValueDescriptorProto struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Number *int32 `protobuf:"varint,2,opt,name=number" json:"number,omitempty"` - Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` - XXX_unrecognized []byte `json:"-"` +func (m *EnumDescriptorProto) GetReservedRange() []*EnumDescriptorProto_EnumReservedRange { + if m != nil { + return m.ReservedRange + } + return nil } -func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} } -func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) } -func (*EnumValueDescriptorProto) ProtoMessage() {} -func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (m *EnumDescriptorProto) GetReservedName() []string { + if m != nil { + return m.ReservedName + } + return nil +} + +// Range of reserved numeric values. Reserved values may not be used by +// entries in the same enum. Reserved ranges may not overlap. +// +// Note that this is distinct from DescriptorProto.ReservedRange in that it +// is inclusive such that it can appropriately represent the entire int32 +// domain. +type EnumDescriptorProto_EnumReservedRange struct { + Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` + End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EnumDescriptorProto_EnumReservedRange) Reset() { *m = EnumDescriptorProto_EnumReservedRange{} } +func (m *EnumDescriptorProto_EnumReservedRange) String() string { return proto.CompactTextString(m) } +func (*EnumDescriptorProto_EnumReservedRange) ProtoMessage() {} +func (*EnumDescriptorProto_EnumReservedRange) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{6, 0} +} +func (m *EnumDescriptorProto_EnumReservedRange) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EnumDescriptorProto_EnumReservedRange.Unmarshal(m, b) +} +func (m *EnumDescriptorProto_EnumReservedRange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EnumDescriptorProto_EnumReservedRange.Marshal(b, m, deterministic) +} +func (dst *EnumDescriptorProto_EnumReservedRange) XXX_Merge(src proto.Message) { + xxx_messageInfo_EnumDescriptorProto_EnumReservedRange.Merge(dst, src) +} +func (m *EnumDescriptorProto_EnumReservedRange) XXX_Size() int { + return xxx_messageInfo_EnumDescriptorProto_EnumReservedRange.Size(m) +} +func (m *EnumDescriptorProto_EnumReservedRange) XXX_DiscardUnknown() { + xxx_messageInfo_EnumDescriptorProto_EnumReservedRange.DiscardUnknown(m) +} + +var xxx_messageInfo_EnumDescriptorProto_EnumReservedRange proto.InternalMessageInfo + +func (m *EnumDescriptorProto_EnumReservedRange) GetStart() int32 { + if m != nil && m.Start != nil { + return *m.Start + } + return 0 +} + +func (m *EnumDescriptorProto_EnumReservedRange) GetEnd() int32 { + if m != nil && m.End != nil { + return *m.End + } + return 0 +} + +// Describes a value within an enum. +type EnumValueDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Number *int32 `protobuf:"varint,2,opt,name=number" json:"number,omitempty"` + Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} } +func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*EnumValueDescriptorProto) ProtoMessage() {} +func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{7} +} +func (m *EnumValueDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EnumValueDescriptorProto.Unmarshal(m, b) +} +func (m *EnumValueDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EnumValueDescriptorProto.Marshal(b, m, deterministic) +} +func (dst *EnumValueDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_EnumValueDescriptorProto.Merge(dst, src) +} +func (m *EnumValueDescriptorProto) XXX_Size() int { + return xxx_messageInfo_EnumValueDescriptorProto.Size(m) +} +func (m *EnumValueDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_EnumValueDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_EnumValueDescriptorProto proto.InternalMessageInfo func (m *EnumValueDescriptorProto) GetName() string { if m != nil && m.Name != nil { @@ -865,16 +1123,37 @@ func (m *EnumValueDescriptorProto) GetOptions() *EnumValueOptions { // Describes a service. type ServiceDescriptorProto struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method" json:"method,omitempty"` - Options *ServiceOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` - XXX_unrecognized []byte `json:"-"` + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method" json:"method,omitempty"` + Options *ServiceOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} } -func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) } -func (*ServiceDescriptorProto) ProtoMessage() {} -func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} } +func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*ServiceDescriptorProto) ProtoMessage() {} +func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{8} +} +func (m *ServiceDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ServiceDescriptorProto.Unmarshal(m, b) +} +func (m *ServiceDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ServiceDescriptorProto.Marshal(b, m, deterministic) +} +func (dst *ServiceDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_ServiceDescriptorProto.Merge(dst, src) +} +func (m *ServiceDescriptorProto) XXX_Size() int { + return xxx_messageInfo_ServiceDescriptorProto.Size(m) +} +func (m *ServiceDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_ServiceDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_ServiceDescriptorProto proto.InternalMessageInfo func (m *ServiceDescriptorProto) GetName() string { if m != nil && m.Name != nil { @@ -908,14 +1187,35 @@ type MethodDescriptorProto struct { // Identifies if client streams multiple client messages ClientStreaming *bool `protobuf:"varint,5,opt,name=client_streaming,json=clientStreaming,def=0" json:"client_streaming,omitempty"` // Identifies if server streams multiple server messages - ServerStreaming *bool `protobuf:"varint,6,opt,name=server_streaming,json=serverStreaming,def=0" json:"server_streaming,omitempty"` - XXX_unrecognized []byte `json:"-"` + ServerStreaming *bool `protobuf:"varint,6,opt,name=server_streaming,json=serverStreaming,def=0" json:"server_streaming,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} } -func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) } -func (*MethodDescriptorProto) ProtoMessage() {} -func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} } +func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*MethodDescriptorProto) ProtoMessage() {} +func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{9} +} +func (m *MethodDescriptorProto) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MethodDescriptorProto.Unmarshal(m, b) +} +func (m *MethodDescriptorProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MethodDescriptorProto.Marshal(b, m, deterministic) +} +func (dst *MethodDescriptorProto) XXX_Merge(src proto.Message) { + xxx_messageInfo_MethodDescriptorProto.Merge(dst, src) +} +func (m *MethodDescriptorProto) XXX_Size() int { + return xxx_messageInfo_MethodDescriptorProto.Size(m) +} +func (m *MethodDescriptorProto) XXX_DiscardUnknown() { + xxx_messageInfo_MethodDescriptorProto.DiscardUnknown(m) +} + +var xxx_messageInfo_MethodDescriptorProto proto.InternalMessageInfo const Default_MethodDescriptorProto_ClientStreaming bool = false const Default_MethodDescriptorProto_ServerStreaming bool = false @@ -982,7 +1282,7 @@ type FileOptions struct { // top-level extensions defined in the file. JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,json=javaMultipleFiles,def=0" json:"java_multiple_files,omitempty"` // This option does nothing. - JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"` + JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"` // Deprecated: Do not use. // If set true, then the Java2 code generator will generate code that // throws an exception whenever an attempt is made to assign a non-UTF-8 // byte sequence to a string field. @@ -1036,24 +1336,46 @@ type FileOptions struct { // is empty. When this option is empty, the package name will be used for // determining the namespace. PhpNamespace *string `protobuf:"bytes,41,opt,name=php_namespace,json=phpNamespace" json:"php_namespace,omitempty"` - // The parser stores options it doesn't recognize here. See above. + // The parser stores options it doesn't recognize here. + // See the documentation for the "Options" section above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` proto.XXX_InternalExtensions `json:"-"` XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *FileOptions) Reset() { *m = FileOptions{} } -func (m *FileOptions) String() string { return proto.CompactTextString(m) } -func (*FileOptions) ProtoMessage() {} -func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (m *FileOptions) Reset() { *m = FileOptions{} } +func (m *FileOptions) String() string { return proto.CompactTextString(m) } +func (*FileOptions) ProtoMessage() {} +func (*FileOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{10} +} var extRange_FileOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_FileOptions } +func (m *FileOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FileOptions.Unmarshal(m, b) +} +func (m *FileOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FileOptions.Marshal(b, m, deterministic) +} +func (dst *FileOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_FileOptions.Merge(dst, src) +} +func (m *FileOptions) XXX_Size() int { + return xxx_messageInfo_FileOptions.Size(m) +} +func (m *FileOptions) XXX_DiscardUnknown() { + xxx_messageInfo_FileOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_FileOptions proto.InternalMessageInfo const Default_FileOptions_JavaMultipleFiles bool = false const Default_FileOptions_JavaStringCheckUtf8 bool = false @@ -1086,6 +1408,7 @@ func (m *FileOptions) GetJavaMultipleFiles() bool { return Default_FileOptions_JavaMultipleFiles } +// Deprecated: Do not use. func (m *FileOptions) GetJavaGenerateEqualsAndHash() bool { if m != nil && m.JavaGenerateEqualsAndHash != nil { return *m.JavaGenerateEqualsAndHash @@ -1251,22 +1574,43 @@ type MessageOptions struct { MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` proto.XXX_InternalExtensions `json:"-"` XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *MessageOptions) Reset() { *m = MessageOptions{} } -func (m *MessageOptions) String() string { return proto.CompactTextString(m) } -func (*MessageOptions) ProtoMessage() {} -func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (m *MessageOptions) Reset() { *m = MessageOptions{} } +func (m *MessageOptions) String() string { return proto.CompactTextString(m) } +func (*MessageOptions) ProtoMessage() {} +func (*MessageOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{11} +} var extRange_MessageOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_MessageOptions } +func (m *MessageOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageOptions.Unmarshal(m, b) +} +func (m *MessageOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageOptions.Marshal(b, m, deterministic) +} +func (dst *MessageOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageOptions.Merge(dst, src) +} +func (m *MessageOptions) XXX_Size() int { + return xxx_messageInfo_MessageOptions.Size(m) +} +func (m *MessageOptions) XXX_DiscardUnknown() { + xxx_messageInfo_MessageOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_MessageOptions proto.InternalMessageInfo const Default_MessageOptions_MessageSetWireFormat bool = false const Default_MessageOptions_NoStandardDescriptorAccessor bool = false @@ -1369,22 +1713,43 @@ type FieldOptions struct { Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` proto.XXX_InternalExtensions `json:"-"` XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *FieldOptions) Reset() { *m = FieldOptions{} } -func (m *FieldOptions) String() string { return proto.CompactTextString(m) } -func (*FieldOptions) ProtoMessage() {} -func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (m *FieldOptions) Reset() { *m = FieldOptions{} } +func (m *FieldOptions) String() string { return proto.CompactTextString(m) } +func (*FieldOptions) ProtoMessage() {} +func (*FieldOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{12} +} var extRange_FieldOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_FieldOptions } +func (m *FieldOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FieldOptions.Unmarshal(m, b) +} +func (m *FieldOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FieldOptions.Marshal(b, m, deterministic) +} +func (dst *FieldOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_FieldOptions.Merge(dst, src) +} +func (m *FieldOptions) XXX_Size() int { + return xxx_messageInfo_FieldOptions.Size(m) +} +func (m *FieldOptions) XXX_DiscardUnknown() { + xxx_messageInfo_FieldOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_FieldOptions proto.InternalMessageInfo const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING const Default_FieldOptions_Jstype FieldOptions_JSType = FieldOptions_JS_NORMAL @@ -1444,22 +1809,43 @@ func (m *FieldOptions) GetUninterpretedOption() []*UninterpretedOption { type OneofOptions struct { // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` proto.XXX_InternalExtensions `json:"-"` XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *OneofOptions) Reset() { *m = OneofOptions{} } -func (m *OneofOptions) String() string { return proto.CompactTextString(m) } -func (*OneofOptions) ProtoMessage() {} -func (*OneofOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (m *OneofOptions) Reset() { *m = OneofOptions{} } +func (m *OneofOptions) String() string { return proto.CompactTextString(m) } +func (*OneofOptions) ProtoMessage() {} +func (*OneofOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{13} +} var extRange_OneofOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*OneofOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_OneofOptions } +func (m *OneofOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OneofOptions.Unmarshal(m, b) +} +func (m *OneofOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OneofOptions.Marshal(b, m, deterministic) +} +func (dst *OneofOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_OneofOptions.Merge(dst, src) +} +func (m *OneofOptions) XXX_Size() int { + return xxx_messageInfo_OneofOptions.Size(m) +} +func (m *OneofOptions) XXX_DiscardUnknown() { + xxx_messageInfo_OneofOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_OneofOptions proto.InternalMessageInfo func (m *OneofOptions) GetUninterpretedOption() []*UninterpretedOption { if m != nil { @@ -1479,22 +1865,43 @@ type EnumOptions struct { Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` proto.XXX_InternalExtensions `json:"-"` XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *EnumOptions) Reset() { *m = EnumOptions{} } -func (m *EnumOptions) String() string { return proto.CompactTextString(m) } -func (*EnumOptions) ProtoMessage() {} -func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (m *EnumOptions) Reset() { *m = EnumOptions{} } +func (m *EnumOptions) String() string { return proto.CompactTextString(m) } +func (*EnumOptions) ProtoMessage() {} +func (*EnumOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{14} +} var extRange_EnumOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_EnumOptions } +func (m *EnumOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EnumOptions.Unmarshal(m, b) +} +func (m *EnumOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EnumOptions.Marshal(b, m, deterministic) +} +func (dst *EnumOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_EnumOptions.Merge(dst, src) +} +func (m *EnumOptions) XXX_Size() int { + return xxx_messageInfo_EnumOptions.Size(m) +} +func (m *EnumOptions) XXX_DiscardUnknown() { + xxx_messageInfo_EnumOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_EnumOptions proto.InternalMessageInfo const Default_EnumOptions_Deprecated bool = false @@ -1527,22 +1934,43 @@ type EnumValueOptions struct { Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` proto.XXX_InternalExtensions `json:"-"` XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} } -func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) } -func (*EnumValueOptions) ProtoMessage() {} -func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} } +func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) } +func (*EnumValueOptions) ProtoMessage() {} +func (*EnumValueOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{15} +} var extRange_EnumValueOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_EnumValueOptions } +func (m *EnumValueOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EnumValueOptions.Unmarshal(m, b) +} +func (m *EnumValueOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EnumValueOptions.Marshal(b, m, deterministic) +} +func (dst *EnumValueOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_EnumValueOptions.Merge(dst, src) +} +func (m *EnumValueOptions) XXX_Size() int { + return xxx_messageInfo_EnumValueOptions.Size(m) +} +func (m *EnumValueOptions) XXX_DiscardUnknown() { + xxx_messageInfo_EnumValueOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_EnumValueOptions proto.InternalMessageInfo const Default_EnumValueOptions_Deprecated bool = false @@ -1568,22 +1996,43 @@ type ServiceOptions struct { Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` proto.XXX_InternalExtensions `json:"-"` XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *ServiceOptions) Reset() { *m = ServiceOptions{} } -func (m *ServiceOptions) String() string { return proto.CompactTextString(m) } -func (*ServiceOptions) ProtoMessage() {} -func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (m *ServiceOptions) Reset() { *m = ServiceOptions{} } +func (m *ServiceOptions) String() string { return proto.CompactTextString(m) } +func (*ServiceOptions) ProtoMessage() {} +func (*ServiceOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{16} +} var extRange_ServiceOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_ServiceOptions } +func (m *ServiceOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ServiceOptions.Unmarshal(m, b) +} +func (m *ServiceOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ServiceOptions.Marshal(b, m, deterministic) +} +func (dst *ServiceOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_ServiceOptions.Merge(dst, src) +} +func (m *ServiceOptions) XXX_Size() int { + return xxx_messageInfo_ServiceOptions.Size(m) +} +func (m *ServiceOptions) XXX_DiscardUnknown() { + xxx_messageInfo_ServiceOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_ServiceOptions proto.InternalMessageInfo const Default_ServiceOptions_Deprecated bool = false @@ -1610,22 +2059,43 @@ type MethodOptions struct { IdempotencyLevel *MethodOptions_IdempotencyLevel `protobuf:"varint,34,opt,name=idempotency_level,json=idempotencyLevel,enum=google.protobuf.MethodOptions_IdempotencyLevel,def=0" json:"idempotency_level,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` proto.XXX_InternalExtensions `json:"-"` XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *MethodOptions) Reset() { *m = MethodOptions{} } -func (m *MethodOptions) String() string { return proto.CompactTextString(m) } -func (*MethodOptions) ProtoMessage() {} -func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (m *MethodOptions) Reset() { *m = MethodOptions{} } +func (m *MethodOptions) String() string { return proto.CompactTextString(m) } +func (*MethodOptions) ProtoMessage() {} +func (*MethodOptions) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{17} +} var extRange_MethodOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_MethodOptions } +func (m *MethodOptions) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MethodOptions.Unmarshal(m, b) +} +func (m *MethodOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MethodOptions.Marshal(b, m, deterministic) +} +func (dst *MethodOptions) XXX_Merge(src proto.Message) { + xxx_messageInfo_MethodOptions.Merge(dst, src) +} +func (m *MethodOptions) XXX_Size() int { + return xxx_messageInfo_MethodOptions.Size(m) +} +func (m *MethodOptions) XXX_DiscardUnknown() { + xxx_messageInfo_MethodOptions.DiscardUnknown(m) +} + +var xxx_messageInfo_MethodOptions proto.InternalMessageInfo const Default_MethodOptions_Deprecated bool = false const Default_MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel = MethodOptions_IDEMPOTENCY_UNKNOWN @@ -1661,19 +2131,40 @@ type UninterpretedOption struct { Name []*UninterpretedOption_NamePart `protobuf:"bytes,2,rep,name=name" json:"name,omitempty"` // The value of the uninterpreted option, in whatever type the tokenizer // identified it as during parsing. Exactly one of these should be set. - IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value,json=identifierValue" json:"identifier_value,omitempty"` - PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value,json=positiveIntValue" json:"positive_int_value,omitempty"` - NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value,json=negativeIntValue" json:"negative_int_value,omitempty"` - DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value,json=doubleValue" json:"double_value,omitempty"` - StringValue []byte `protobuf:"bytes,7,opt,name=string_value,json=stringValue" json:"string_value,omitempty"` - AggregateValue *string `protobuf:"bytes,8,opt,name=aggregate_value,json=aggregateValue" json:"aggregate_value,omitempty"` - XXX_unrecognized []byte `json:"-"` + IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value,json=identifierValue" json:"identifier_value,omitempty"` + PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value,json=positiveIntValue" json:"positive_int_value,omitempty"` + NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value,json=negativeIntValue" json:"negative_int_value,omitempty"` + DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value,json=doubleValue" json:"double_value,omitempty"` + StringValue []byte `protobuf:"bytes,7,opt,name=string_value,json=stringValue" json:"string_value,omitempty"` + AggregateValue *string `protobuf:"bytes,8,opt,name=aggregate_value,json=aggregateValue" json:"aggregate_value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} } -func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) } -func (*UninterpretedOption) ProtoMessage() {} -func (*UninterpretedOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} } +func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) } +func (*UninterpretedOption) ProtoMessage() {} +func (*UninterpretedOption) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{18} +} +func (m *UninterpretedOption) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UninterpretedOption.Unmarshal(m, b) +} +func (m *UninterpretedOption) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UninterpretedOption.Marshal(b, m, deterministic) +} +func (dst *UninterpretedOption) XXX_Merge(src proto.Message) { + xxx_messageInfo_UninterpretedOption.Merge(dst, src) +} +func (m *UninterpretedOption) XXX_Size() int { + return xxx_messageInfo_UninterpretedOption.Size(m) +} +func (m *UninterpretedOption) XXX_DiscardUnknown() { + xxx_messageInfo_UninterpretedOption.DiscardUnknown(m) +} + +var xxx_messageInfo_UninterpretedOption proto.InternalMessageInfo func (m *UninterpretedOption) GetName() []*UninterpretedOption_NamePart { if m != nil { @@ -1730,17 +2221,36 @@ func (m *UninterpretedOption) GetAggregateValue() string { // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents // "foo.(bar.baz).qux". type UninterpretedOption_NamePart struct { - NamePart *string `protobuf:"bytes,1,req,name=name_part,json=namePart" json:"name_part,omitempty"` - IsExtension *bool `protobuf:"varint,2,req,name=is_extension,json=isExtension" json:"is_extension,omitempty"` - XXX_unrecognized []byte `json:"-"` + NamePart *string `protobuf:"bytes,1,req,name=name_part,json=namePart" json:"name_part,omitempty"` + IsExtension *bool `protobuf:"varint,2,req,name=is_extension,json=isExtension" json:"is_extension,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *UninterpretedOption_NamePart) Reset() { *m = UninterpretedOption_NamePart{} } func (m *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(m) } func (*UninterpretedOption_NamePart) ProtoMessage() {} func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{18, 0} + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{18, 0} } +func (m *UninterpretedOption_NamePart) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UninterpretedOption_NamePart.Unmarshal(m, b) +} +func (m *UninterpretedOption_NamePart) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UninterpretedOption_NamePart.Marshal(b, m, deterministic) +} +func (dst *UninterpretedOption_NamePart) XXX_Merge(src proto.Message) { + xxx_messageInfo_UninterpretedOption_NamePart.Merge(dst, src) +} +func (m *UninterpretedOption_NamePart) XXX_Size() int { + return xxx_messageInfo_UninterpretedOption_NamePart.Size(m) +} +func (m *UninterpretedOption_NamePart) XXX_DiscardUnknown() { + xxx_messageInfo_UninterpretedOption_NamePart.DiscardUnknown(m) +} + +var xxx_messageInfo_UninterpretedOption_NamePart proto.InternalMessageInfo func (m *UninterpretedOption_NamePart) GetNamePart() string { if m != nil && m.NamePart != nil { @@ -1802,14 +2312,35 @@ type SourceCodeInfo struct { // - Code which tries to interpret locations should probably be designed to // ignore those that it doesn't understand, as more types of locations could // be recorded in the future. - Location []*SourceCodeInfo_Location `protobuf:"bytes,1,rep,name=location" json:"location,omitempty"` - XXX_unrecognized []byte `json:"-"` + Location []*SourceCodeInfo_Location `protobuf:"bytes,1,rep,name=location" json:"location,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} } -func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) } -func (*SourceCodeInfo) ProtoMessage() {} -func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} } +func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) } +func (*SourceCodeInfo) ProtoMessage() {} +func (*SourceCodeInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{19} +} +func (m *SourceCodeInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SourceCodeInfo.Unmarshal(m, b) +} +func (m *SourceCodeInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SourceCodeInfo.Marshal(b, m, deterministic) +} +func (dst *SourceCodeInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_SourceCodeInfo.Merge(dst, src) +} +func (m *SourceCodeInfo) XXX_Size() int { + return xxx_messageInfo_SourceCodeInfo.Size(m) +} +func (m *SourceCodeInfo) XXX_DiscardUnknown() { + xxx_messageInfo_SourceCodeInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_SourceCodeInfo proto.InternalMessageInfo func (m *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location { if m != nil { @@ -1899,13 +2430,34 @@ type SourceCodeInfo_Location struct { LeadingComments *string `protobuf:"bytes,3,opt,name=leading_comments,json=leadingComments" json:"leading_comments,omitempty"` TrailingComments *string `protobuf:"bytes,4,opt,name=trailing_comments,json=trailingComments" json:"trailing_comments,omitempty"` LeadingDetachedComments []string `protobuf:"bytes,6,rep,name=leading_detached_comments,json=leadingDetachedComments" json:"leading_detached_comments,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} } -func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) } -func (*SourceCodeInfo_Location) ProtoMessage() {} -func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} } +func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} } +func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) } +func (*SourceCodeInfo_Location) ProtoMessage() {} +func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{19, 0} +} +func (m *SourceCodeInfo_Location) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SourceCodeInfo_Location.Unmarshal(m, b) +} +func (m *SourceCodeInfo_Location) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SourceCodeInfo_Location.Marshal(b, m, deterministic) +} +func (dst *SourceCodeInfo_Location) XXX_Merge(src proto.Message) { + xxx_messageInfo_SourceCodeInfo_Location.Merge(dst, src) +} +func (m *SourceCodeInfo_Location) XXX_Size() int { + return xxx_messageInfo_SourceCodeInfo_Location.Size(m) +} +func (m *SourceCodeInfo_Location) XXX_DiscardUnknown() { + xxx_messageInfo_SourceCodeInfo_Location.DiscardUnknown(m) +} + +var xxx_messageInfo_SourceCodeInfo_Location proto.InternalMessageInfo func (m *SourceCodeInfo_Location) GetPath() []int32 { if m != nil { @@ -1948,14 +2500,35 @@ func (m *SourceCodeInfo_Location) GetLeadingDetachedComments() []string { type GeneratedCodeInfo struct { // An Annotation connects some span of text in generated code to an element // of its generating .proto file. - Annotation []*GeneratedCodeInfo_Annotation `protobuf:"bytes,1,rep,name=annotation" json:"annotation,omitempty"` - XXX_unrecognized []byte `json:"-"` + Annotation []*GeneratedCodeInfo_Annotation `protobuf:"bytes,1,rep,name=annotation" json:"annotation,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *GeneratedCodeInfo) Reset() { *m = GeneratedCodeInfo{} } -func (m *GeneratedCodeInfo) String() string { return proto.CompactTextString(m) } -func (*GeneratedCodeInfo) ProtoMessage() {} -func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (m *GeneratedCodeInfo) Reset() { *m = GeneratedCodeInfo{} } +func (m *GeneratedCodeInfo) String() string { return proto.CompactTextString(m) } +func (*GeneratedCodeInfo) ProtoMessage() {} +func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{20} +} +func (m *GeneratedCodeInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GeneratedCodeInfo.Unmarshal(m, b) +} +func (m *GeneratedCodeInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GeneratedCodeInfo.Marshal(b, m, deterministic) +} +func (dst *GeneratedCodeInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_GeneratedCodeInfo.Merge(dst, src) +} +func (m *GeneratedCodeInfo) XXX_Size() int { + return xxx_messageInfo_GeneratedCodeInfo.Size(m) +} +func (m *GeneratedCodeInfo) XXX_DiscardUnknown() { + xxx_messageInfo_GeneratedCodeInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_GeneratedCodeInfo proto.InternalMessageInfo func (m *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation { if m != nil { @@ -1976,16 +2549,35 @@ type GeneratedCodeInfo_Annotation struct { // Identifies the ending offset in bytes in the generated code that // relates to the identified offset. The end offset should be one past // the last relevant byte (so the length of the text = end - begin). - End *int32 `protobuf:"varint,4,opt,name=end" json:"end,omitempty"` - XXX_unrecognized []byte `json:"-"` + End *int32 `protobuf:"varint,4,opt,name=end" json:"end,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *GeneratedCodeInfo_Annotation) Reset() { *m = GeneratedCodeInfo_Annotation{} } func (m *GeneratedCodeInfo_Annotation) String() string { return proto.CompactTextString(m) } func (*GeneratedCodeInfo_Annotation) ProtoMessage() {} func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{20, 0} + return fileDescriptor_descriptor_4df4cb5f42392df6, []int{20, 0} } +func (m *GeneratedCodeInfo_Annotation) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GeneratedCodeInfo_Annotation.Unmarshal(m, b) +} +func (m *GeneratedCodeInfo_Annotation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GeneratedCodeInfo_Annotation.Marshal(b, m, deterministic) +} +func (dst *GeneratedCodeInfo_Annotation) XXX_Merge(src proto.Message) { + xxx_messageInfo_GeneratedCodeInfo_Annotation.Merge(dst, src) +} +func (m *GeneratedCodeInfo_Annotation) XXX_Size() int { + return xxx_messageInfo_GeneratedCodeInfo_Annotation.Size(m) +} +func (m *GeneratedCodeInfo_Annotation) XXX_DiscardUnknown() { + xxx_messageInfo_GeneratedCodeInfo_Annotation.DiscardUnknown(m) +} + +var xxx_messageInfo_GeneratedCodeInfo_Annotation proto.InternalMessageInfo func (m *GeneratedCodeInfo_Annotation) GetPath() []int32 { if m != nil { @@ -2025,6 +2617,7 @@ func init() { proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto") proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto") proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto") + proto.RegisterType((*EnumDescriptorProto_EnumReservedRange)(nil), "google.protobuf.EnumDescriptorProto.EnumReservedRange") proto.RegisterType((*EnumValueDescriptorProto)(nil), "google.protobuf.EnumValueDescriptorProto") proto.RegisterType((*ServiceDescriptorProto)(nil), "google.protobuf.ServiceDescriptorProto") proto.RegisterType((*MethodDescriptorProto)(nil), "google.protobuf.MethodDescriptorProto") @@ -2050,166 +2643,170 @@ func init() { proto.RegisterEnum("google.protobuf.MethodOptions_IdempotencyLevel", MethodOptions_IdempotencyLevel_name, MethodOptions_IdempotencyLevel_value) } -func init() { proto.RegisterFile("google/protobuf/descriptor.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 2519 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x6e, 0x1b, 0xc7, - 0x15, 0x0e, 0x7f, 0x45, 0x1e, 0x52, 0xd4, 0x68, 0xa4, 0xd8, 0x6b, 0xe5, 0xc7, 0x32, 0xf3, 0x63, - 0xd9, 0x69, 0xa8, 0x40, 0xb1, 0x1d, 0x47, 0x29, 0xd2, 0x52, 0xe4, 0x5a, 0xa1, 0x4a, 0x91, 0xec, - 0x92, 0x6a, 0x7e, 0x6e, 0x16, 0xa3, 0xdd, 0x21, 0xb9, 0xf6, 0x72, 0x77, 0xb3, 0xbb, 0xb4, 0xad, - 0xa0, 0x17, 0x06, 0x7a, 0x55, 0xa0, 0x0f, 0x50, 0x14, 0x45, 0x2f, 0x72, 0x13, 0xa0, 0x0f, 0x50, - 0x20, 0x77, 0x7d, 0x82, 0x02, 0x79, 0x83, 0xa2, 0x28, 0xd0, 0x3e, 0x46, 0x31, 0x33, 0xbb, 0xcb, - 0x5d, 0xfe, 0xc4, 0x6a, 0x80, 0x38, 0x57, 0xe4, 0x7c, 0xe7, 0x3b, 0x67, 0xce, 0x9c, 0x39, 0x33, - 0x73, 0x66, 0x16, 0x76, 0x47, 0xb6, 0x3d, 0x32, 0xe9, 0xbe, 0xe3, 0xda, 0xbe, 0x7d, 0x3e, 0x1d, - 0xee, 0xeb, 0xd4, 0xd3, 0x5c, 0xc3, 0xf1, 0x6d, 0xb7, 0xc6, 0x31, 0xbc, 0x21, 0x18, 0xb5, 0x90, - 0x51, 0x3d, 0x85, 0xcd, 0x07, 0x86, 0x49, 0x9b, 0x11, 0xb1, 0x4f, 0x7d, 0x7c, 0x1f, 0xb2, 0x43, - 0xc3, 0xa4, 0x52, 0x6a, 0x37, 0xb3, 0x57, 0x3a, 0x78, 0xb3, 0x36, 0xa7, 0x54, 0x4b, 0x6a, 0xf4, - 0x18, 0xac, 0x70, 0x8d, 0xea, 0xbf, 0xb3, 0xb0, 0xb5, 0x44, 0x8a, 0x31, 0x64, 0x2d, 0x32, 0x61, - 0x16, 0x53, 0x7b, 0x45, 0x85, 0xff, 0xc7, 0x12, 0xac, 0x39, 0x44, 0x7b, 0x44, 0x46, 0x54, 0x4a, - 0x73, 0x38, 0x6c, 0xe2, 0xd7, 0x01, 0x74, 0xea, 0x50, 0x4b, 0xa7, 0x96, 0x76, 0x21, 0x65, 0x76, - 0x33, 0x7b, 0x45, 0x25, 0x86, 0xe0, 0x77, 0x60, 0xd3, 0x99, 0x9e, 0x9b, 0x86, 0xa6, 0xc6, 0x68, - 0xb0, 0x9b, 0xd9, 0xcb, 0x29, 0x48, 0x08, 0x9a, 0x33, 0xf2, 0x4d, 0xd8, 0x78, 0x42, 0xc9, 0xa3, - 0x38, 0xb5, 0xc4, 0xa9, 0x15, 0x06, 0xc7, 0x88, 0x0d, 0x28, 0x4f, 0xa8, 0xe7, 0x91, 0x11, 0x55, - 0xfd, 0x0b, 0x87, 0x4a, 0x59, 0x3e, 0xfa, 0xdd, 0x85, 0xd1, 0xcf, 0x8f, 0xbc, 0x14, 0x68, 0x0d, - 0x2e, 0x1c, 0x8a, 0xeb, 0x50, 0xa4, 0xd6, 0x74, 0x22, 0x2c, 0xe4, 0x56, 0xc4, 0x4f, 0xb6, 0xa6, - 0x93, 0x79, 0x2b, 0x05, 0xa6, 0x16, 0x98, 0x58, 0xf3, 0xa8, 0xfb, 0xd8, 0xd0, 0xa8, 0x94, 0xe7, - 0x06, 0x6e, 0x2e, 0x18, 0xe8, 0x0b, 0xf9, 0xbc, 0x8d, 0x50, 0x0f, 0x37, 0xa0, 0x48, 0x9f, 0xfa, - 0xd4, 0xf2, 0x0c, 0xdb, 0x92, 0xd6, 0xb8, 0x91, 0xb7, 0x96, 0xcc, 0x22, 0x35, 0xf5, 0x79, 0x13, - 0x33, 0x3d, 0x7c, 0x0f, 0xd6, 0x6c, 0xc7, 0x37, 0x6c, 0xcb, 0x93, 0x0a, 0xbb, 0xa9, 0xbd, 0xd2, - 0xc1, 0xab, 0x4b, 0x13, 0xa1, 0x2b, 0x38, 0x4a, 0x48, 0xc6, 0x2d, 0x40, 0x9e, 0x3d, 0x75, 0x35, - 0xaa, 0x6a, 0xb6, 0x4e, 0x55, 0xc3, 0x1a, 0xda, 0x52, 0x91, 0x1b, 0xb8, 0xbe, 0x38, 0x10, 0x4e, - 0x6c, 0xd8, 0x3a, 0x6d, 0x59, 0x43, 0x5b, 0xa9, 0x78, 0x89, 0x36, 0xbe, 0x02, 0x79, 0xef, 0xc2, - 0xf2, 0xc9, 0x53, 0xa9, 0xcc, 0x33, 0x24, 0x68, 0x55, 0xbf, 0xcd, 0xc3, 0xc6, 0x65, 0x52, 0xec, - 0x23, 0xc8, 0x0d, 0xd9, 0x28, 0xa5, 0xf4, 0xff, 0x13, 0x03, 0xa1, 0x93, 0x0c, 0x62, 0xfe, 0x07, - 0x06, 0xb1, 0x0e, 0x25, 0x8b, 0x7a, 0x3e, 0xd5, 0x45, 0x46, 0x64, 0x2e, 0x99, 0x53, 0x20, 0x94, - 0x16, 0x53, 0x2a, 0xfb, 0x83, 0x52, 0xea, 0x33, 0xd8, 0x88, 0x5c, 0x52, 0x5d, 0x62, 0x8d, 0xc2, - 0xdc, 0xdc, 0x7f, 0x9e, 0x27, 0x35, 0x39, 0xd4, 0x53, 0x98, 0x9a, 0x52, 0xa1, 0x89, 0x36, 0x6e, - 0x02, 0xd8, 0x16, 0xb5, 0x87, 0xaa, 0x4e, 0x35, 0x53, 0x2a, 0xac, 0x88, 0x52, 0x97, 0x51, 0x16, - 0xa2, 0x64, 0x0b, 0x54, 0x33, 0xf1, 0x87, 0xb3, 0x54, 0x5b, 0x5b, 0x91, 0x29, 0xa7, 0x62, 0x91, - 0x2d, 0x64, 0xdb, 0x19, 0x54, 0x5c, 0xca, 0xf2, 0x9e, 0xea, 0xc1, 0xc8, 0x8a, 0xdc, 0x89, 0xda, - 0x73, 0x47, 0xa6, 0x04, 0x6a, 0x62, 0x60, 0xeb, 0x6e, 0xbc, 0x89, 0xdf, 0x80, 0x08, 0x50, 0x79, - 0x5a, 0x01, 0xdf, 0x85, 0xca, 0x21, 0xd8, 0x21, 0x13, 0xba, 0xf3, 0x15, 0x54, 0x92, 0xe1, 0xc1, - 0xdb, 0x90, 0xf3, 0x7c, 0xe2, 0xfa, 0x3c, 0x0b, 0x73, 0x8a, 0x68, 0x60, 0x04, 0x19, 0x6a, 0xe9, - 0x7c, 0x97, 0xcb, 0x29, 0xec, 0x2f, 0xfe, 0xe5, 0x6c, 0xc0, 0x19, 0x3e, 0xe0, 0xb7, 0x17, 0x67, - 0x34, 0x61, 0x79, 0x7e, 0xdc, 0x3b, 0x1f, 0xc0, 0x7a, 0x62, 0x00, 0x97, 0xed, 0xba, 0xfa, 0x5b, - 0x78, 0x79, 0xa9, 0x69, 0xfc, 0x19, 0x6c, 0x4f, 0x2d, 0xc3, 0xf2, 0xa9, 0xeb, 0xb8, 0x94, 0x65, - 0xac, 0xe8, 0x4a, 0xfa, 0xcf, 0xda, 0x8a, 0x9c, 0x3b, 0x8b, 0xb3, 0x85, 0x15, 0x65, 0x6b, 0xba, - 0x08, 0xde, 0x2e, 0x16, 0xfe, 0xbb, 0x86, 0x9e, 0x3d, 0x7b, 0xf6, 0x2c, 0x5d, 0xfd, 0x63, 0x1e, - 0xb6, 0x97, 0xad, 0x99, 0xa5, 0xcb, 0xf7, 0x0a, 0xe4, 0xad, 0xe9, 0xe4, 0x9c, 0xba, 0x3c, 0x48, - 0x39, 0x25, 0x68, 0xe1, 0x3a, 0xe4, 0x4c, 0x72, 0x4e, 0x4d, 0x29, 0xbb, 0x9b, 0xda, 0xab, 0x1c, - 0xbc, 0x73, 0xa9, 0x55, 0x59, 0x6b, 0x33, 0x15, 0x45, 0x68, 0xe2, 0x8f, 0x21, 0x1b, 0x6c, 0xd1, - 0xcc, 0xc2, 0xed, 0xcb, 0x59, 0x60, 0x6b, 0x49, 0xe1, 0x7a, 0xf8, 0x15, 0x28, 0xb2, 0x5f, 0x91, - 0x1b, 0x79, 0xee, 0x73, 0x81, 0x01, 0x2c, 0x2f, 0xf0, 0x0e, 0x14, 0xf8, 0x32, 0xd1, 0x69, 0x78, - 0xb4, 0x45, 0x6d, 0x96, 0x58, 0x3a, 0x1d, 0x92, 0xa9, 0xe9, 0xab, 0x8f, 0x89, 0x39, 0xa5, 0x3c, - 0xe1, 0x8b, 0x4a, 0x39, 0x00, 0x7f, 0xc3, 0x30, 0x7c, 0x1d, 0x4a, 0x62, 0x55, 0x19, 0x96, 0x4e, - 0x9f, 0xf2, 0xdd, 0x33, 0xa7, 0x88, 0x85, 0xd6, 0x62, 0x08, 0xeb, 0xfe, 0xa1, 0x67, 0x5b, 0x61, - 0x6a, 0xf2, 0x2e, 0x18, 0xc0, 0xbb, 0xff, 0x60, 0x7e, 0xe3, 0x7e, 0x6d, 0xf9, 0xf0, 0xe6, 0x73, - 0xaa, 0xfa, 0xb7, 0x34, 0x64, 0xf9, 0x7e, 0xb1, 0x01, 0xa5, 0xc1, 0xe7, 0x3d, 0x59, 0x6d, 0x76, - 0xcf, 0x8e, 0xda, 0x32, 0x4a, 0xe1, 0x0a, 0x00, 0x07, 0x1e, 0xb4, 0xbb, 0xf5, 0x01, 0x4a, 0x47, - 0xed, 0x56, 0x67, 0x70, 0xef, 0x0e, 0xca, 0x44, 0x0a, 0x67, 0x02, 0xc8, 0xc6, 0x09, 0xef, 0x1f, - 0xa0, 0x1c, 0x46, 0x50, 0x16, 0x06, 0x5a, 0x9f, 0xc9, 0xcd, 0x7b, 0x77, 0x50, 0x3e, 0x89, 0xbc, - 0x7f, 0x80, 0xd6, 0xf0, 0x3a, 0x14, 0x39, 0x72, 0xd4, 0xed, 0xb6, 0x51, 0x21, 0xb2, 0xd9, 0x1f, - 0x28, 0xad, 0xce, 0x31, 0x2a, 0x46, 0x36, 0x8f, 0x95, 0xee, 0x59, 0x0f, 0x41, 0x64, 0xe1, 0x54, - 0xee, 0xf7, 0xeb, 0xc7, 0x32, 0x2a, 0x45, 0x8c, 0xa3, 0xcf, 0x07, 0x72, 0x1f, 0x95, 0x13, 0x6e, - 0xbd, 0x7f, 0x80, 0xd6, 0xa3, 0x2e, 0xe4, 0xce, 0xd9, 0x29, 0xaa, 0xe0, 0x4d, 0x58, 0x17, 0x5d, - 0x84, 0x4e, 0x6c, 0xcc, 0x41, 0xf7, 0xee, 0x20, 0x34, 0x73, 0x44, 0x58, 0xd9, 0x4c, 0x00, 0xf7, - 0xee, 0x20, 0x5c, 0x6d, 0x40, 0x8e, 0x67, 0x17, 0xc6, 0x50, 0x69, 0xd7, 0x8f, 0xe4, 0xb6, 0xda, - 0xed, 0x0d, 0x5a, 0xdd, 0x4e, 0xbd, 0x8d, 0x52, 0x33, 0x4c, 0x91, 0x7f, 0x7d, 0xd6, 0x52, 0xe4, - 0x26, 0x4a, 0xc7, 0xb1, 0x9e, 0x5c, 0x1f, 0xc8, 0x4d, 0x94, 0xa9, 0x6a, 0xb0, 0xbd, 0x6c, 0x9f, - 0x5c, 0xba, 0x32, 0x62, 0x53, 0x9c, 0x5e, 0x31, 0xc5, 0xdc, 0xd6, 0xc2, 0x14, 0x7f, 0x9d, 0x82, - 0xad, 0x25, 0x67, 0xc5, 0xd2, 0x4e, 0x7e, 0x01, 0x39, 0x91, 0xa2, 0xe2, 0xf4, 0xbc, 0xb5, 0xf4, - 0xd0, 0xe1, 0x09, 0xbb, 0x70, 0x82, 0x72, 0xbd, 0x78, 0x05, 0x91, 0x59, 0x51, 0x41, 0x30, 0x13, - 0x0b, 0x4e, 0xfe, 0x2e, 0x05, 0xd2, 0x2a, 0xdb, 0xcf, 0xd9, 0x28, 0xd2, 0x89, 0x8d, 0xe2, 0xa3, - 0x79, 0x07, 0x6e, 0xac, 0x1e, 0xc3, 0x82, 0x17, 0xdf, 0xa4, 0xe0, 0xca, 0xf2, 0x42, 0x6b, 0xa9, - 0x0f, 0x1f, 0x43, 0x7e, 0x42, 0xfd, 0xb1, 0x1d, 0x16, 0x1b, 0x6f, 0x2f, 0x39, 0xc2, 0x98, 0x78, - 0x3e, 0x56, 0x81, 0x56, 0xfc, 0x0c, 0xcc, 0xac, 0xaa, 0x96, 0x84, 0x37, 0x0b, 0x9e, 0xfe, 0x3e, - 0x0d, 0x2f, 0x2f, 0x35, 0xbe, 0xd4, 0xd1, 0xd7, 0x00, 0x0c, 0xcb, 0x99, 0xfa, 0xa2, 0xa0, 0x10, - 0xfb, 0x53, 0x91, 0x23, 0x7c, 0xed, 0xb3, 0xbd, 0x67, 0xea, 0x47, 0xf2, 0x0c, 0x97, 0x83, 0x80, - 0x38, 0xe1, 0xfe, 0xcc, 0xd1, 0x2c, 0x77, 0xf4, 0xf5, 0x15, 0x23, 0x5d, 0x38, 0xab, 0xdf, 0x03, - 0xa4, 0x99, 0x06, 0xb5, 0x7c, 0xd5, 0xf3, 0x5d, 0x4a, 0x26, 0x86, 0x35, 0xe2, 0x1b, 0x70, 0xe1, - 0x30, 0x37, 0x24, 0xa6, 0x47, 0x95, 0x0d, 0x21, 0xee, 0x87, 0x52, 0xa6, 0xc1, 0xcf, 0x38, 0x37, - 0xa6, 0x91, 0x4f, 0x68, 0x08, 0x71, 0xa4, 0x51, 0xfd, 0xb6, 0x00, 0xa5, 0x58, 0x59, 0x8a, 0x6f, - 0x40, 0xf9, 0x21, 0x79, 0x4c, 0xd4, 0xf0, 0xaa, 0x21, 0x22, 0x51, 0x62, 0x58, 0x2f, 0xb8, 0x6e, - 0xbc, 0x07, 0xdb, 0x9c, 0x62, 0x4f, 0x7d, 0xea, 0xaa, 0x9a, 0x49, 0x3c, 0x8f, 0x07, 0xad, 0xc0, - 0xa9, 0x98, 0xc9, 0xba, 0x4c, 0xd4, 0x08, 0x25, 0xf8, 0x2e, 0x6c, 0x71, 0x8d, 0xc9, 0xd4, 0xf4, - 0x0d, 0xc7, 0xa4, 0x2a, 0xbb, 0xfc, 0x78, 0x7c, 0x23, 0x8e, 0x3c, 0xdb, 0x64, 0x8c, 0xd3, 0x80, - 0xc0, 0x3c, 0xf2, 0x70, 0x13, 0x5e, 0xe3, 0x6a, 0x23, 0x6a, 0x51, 0x97, 0xf8, 0x54, 0xa5, 0x5f, - 0x4e, 0x89, 0xe9, 0xa9, 0xc4, 0xd2, 0xd5, 0x31, 0xf1, 0xc6, 0xd2, 0x36, 0x33, 0x70, 0x94, 0x96, - 0x52, 0xca, 0x35, 0x46, 0x3c, 0x0e, 0x78, 0x32, 0xa7, 0xd5, 0x2d, 0xfd, 0x13, 0xe2, 0x8d, 0xf1, - 0x21, 0x5c, 0xe1, 0x56, 0x3c, 0xdf, 0x35, 0xac, 0x91, 0xaa, 0x8d, 0xa9, 0xf6, 0x48, 0x9d, 0xfa, - 0xc3, 0xfb, 0xd2, 0x2b, 0xf1, 0xfe, 0xb9, 0x87, 0x7d, 0xce, 0x69, 0x30, 0xca, 0x99, 0x3f, 0xbc, - 0x8f, 0xfb, 0x50, 0x66, 0x93, 0x31, 0x31, 0xbe, 0xa2, 0xea, 0xd0, 0x76, 0xf9, 0xc9, 0x52, 0x59, - 0xb2, 0xb2, 0x63, 0x11, 0xac, 0x75, 0x03, 0x85, 0x53, 0x5b, 0xa7, 0x87, 0xb9, 0x7e, 0x4f, 0x96, - 0x9b, 0x4a, 0x29, 0xb4, 0xf2, 0xc0, 0x76, 0x59, 0x42, 0x8d, 0xec, 0x28, 0xc0, 0x25, 0x91, 0x50, - 0x23, 0x3b, 0x0c, 0xef, 0x5d, 0xd8, 0xd2, 0x34, 0x31, 0x66, 0x43, 0x53, 0x83, 0x2b, 0x8a, 0x27, - 0xa1, 0x44, 0xb0, 0x34, 0xed, 0x58, 0x10, 0x82, 0x1c, 0xf7, 0xf0, 0x87, 0xf0, 0xf2, 0x2c, 0x58, - 0x71, 0xc5, 0xcd, 0x85, 0x51, 0xce, 0xab, 0xde, 0x85, 0x2d, 0xe7, 0x62, 0x51, 0x11, 0x27, 0x7a, - 0x74, 0x2e, 0xe6, 0xd5, 0x3e, 0x80, 0x6d, 0x67, 0xec, 0x2c, 0xea, 0xdd, 0x8e, 0xeb, 0x61, 0x67, - 0xec, 0xcc, 0x2b, 0xbe, 0xc5, 0xef, 0xab, 0x2e, 0xd5, 0x88, 0x4f, 0x75, 0xe9, 0x6a, 0x9c, 0x1e, - 0x13, 0xe0, 0x7d, 0x40, 0x9a, 0xa6, 0x52, 0x8b, 0x9c, 0x9b, 0x54, 0x25, 0x2e, 0xb5, 0x88, 0x27, - 0x5d, 0x8f, 0x93, 0x2b, 0x9a, 0x26, 0x73, 0x69, 0x9d, 0x0b, 0xf1, 0x6d, 0xd8, 0xb4, 0xcf, 0x1f, - 0x6a, 0x22, 0x25, 0x55, 0xc7, 0xa5, 0x43, 0xe3, 0xa9, 0xf4, 0x26, 0x8f, 0xef, 0x06, 0x13, 0xf0, - 0x84, 0xec, 0x71, 0x18, 0xdf, 0x02, 0xa4, 0x79, 0x63, 0xe2, 0x3a, 0xbc, 0x26, 0xf0, 0x1c, 0xa2, - 0x51, 0xe9, 0x2d, 0x41, 0x15, 0x78, 0x27, 0x84, 0xd9, 0x92, 0xf0, 0x9e, 0x18, 0x43, 0x3f, 0xb4, - 0x78, 0x53, 0x2c, 0x09, 0x8e, 0x05, 0xd6, 0xf6, 0x00, 0xb1, 0x50, 0x24, 0x3a, 0xde, 0xe3, 0xb4, - 0x8a, 0x33, 0x76, 0xe2, 0xfd, 0xbe, 0x01, 0xeb, 0x8c, 0x39, 0xeb, 0xf4, 0x96, 0xa8, 0x67, 0x9c, - 0x71, 0xac, 0xc7, 0x1f, 0xad, 0xb4, 0xac, 0x1e, 0x42, 0x39, 0x9e, 0x9f, 0xb8, 0x08, 0x22, 0x43, - 0x51, 0x8a, 0x9d, 0xf5, 0x8d, 0x6e, 0x93, 0x9d, 0xd2, 0x5f, 0xc8, 0x28, 0xcd, 0xaa, 0x85, 0x76, - 0x6b, 0x20, 0xab, 0xca, 0x59, 0x67, 0xd0, 0x3a, 0x95, 0x51, 0x26, 0x56, 0x96, 0x9e, 0x64, 0x0b, - 0x6f, 0xa3, 0x9b, 0xd5, 0xef, 0xd2, 0x50, 0x49, 0xde, 0x33, 0xf0, 0xcf, 0xe1, 0x6a, 0xf8, 0x28, - 0xe0, 0x51, 0x5f, 0x7d, 0x62, 0xb8, 0x7c, 0xe1, 0x4c, 0x88, 0xa8, 0xb3, 0xa3, 0xa9, 0xdb, 0x0e, - 0x58, 0x7d, 0xea, 0x7f, 0x6a, 0xb8, 0x6c, 0x59, 0x4c, 0x88, 0x8f, 0xdb, 0x70, 0xdd, 0xb2, 0x55, - 0xcf, 0x27, 0x96, 0x4e, 0x5c, 0x5d, 0x9d, 0x3d, 0xc7, 0xa8, 0x44, 0xd3, 0xa8, 0xe7, 0xd9, 0xe2, - 0xc0, 0x8a, 0xac, 0xbc, 0x6a, 0xd9, 0xfd, 0x80, 0x3c, 0xdb, 0xc9, 0xeb, 0x01, 0x75, 0x2e, 0xcd, - 0x32, 0xab, 0xd2, 0xec, 0x15, 0x28, 0x4e, 0x88, 0xa3, 0x52, 0xcb, 0x77, 0x2f, 0x78, 0x75, 0x59, - 0x50, 0x0a, 0x13, 0xe2, 0xc8, 0xac, 0xfd, 0x42, 0x8a, 0xfc, 0x93, 0x6c, 0xa1, 0x80, 0x8a, 0x27, - 0xd9, 0x42, 0x11, 0x41, 0xf5, 0x5f, 0x19, 0x28, 0xc7, 0xab, 0x4d, 0x56, 0xbc, 0x6b, 0xfc, 0x64, - 0x49, 0xf1, 0xbd, 0xe7, 0x8d, 0xef, 0xad, 0x4d, 0x6b, 0x0d, 0x76, 0xe4, 0x1c, 0xe6, 0x45, 0x0d, - 0xa8, 0x08, 0x4d, 0x76, 0xdc, 0xb3, 0xdd, 0x86, 0x8a, 0x7b, 0x4d, 0x41, 0x09, 0x5a, 0xf8, 0x18, - 0xf2, 0x0f, 0x3d, 0x6e, 0x3b, 0xcf, 0x6d, 0xbf, 0xf9, 0xfd, 0xb6, 0x4f, 0xfa, 0xdc, 0x78, 0xf1, - 0xa4, 0xaf, 0x76, 0xba, 0xca, 0x69, 0xbd, 0xad, 0x04, 0xea, 0xf8, 0x1a, 0x64, 0x4d, 0xf2, 0xd5, - 0x45, 0xf2, 0x70, 0xe2, 0xd0, 0x65, 0x27, 0xe1, 0x1a, 0x64, 0x9f, 0x50, 0xf2, 0x28, 0x79, 0x24, - 0x70, 0xe8, 0x47, 0x5c, 0x0c, 0xfb, 0x90, 0xe3, 0xf1, 0xc2, 0x00, 0x41, 0xc4, 0xd0, 0x4b, 0xb8, - 0x00, 0xd9, 0x46, 0x57, 0x61, 0x0b, 0x02, 0x41, 0x59, 0xa0, 0x6a, 0xaf, 0x25, 0x37, 0x64, 0x94, - 0xae, 0xde, 0x85, 0xbc, 0x08, 0x02, 0x5b, 0x2c, 0x51, 0x18, 0xd0, 0x4b, 0x41, 0x33, 0xb0, 0x91, - 0x0a, 0xa5, 0x67, 0xa7, 0x47, 0xb2, 0x82, 0xd2, 0xc9, 0xa9, 0xce, 0xa2, 0x5c, 0xd5, 0x83, 0x72, - 0xbc, 0xdc, 0x7c, 0x31, 0x57, 0xc9, 0xbf, 0xa7, 0xa0, 0x14, 0x2b, 0x1f, 0x59, 0xe1, 0x42, 0x4c, - 0xd3, 0x7e, 0xa2, 0x12, 0xd3, 0x20, 0x5e, 0x90, 0x1a, 0xc0, 0xa1, 0x3a, 0x43, 0x2e, 0x3b, 0x75, - 0x2f, 0x68, 0x89, 0xe4, 0x50, 0xbe, 0xfa, 0x97, 0x14, 0xa0, 0xf9, 0x02, 0x74, 0xce, 0xcd, 0xd4, - 0x4f, 0xe9, 0x66, 0xf5, 0xcf, 0x29, 0xa8, 0x24, 0xab, 0xce, 0x39, 0xf7, 0x6e, 0xfc, 0xa4, 0xee, - 0xfd, 0x33, 0x0d, 0xeb, 0x89, 0x5a, 0xf3, 0xb2, 0xde, 0x7d, 0x09, 0x9b, 0x86, 0x4e, 0x27, 0x8e, - 0xed, 0x53, 0x4b, 0xbb, 0x50, 0x4d, 0xfa, 0x98, 0x9a, 0x52, 0x95, 0x6f, 0x1a, 0xfb, 0xdf, 0x5f, - 0xcd, 0xd6, 0x5a, 0x33, 0xbd, 0x36, 0x53, 0x3b, 0xdc, 0x6a, 0x35, 0xe5, 0xd3, 0x5e, 0x77, 0x20, - 0x77, 0x1a, 0x9f, 0xab, 0x67, 0x9d, 0x5f, 0x75, 0xba, 0x9f, 0x76, 0x14, 0x64, 0xcc, 0xd1, 0x7e, - 0xc4, 0x65, 0xdf, 0x03, 0x34, 0xef, 0x14, 0xbe, 0x0a, 0xcb, 0xdc, 0x42, 0x2f, 0xe1, 0x2d, 0xd8, - 0xe8, 0x74, 0xd5, 0x7e, 0xab, 0x29, 0xab, 0xf2, 0x83, 0x07, 0x72, 0x63, 0xd0, 0x17, 0xd7, 0xfb, - 0x88, 0x3d, 0x48, 0x2c, 0xf0, 0xea, 0x9f, 0x32, 0xb0, 0xb5, 0xc4, 0x13, 0x5c, 0x0f, 0x6e, 0x16, - 0xe2, 0xb2, 0xf3, 0xee, 0x65, 0xbc, 0xaf, 0xb1, 0x82, 0xa0, 0x47, 0x5c, 0x3f, 0xb8, 0x88, 0xdc, - 0x02, 0x16, 0x25, 0xcb, 0x37, 0x86, 0x06, 0x75, 0x83, 0xd7, 0x10, 0x71, 0xdd, 0xd8, 0x98, 0xe1, - 0xe2, 0x41, 0xe4, 0x67, 0x80, 0x1d, 0xdb, 0x33, 0x7c, 0xe3, 0x31, 0x55, 0x0d, 0x2b, 0x7c, 0x3a, - 0x61, 0xd7, 0x8f, 0xac, 0x82, 0x42, 0x49, 0xcb, 0xf2, 0x23, 0xb6, 0x45, 0x47, 0x64, 0x8e, 0xcd, - 0x36, 0xf3, 0x8c, 0x82, 0x42, 0x49, 0xc4, 0xbe, 0x01, 0x65, 0xdd, 0x9e, 0xb2, 0x9a, 0x4c, 0xf0, - 0xd8, 0xd9, 0x91, 0x52, 0x4a, 0x02, 0x8b, 0x28, 0x41, 0xb5, 0x3d, 0x7b, 0xb3, 0x29, 0x2b, 0x25, - 0x81, 0x09, 0xca, 0x4d, 0xd8, 0x20, 0xa3, 0x91, 0xcb, 0x8c, 0x87, 0x86, 0xc4, 0xfd, 0xa1, 0x12, - 0xc1, 0x9c, 0xb8, 0x73, 0x02, 0x85, 0x30, 0x0e, 0xec, 0xa8, 0x66, 0x91, 0x50, 0x1d, 0xf1, 0x6e, - 0x97, 0xde, 0x2b, 0x2a, 0x05, 0x2b, 0x14, 0xde, 0x80, 0xb2, 0xe1, 0xa9, 0xb3, 0x27, 0xe8, 0xf4, - 0x6e, 0x7a, 0xaf, 0xa0, 0x94, 0x0c, 0x2f, 0x7a, 0xbe, 0xab, 0x7e, 0x93, 0x86, 0x4a, 0xf2, 0x09, - 0x1d, 0x37, 0xa1, 0x60, 0xda, 0x1a, 0xe1, 0xa9, 0x25, 0xbe, 0xdf, 0xec, 0x3d, 0xe7, 0xd5, 0xbd, - 0xd6, 0x0e, 0xf8, 0x4a, 0xa4, 0xb9, 0xf3, 0x8f, 0x14, 0x14, 0x42, 0x18, 0x5f, 0x81, 0xac, 0x43, - 0xfc, 0x31, 0x37, 0x97, 0x3b, 0x4a, 0xa3, 0x94, 0xc2, 0xdb, 0x0c, 0xf7, 0x1c, 0x62, 0xf1, 0x14, - 0x08, 0x70, 0xd6, 0x66, 0xf3, 0x6a, 0x52, 0xa2, 0xf3, 0xcb, 0x89, 0x3d, 0x99, 0x50, 0xcb, 0xf7, - 0xc2, 0x79, 0x0d, 0xf0, 0x46, 0x00, 0xe3, 0x77, 0x60, 0xd3, 0x77, 0x89, 0x61, 0x26, 0xb8, 0x59, - 0xce, 0x45, 0xa1, 0x20, 0x22, 0x1f, 0xc2, 0xb5, 0xd0, 0xae, 0x4e, 0x7d, 0xa2, 0x8d, 0xa9, 0x3e, - 0x53, 0xca, 0xf3, 0xf7, 0xd9, 0xab, 0x01, 0xa1, 0x19, 0xc8, 0x43, 0xdd, 0xea, 0x77, 0x29, 0xd8, - 0x0c, 0xaf, 0x53, 0x7a, 0x14, 0xac, 0x53, 0x00, 0x62, 0x59, 0xb6, 0x1f, 0x0f, 0xd7, 0x62, 0x2a, - 0x2f, 0xe8, 0xd5, 0xea, 0x91, 0x92, 0x12, 0x33, 0xb0, 0x33, 0x01, 0x98, 0x49, 0x56, 0x86, 0xed, - 0x3a, 0x94, 0x82, 0xef, 0x23, 0xfc, 0x23, 0x9b, 0xb8, 0x80, 0x83, 0x80, 0xd8, 0xbd, 0x0b, 0x6f, - 0x43, 0xee, 0x9c, 0x8e, 0x0c, 0x2b, 0x78, 0xf5, 0x14, 0x8d, 0xf0, 0x25, 0x37, 0x1b, 0xbd, 0xe4, - 0x1e, 0xfd, 0x21, 0x05, 0x5b, 0x9a, 0x3d, 0x99, 0xf7, 0xf7, 0x08, 0xcd, 0xbd, 0x02, 0x78, 0x9f, - 0xa4, 0xbe, 0xf8, 0x78, 0x64, 0xf8, 0xe3, 0xe9, 0x79, 0x4d, 0xb3, 0x27, 0xfb, 0x23, 0xdb, 0x24, - 0xd6, 0x68, 0xf6, 0x95, 0x90, 0xff, 0xd1, 0xde, 0x1d, 0x51, 0xeb, 0xdd, 0x91, 0x1d, 0xfb, 0x66, - 0xf8, 0xd1, 0xec, 0xef, 0xd7, 0xe9, 0xcc, 0x71, 0xef, 0xe8, 0xaf, 0xe9, 0x9d, 0x63, 0xd1, 0x57, - 0x2f, 0x8c, 0x8d, 0x42, 0x87, 0x26, 0xd5, 0xd8, 0x78, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x0c, - 0xab, 0xb6, 0x37, 0x7e, 0x1c, 0x00, 0x00, +func init() { + proto.RegisterFile("google/protobuf/descriptor.proto", fileDescriptor_descriptor_4df4cb5f42392df6) +} + +var fileDescriptor_descriptor_4df4cb5f42392df6 = []byte{ + // 2555 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x6e, 0x1b, 0xc7, + 0xf5, 0xcf, 0xf2, 0x4b, 0xe4, 0x21, 0x45, 0x8d, 0x46, 0x8a, 0xbd, 0x56, 0x3e, 0x2c, 0x33, 0x1f, + 0x96, 0x9d, 0x7f, 0xa8, 0xc0, 0xb1, 0x1d, 0x47, 0xfe, 0x23, 0x2d, 0x45, 0xae, 0x15, 0xaa, 0x12, + 0xc9, 0x2e, 0xa9, 0xe6, 0x03, 0x28, 0x16, 0xa3, 0xdd, 0x21, 0xb9, 0xf6, 0x72, 0x77, 0xb3, 0xbb, + 0xb4, 0xad, 0xa0, 0x17, 0x06, 0x7a, 0xd5, 0xab, 0xde, 0x16, 0x45, 0xd1, 0x8b, 0xde, 0x04, 0xe8, + 0x03, 0x14, 0xc8, 0x5d, 0x9f, 0xa0, 0x40, 0xde, 0xa0, 0x68, 0x0b, 0xb4, 0x8f, 0xd0, 0xcb, 0x62, + 0x66, 0x76, 0x97, 0xbb, 0x24, 0x15, 0x2b, 0x01, 0xe2, 0x5c, 0x91, 0xf3, 0x9b, 0xdf, 0x39, 0x73, + 0xe6, 0xcc, 0x99, 0x33, 0x67, 0x66, 0x61, 0x7b, 0xe4, 0x38, 0x23, 0x8b, 0xee, 0xba, 0x9e, 0x13, + 0x38, 0xa7, 0xd3, 0xe1, 0xae, 0x41, 0x7d, 0xdd, 0x33, 0xdd, 0xc0, 0xf1, 0xea, 0x1c, 0xc3, 0x6b, + 0x82, 0x51, 0x8f, 0x18, 0xb5, 0x63, 0x58, 0x7f, 0x60, 0x5a, 0xb4, 0x15, 0x13, 0xfb, 0x34, 0xc0, + 0xf7, 0x20, 0x37, 0x34, 0x2d, 0x2a, 0x4b, 0xdb, 0xd9, 0x9d, 0xf2, 0xad, 0x37, 0xeb, 0x73, 0x42, + 0xf5, 0xb4, 0x44, 0x8f, 0xc1, 0x2a, 0x97, 0xa8, 0xfd, 0x2b, 0x07, 0x1b, 0x4b, 0x7a, 0x31, 0x86, + 0x9c, 0x4d, 0x26, 0x4c, 0xa3, 0xb4, 0x53, 0x52, 0xf9, 0x7f, 0x2c, 0xc3, 0x8a, 0x4b, 0xf4, 0x47, + 0x64, 0x44, 0xe5, 0x0c, 0x87, 0xa3, 0x26, 0x7e, 0x1d, 0xc0, 0xa0, 0x2e, 0xb5, 0x0d, 0x6a, 0xeb, + 0x67, 0x72, 0x76, 0x3b, 0xbb, 0x53, 0x52, 0x13, 0x08, 0x7e, 0x07, 0xd6, 0xdd, 0xe9, 0xa9, 0x65, + 0xea, 0x5a, 0x82, 0x06, 0xdb, 0xd9, 0x9d, 0xbc, 0x8a, 0x44, 0x47, 0x6b, 0x46, 0xbe, 0x0e, 0x6b, + 0x4f, 0x28, 0x79, 0x94, 0xa4, 0x96, 0x39, 0xb5, 0xca, 0xe0, 0x04, 0xb1, 0x09, 0x95, 0x09, 0xf5, + 0x7d, 0x32, 0xa2, 0x5a, 0x70, 0xe6, 0x52, 0x39, 0xc7, 0x67, 0xbf, 0xbd, 0x30, 0xfb, 0xf9, 0x99, + 0x97, 0x43, 0xa9, 0xc1, 0x99, 0x4b, 0x71, 0x03, 0x4a, 0xd4, 0x9e, 0x4e, 0x84, 0x86, 0xfc, 0x39, + 0xfe, 0x53, 0xec, 0xe9, 0x64, 0x5e, 0x4b, 0x91, 0x89, 0x85, 0x2a, 0x56, 0x7c, 0xea, 0x3d, 0x36, + 0x75, 0x2a, 0x17, 0xb8, 0x82, 0xeb, 0x0b, 0x0a, 0xfa, 0xa2, 0x7f, 0x5e, 0x47, 0x24, 0x87, 0x9b, + 0x50, 0xa2, 0x4f, 0x03, 0x6a, 0xfb, 0xa6, 0x63, 0xcb, 0x2b, 0x5c, 0xc9, 0x5b, 0x4b, 0x56, 0x91, + 0x5a, 0xc6, 0xbc, 0x8a, 0x99, 0x1c, 0xbe, 0x0b, 0x2b, 0x8e, 0x1b, 0x98, 0x8e, 0xed, 0xcb, 0xc5, + 0x6d, 0x69, 0xa7, 0x7c, 0xeb, 0xd5, 0xa5, 0x81, 0xd0, 0x15, 0x1c, 0x35, 0x22, 0xe3, 0x36, 0x20, + 0xdf, 0x99, 0x7a, 0x3a, 0xd5, 0x74, 0xc7, 0xa0, 0x9a, 0x69, 0x0f, 0x1d, 0xb9, 0xc4, 0x15, 0x5c, + 0x5d, 0x9c, 0x08, 0x27, 0x36, 0x1d, 0x83, 0xb6, 0xed, 0xa1, 0xa3, 0x56, 0xfd, 0x54, 0x1b, 0x5f, + 0x82, 0x82, 0x7f, 0x66, 0x07, 0xe4, 0xa9, 0x5c, 0xe1, 0x11, 0x12, 0xb6, 0x6a, 0x5f, 0x17, 0x60, + 0xed, 0x22, 0x21, 0x76, 0x1f, 0xf2, 0x43, 0x36, 0x4b, 0x39, 0xf3, 0x5d, 0x7c, 0x20, 0x64, 0xd2, + 0x4e, 0x2c, 0x7c, 0x4f, 0x27, 0x36, 0xa0, 0x6c, 0x53, 0x3f, 0xa0, 0x86, 0x88, 0x88, 0xec, 0x05, + 0x63, 0x0a, 0x84, 0xd0, 0x62, 0x48, 0xe5, 0xbe, 0x57, 0x48, 0x7d, 0x0a, 0x6b, 0xb1, 0x49, 0x9a, + 0x47, 0xec, 0x51, 0x14, 0x9b, 0xbb, 0xcf, 0xb3, 0xa4, 0xae, 0x44, 0x72, 0x2a, 0x13, 0x53, 0xab, + 0x34, 0xd5, 0xc6, 0x2d, 0x00, 0xc7, 0xa6, 0xce, 0x50, 0x33, 0xa8, 0x6e, 0xc9, 0xc5, 0x73, 0xbc, + 0xd4, 0x65, 0x94, 0x05, 0x2f, 0x39, 0x02, 0xd5, 0x2d, 0xfc, 0xe1, 0x2c, 0xd4, 0x56, 0xce, 0x89, + 0x94, 0x63, 0xb1, 0xc9, 0x16, 0xa2, 0xed, 0x04, 0xaa, 0x1e, 0x65, 0x71, 0x4f, 0x8d, 0x70, 0x66, + 0x25, 0x6e, 0x44, 0xfd, 0xb9, 0x33, 0x53, 0x43, 0x31, 0x31, 0xb1, 0x55, 0x2f, 0xd9, 0xc4, 0x6f, + 0x40, 0x0c, 0x68, 0x3c, 0xac, 0x80, 0x67, 0xa1, 0x4a, 0x04, 0x76, 0xc8, 0x84, 0x6e, 0x7d, 0x09, + 0xd5, 0xb4, 0x7b, 0xf0, 0x26, 0xe4, 0xfd, 0x80, 0x78, 0x01, 0x8f, 0xc2, 0xbc, 0x2a, 0x1a, 0x18, + 0x41, 0x96, 0xda, 0x06, 0xcf, 0x72, 0x79, 0x95, 0xfd, 0xc5, 0x3f, 0x9d, 0x4d, 0x38, 0xcb, 0x27, + 0xfc, 0xf6, 0xe2, 0x8a, 0xa6, 0x34, 0xcf, 0xcf, 0x7b, 0xeb, 0x03, 0x58, 0x4d, 0x4d, 0xe0, 0xa2, + 0x43, 0xd7, 0x7e, 0x05, 0x2f, 0x2f, 0x55, 0x8d, 0x3f, 0x85, 0xcd, 0xa9, 0x6d, 0xda, 0x01, 0xf5, + 0x5c, 0x8f, 0xb2, 0x88, 0x15, 0x43, 0xc9, 0xff, 0x5e, 0x39, 0x27, 0xe6, 0x4e, 0x92, 0x6c, 0xa1, + 0x45, 0xdd, 0x98, 0x2e, 0x82, 0x37, 0x4b, 0xc5, 0xff, 0xac, 0xa0, 0x67, 0xcf, 0x9e, 0x3d, 0xcb, + 0xd4, 0x7e, 0x57, 0x80, 0xcd, 0x65, 0x7b, 0x66, 0xe9, 0xf6, 0xbd, 0x04, 0x05, 0x7b, 0x3a, 0x39, + 0xa5, 0x1e, 0x77, 0x52, 0x5e, 0x0d, 0x5b, 0xb8, 0x01, 0x79, 0x8b, 0x9c, 0x52, 0x4b, 0xce, 0x6d, + 0x4b, 0x3b, 0xd5, 0x5b, 0xef, 0x5c, 0x68, 0x57, 0xd6, 0x8f, 0x98, 0x88, 0x2a, 0x24, 0xf1, 0x47, + 0x90, 0x0b, 0x53, 0x34, 0xd3, 0x70, 0xf3, 0x62, 0x1a, 0xd8, 0x5e, 0x52, 0xb9, 0x1c, 0x7e, 0x05, + 0x4a, 0xec, 0x57, 0xc4, 0x46, 0x81, 0xdb, 0x5c, 0x64, 0x00, 0x8b, 0x0b, 0xbc, 0x05, 0x45, 0xbe, + 0x4d, 0x0c, 0x1a, 0x1d, 0x6d, 0x71, 0x9b, 0x05, 0x96, 0x41, 0x87, 0x64, 0x6a, 0x05, 0xda, 0x63, + 0x62, 0x4d, 0x29, 0x0f, 0xf8, 0x92, 0x5a, 0x09, 0xc1, 0x5f, 0x30, 0x0c, 0x5f, 0x85, 0xb2, 0xd8, + 0x55, 0xa6, 0x6d, 0xd0, 0xa7, 0x3c, 0x7b, 0xe6, 0x55, 0xb1, 0xd1, 0xda, 0x0c, 0x61, 0xc3, 0x3f, + 0xf4, 0x1d, 0x3b, 0x0a, 0x4d, 0x3e, 0x04, 0x03, 0xf8, 0xf0, 0x1f, 0xcc, 0x27, 0xee, 0xd7, 0x96, + 0x4f, 0x6f, 0x3e, 0xa6, 0x6a, 0x7f, 0xc9, 0x40, 0x8e, 0xe7, 0x8b, 0x35, 0x28, 0x0f, 0x3e, 0xeb, + 0x29, 0x5a, 0xab, 0x7b, 0xb2, 0x7f, 0xa4, 0x20, 0x09, 0x57, 0x01, 0x38, 0xf0, 0xe0, 0xa8, 0xdb, + 0x18, 0xa0, 0x4c, 0xdc, 0x6e, 0x77, 0x06, 0x77, 0x6f, 0xa3, 0x6c, 0x2c, 0x70, 0x22, 0x80, 0x5c, + 0x92, 0xf0, 0xfe, 0x2d, 0x94, 0xc7, 0x08, 0x2a, 0x42, 0x41, 0xfb, 0x53, 0xa5, 0x75, 0xf7, 0x36, + 0x2a, 0xa4, 0x91, 0xf7, 0x6f, 0xa1, 0x15, 0xbc, 0x0a, 0x25, 0x8e, 0xec, 0x77, 0xbb, 0x47, 0xa8, + 0x18, 0xeb, 0xec, 0x0f, 0xd4, 0x76, 0xe7, 0x00, 0x95, 0x62, 0x9d, 0x07, 0x6a, 0xf7, 0xa4, 0x87, + 0x20, 0xd6, 0x70, 0xac, 0xf4, 0xfb, 0x8d, 0x03, 0x05, 0x95, 0x63, 0xc6, 0xfe, 0x67, 0x03, 0xa5, + 0x8f, 0x2a, 0x29, 0xb3, 0xde, 0xbf, 0x85, 0x56, 0xe3, 0x21, 0x94, 0xce, 0xc9, 0x31, 0xaa, 0xe2, + 0x75, 0x58, 0x15, 0x43, 0x44, 0x46, 0xac, 0xcd, 0x41, 0x77, 0x6f, 0x23, 0x34, 0x33, 0x44, 0x68, + 0x59, 0x4f, 0x01, 0x77, 0x6f, 0x23, 0x5c, 0x6b, 0x42, 0x9e, 0x47, 0x17, 0xc6, 0x50, 0x3d, 0x6a, + 0xec, 0x2b, 0x47, 0x5a, 0xb7, 0x37, 0x68, 0x77, 0x3b, 0x8d, 0x23, 0x24, 0xcd, 0x30, 0x55, 0xf9, + 0xf9, 0x49, 0x5b, 0x55, 0x5a, 0x28, 0x93, 0xc4, 0x7a, 0x4a, 0x63, 0xa0, 0xb4, 0x50, 0xb6, 0xa6, + 0xc3, 0xe6, 0xb2, 0x3c, 0xb9, 0x74, 0x67, 0x24, 0x96, 0x38, 0x73, 0xce, 0x12, 0x73, 0x5d, 0x0b, + 0x4b, 0xfc, 0xcf, 0x0c, 0x6c, 0x2c, 0x39, 0x2b, 0x96, 0x0e, 0xf2, 0x13, 0xc8, 0x8b, 0x10, 0x15, + 0xa7, 0xe7, 0x8d, 0xa5, 0x87, 0x0e, 0x0f, 0xd8, 0x85, 0x13, 0x94, 0xcb, 0x25, 0x2b, 0x88, 0xec, + 0x39, 0x15, 0x04, 0x53, 0xb1, 0x90, 0xd3, 0x7f, 0xb9, 0x90, 0xd3, 0xc5, 0xb1, 0x77, 0xf7, 0x22, + 0xc7, 0x1e, 0xc7, 0xbe, 0x5b, 0x6e, 0xcf, 0x2f, 0xc9, 0xed, 0xf7, 0x61, 0x7d, 0x41, 0xd1, 0x85, + 0x73, 0xec, 0xaf, 0x25, 0x90, 0xcf, 0x73, 0xce, 0x73, 0x32, 0x5d, 0x26, 0x95, 0xe9, 0xee, 0xcf, + 0x7b, 0xf0, 0xda, 0xf9, 0x8b, 0xb0, 0xb0, 0xd6, 0x5f, 0x49, 0x70, 0x69, 0x79, 0xa5, 0xb8, 0xd4, + 0x86, 0x8f, 0xa0, 0x30, 0xa1, 0xc1, 0xd8, 0x89, 0xaa, 0xa5, 0xb7, 0x97, 0x9c, 0xc1, 0xac, 0x7b, + 0x7e, 0xb1, 0x43, 0xa9, 0xe4, 0x21, 0x9e, 0x3d, 0xaf, 0xdc, 0x13, 0xd6, 0x2c, 0x58, 0xfa, 0x9b, + 0x0c, 0xbc, 0xbc, 0x54, 0xf9, 0x52, 0x43, 0x5f, 0x03, 0x30, 0x6d, 0x77, 0x1a, 0x88, 0x8a, 0x48, + 0x24, 0xd8, 0x12, 0x47, 0x78, 0xf2, 0x62, 0xc9, 0x73, 0x1a, 0xc4, 0xfd, 0x59, 0xde, 0x0f, 0x02, + 0xe2, 0x84, 0x7b, 0x33, 0x43, 0x73, 0xdc, 0xd0, 0xd7, 0xcf, 0x99, 0xe9, 0x42, 0x60, 0xbe, 0x07, + 0x48, 0xb7, 0x4c, 0x6a, 0x07, 0x9a, 0x1f, 0x78, 0x94, 0x4c, 0x4c, 0x7b, 0xc4, 0x4f, 0x90, 0xe2, + 0x5e, 0x7e, 0x48, 0x2c, 0x9f, 0xaa, 0x6b, 0xa2, 0xbb, 0x1f, 0xf5, 0x32, 0x09, 0x1e, 0x40, 0x5e, + 0x42, 0xa2, 0x90, 0x92, 0x10, 0xdd, 0xb1, 0x44, 0xed, 0xeb, 0x22, 0x94, 0x13, 0x75, 0x35, 0xbe, + 0x06, 0x95, 0x87, 0xe4, 0x31, 0xd1, 0xa2, 0xbb, 0x92, 0xf0, 0x44, 0x99, 0x61, 0xbd, 0xf0, 0xbe, + 0xf4, 0x1e, 0x6c, 0x72, 0x8a, 0x33, 0x0d, 0xa8, 0xa7, 0xe9, 0x16, 0xf1, 0x7d, 0xee, 0xb4, 0x22, + 0xa7, 0x62, 0xd6, 0xd7, 0x65, 0x5d, 0xcd, 0xa8, 0x07, 0xdf, 0x81, 0x0d, 0x2e, 0x31, 0x99, 0x5a, + 0x81, 0xe9, 0x5a, 0x54, 0x63, 0xb7, 0x37, 0x9f, 0x9f, 0x24, 0xb1, 0x65, 0xeb, 0x8c, 0x71, 0x1c, + 0x12, 0x98, 0x45, 0x3e, 0x6e, 0xc1, 0x6b, 0x5c, 0x6c, 0x44, 0x6d, 0xea, 0x91, 0x80, 0x6a, 0xf4, + 0x8b, 0x29, 0xb1, 0x7c, 0x8d, 0xd8, 0x86, 0x36, 0x26, 0xfe, 0x58, 0xde, 0x64, 0x0a, 0xf6, 0x33, + 0xb2, 0xa4, 0x5e, 0x61, 0xc4, 0x83, 0x90, 0xa7, 0x70, 0x5a, 0xc3, 0x36, 0x3e, 0x26, 0xfe, 0x18, + 0xef, 0xc1, 0x25, 0xae, 0xc5, 0x0f, 0x3c, 0xd3, 0x1e, 0x69, 0xfa, 0x98, 0xea, 0x8f, 0xb4, 0x69, + 0x30, 0xbc, 0x27, 0xbf, 0x92, 0x1c, 0x9f, 0x5b, 0xd8, 0xe7, 0x9c, 0x26, 0xa3, 0x9c, 0x04, 0xc3, + 0x7b, 0xb8, 0x0f, 0x15, 0xb6, 0x18, 0x13, 0xf3, 0x4b, 0xaa, 0x0d, 0x1d, 0x8f, 0x1f, 0x8d, 0xd5, + 0x25, 0xa9, 0x29, 0xe1, 0xc1, 0x7a, 0x37, 0x14, 0x38, 0x76, 0x0c, 0xba, 0x97, 0xef, 0xf7, 0x14, + 0xa5, 0xa5, 0x96, 0x23, 0x2d, 0x0f, 0x1c, 0x8f, 0x05, 0xd4, 0xc8, 0x89, 0x1d, 0x5c, 0x16, 0x01, + 0x35, 0x72, 0x22, 0xf7, 0xde, 0x81, 0x0d, 0x5d, 0x17, 0x73, 0x36, 0x75, 0x2d, 0xbc, 0x63, 0xf9, + 0x32, 0x4a, 0x39, 0x4b, 0xd7, 0x0f, 0x04, 0x21, 0x8c, 0x71, 0x1f, 0x7f, 0x08, 0x2f, 0xcf, 0x9c, + 0x95, 0x14, 0x5c, 0x5f, 0x98, 0xe5, 0xbc, 0xe8, 0x1d, 0xd8, 0x70, 0xcf, 0x16, 0x05, 0x71, 0x6a, + 0x44, 0xf7, 0x6c, 0x5e, 0xec, 0x03, 0xd8, 0x74, 0xc7, 0xee, 0xa2, 0xdc, 0xcd, 0xa4, 0x1c, 0x76, + 0xc7, 0xee, 0xbc, 0xe0, 0x5b, 0xfc, 0xc2, 0xed, 0x51, 0x9d, 0x04, 0xd4, 0x90, 0x2f, 0x27, 0xe9, + 0x89, 0x0e, 0xbc, 0x0b, 0x48, 0xd7, 0x35, 0x6a, 0x93, 0x53, 0x8b, 0x6a, 0xc4, 0xa3, 0x36, 0xf1, + 0xe5, 0xab, 0x49, 0x72, 0x55, 0xd7, 0x15, 0xde, 0xdb, 0xe0, 0x9d, 0xf8, 0x26, 0xac, 0x3b, 0xa7, + 0x0f, 0x75, 0x11, 0x92, 0x9a, 0xeb, 0xd1, 0xa1, 0xf9, 0x54, 0x7e, 0x93, 0xfb, 0x77, 0x8d, 0x75, + 0xf0, 0x80, 0xec, 0x71, 0x18, 0xdf, 0x00, 0xa4, 0xfb, 0x63, 0xe2, 0xb9, 0x3c, 0x27, 0xfb, 0x2e, + 0xd1, 0xa9, 0xfc, 0x96, 0xa0, 0x0a, 0xbc, 0x13, 0xc1, 0x6c, 0x4b, 0xf8, 0x4f, 0xcc, 0x61, 0x10, + 0x69, 0xbc, 0x2e, 0xb6, 0x04, 0xc7, 0x42, 0x6d, 0x3b, 0x80, 0x98, 0x2b, 0x52, 0x03, 0xef, 0x70, + 0x5a, 0xd5, 0x1d, 0xbb, 0xc9, 0x71, 0xdf, 0x80, 0x55, 0xc6, 0x9c, 0x0d, 0x7a, 0x43, 0x14, 0x64, + 0xee, 0x38, 0x31, 0xe2, 0x0f, 0x56, 0x1b, 0xd7, 0xf6, 0xa0, 0x92, 0x8c, 0x4f, 0x5c, 0x02, 0x11, + 0xa1, 0x48, 0x62, 0xc5, 0x4a, 0xb3, 0xdb, 0x62, 0x65, 0xc6, 0xe7, 0x0a, 0xca, 0xb0, 0x72, 0xe7, + 0xa8, 0x3d, 0x50, 0x34, 0xf5, 0xa4, 0x33, 0x68, 0x1f, 0x2b, 0x28, 0x9b, 0xa8, 0xab, 0x0f, 0x73, + 0xc5, 0xb7, 0xd1, 0xf5, 0xda, 0x37, 0x19, 0xa8, 0xa6, 0x2f, 0x4a, 0xf8, 0xff, 0xe1, 0x72, 0xf4, + 0xaa, 0xe1, 0xd3, 0x40, 0x7b, 0x62, 0x7a, 0x7c, 0xe3, 0x4c, 0x88, 0x38, 0xc4, 0xe2, 0xa5, 0xdb, + 0x0c, 0x59, 0x7d, 0x1a, 0x7c, 0x62, 0x7a, 0x6c, 0x5b, 0x4c, 0x48, 0x80, 0x8f, 0xe0, 0xaa, 0xed, + 0x68, 0x7e, 0x40, 0x6c, 0x83, 0x78, 0x86, 0x36, 0x7b, 0x4f, 0xd2, 0x88, 0xae, 0x53, 0xdf, 0x77, + 0xc4, 0x81, 0x15, 0x6b, 0x79, 0xd5, 0x76, 0xfa, 0x21, 0x79, 0x96, 0xc9, 0x1b, 0x21, 0x75, 0x2e, + 0xcc, 0xb2, 0xe7, 0x85, 0xd9, 0x2b, 0x50, 0x9a, 0x10, 0x57, 0xa3, 0x76, 0xe0, 0x9d, 0xf1, 0xf2, + 0xb8, 0xa8, 0x16, 0x27, 0xc4, 0x55, 0x58, 0xfb, 0x85, 0xdc, 0x52, 0x0e, 0x73, 0xc5, 0x22, 0x2a, + 0x1d, 0xe6, 0x8a, 0x25, 0x04, 0xb5, 0x7f, 0x64, 0xa1, 0x92, 0x2c, 0x97, 0xd9, 0xed, 0x43, 0xe7, + 0x27, 0x8b, 0xc4, 0x73, 0xcf, 0x1b, 0xdf, 0x5a, 0x5c, 0xd7, 0x9b, 0xec, 0xc8, 0xd9, 0x2b, 0x88, + 0x22, 0x56, 0x15, 0x92, 0xec, 0xb8, 0x67, 0xd9, 0x86, 0x8a, 0xa2, 0xa1, 0xa8, 0x86, 0x2d, 0x7c, + 0x00, 0x85, 0x87, 0x3e, 0xd7, 0x5d, 0xe0, 0xba, 0xdf, 0xfc, 0x76, 0xdd, 0x87, 0x7d, 0xae, 0xbc, + 0x74, 0xd8, 0xd7, 0x3a, 0x5d, 0xf5, 0xb8, 0x71, 0xa4, 0x86, 0xe2, 0xf8, 0x0a, 0xe4, 0x2c, 0xf2, + 0xe5, 0x59, 0xfa, 0x70, 0xe2, 0xd0, 0x45, 0x17, 0xe1, 0x0a, 0xe4, 0x9e, 0x50, 0xf2, 0x28, 0x7d, + 0x24, 0x70, 0xe8, 0x07, 0xdc, 0x0c, 0xbb, 0x90, 0xe7, 0xfe, 0xc2, 0x00, 0xa1, 0xc7, 0xd0, 0x4b, + 0xb8, 0x08, 0xb9, 0x66, 0x57, 0x65, 0x1b, 0x02, 0x41, 0x45, 0xa0, 0x5a, 0xaf, 0xad, 0x34, 0x15, + 0x94, 0xa9, 0xdd, 0x81, 0x82, 0x70, 0x02, 0xdb, 0x2c, 0xb1, 0x1b, 0xd0, 0x4b, 0x61, 0x33, 0xd4, + 0x21, 0x45, 0xbd, 0x27, 0xc7, 0xfb, 0x8a, 0x8a, 0x32, 0xe9, 0xa5, 0xce, 0xa1, 0x7c, 0xcd, 0x87, + 0x4a, 0xb2, 0x5e, 0x7e, 0x31, 0x77, 0xe1, 0xbf, 0x4a, 0x50, 0x4e, 0xd4, 0xbf, 0xac, 0x70, 0x21, + 0x96, 0xe5, 0x3c, 0xd1, 0x88, 0x65, 0x12, 0x3f, 0x0c, 0x0d, 0xe0, 0x50, 0x83, 0x21, 0x17, 0x5d, + 0xba, 0x17, 0xb4, 0x45, 0xf2, 0xa8, 0x50, 0xfb, 0xa3, 0x04, 0x68, 0xbe, 0x00, 0x9d, 0x33, 0x53, + 0xfa, 0x31, 0xcd, 0xac, 0xfd, 0x41, 0x82, 0x6a, 0xba, 0xea, 0x9c, 0x33, 0xef, 0xda, 0x8f, 0x6a, + 0xde, 0xdf, 0x33, 0xb0, 0x9a, 0xaa, 0x35, 0x2f, 0x6a, 0xdd, 0x17, 0xb0, 0x6e, 0x1a, 0x74, 0xe2, + 0x3a, 0x01, 0xb5, 0xf5, 0x33, 0xcd, 0xa2, 0x8f, 0xa9, 0x25, 0xd7, 0x78, 0xd2, 0xd8, 0xfd, 0xf6, + 0x6a, 0xb6, 0xde, 0x9e, 0xc9, 0x1d, 0x31, 0xb1, 0xbd, 0x8d, 0x76, 0x4b, 0x39, 0xee, 0x75, 0x07, + 0x4a, 0xa7, 0xf9, 0x99, 0x76, 0xd2, 0xf9, 0x59, 0xa7, 0xfb, 0x49, 0x47, 0x45, 0xe6, 0x1c, 0xed, + 0x07, 0xdc, 0xf6, 0x3d, 0x40, 0xf3, 0x46, 0xe1, 0xcb, 0xb0, 0xcc, 0x2c, 0xf4, 0x12, 0xde, 0x80, + 0xb5, 0x4e, 0x57, 0xeb, 0xb7, 0x5b, 0x8a, 0xa6, 0x3c, 0x78, 0xa0, 0x34, 0x07, 0x7d, 0xf1, 0x3e, + 0x11, 0xb3, 0x07, 0xa9, 0x0d, 0x5e, 0xfb, 0x7d, 0x16, 0x36, 0x96, 0x58, 0x82, 0x1b, 0xe1, 0xcd, + 0x42, 0x5c, 0x76, 0xde, 0xbd, 0x88, 0xf5, 0x75, 0x56, 0x10, 0xf4, 0x88, 0x17, 0x84, 0x17, 0x91, + 0x1b, 0xc0, 0xbc, 0x64, 0x07, 0xe6, 0xd0, 0xa4, 0x5e, 0xf8, 0x9c, 0x23, 0xae, 0x1b, 0x6b, 0x33, + 0x5c, 0xbc, 0xe8, 0xfc, 0x1f, 0x60, 0xd7, 0xf1, 0xcd, 0xc0, 0x7c, 0x4c, 0x35, 0xd3, 0x8e, 0xde, + 0x7e, 0xd8, 0xf5, 0x23, 0xa7, 0xa2, 0xa8, 0xa7, 0x6d, 0x07, 0x31, 0xdb, 0xa6, 0x23, 0x32, 0xc7, + 0x66, 0xc9, 0x3c, 0xab, 0xa2, 0xa8, 0x27, 0x66, 0x5f, 0x83, 0x8a, 0xe1, 0x4c, 0x59, 0x4d, 0x26, + 0x78, 0xec, 0xec, 0x90, 0xd4, 0xb2, 0xc0, 0x62, 0x4a, 0x58, 0x6d, 0xcf, 0x1e, 0x9d, 0x2a, 0x6a, + 0x59, 0x60, 0x82, 0x72, 0x1d, 0xd6, 0xc8, 0x68, 0xe4, 0x31, 0xe5, 0x91, 0x22, 0x71, 0x7f, 0xa8, + 0xc6, 0x30, 0x27, 0x6e, 0x1d, 0x42, 0x31, 0xf2, 0x03, 0x3b, 0xaa, 0x99, 0x27, 0x34, 0x57, 0x5c, + 0x8a, 0x33, 0x3b, 0x25, 0xb5, 0x68, 0x47, 0x9d, 0xd7, 0xa0, 0x62, 0xfa, 0xda, 0xec, 0x0d, 0x3d, + 0xb3, 0x9d, 0xd9, 0x29, 0xaa, 0x65, 0xd3, 0x8f, 0xdf, 0x1f, 0x6b, 0x5f, 0x65, 0xa0, 0x9a, 0xfe, + 0x06, 0x80, 0x5b, 0x50, 0xb4, 0x1c, 0x9d, 0xf0, 0xd0, 0x12, 0x1f, 0xa0, 0x76, 0x9e, 0xf3, 0xd9, + 0xa0, 0x7e, 0x14, 0xf2, 0xd5, 0x58, 0x72, 0xeb, 0x6f, 0x12, 0x14, 0x23, 0x18, 0x5f, 0x82, 0x9c, + 0x4b, 0x82, 0x31, 0x57, 0x97, 0xdf, 0xcf, 0x20, 0x49, 0xe5, 0x6d, 0x86, 0xfb, 0x2e, 0xb1, 0x79, + 0x08, 0x84, 0x38, 0x6b, 0xb3, 0x75, 0xb5, 0x28, 0x31, 0xf8, 0xe5, 0xc4, 0x99, 0x4c, 0xa8, 0x1d, + 0xf8, 0xd1, 0xba, 0x86, 0x78, 0x33, 0x84, 0xf1, 0x3b, 0xb0, 0x1e, 0x78, 0xc4, 0xb4, 0x52, 0xdc, + 0x1c, 0xe7, 0xa2, 0xa8, 0x23, 0x26, 0xef, 0xc1, 0x95, 0x48, 0xaf, 0x41, 0x03, 0xa2, 0x8f, 0xa9, + 0x31, 0x13, 0x2a, 0xf0, 0x47, 0x88, 0xcb, 0x21, 0xa1, 0x15, 0xf6, 0x47, 0xb2, 0xb5, 0x6f, 0x24, + 0x58, 0x8f, 0xae, 0x53, 0x46, 0xec, 0xac, 0x63, 0x00, 0x62, 0xdb, 0x4e, 0x90, 0x74, 0xd7, 0x62, + 0x28, 0x2f, 0xc8, 0xd5, 0x1b, 0xb1, 0x90, 0x9a, 0x50, 0xb0, 0x35, 0x01, 0x98, 0xf5, 0x9c, 0xeb, + 0xb6, 0xab, 0x50, 0x0e, 0x3f, 0xf0, 0xf0, 0xaf, 0x84, 0xe2, 0x02, 0x0e, 0x02, 0x62, 0xf7, 0x2e, + 0xbc, 0x09, 0xf9, 0x53, 0x3a, 0x32, 0xed, 0xf0, 0xd9, 0x56, 0x34, 0xa2, 0x67, 0x92, 0x5c, 0xfc, + 0x4c, 0xb2, 0xff, 0x5b, 0x09, 0x36, 0x74, 0x67, 0x32, 0x6f, 0xef, 0x3e, 0x9a, 0x7b, 0x05, 0xf0, + 0x3f, 0x96, 0x3e, 0xff, 0x68, 0x64, 0x06, 0xe3, 0xe9, 0x69, 0x5d, 0x77, 0x26, 0xbb, 0x23, 0xc7, + 0x22, 0xf6, 0x68, 0xf6, 0x99, 0x93, 0xff, 0xd1, 0xdf, 0x1d, 0x51, 0xfb, 0xdd, 0x91, 0x93, 0xf8, + 0xe8, 0x79, 0x7f, 0xf6, 0xf7, 0xbf, 0x92, 0xf4, 0xa7, 0x4c, 0xf6, 0xa0, 0xb7, 0xff, 0xe7, 0xcc, + 0xd6, 0x81, 0x18, 0xae, 0x17, 0xb9, 0x47, 0xa5, 0x43, 0x8b, 0xea, 0x6c, 0xca, 0xff, 0x0b, 0x00, + 0x00, 0xff, 0xff, 0x1a, 0x28, 0x25, 0x79, 0x42, 0x1d, 0x00, 0x00, } diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto index 4d4fb378f50..8697a50de4a 100644 --- a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto @@ -45,6 +45,7 @@ option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; option csharp_namespace = "Google.Protobuf.Reflection"; option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; // descriptor.proto must be optimized for speed because reflection-based // algorithms don't work during bootstrapping. @@ -225,6 +226,26 @@ message EnumDescriptorProto { repeated EnumValueDescriptorProto value = 2; optional EnumOptions options = 3; + + // Range of reserved numeric values. Reserved values may not be used by + // entries in the same enum. Reserved ranges may not overlap. + // + // Note that this is distinct from DescriptorProto.ReservedRange in that it + // is inclusive such that it can appropriately represent the entire int32 + // domain. + message EnumReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Inclusive. + } + + // Range of reserved numeric values. Reserved numeric values may not be used + // by enum values in the same enum declaration. Reserved ranges may not + // overlap. + repeated EnumReservedRange reserved_range = 4; + + // Reserved enum value names, which may not be reused. A given name may only + // be reserved once. + repeated string reserved_name = 5; } // Describes a value within an enum. @@ -396,10 +417,12 @@ message FileOptions { // determining the namespace. optional string php_namespace = 41; - // The parser stores options it doesn't recognize here. See above. + // The parser stores options it doesn't recognize here. + // See the documentation for the "Options" section above. repeated UninterpretedOption uninterpreted_option = 999; - // Clients can define custom options in extensions of this message. See above. + // Clients can define custom options in extensions of this message. + // See the documentation for the "Options" section above. extensions 1000 to max; reserved 38; diff --git a/vendor/github.com/golang/protobuf/ptypes/BUILD b/vendor/github.com/golang/protobuf/ptypes/BUILD index a5f7c6c9cde..af97601b60f 100644 --- a/vendor/github.com/golang/protobuf/ptypes/BUILD +++ b/vendor/github.com/golang/protobuf/ptypes/BUILD @@ -31,9 +31,9 @@ filegroup( ":package-srcs", "//vendor/github.com/golang/protobuf/ptypes/any:all-srcs", "//vendor/github.com/golang/protobuf/ptypes/duration:all-srcs", - "//vendor/github.com/golang/protobuf/ptypes/empty:all-srcs", "//vendor/github.com/golang/protobuf/ptypes/struct:all-srcs", "//vendor/github.com/golang/protobuf/ptypes/timestamp:all-srcs", + "//vendor/github.com/golang/protobuf/ptypes/wrappers:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go b/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go index f34601723de..4ab3551b7f0 100644 --- a/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go +++ b/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go @@ -1,15 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // source: google/protobuf/any.proto -/* -Package any is a generated protocol buffer package. - -It is generated from these files: - google/protobuf/any.proto - -It has these top-level messages: - Any -*/ package any import proto "github.com/golang/protobuf/proto" @@ -132,14 +123,36 @@ type Any struct { // TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"` // Must be a valid serialized protocol buffer of the above specified type. - Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Any) Reset() { *m = Any{} } -func (m *Any) String() string { return proto.CompactTextString(m) } -func (*Any) ProtoMessage() {} -func (*Any) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -func (*Any) XXX_WellKnownType() string { return "Any" } +func (m *Any) Reset() { *m = Any{} } +func (m *Any) String() string { return proto.CompactTextString(m) } +func (*Any) ProtoMessage() {} +func (*Any) Descriptor() ([]byte, []int) { + return fileDescriptor_any_744b9ca530f228db, []int{0} +} +func (*Any) XXX_WellKnownType() string { return "Any" } +func (m *Any) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Any.Unmarshal(m, b) +} +func (m *Any) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Any.Marshal(b, m, deterministic) +} +func (dst *Any) XXX_Merge(src proto.Message) { + xxx_messageInfo_Any.Merge(dst, src) +} +func (m *Any) XXX_Size() int { + return xxx_messageInfo_Any.Size(m) +} +func (m *Any) XXX_DiscardUnknown() { + xxx_messageInfo_Any.DiscardUnknown(m) +} + +var xxx_messageInfo_Any proto.InternalMessageInfo func (m *Any) GetTypeUrl() string { if m != nil { @@ -159,9 +172,9 @@ func init() { proto.RegisterType((*Any)(nil), "google.protobuf.Any") } -func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor0) } +func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_any_744b9ca530f228db) } -var fileDescriptor0 = []byte{ +var fileDescriptor_any_744b9ca530f228db = []byte{ // 185 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f, 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4, diff --git a/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go b/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go index b2410a098eb..0333aebfef2 100644 --- a/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go +++ b/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go @@ -1,15 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // source: google/protobuf/duration.proto -/* -Package duration is a generated protocol buffer package. - -It is generated from these files: - google/protobuf/duration.proto - -It has these top-level messages: - Duration -*/ package duration import proto "github.com/golang/protobuf/proto" @@ -98,14 +89,36 @@ type Duration struct { // of one second or more, a non-zero value for the `nanos` field must be // of the same sign as the `seconds` field. Must be from -999,999,999 // to +999,999,999 inclusive. - Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` + Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Duration) Reset() { *m = Duration{} } -func (m *Duration) String() string { return proto.CompactTextString(m) } -func (*Duration) ProtoMessage() {} -func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -func (*Duration) XXX_WellKnownType() string { return "Duration" } +func (m *Duration) Reset() { *m = Duration{} } +func (m *Duration) String() string { return proto.CompactTextString(m) } +func (*Duration) ProtoMessage() {} +func (*Duration) Descriptor() ([]byte, []int) { + return fileDescriptor_duration_e7d612259e3f0613, []int{0} +} +func (*Duration) XXX_WellKnownType() string { return "Duration" } +func (m *Duration) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Duration.Unmarshal(m, b) +} +func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Duration.Marshal(b, m, deterministic) +} +func (dst *Duration) XXX_Merge(src proto.Message) { + xxx_messageInfo_Duration.Merge(dst, src) +} +func (m *Duration) XXX_Size() int { + return xxx_messageInfo_Duration.Size(m) +} +func (m *Duration) XXX_DiscardUnknown() { + xxx_messageInfo_Duration.DiscardUnknown(m) +} + +var xxx_messageInfo_Duration proto.InternalMessageInfo func (m *Duration) GetSeconds() int64 { if m != nil { @@ -125,9 +138,11 @@ func init() { proto.RegisterType((*Duration)(nil), "google.protobuf.Duration") } -func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor0) } +func init() { + proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_duration_e7d612259e3f0613) +} -var fileDescriptor0 = []byte{ +var fileDescriptor_duration_e7d612259e3f0613 = []byte{ // 190 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f, 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a, diff --git a/vendor/github.com/golang/protobuf/ptypes/empty/empty.pb.go b/vendor/github.com/golang/protobuf/ptypes/empty/empty.pb.go deleted file mode 100644 index e877b72c3f5..00000000000 --- a/vendor/github.com/golang/protobuf/ptypes/empty/empty.pb.go +++ /dev/null @@ -1,66 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: google/protobuf/empty.proto - -/* -Package empty is a generated protocol buffer package. - -It is generated from these files: - google/protobuf/empty.proto - -It has these top-level messages: - Empty -*/ -package empty - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -// 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.ProtoPackageIsVersion2 // please upgrade the proto package - -// 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: -// -// service Foo { -// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); -// } -// -// The JSON representation for `Empty` is empty JSON object `{}`. -type Empty struct { -} - -func (m *Empty) Reset() { *m = Empty{} } -func (m *Empty) String() string { return proto.CompactTextString(m) } -func (*Empty) ProtoMessage() {} -func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -func (*Empty) XXX_WellKnownType() string { return "Empty" } - -func init() { - proto.RegisterType((*Empty)(nil), "google.protobuf.Empty") -} - -func init() { proto.RegisterFile("google/protobuf/empty.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 148 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4e, 0xcf, 0xcf, 0x4f, - 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcd, 0x2d, 0x28, - 0xa9, 0xd4, 0x03, 0x73, 0x85, 0xf8, 0x21, 0x92, 0x7a, 0x30, 0x49, 0x25, 0x76, 0x2e, 0x56, 0x57, - 0x90, 0xbc, 0x53, 0x19, 0x97, 0x70, 0x72, 0x7e, 0xae, 0x1e, 0x9a, 0xbc, 0x13, 0x17, 0x58, 0x36, - 0x00, 0xc4, 0x0d, 0x60, 0x8c, 0x52, 0x4f, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, - 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0x47, 0x58, 0x53, 0x50, 0x52, 0x59, 0x90, 0x5a, 0x0c, - 0xb1, 0xed, 0x07, 0x23, 0xe3, 0x22, 0x26, 0x66, 0xf7, 0x00, 0xa7, 0x55, 0x4c, 0x72, 0xee, 0x10, - 0x13, 0x03, 0xa0, 0xea, 0xf4, 0xc2, 0x53, 0x73, 0x72, 0xbc, 0xf3, 0xf2, 0xcb, 0xf3, 0x42, 0x40, - 0xea, 0x93, 0xd8, 0xc0, 0x06, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x64, 0xd4, 0xb3, 0xa6, - 0xb7, 0x00, 0x00, 0x00, -} diff --git a/vendor/github.com/golang/protobuf/ptypes/regen.sh b/vendor/github.com/golang/protobuf/ptypes/regen.sh deleted file mode 100755 index b50a9414ac2..00000000000 --- a/vendor/github.com/golang/protobuf/ptypes/regen.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -e -# -# This script fetches and rebuilds the "well-known types" protocol buffers. -# To run this you will need protoc and goprotobuf installed; -# see https://github.com/golang/protobuf for instructions. -# You also need Go and Git installed. - -PKG=github.com/golang/protobuf/ptypes -UPSTREAM=https://github.com/google/protobuf -UPSTREAM_SUBDIR=src/google/protobuf -PROTO_FILES=(any duration empty struct timestamp wrappers) - -function die() { - echo 1>&2 $* - exit 1 -} - -# Sanity check that the right tools are accessible. -for tool in go git protoc protoc-gen-go; do - q=$(which $tool) || die "didn't find $tool" - echo 1>&2 "$tool: $q" -done - -tmpdir=$(mktemp -d -t regen-wkt.XXXXXX) -trap 'rm -rf $tmpdir' EXIT - -echo -n 1>&2 "finding package dir... " -pkgdir=$(go list -f '{{.Dir}}' $PKG) -echo 1>&2 $pkgdir -base=$(echo $pkgdir | sed "s,/$PKG\$,,") -echo 1>&2 "base: $base" -cd "$base" - -echo 1>&2 "fetching latest protos... " -git clone -q $UPSTREAM $tmpdir - -for file in ${PROTO_FILES[@]}; do - echo 1>&2 "* $file" - protoc --go_out=. -I$tmpdir/src $tmpdir/src/google/protobuf/$file.proto || die - cp $tmpdir/src/google/protobuf/$file.proto $PKG/$file -done - -echo 1>&2 "All OK" diff --git a/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go b/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go index 4cfe6081879..550817bb341 100644 --- a/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go +++ b/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go @@ -1,17 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // source: google/protobuf/struct.proto -/* -Package structpb is a generated protocol buffer package. - -It is generated from these files: - google/protobuf/struct.proto - -It has these top-level messages: - Struct - Value - ListValue -*/ package structpb import proto "github.com/golang/protobuf/proto" @@ -50,8 +39,10 @@ var NullValue_value = map[string]int32{ func (x NullValue) String() string { return proto.EnumName(NullValue_name, int32(x)) } -func (NullValue) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -func (NullValue) XXX_WellKnownType() string { return "NullValue" } +func (NullValue) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_struct_3a5a94e0c7801b27, []int{0} +} +func (NullValue) XXX_WellKnownType() string { return "NullValue" } // `Struct` represents a structured data value, consisting of fields // which map to dynamically typed values. In some languages, `Struct` @@ -63,14 +54,36 @@ func (NullValue) XXX_WellKnownType() string { return "NullValue" } // The JSON representation for `Struct` is JSON object. type Struct struct { // Unordered map of dynamically typed values. - Fields map[string]*Value `protobuf:"bytes,1,rep,name=fields" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Fields map[string]*Value `protobuf:"bytes,1,rep,name=fields" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Struct) Reset() { *m = Struct{} } -func (m *Struct) String() string { return proto.CompactTextString(m) } -func (*Struct) ProtoMessage() {} -func (*Struct) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -func (*Struct) XXX_WellKnownType() string { return "Struct" } +func (m *Struct) Reset() { *m = Struct{} } +func (m *Struct) String() string { return proto.CompactTextString(m) } +func (*Struct) ProtoMessage() {} +func (*Struct) Descriptor() ([]byte, []int) { + return fileDescriptor_struct_3a5a94e0c7801b27, []int{0} +} +func (*Struct) XXX_WellKnownType() string { return "Struct" } +func (m *Struct) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Struct.Unmarshal(m, b) +} +func (m *Struct) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Struct.Marshal(b, m, deterministic) +} +func (dst *Struct) XXX_Merge(src proto.Message) { + xxx_messageInfo_Struct.Merge(dst, src) +} +func (m *Struct) XXX_Size() int { + return xxx_messageInfo_Struct.Size(m) +} +func (m *Struct) XXX_DiscardUnknown() { + xxx_messageInfo_Struct.DiscardUnknown(m) +} + +var xxx_messageInfo_Struct proto.InternalMessageInfo func (m *Struct) GetFields() map[string]*Value { if m != nil { @@ -95,14 +108,36 @@ type Value struct { // *Value_BoolValue // *Value_StructValue // *Value_ListValue - Kind isValue_Kind `protobuf_oneof:"kind"` + Kind isValue_Kind `protobuf_oneof:"kind"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Value) Reset() { *m = Value{} } -func (m *Value) String() string { return proto.CompactTextString(m) } -func (*Value) ProtoMessage() {} -func (*Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } -func (*Value) XXX_WellKnownType() string { return "Value" } +func (m *Value) Reset() { *m = Value{} } +func (m *Value) String() string { return proto.CompactTextString(m) } +func (*Value) ProtoMessage() {} +func (*Value) Descriptor() ([]byte, []int) { + return fileDescriptor_struct_3a5a94e0c7801b27, []int{1} +} +func (*Value) XXX_WellKnownType() string { return "Value" } +func (m *Value) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Value.Unmarshal(m, b) +} +func (m *Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Value.Marshal(b, m, deterministic) +} +func (dst *Value) XXX_Merge(src proto.Message) { + xxx_messageInfo_Value.Merge(dst, src) +} +func (m *Value) XXX_Size() int { + return xxx_messageInfo_Value.Size(m) +} +func (m *Value) XXX_DiscardUnknown() { + xxx_messageInfo_Value.DiscardUnknown(m) +} + +var xxx_messageInfo_Value proto.InternalMessageInfo type isValue_Kind interface { isValue_Kind() @@ -289,26 +324,26 @@ func _Value_OneofSizer(msg proto.Message) (n int) { // kind switch x := m.Kind.(type) { case *Value_NullValue: - n += proto.SizeVarint(1<<3 | proto.WireVarint) + n += 1 // tag and wire n += proto.SizeVarint(uint64(x.NullValue)) case *Value_NumberValue: - n += proto.SizeVarint(2<<3 | proto.WireFixed64) + n += 1 // tag and wire n += 8 case *Value_StringValue: - n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += 1 // tag and wire n += proto.SizeVarint(uint64(len(x.StringValue))) n += len(x.StringValue) case *Value_BoolValue: - n += proto.SizeVarint(4<<3 | proto.WireVarint) + n += 1 // tag and wire n += 1 case *Value_StructValue: s := proto.Size(x.StructValue) - n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += 1 // tag and wire n += proto.SizeVarint(uint64(s)) n += s case *Value_ListValue: s := proto.Size(x.ListValue) - n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += 1 // tag and wire n += proto.SizeVarint(uint64(s)) n += s case nil: @@ -323,14 +358,36 @@ func _Value_OneofSizer(msg proto.Message) (n int) { // The JSON representation for `ListValue` is JSON array. type ListValue struct { // Repeated field of dynamically typed values. - Values []*Value `protobuf:"bytes,1,rep,name=values" json:"values,omitempty"` + Values []*Value `protobuf:"bytes,1,rep,name=values" json:"values,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *ListValue) Reset() { *m = ListValue{} } -func (m *ListValue) String() string { return proto.CompactTextString(m) } -func (*ListValue) ProtoMessage() {} -func (*ListValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } -func (*ListValue) XXX_WellKnownType() string { return "ListValue" } +func (m *ListValue) Reset() { *m = ListValue{} } +func (m *ListValue) String() string { return proto.CompactTextString(m) } +func (*ListValue) ProtoMessage() {} +func (*ListValue) Descriptor() ([]byte, []int) { + return fileDescriptor_struct_3a5a94e0c7801b27, []int{2} +} +func (*ListValue) XXX_WellKnownType() string { return "ListValue" } +func (m *ListValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListValue.Unmarshal(m, b) +} +func (m *ListValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListValue.Marshal(b, m, deterministic) +} +func (dst *ListValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListValue.Merge(dst, src) +} +func (m *ListValue) XXX_Size() int { + return xxx_messageInfo_ListValue.Size(m) +} +func (m *ListValue) XXX_DiscardUnknown() { + xxx_messageInfo_ListValue.DiscardUnknown(m) +} + +var xxx_messageInfo_ListValue proto.InternalMessageInfo func (m *ListValue) GetValues() []*Value { if m != nil { @@ -341,14 +398,17 @@ func (m *ListValue) GetValues() []*Value { func init() { proto.RegisterType((*Struct)(nil), "google.protobuf.Struct") + proto.RegisterMapType((map[string]*Value)(nil), "google.protobuf.Struct.FieldsEntry") proto.RegisterType((*Value)(nil), "google.protobuf.Value") proto.RegisterType((*ListValue)(nil), "google.protobuf.ListValue") proto.RegisterEnum("google.protobuf.NullValue", NullValue_name, NullValue_value) } -func init() { proto.RegisterFile("google/protobuf/struct.proto", fileDescriptor0) } +func init() { + proto.RegisterFile("google/protobuf/struct.proto", fileDescriptor_struct_3a5a94e0c7801b27) +} -var fileDescriptor0 = []byte{ +var fileDescriptor_struct_3a5a94e0c7801b27 = []byte{ // 417 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0x41, 0x8b, 0xd3, 0x40, 0x14, 0xc7, 0x3b, 0xc9, 0x36, 0x98, 0x17, 0x59, 0x97, 0x11, 0xb4, 0xac, 0xa2, 0xa1, 0x7b, 0x09, diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go index e23e4a25daf..b590be7b5f6 100644 --- a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go +++ b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go @@ -1,15 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // source: google/protobuf/timestamp.proto -/* -Package timestamp is a generated protocol buffer package. - -It is generated from these files: - google/protobuf/timestamp.proto - -It has these top-level messages: - Timestamp -*/ package timestamp import proto "github.com/golang/protobuf/proto" @@ -101,7 +92,7 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) // with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one // can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( -// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()) +// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--) // to obtain a formatter capable of generating timestamps in this format. // // @@ -114,14 +105,36 @@ type Timestamp struct { // second values with fractions must still have non-negative nanos values // that count forward in time. Must be from 0 to 999,999,999 // inclusive. - Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` + Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Timestamp) Reset() { *m = Timestamp{} } -func (m *Timestamp) String() string { return proto.CompactTextString(m) } -func (*Timestamp) ProtoMessage() {} -func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" } +func (m *Timestamp) Reset() { *m = Timestamp{} } +func (m *Timestamp) String() string { return proto.CompactTextString(m) } +func (*Timestamp) ProtoMessage() {} +func (*Timestamp) Descriptor() ([]byte, []int) { + return fileDescriptor_timestamp_b826e8e5fba671a8, []int{0} +} +func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" } +func (m *Timestamp) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Timestamp.Unmarshal(m, b) +} +func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic) +} +func (dst *Timestamp) XXX_Merge(src proto.Message) { + xxx_messageInfo_Timestamp.Merge(dst, src) +} +func (m *Timestamp) XXX_Size() int { + return xxx_messageInfo_Timestamp.Size(m) +} +func (m *Timestamp) XXX_DiscardUnknown() { + xxx_messageInfo_Timestamp.DiscardUnknown(m) +} + +var xxx_messageInfo_Timestamp proto.InternalMessageInfo func (m *Timestamp) GetSeconds() int64 { if m != nil { @@ -141,9 +154,11 @@ func init() { proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp") } -func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor0) } +func init() { + proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_timestamp_b826e8e5fba671a8) +} -var fileDescriptor0 = []byte{ +var fileDescriptor_timestamp_b826e8e5fba671a8 = []byte{ // 191 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f, 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d, diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto index b7cbd17502f..06750ab1f12 100644 --- a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto +++ b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto @@ -114,7 +114,7 @@ option objc_class_prefix = "GPB"; // to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) // with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one // can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( -// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()) +// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--) // to obtain a formatter capable of generating timestamps in this format. // // diff --git a/vendor/github.com/golang/protobuf/ptypes/empty/BUILD b/vendor/github.com/golang/protobuf/ptypes/wrappers/BUILD similarity index 82% rename from vendor/github.com/golang/protobuf/ptypes/empty/BUILD rename to vendor/github.com/golang/protobuf/ptypes/wrappers/BUILD index 20ff3201e8f..ab9f1239a46 100644 --- a/vendor/github.com/golang/protobuf/ptypes/empty/BUILD +++ b/vendor/github.com/golang/protobuf/ptypes/wrappers/BUILD @@ -2,14 +2,14 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") filegroup( name = "go_default_library_protos", - srcs = ["empty.proto"], + srcs = ["wrappers.proto"], visibility = ["//visibility:public"], ) go_library( name = "go_default_library", - srcs = ["empty.pb.go"], - importpath = "github.com/golang/protobuf/ptypes/empty", + srcs = ["wrappers.pb.go"], + importpath = "github.com/golang/protobuf/ptypes/wrappers", visibility = ["//visibility:public"], deps = ["//vendor/github.com/golang/protobuf/proto:go_default_library"], ) diff --git a/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go new file mode 100644 index 00000000000..7d6b0bfcc0f --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go @@ -0,0 +1,443 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/wrappers.proto + +package wrappers + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// 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.ProtoPackageIsVersion2 // please upgrade the proto package + +// Wrapper message for `double`. +// +// The JSON representation for `DoubleValue` is JSON number. +type DoubleValue struct { + // The double value. + Value float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DoubleValue) Reset() { *m = DoubleValue{} } +func (m *DoubleValue) String() string { return proto.CompactTextString(m) } +func (*DoubleValue) ProtoMessage() {} +func (*DoubleValue) Descriptor() ([]byte, []int) { + return fileDescriptor_wrappers_16c7c35c009f3253, []int{0} +} +func (*DoubleValue) XXX_WellKnownType() string { return "DoubleValue" } +func (m *DoubleValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DoubleValue.Unmarshal(m, b) +} +func (m *DoubleValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DoubleValue.Marshal(b, m, deterministic) +} +func (dst *DoubleValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_DoubleValue.Merge(dst, src) +} +func (m *DoubleValue) XXX_Size() int { + return xxx_messageInfo_DoubleValue.Size(m) +} +func (m *DoubleValue) XXX_DiscardUnknown() { + xxx_messageInfo_DoubleValue.DiscardUnknown(m) +} + +var xxx_messageInfo_DoubleValue proto.InternalMessageInfo + +func (m *DoubleValue) GetValue() float64 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `float`. +// +// The JSON representation for `FloatValue` is JSON number. +type FloatValue struct { + // The float value. + Value float32 `protobuf:"fixed32,1,opt,name=value" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FloatValue) Reset() { *m = FloatValue{} } +func (m *FloatValue) String() string { return proto.CompactTextString(m) } +func (*FloatValue) ProtoMessage() {} +func (*FloatValue) Descriptor() ([]byte, []int) { + return fileDescriptor_wrappers_16c7c35c009f3253, []int{1} +} +func (*FloatValue) XXX_WellKnownType() string { return "FloatValue" } +func (m *FloatValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FloatValue.Unmarshal(m, b) +} +func (m *FloatValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FloatValue.Marshal(b, m, deterministic) +} +func (dst *FloatValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_FloatValue.Merge(dst, src) +} +func (m *FloatValue) XXX_Size() int { + return xxx_messageInfo_FloatValue.Size(m) +} +func (m *FloatValue) XXX_DiscardUnknown() { + xxx_messageInfo_FloatValue.DiscardUnknown(m) +} + +var xxx_messageInfo_FloatValue proto.InternalMessageInfo + +func (m *FloatValue) GetValue() float32 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `int64`. +// +// The JSON representation for `Int64Value` is JSON string. +type Int64Value struct { + // The int64 value. + Value int64 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Int64Value) Reset() { *m = Int64Value{} } +func (m *Int64Value) String() string { return proto.CompactTextString(m) } +func (*Int64Value) ProtoMessage() {} +func (*Int64Value) Descriptor() ([]byte, []int) { + return fileDescriptor_wrappers_16c7c35c009f3253, []int{2} +} +func (*Int64Value) XXX_WellKnownType() string { return "Int64Value" } +func (m *Int64Value) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Int64Value.Unmarshal(m, b) +} +func (m *Int64Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Int64Value.Marshal(b, m, deterministic) +} +func (dst *Int64Value) XXX_Merge(src proto.Message) { + xxx_messageInfo_Int64Value.Merge(dst, src) +} +func (m *Int64Value) XXX_Size() int { + return xxx_messageInfo_Int64Value.Size(m) +} +func (m *Int64Value) XXX_DiscardUnknown() { + xxx_messageInfo_Int64Value.DiscardUnknown(m) +} + +var xxx_messageInfo_Int64Value proto.InternalMessageInfo + +func (m *Int64Value) GetValue() int64 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `uint64`. +// +// The JSON representation for `UInt64Value` is JSON string. +type UInt64Value struct { + // The uint64 value. + Value uint64 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UInt64Value) Reset() { *m = UInt64Value{} } +func (m *UInt64Value) String() string { return proto.CompactTextString(m) } +func (*UInt64Value) ProtoMessage() {} +func (*UInt64Value) Descriptor() ([]byte, []int) { + return fileDescriptor_wrappers_16c7c35c009f3253, []int{3} +} +func (*UInt64Value) XXX_WellKnownType() string { return "UInt64Value" } +func (m *UInt64Value) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UInt64Value.Unmarshal(m, b) +} +func (m *UInt64Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UInt64Value.Marshal(b, m, deterministic) +} +func (dst *UInt64Value) XXX_Merge(src proto.Message) { + xxx_messageInfo_UInt64Value.Merge(dst, src) +} +func (m *UInt64Value) XXX_Size() int { + return xxx_messageInfo_UInt64Value.Size(m) +} +func (m *UInt64Value) XXX_DiscardUnknown() { + xxx_messageInfo_UInt64Value.DiscardUnknown(m) +} + +var xxx_messageInfo_UInt64Value proto.InternalMessageInfo + +func (m *UInt64Value) GetValue() uint64 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +type Int32Value struct { + // The int32 value. + Value int32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Int32Value) Reset() { *m = Int32Value{} } +func (m *Int32Value) String() string { return proto.CompactTextString(m) } +func (*Int32Value) ProtoMessage() {} +func (*Int32Value) Descriptor() ([]byte, []int) { + return fileDescriptor_wrappers_16c7c35c009f3253, []int{4} +} +func (*Int32Value) XXX_WellKnownType() string { return "Int32Value" } +func (m *Int32Value) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Int32Value.Unmarshal(m, b) +} +func (m *Int32Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Int32Value.Marshal(b, m, deterministic) +} +func (dst *Int32Value) XXX_Merge(src proto.Message) { + xxx_messageInfo_Int32Value.Merge(dst, src) +} +func (m *Int32Value) XXX_Size() int { + return xxx_messageInfo_Int32Value.Size(m) +} +func (m *Int32Value) XXX_DiscardUnknown() { + xxx_messageInfo_Int32Value.DiscardUnknown(m) +} + +var xxx_messageInfo_Int32Value proto.InternalMessageInfo + +func (m *Int32Value) GetValue() int32 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `uint32`. +// +// The JSON representation for `UInt32Value` is JSON number. +type UInt32Value struct { + // The uint32 value. + Value uint32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UInt32Value) Reset() { *m = UInt32Value{} } +func (m *UInt32Value) String() string { return proto.CompactTextString(m) } +func (*UInt32Value) ProtoMessage() {} +func (*UInt32Value) Descriptor() ([]byte, []int) { + return fileDescriptor_wrappers_16c7c35c009f3253, []int{5} +} +func (*UInt32Value) XXX_WellKnownType() string { return "UInt32Value" } +func (m *UInt32Value) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UInt32Value.Unmarshal(m, b) +} +func (m *UInt32Value) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UInt32Value.Marshal(b, m, deterministic) +} +func (dst *UInt32Value) XXX_Merge(src proto.Message) { + xxx_messageInfo_UInt32Value.Merge(dst, src) +} +func (m *UInt32Value) XXX_Size() int { + return xxx_messageInfo_UInt32Value.Size(m) +} +func (m *UInt32Value) XXX_DiscardUnknown() { + xxx_messageInfo_UInt32Value.DiscardUnknown(m) +} + +var xxx_messageInfo_UInt32Value proto.InternalMessageInfo + +func (m *UInt32Value) GetValue() uint32 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `bool`. +// +// The JSON representation for `BoolValue` is JSON `true` and `false`. +type BoolValue struct { + // The bool value. + Value bool `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BoolValue) Reset() { *m = BoolValue{} } +func (m *BoolValue) String() string { return proto.CompactTextString(m) } +func (*BoolValue) ProtoMessage() {} +func (*BoolValue) Descriptor() ([]byte, []int) { + return fileDescriptor_wrappers_16c7c35c009f3253, []int{6} +} +func (*BoolValue) XXX_WellKnownType() string { return "BoolValue" } +func (m *BoolValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BoolValue.Unmarshal(m, b) +} +func (m *BoolValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BoolValue.Marshal(b, m, deterministic) +} +func (dst *BoolValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_BoolValue.Merge(dst, src) +} +func (m *BoolValue) XXX_Size() int { + return xxx_messageInfo_BoolValue.Size(m) +} +func (m *BoolValue) XXX_DiscardUnknown() { + xxx_messageInfo_BoolValue.DiscardUnknown(m) +} + +var xxx_messageInfo_BoolValue proto.InternalMessageInfo + +func (m *BoolValue) GetValue() bool { + if m != nil { + return m.Value + } + return false +} + +// Wrapper message for `string`. +// +// The JSON representation for `StringValue` is JSON string. +type StringValue struct { + // The string value. + Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StringValue) Reset() { *m = StringValue{} } +func (m *StringValue) String() string { return proto.CompactTextString(m) } +func (*StringValue) ProtoMessage() {} +func (*StringValue) Descriptor() ([]byte, []int) { + return fileDescriptor_wrappers_16c7c35c009f3253, []int{7} +} +func (*StringValue) XXX_WellKnownType() string { return "StringValue" } +func (m *StringValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StringValue.Unmarshal(m, b) +} +func (m *StringValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StringValue.Marshal(b, m, deterministic) +} +func (dst *StringValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_StringValue.Merge(dst, src) +} +func (m *StringValue) XXX_Size() int { + return xxx_messageInfo_StringValue.Size(m) +} +func (m *StringValue) XXX_DiscardUnknown() { + xxx_messageInfo_StringValue.DiscardUnknown(m) +} + +var xxx_messageInfo_StringValue proto.InternalMessageInfo + +func (m *StringValue) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +// Wrapper message for `bytes`. +// +// The JSON representation for `BytesValue` is JSON string. +type BytesValue struct { + // The bytes value. + Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BytesValue) Reset() { *m = BytesValue{} } +func (m *BytesValue) String() string { return proto.CompactTextString(m) } +func (*BytesValue) ProtoMessage() {} +func (*BytesValue) Descriptor() ([]byte, []int) { + return fileDescriptor_wrappers_16c7c35c009f3253, []int{8} +} +func (*BytesValue) XXX_WellKnownType() string { return "BytesValue" } +func (m *BytesValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BytesValue.Unmarshal(m, b) +} +func (m *BytesValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BytesValue.Marshal(b, m, deterministic) +} +func (dst *BytesValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_BytesValue.Merge(dst, src) +} +func (m *BytesValue) XXX_Size() int { + return xxx_messageInfo_BytesValue.Size(m) +} +func (m *BytesValue) XXX_DiscardUnknown() { + xxx_messageInfo_BytesValue.DiscardUnknown(m) +} + +var xxx_messageInfo_BytesValue proto.InternalMessageInfo + +func (m *BytesValue) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func init() { + proto.RegisterType((*DoubleValue)(nil), "google.protobuf.DoubleValue") + proto.RegisterType((*FloatValue)(nil), "google.protobuf.FloatValue") + proto.RegisterType((*Int64Value)(nil), "google.protobuf.Int64Value") + proto.RegisterType((*UInt64Value)(nil), "google.protobuf.UInt64Value") + proto.RegisterType((*Int32Value)(nil), "google.protobuf.Int32Value") + proto.RegisterType((*UInt32Value)(nil), "google.protobuf.UInt32Value") + proto.RegisterType((*BoolValue)(nil), "google.protobuf.BoolValue") + proto.RegisterType((*StringValue)(nil), "google.protobuf.StringValue") + proto.RegisterType((*BytesValue)(nil), "google.protobuf.BytesValue") +} + +func init() { + proto.RegisterFile("google/protobuf/wrappers.proto", fileDescriptor_wrappers_16c7c35c009f3253) +} + +var fileDescriptor_wrappers_16c7c35c009f3253 = []byte{ + // 259 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f, + 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x2f, 0x4a, 0x2c, + 0x28, 0x48, 0x2d, 0x2a, 0xd6, 0x03, 0x8b, 0x08, 0xf1, 0x43, 0xe4, 0xf5, 0x60, 0xf2, 0x4a, 0xca, + 0x5c, 0xdc, 0x2e, 0xf9, 0xa5, 0x49, 0x39, 0xa9, 0x61, 0x89, 0x39, 0xa5, 0xa9, 0x42, 0x22, 0x5c, + 0xac, 0x65, 0x20, 0x86, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x63, 0x10, 0x84, 0xa3, 0xa4, 0xc4, 0xc5, + 0xe5, 0x96, 0x93, 0x9f, 0x58, 0x82, 0x45, 0x0d, 0x13, 0x92, 0x1a, 0xcf, 0xbc, 0x12, 0x33, 0x13, + 0x2c, 0x6a, 0x98, 0x61, 0x6a, 0x94, 0xb9, 0xb8, 0x43, 0x71, 0x29, 0x62, 0x41, 0x35, 0xc8, 0xd8, + 0x08, 0x8b, 0x1a, 0x56, 0x34, 0x83, 0xb0, 0x2a, 0xe2, 0x85, 0x29, 0x52, 0xe4, 0xe2, 0x74, 0xca, + 0xcf, 0xcf, 0xc1, 0xa2, 0x84, 0x03, 0xc9, 0x9c, 0xe0, 0x92, 0xa2, 0xcc, 0xbc, 0x74, 0x2c, 0x8a, + 0x38, 0x91, 0x1c, 0xe4, 0x54, 0x59, 0x92, 0x5a, 0x8c, 0x45, 0x0d, 0x0f, 0x54, 0x8d, 0x53, 0x0d, + 0x97, 0x70, 0x72, 0x7e, 0xae, 0x1e, 0x5a, 0xe8, 0x3a, 0xf1, 0x86, 0x43, 0x83, 0x3f, 0x00, 0x24, + 0x12, 0xc0, 0x18, 0xa5, 0x95, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x9f, + 0x9e, 0x9f, 0x93, 0x98, 0x97, 0x8e, 0x88, 0xaa, 0x82, 0x92, 0xca, 0x82, 0xd4, 0x62, 0x78, 0x8c, + 0xfd, 0x60, 0x64, 0x5c, 0xc4, 0xc4, 0xec, 0x1e, 0xe0, 0xb4, 0x8a, 0x49, 0xce, 0x1d, 0x62, 0x6e, + 0x00, 0x54, 0xa9, 0x5e, 0x78, 0x6a, 0x4e, 0x8e, 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0x48, 0x4b, + 0x12, 0x1b, 0xd8, 0x0c, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x19, 0x6c, 0xb9, 0xb8, 0xfe, + 0x01, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/empty/empty.proto b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto similarity index 51% rename from vendor/github.com/golang/protobuf/ptypes/empty/empty.proto rename to vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto index 03cacd23308..01947639ac4 100644 --- a/vendor/github.com/golang/protobuf/ptypes/empty/empty.proto +++ b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto @@ -28,25 +28,91 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Wrappers for primitive (non-message) types. These types are useful +// for embedding primitives in the `google.protobuf.Any` type and for places +// where we need to distinguish between the absence of a primitive +// typed field and its default value. + syntax = "proto3"; package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option go_package = "github.com/golang/protobuf/ptypes/empty"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/wrappers"; option java_package = "com.google.protobuf"; -option java_outer_classname = "EmptyProto"; +option java_outer_classname = "WrappersProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; -option cc_enable_arenas = true; -// 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: +// Wrapper message for `double`. // -// service Foo { -// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); -// } +// The JSON representation for `DoubleValue` is JSON number. +message DoubleValue { + // The double value. + double value = 1; +} + +// Wrapper message for `float`. // -// The JSON representation for `Empty` is empty JSON object `{}`. -message Empty {} +// The JSON representation for `FloatValue` is JSON number. +message FloatValue { + // The float value. + float value = 1; +} + +// Wrapper message for `int64`. +// +// The JSON representation for `Int64Value` is JSON string. +message Int64Value { + // The int64 value. + int64 value = 1; +} + +// Wrapper message for `uint64`. +// +// The JSON representation for `UInt64Value` is JSON string. +message UInt64Value { + // The uint64 value. + uint64 value = 1; +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +message Int32Value { + // The int32 value. + int32 value = 1; +} + +// Wrapper message for `uint32`. +// +// The JSON representation for `UInt32Value` is JSON number. +message UInt32Value { + // The uint32 value. + uint32 value = 1; +} + +// Wrapper message for `bool`. +// +// The JSON representation for `BoolValue` is JSON `true` and `false`. +message BoolValue { + // The bool value. + bool value = 1; +} + +// Wrapper message for `string`. +// +// The JSON representation for `StringValue` is JSON string. +message StringValue { + // The string value. + string value = 1; +} + +// Wrapper message for `bytes`. +// +// The JSON representation for `BytesValue` is JSON string. +message BytesValue { + // The bytes value. + bytes value = 1; +} diff --git a/vendor/github.com/google/cadvisor/cache/memory/memory.go b/vendor/github.com/google/cadvisor/cache/memory/memory.go index ae8eb899d8b..038f9b17aa7 100644 --- a/vendor/github.com/google/cadvisor/cache/memory/memory.go +++ b/vendor/github.com/google/cadvisor/cache/memory/memory.go @@ -70,16 +70,16 @@ type InMemoryCache struct { backend storage.StorageDriver } -func (self *InMemoryCache) AddStats(ref info.ContainerReference, stats *info.ContainerStats) error { +func (self *InMemoryCache) AddStats(cInfo *info.ContainerInfo, stats *info.ContainerStats) error { var cstore *containerCache var ok bool func() { self.lock.Lock() defer self.lock.Unlock() - if cstore, ok = self.containerCacheMap[ref.Name]; !ok { - cstore = newContainerStore(ref, self.maxAge) - self.containerCacheMap[ref.Name] = cstore + if cstore, ok = self.containerCacheMap[cInfo.ContainerReference.Name]; !ok { + cstore = newContainerStore(cInfo.ContainerReference, self.maxAge) + self.containerCacheMap[cInfo.ContainerReference.Name] = cstore } }() @@ -87,7 +87,7 @@ func (self *InMemoryCache) AddStats(ref info.ContainerReference, stats *info.Con // TODO(monnand): To deal with long delay write operations, we // may want to start a pool of goroutines to do write // operations. - if err := self.backend.AddStats(ref, stats); err != nil { + if err := self.backend.AddStats(cInfo, stats); err != nil { glog.Error(err) } } diff --git a/vendor/github.com/google/cadvisor/container/containerd/BUILD b/vendor/github.com/google/cadvisor/container/containerd/BUILD index 8dfb3469b72..bc635f38a34 100644 --- a/vendor/github.com/google/cadvisor/container/containerd/BUILD +++ b/vendor/github.com/google/cadvisor/container/containerd/BUILD @@ -18,15 +18,14 @@ go_library( "//vendor/github.com/containerd/containerd/dialer:go_default_library", "//vendor/github.com/containerd/containerd/errdefs:go_default_library", "//vendor/github.com/containerd/containerd/namespaces:go_default_library", + "//vendor/github.com/gogo/protobuf/types:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/golang/protobuf/ptypes/empty:go_default_library", "//vendor/github.com/google/cadvisor/container:go_default_library", "//vendor/github.com/google/cadvisor/container/common:go_default_library", "//vendor/github.com/google/cadvisor/container/libcontainer:go_default_library", "//vendor/github.com/google/cadvisor/fs:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library", "//vendor/github.com/google/cadvisor/manager/watcher:go_default_library", - "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library", "//vendor/github.com/opencontainers/runtime-spec/specs-go:go_default_library", diff --git a/vendor/github.com/google/cadvisor/container/containerd/client.go b/vendor/github.com/google/cadvisor/container/containerd/client.go index 365f54a71ac..4eccf4f6b66 100644 --- a/vendor/github.com/google/cadvisor/container/containerd/client.go +++ b/vendor/github.com/google/cadvisor/container/containerd/client.go @@ -16,6 +16,8 @@ package containerd import ( "context" + "fmt" + "net" "sync" "time" @@ -25,7 +27,7 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/dialer" "github.com/containerd/containerd/errdefs" - pempty "github.com/golang/protobuf/ptypes/empty" + ptypes "github.com/gogo/protobuf/types" "google.golang.org/grpc" ) @@ -49,16 +51,29 @@ type containerdClient interface { var once sync.Once var ctrdClient containerdClient = nil +const ( + address = "/run/containerd/containerd.sock" + maxBackoffDelay = 3 * time.Second + connectionTimeout = 2 * time.Second +) + // Client creates a containerd client func Client() (containerdClient, error) { var retErr error once.Do(func() { + tryConn, err := net.DialTimeout("unix", address, connectionTimeout) + if err != nil { + retErr = fmt.Errorf("containerd: cannot unix dial containerd api service: %v", err) + return + } + tryConn.Close() + gopts := []grpc.DialOption{ grpc.WithInsecure(), grpc.WithDialer(dialer.Dialer), grpc.WithBlock(), - grpc.WithTimeout(2 * time.Second), - grpc.WithBackoffMaxDelay(3 * time.Second), + grpc.WithBackoffMaxDelay(maxBackoffDelay), + grpc.WithTimeout(connectionTimeout), } unary, stream := newNSInterceptors(k8sNamespace) gopts = append(gopts, @@ -66,7 +81,7 @@ func Client() (containerdClient, error) { grpc.WithStreamInterceptor(stream), ) - conn, err := grpc.Dial(dialer.DialAddress("/var/run/containerd/containerd.sock"), gopts...) + conn, err := grpc.Dial(dialer.DialAddress(address), gopts...) if err != nil { retErr = err return @@ -101,7 +116,7 @@ func (c *client) TaskPid(ctx context.Context, id string) (uint32, error) { } func (c *client) Version(ctx context.Context) (string, error) { - response, err := c.versionService.Version(ctx, &pempty.Empty{}) + response, err := c.versionService.Version(ctx, &ptypes.Empty{}) if err != nil { return "", errdefs.FromGRPC(err) } diff --git a/vendor/github.com/google/cadvisor/container/containerd/handler.go b/vendor/github.com/google/cadvisor/container/containerd/handler.go index 52ab24018d3..a8095f42703 100644 --- a/vendor/github.com/google/cadvisor/container/containerd/handler.go +++ b/vendor/github.com/google/cadvisor/container/containerd/handler.go @@ -23,7 +23,6 @@ import ( "time" "github.com/containerd/containerd/errdefs" - "github.com/opencontainers/runc/libcontainer/cgroups" cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs" libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs" "golang.org/x/net/context" @@ -37,31 +36,21 @@ import ( ) type containerdContainerHandler struct { - client containerdClient - name string - id string - aliases []string machineInfoFactory info.MachineInfoFactory // Absolute path to the cgroup hierarchies of this container. // (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test") cgroupPaths map[string]string - // Manager of this container's cgroups. - cgroupManager cgroups.Manager - fsInfo fs.FsInfo - poolName string - // Time at which this container was created. - creationTime time.Time + fsInfo fs.FsInfo // Metadata associated with the container. - labels map[string]string - envs map[string]string - // The container PID used to switch namespaces as required - pid int + reference info.ContainerReference + envs map[string]string + labels map[string]string // Image name used for this container. image string - // The host root FS to read - rootFs string // Filesystem handler. ignoreMetrics container.MetricSet + + libcontainerHandler *containerlibcontainer.Handler } var _ container.ContainerHandler = &containerdContainerHandler{} @@ -131,25 +120,27 @@ func newContainerdContainerHandler( rootfs = "/rootfs" } + containerReference := info.ContainerReference{ + Id: id, + Name: name, + Namespace: k8sContainerdNamespace, + Aliases: []string{id, name}, + } + + libcontainerHandler := containerlibcontainer.NewHandler(cgroupManager, rootfs, int(taskPid), ignoreMetrics) + handler := &containerdContainerHandler{ - id: id, - client: client, - name: name, - machineInfoFactory: machineInfoFactory, - cgroupPaths: cgroupPaths, - cgroupManager: cgroupManager, - rootFs: rootfs, - fsInfo: fsInfo, - envs: make(map[string]string), - labels: make(map[string]string), - ignoreMetrics: ignoreMetrics, - pid: int(taskPid), - creationTime: cntr.CreatedAt, + machineInfoFactory: machineInfoFactory, + cgroupPaths: cgroupPaths, + fsInfo: fsInfo, + envs: make(map[string]string), + labels: cntr.Labels, + ignoreMetrics: ignoreMetrics, + reference: containerReference, + libcontainerHandler: libcontainerHandler, } // Add the name and bare ID as aliases of the container. - handler.labels = cntr.Labels handler.image = cntr.Image - handler.aliases = []string{id, name} for _, envVar := range spec.Process.Env { if envVar != "" { splits := strings.SplitN(envVar, "=", 2) @@ -163,13 +154,7 @@ func newContainerdContainerHandler( } func (self *containerdContainerHandler) ContainerReference() (info.ContainerReference, error) { - return info.ContainerReference{ - Id: self.id, - Name: self.name, - Namespace: k8sContainerdNamespace, - Labels: self.labels, - Aliases: self.aliases, - }, nil + return self.reference, nil } func (self *containerdContainerHandler) needNet() bool { @@ -208,7 +193,7 @@ func (self *containerdContainerHandler) getFsStats(stats *info.ContainerStats) e } func (self *containerdContainerHandler) GetStats() (*info.ContainerStats, error) { - stats, err := containerlibcontainer.GetStats(self.cgroupManager, self.rootFs, self.pid, self.ignoreMetrics) + stats, err := self.libcontainerHandler.GetStats() if err != nil { return stats, err } @@ -232,7 +217,7 @@ func (self *containerdContainerHandler) ListContainers(listType container.ListTy func (self *containerdContainerHandler) GetCgroupPath(resource string) (string, error) { path, ok := self.cgroupPaths[resource] if !ok { - return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, self.name) + return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, self.reference.Name) } return path, nil } @@ -242,7 +227,7 @@ func (self *containerdContainerHandler) GetContainerLabels() map[string]string { } func (self *containerdContainerHandler) ListProcesses(listType container.ListType) ([]int, error) { - return containerlibcontainer.GetProcesses(self.cgroupManager) + return self.libcontainerHandler.GetProcesses() } func (self *containerdContainerHandler) Exists() bool { diff --git a/vendor/github.com/google/cadvisor/container/crio/BUILD b/vendor/github.com/google/cadvisor/container/crio/BUILD index be1b74e7db5..975a35e24c8 100644 --- a/vendor/github.com/google/cadvisor/container/crio/BUILD +++ b/vendor/github.com/google/cadvisor/container/crio/BUILD @@ -17,7 +17,6 @@ go_library( "//vendor/github.com/google/cadvisor/fs:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library", "//vendor/github.com/google/cadvisor/manager/watcher:go_default_library", - "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library", ], diff --git a/vendor/github.com/google/cadvisor/container/crio/handler.go b/vendor/github.com/google/cadvisor/container/crio/handler.go index 024341da8ab..13311c57fee 100644 --- a/vendor/github.com/google/cadvisor/container/crio/handler.go +++ b/vendor/github.com/google/cadvisor/container/crio/handler.go @@ -21,7 +21,6 @@ import ( "path/filepath" "strconv" "strings" - "time" "github.com/google/cadvisor/container" "github.com/google/cadvisor/container/common" @@ -29,48 +28,32 @@ import ( "github.com/google/cadvisor/fs" info "github.com/google/cadvisor/info/v1" - "github.com/opencontainers/runc/libcontainer/cgroups" cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs" libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs" ) type crioContainerHandler struct { - name string - id string - aliases []string machineInfoFactory info.MachineInfoFactory // Absolute path to the cgroup hierarchies of this container. // (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test") cgroupPaths map[string]string - // Manager of this container's cgroups. - cgroupManager cgroups.Manager - // the CRI-O storage driver storageDriver storageDriver fsInfo fs.FsInfo rootfsStorageDir string - // Time at which this container was created. - creationTime time.Time - // Metadata associated with the container. - labels map[string]string envs map[string]string + labels map[string]string // TODO // crio version handling... - // The container PID used to switch namespaces as required - pid int - // Image name used for this container. image string - // The host root FS to read - rootFs string - // The network mode of the container // TODO @@ -84,6 +67,10 @@ type crioContainerHandler struct { // container restart count restartCount int + + reference info.ContainerReference + + libcontainerHandler *containerlibcontainer.Handler } var _ container.ContainerHandler = &crioContainerHandler{} @@ -150,25 +137,29 @@ func newCrioContainerHandler( rootfsStorageDir = filepath.Join(rootfsStorageDir, "diff") } - // TODO: extract object mother method - handler := &crioContainerHandler{ - id: id, - name: name, - machineInfoFactory: machineInfoFactory, - cgroupPaths: cgroupPaths, - cgroupManager: cgroupManager, - storageDriver: storageDriver, - fsInfo: fsInfo, - rootFs: rootFs, - rootfsStorageDir: rootfsStorageDir, - envs: make(map[string]string), - ignoreMetrics: ignoreMetrics, + containerReference := info.ContainerReference{ + Id: id, + Name: name, + Aliases: []string{cInfo.Name, id}, + Namespace: CrioNamespace, + } + + libcontainerHandler := containerlibcontainer.NewHandler(cgroupManager, rootFs, cInfo.Pid, ignoreMetrics) + + // TODO: extract object mother method + handler := &crioContainerHandler{ + machineInfoFactory: machineInfoFactory, + cgroupPaths: cgroupPaths, + storageDriver: storageDriver, + fsInfo: fsInfo, + rootfsStorageDir: rootfsStorageDir, + envs: make(map[string]string), + labels: cInfo.Labels, + ignoreMetrics: ignoreMetrics, + reference: containerReference, + libcontainerHandler: libcontainerHandler, } - handler.creationTime = time.Unix(0, cInfo.CreatedTime) - handler.pid = cInfo.Pid - handler.aliases = append(handler.aliases, cInfo.Name, id) - handler.labels = cInfo.Labels handler.image = cInfo.Image // TODO: we wantd to know graph driver DeviceId (dont think this is needed now) @@ -204,13 +195,7 @@ func (self *crioContainerHandler) Cleanup() { } func (self *crioContainerHandler) ContainerReference() (info.ContainerReference, error) { - return info.ContainerReference{ - Id: self.id, - Name: self.name, - Aliases: self.aliases, - Namespace: CrioNamespace, - Labels: self.labels, - }, nil + return self.reference, nil } func (self *crioContainerHandler) needNet() bool { @@ -286,7 +271,7 @@ func (self *crioContainerHandler) getFsStats(stats *info.ContainerStats) error { } func (self *crioContainerHandler) GetStats() (*info.ContainerStats, error) { - stats, err := containerlibcontainer.GetStats(self.cgroupManager, self.rootFs, self.pid, self.ignoreMetrics) + stats, err := self.libcontainerHandler.GetStats() if err != nil { return stats, err } @@ -315,7 +300,7 @@ func (self *crioContainerHandler) ListContainers(listType container.ListType) ([ func (self *crioContainerHandler) GetCgroupPath(resource string) (string, error) { path, ok := self.cgroupPaths[resource] if !ok { - return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, self.name) + return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, self.reference.Name) } return path, nil } @@ -329,7 +314,7 @@ func (self *crioContainerHandler) GetContainerIPAddress() string { } func (self *crioContainerHandler) ListProcesses(listType container.ListType) ([]int, error) { - return containerlibcontainer.GetProcesses(self.cgroupManager) + return self.libcontainerHandler.GetProcesses() } func (self *crioContainerHandler) Exists() bool { diff --git a/vendor/github.com/google/cadvisor/container/docker/BUILD b/vendor/github.com/google/cadvisor/container/docker/BUILD index 905d8714f40..74d2590e76f 100644 --- a/vendor/github.com/google/cadvisor/container/docker/BUILD +++ b/vendor/github.com/google/cadvisor/container/docker/BUILD @@ -27,7 +27,6 @@ go_library( "//vendor/github.com/google/cadvisor/manager/watcher:go_default_library", "//vendor/github.com/google/cadvisor/utils/docker:go_default_library", "//vendor/github.com/google/cadvisor/zfs:go_default_library", - "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library", "//vendor/golang.org/x/net/context:go_default_library", diff --git a/vendor/github.com/google/cadvisor/container/docker/handler.go b/vendor/github.com/google/cadvisor/container/docker/handler.go index 8f63d02eb04..22b9455f3f3 100644 --- a/vendor/github.com/google/cadvisor/container/docker/handler.go +++ b/vendor/github.com/google/cadvisor/container/docker/handler.go @@ -35,7 +35,6 @@ import ( dockercontainer "github.com/docker/docker/api/types/container" docker "github.com/docker/docker/client" "github.com/golang/glog" - "github.com/opencontainers/runc/libcontainer/cgroups" cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs" libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs" "golang.org/x/net/context" @@ -52,53 +51,29 @@ const ( ) type dockerContainerHandler struct { - client *docker.Client - name string - id string - aliases []string + + // machineInfoFactory provides info.MachineInfo machineInfoFactory info.MachineInfoFactory // Absolute path to the cgroup hierarchies of this container. // (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test") cgroupPaths map[string]string - // Manager of this container's cgroups. - cgroupManager cgroups.Manager - // the docker storage driver storageDriver storageDriver fsInfo fs.FsInfo rootfsStorageDir string - // devicemapper state - - // the devicemapper poolname - poolName string - // the devicemapper device id for the container - deviceID string - - // zfs Filesystem - zfsFilesystem string - - // zfsParent is the parent for docker zfs - zfsParent string - // Time at which this container was created. creationTime time.Time // Metadata associated with the container. - labels map[string]string envs map[string]string - - // The container PID used to switch namespaces as required - pid int + labels map[string]string // Image name used for this container. image string - // The host root FS to read - rootFs string - // The network mode of the container networkMode dockercontainer.NetworkMode @@ -110,14 +85,19 @@ type dockerContainerHandler struct { ignoreMetrics container.MetricSet - // thin pool watcher - thinPoolWatcher *devicemapper.ThinPoolWatcher + // the devicemapper poolname + poolName string - // zfs watcher - zfsWatcher *zfs.ZfsWatcher + // zfsParent is the parent for docker zfs + zfsParent string // container restart count restartCount int + + // Reference to the container + reference info.ContainerReference + + libcontainerHandler *containerlibcontainer.Handler } var _ container.ContainerHandler = &dockerContainerHandler{} @@ -210,46 +190,42 @@ func newDockerContainerHandler( zfsFilesystem = path.Join(zfsParent, rwLayerID) } - // TODO: extract object mother method - handler := &dockerContainerHandler{ - id: id, - client: client, - name: name, - machineInfoFactory: machineInfoFactory, - cgroupPaths: cgroupPaths, - cgroupManager: cgroupManager, - storageDriver: storageDriver, - fsInfo: fsInfo, - rootFs: rootFs, - poolName: thinPoolName, - zfsFilesystem: zfsFilesystem, - rootfsStorageDir: rootfsStorageDir, - envs: make(map[string]string), - ignoreMetrics: ignoreMetrics, - thinPoolWatcher: thinPoolWatcher, - zfsWatcher: zfsWatcher, - zfsParent: zfsParent, - } - // We assume that if Inspect fails then the container is not known to docker. ctnr, err := client.ContainerInspect(context.Background(), id) if err != nil { return nil, fmt.Errorf("failed to inspect container %q: %v", id, err) } + + // TODO: extract object mother method + handler := &dockerContainerHandler{ + machineInfoFactory: machineInfoFactory, + cgroupPaths: cgroupPaths, + fsInfo: fsInfo, + storageDriver: storageDriver, + poolName: thinPoolName, + rootfsStorageDir: rootfsStorageDir, + envs: make(map[string]string), + labels: ctnr.Config.Labels, + ignoreMetrics: ignoreMetrics, + zfsParent: zfsParent, + } // Timestamp returned by Docker is in time.RFC3339Nano format. handler.creationTime, err = time.Parse(time.RFC3339Nano, ctnr.Created) if err != nil { // This should not happen, report the error just in case return nil, fmt.Errorf("failed to parse the create timestamp %q for container %q: %v", ctnr.Created, id, err) } - handler.pid = ctnr.State.Pid + handler.libcontainerHandler = containerlibcontainer.NewHandler(cgroupManager, rootFs, ctnr.State.Pid, ignoreMetrics) // Add the name and bare ID as aliases of the container. - handler.aliases = append(handler.aliases, strings.TrimPrefix(ctnr.Name, "/"), id) - handler.labels = ctnr.Config.Labels + handler.reference = info.ContainerReference{ + Id: id, + Name: name, + Aliases: []string{strings.TrimPrefix(ctnr.Name, "/"), id}, + Namespace: DockerNamespace, + } handler.image = ctnr.Config.Image handler.networkMode = ctnr.HostConfig.NetworkMode - handler.deviceID = ctnr.GraphDriver.Data["DeviceId"] handler.restartCount = ctnr.RestartCount // Obtain the IP address for the contianer. @@ -273,7 +249,7 @@ func newDockerContainerHandler( fsHandler: common.NewFsHandler(common.DefaultPeriod, rootfsStorageDir, otherStorageDir, fsInfo), thinPoolWatcher: thinPoolWatcher, zfsWatcher: zfsWatcher, - deviceID: handler.deviceID, + deviceID: ctnr.GraphDriver.Data["DeviceId"], zfsFilesystem: zfsFilesystem, } } @@ -365,13 +341,7 @@ func (self *dockerContainerHandler) Cleanup() { } func (self *dockerContainerHandler) ContainerReference() (info.ContainerReference, error) { - return info.ContainerReference{ - Id: self.id, - Name: self.name, - Aliases: self.aliases, - Namespace: DockerNamespace, - Labels: self.labels, - }, nil + return self.reference, nil } func (self *dockerContainerHandler) needNet() bool { @@ -455,7 +425,7 @@ func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error // TODO(vmarmol): Get from libcontainer API instead of cgroup manager when we don't have to support older Dockers. func (self *dockerContainerHandler) GetStats() (*info.ContainerStats, error) { - stats, err := containerlibcontainer.GetStats(self.cgroupManager, self.rootFs, self.pid, self.ignoreMetrics) + stats, err := self.libcontainerHandler.GetStats() if err != nil { return stats, err } @@ -484,7 +454,7 @@ func (self *dockerContainerHandler) ListContainers(listType container.ListType) func (self *dockerContainerHandler) GetCgroupPath(resource string) (string, error) { path, ok := self.cgroupPaths[resource] if !ok { - return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, self.name) + return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, self.reference.Name) } return path, nil } @@ -498,7 +468,7 @@ func (self *dockerContainerHandler) GetContainerIPAddress() string { } func (self *dockerContainerHandler) ListProcesses(listType container.ListType) ([]int, error) { - return containerlibcontainer.GetProcesses(self.cgroupManager) + return self.libcontainerHandler.GetProcesses() } func (self *dockerContainerHandler) Exists() bool { diff --git a/vendor/github.com/google/cadvisor/container/factory.go b/vendor/github.com/google/cadvisor/container/factory.go index 07445f9dd70..cf5b463e0e4 100644 --- a/vendor/github.com/google/cadvisor/container/factory.go +++ b/vendor/github.com/google/cadvisor/container/factory.go @@ -41,16 +41,17 @@ type ContainerHandlerFactory interface { type MetricKind string const ( - CpuUsageMetrics MetricKind = "cpu" - PerCpuUsageMetrics MetricKind = "percpu" - MemoryUsageMetrics MetricKind = "memory" - CpuLoadMetrics MetricKind = "cpuLoad" - DiskIOMetrics MetricKind = "diskIO" - DiskUsageMetrics MetricKind = "disk" - NetworkUsageMetrics MetricKind = "network" - NetworkTcpUsageMetrics MetricKind = "tcp" - NetworkUdpUsageMetrics MetricKind = "udp" - AppMetrics MetricKind = "app" + CpuUsageMetrics MetricKind = "cpu" + ProcessSchedulerMetrics MetricKind = "sched" + PerCpuUsageMetrics MetricKind = "percpu" + MemoryUsageMetrics MetricKind = "memory" + CpuLoadMetrics MetricKind = "cpuLoad" + DiskIOMetrics MetricKind = "diskIO" + DiskUsageMetrics MetricKind = "disk" + NetworkUsageMetrics MetricKind = "network" + NetworkTcpUsageMetrics MetricKind = "tcp" + NetworkUdpUsageMetrics MetricKind = "udp" + AppMetrics MetricKind = "app" ) func (mk MetricKind) String() string { diff --git a/vendor/github.com/google/cadvisor/container/libcontainer/BUILD b/vendor/github.com/google/cadvisor/container/libcontainer/BUILD index 65cfd748b89..b414dc055b2 100644 --- a/vendor/github.com/google/cadvisor/container/libcontainer/BUILD +++ b/vendor/github.com/google/cadvisor/container/libcontainer/BUILD @@ -2,7 +2,10 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", - srcs = ["helpers.go"], + srcs = [ + "handler.go", + "helpers.go", + ], cgo = True, importpath = "github.com/google/cadvisor/container/libcontainer", visibility = ["//visibility:public"], diff --git a/vendor/github.com/google/cadvisor/container/libcontainer/handler.go b/vendor/github.com/google/cadvisor/container/libcontainer/handler.go new file mode 100644 index 00000000000..9bc5f653ba8 --- /dev/null +++ b/vendor/github.com/google/cadvisor/container/libcontainer/handler.go @@ -0,0 +1,566 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 libcontainer + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "os" + "path" + "strconv" + "strings" + "time" + + "github.com/google/cadvisor/container" + info "github.com/google/cadvisor/info/v1" + + "bytes" + "github.com/golang/glog" + "github.com/opencontainers/runc/libcontainer" + "github.com/opencontainers/runc/libcontainer/cgroups" +) + +/* +#include +*/ +import "C" + +type Handler struct { + cgroupManager cgroups.Manager + rootFs string + pid int + ignoreMetrics container.MetricSet + pidMetricsCache map[int]*info.CpuSchedstat +} + +func NewHandler(cgroupManager cgroups.Manager, rootFs string, pid int, ignoreMetrics container.MetricSet) *Handler { + return &Handler{ + cgroupManager: cgroupManager, + rootFs: rootFs, + pid: pid, + ignoreMetrics: ignoreMetrics, + pidMetricsCache: make(map[int]*info.CpuSchedstat), + } +} + +// Get cgroup and networking stats of the specified container +func (h *Handler) GetStats() (*info.ContainerStats, error) { + cgroupStats, err := h.cgroupManager.GetStats() + if err != nil { + return nil, err + } + libcontainerStats := &libcontainer.Stats{ + CgroupStats: cgroupStats, + } + withPerCPU := !h.ignoreMetrics.Has(container.PerCpuUsageMetrics) + stats := newContainerStats(libcontainerStats, withPerCPU) + + if !h.ignoreMetrics.Has(container.ProcessSchedulerMetrics) { + pids, err := h.cgroupManager.GetAllPids() + if err != nil { + glog.V(4).Infof("Could not get PIDs for container %d: %v", h.pid, err) + } else { + stats.Cpu.Schedstat, err = schedulerStatsFromProcs(h.rootFs, pids, h.pidMetricsCache) + if err != nil { + glog.V(4).Infof("Unable to get Process Scheduler Stats: %v", err) + } + } + } + + // If we know the pid then get network stats from /proc//net/dev + if h.pid == 0 { + return stats, nil + } + if !h.ignoreMetrics.Has(container.NetworkUsageMetrics) { + netStats, err := networkStatsFromProc(h.rootFs, h.pid) + if err != nil { + glog.V(4).Infof("Unable to get network stats from pid %d: %v", h.pid, err) + } else { + stats.Network.Interfaces = append(stats.Network.Interfaces, netStats...) + } + } + if !h.ignoreMetrics.Has(container.NetworkTcpUsageMetrics) { + t, err := tcpStatsFromProc(h.rootFs, h.pid, "net/tcp") + if err != nil { + glog.V(4).Infof("Unable to get tcp stats from pid %d: %v", h.pid, err) + } else { + stats.Network.Tcp = t + } + + t6, err := tcpStatsFromProc(h.rootFs, h.pid, "net/tcp6") + if err != nil { + glog.V(4).Infof("Unable to get tcp6 stats from pid %d: %v", h.pid, err) + } else { + stats.Network.Tcp6 = t6 + } + } + if !h.ignoreMetrics.Has(container.NetworkUdpUsageMetrics) { + u, err := udpStatsFromProc(h.rootFs, h.pid, "net/udp") + if err != nil { + glog.V(4).Infof("Unable to get udp stats from pid %d: %v", h.pid, err) + } else { + stats.Network.Udp = u + } + + u6, err := udpStatsFromProc(h.rootFs, h.pid, "net/udp6") + if err != nil { + glog.V(4).Infof("Unable to get udp6 stats from pid %d: %v", h.pid, err) + } else { + stats.Network.Udp6 = u6 + } + } + + // For backwards compatibility. + if len(stats.Network.Interfaces) > 0 { + stats.Network.InterfaceStats = stats.Network.Interfaces[0] + } + + return stats, nil +} + +func schedulerStatsFromProcs(rootFs string, pids []int, pidMetricsCache map[int]*info.CpuSchedstat) (info.CpuSchedstat, error) { + for _, pid := range pids { + f, err := os.Open(path.Join(rootFs, "proc", strconv.Itoa(pid), "schedstat")) + if err != nil { + return info.CpuSchedstat{}, fmt.Errorf("couldn't open scheduler statistics for process %d: %v", pid, err) + } + defer f.Close() + contents, err := ioutil.ReadAll(f) + if err != nil { + return info.CpuSchedstat{}, fmt.Errorf("couldn't read scheduler statistics for process %d: %v", pid, err) + } + rawMetrics := bytes.Split(bytes.TrimRight(contents, "\n"), []byte(" ")) + if len(rawMetrics) != 3 { + return info.CpuSchedstat{}, fmt.Errorf("unexpected number of metrics in schedstat file for process %d", pid) + } + cacheEntry, ok := pidMetricsCache[pid] + if !ok { + cacheEntry = &info.CpuSchedstat{} + pidMetricsCache[pid] = cacheEntry + } + for i, rawMetric := range rawMetrics { + metric, err := strconv.ParseUint(string(rawMetric), 10, 64) + if err != nil { + return info.CpuSchedstat{}, fmt.Errorf("parsing error while reading scheduler statistics for process: %d: %v", pid, err) + } + switch i { + case 0: + cacheEntry.RunTime = metric + case 1: + cacheEntry.RunqueueTime = metric + case 2: + cacheEntry.RunPeriods = metric + } + } + } + schedstats := info.CpuSchedstat{} + for _, v := range pidMetricsCache { + schedstats.RunPeriods += v.RunPeriods + schedstats.RunqueueTime += v.RunqueueTime + schedstats.RunTime += v.RunTime + } + return schedstats, nil +} + +func networkStatsFromProc(rootFs string, pid int) ([]info.InterfaceStats, error) { + netStatsFile := path.Join(rootFs, "proc", strconv.Itoa(pid), "/net/dev") + + ifaceStats, err := scanInterfaceStats(netStatsFile) + if err != nil { + return []info.InterfaceStats{}, fmt.Errorf("couldn't read network stats: %v", err) + } + + return ifaceStats, nil +} + +var ( + ignoredDevicePrefixes = []string{"lo", "veth", "docker"} +) + +func isIgnoredDevice(ifName string) bool { + for _, prefix := range ignoredDevicePrefixes { + if strings.HasPrefix(strings.ToLower(ifName), prefix) { + return true + } + } + return false +} + +func scanInterfaceStats(netStatsFile string) ([]info.InterfaceStats, error) { + file, err := os.Open(netStatsFile) + if err != nil { + return nil, fmt.Errorf("failure opening %s: %v", netStatsFile, err) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + + // Discard header lines + for i := 0; i < 2; i++ { + if b := scanner.Scan(); !b { + return nil, scanner.Err() + } + } + + stats := []info.InterfaceStats{} + for scanner.Scan() { + line := scanner.Text() + line = strings.Replace(line, ":", "", -1) + + fields := strings.Fields(line) + // If the format of the line is invalid then don't trust any of the stats + // in this file. + if len(fields) != 17 { + return nil, fmt.Errorf("invalid interface stats line: %v", line) + } + + devName := fields[0] + if isIgnoredDevice(devName) { + continue + } + + i := info.InterfaceStats{ + Name: devName, + } + + statFields := append(fields[1:5], fields[9:13]...) + statPointers := []*uint64{ + &i.RxBytes, &i.RxPackets, &i.RxErrors, &i.RxDropped, + &i.TxBytes, &i.TxPackets, &i.TxErrors, &i.TxDropped, + } + + err := setInterfaceStatValues(statFields, statPointers) + if err != nil { + return nil, fmt.Errorf("cannot parse interface stats (%v): %v", err, line) + } + + stats = append(stats, i) + } + + return stats, nil +} + +func setInterfaceStatValues(fields []string, pointers []*uint64) error { + for i, v := range fields { + val, err := strconv.ParseUint(v, 10, 64) + if err != nil { + return err + } + *pointers[i] = val + } + return nil +} + +func tcpStatsFromProc(rootFs string, pid int, file string) (info.TcpStat, error) { + tcpStatsFile := path.Join(rootFs, "proc", strconv.Itoa(pid), file) + + tcpStats, err := scanTcpStats(tcpStatsFile) + if err != nil { + return tcpStats, fmt.Errorf("couldn't read tcp stats: %v", err) + } + + return tcpStats, nil +} + +func scanTcpStats(tcpStatsFile string) (info.TcpStat, error) { + + var stats info.TcpStat + + data, err := ioutil.ReadFile(tcpStatsFile) + if err != nil { + return stats, fmt.Errorf("failure opening %s: %v", tcpStatsFile, err) + } + + tcpStateMap := map[string]uint64{ + "01": 0, //ESTABLISHED + "02": 0, //SYN_SENT + "03": 0, //SYN_RECV + "04": 0, //FIN_WAIT1 + "05": 0, //FIN_WAIT2 + "06": 0, //TIME_WAIT + "07": 0, //CLOSE + "08": 0, //CLOSE_WAIT + "09": 0, //LAST_ACK + "0A": 0, //LISTEN + "0B": 0, //CLOSING + } + + reader := strings.NewReader(string(data)) + scanner := bufio.NewScanner(reader) + + scanner.Split(bufio.ScanLines) + + // Discard header line + if b := scanner.Scan(); !b { + return stats, scanner.Err() + } + + for scanner.Scan() { + line := scanner.Text() + + state := strings.Fields(line) + // TCP state is the 4th field. + // Format: sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode + tcpState := state[3] + _, ok := tcpStateMap[tcpState] + if !ok { + return stats, fmt.Errorf("invalid TCP stats line: %v", line) + } + tcpStateMap[tcpState]++ + } + + stats = info.TcpStat{ + Established: tcpStateMap["01"], + SynSent: tcpStateMap["02"], + SynRecv: tcpStateMap["03"], + FinWait1: tcpStateMap["04"], + FinWait2: tcpStateMap["05"], + TimeWait: tcpStateMap["06"], + Close: tcpStateMap["07"], + CloseWait: tcpStateMap["08"], + LastAck: tcpStateMap["09"], + Listen: tcpStateMap["0A"], + Closing: tcpStateMap["0B"], + } + + return stats, nil +} + +func udpStatsFromProc(rootFs string, pid int, file string) (info.UdpStat, error) { + var err error + var udpStats info.UdpStat + + udpStatsFile := path.Join(rootFs, "proc", strconv.Itoa(pid), file) + + r, err := os.Open(udpStatsFile) + if err != nil { + return udpStats, fmt.Errorf("failure opening %s: %v", udpStatsFile, err) + } + + udpStats, err = scanUdpStats(r) + if err != nil { + return udpStats, fmt.Errorf("couldn't read udp stats: %v", err) + } + + return udpStats, nil +} + +func scanUdpStats(r io.Reader) (info.UdpStat, error) { + var stats info.UdpStat + + scanner := bufio.NewScanner(r) + scanner.Split(bufio.ScanLines) + + // Discard header line + if b := scanner.Scan(); !b { + return stats, scanner.Err() + } + + listening := uint64(0) + dropped := uint64(0) + rxQueued := uint64(0) + txQueued := uint64(0) + + for scanner.Scan() { + line := scanner.Text() + // Format: sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops + + listening++ + + fs := strings.Fields(line) + if len(fs) != 13 { + continue + } + + rx, tx := uint64(0), uint64(0) + fmt.Sscanf(fs[4], "%X:%X", &rx, &tx) + rxQueued += rx + txQueued += tx + + d, err := strconv.Atoi(string(fs[12])) + if err != nil { + continue + } + dropped += uint64(d) + } + + stats = info.UdpStat{ + Listen: listening, + Dropped: dropped, + RxQueued: rxQueued, + TxQueued: txQueued, + } + + return stats, nil +} + +func (h *Handler) GetProcesses() ([]int, error) { + pids, err := h.cgroupManager.GetPids() + if err != nil { + return nil, err + } + return pids, nil +} + +func minUint32(x, y uint32) uint32 { + if x < y { + return x + } + return y +} + +// var to allow unit tests to stub it out +var numCpusFunc = getNumberOnlineCPUs + +// Convert libcontainer stats to info.ContainerStats. +func setCpuStats(s *cgroups.Stats, ret *info.ContainerStats, withPerCPU bool) { + ret.Cpu.Usage.User = s.CpuStats.CpuUsage.UsageInUsermode + ret.Cpu.Usage.System = s.CpuStats.CpuUsage.UsageInKernelmode + ret.Cpu.Usage.Total = s.CpuStats.CpuUsage.TotalUsage + ret.Cpu.CFS.Periods = s.CpuStats.ThrottlingData.Periods + ret.Cpu.CFS.ThrottledPeriods = s.CpuStats.ThrottlingData.ThrottledPeriods + ret.Cpu.CFS.ThrottledTime = s.CpuStats.ThrottlingData.ThrottledTime + + if !withPerCPU { + return + } + if len(s.CpuStats.CpuUsage.PercpuUsage) == 0 { + // libcontainer's 'GetStats' can leave 'PercpuUsage' nil if it skipped the + // cpuacct subsystem. + return + } + + numPossible := uint32(len(s.CpuStats.CpuUsage.PercpuUsage)) + // Note that as of https://patchwork.kernel.org/patch/8607101/ (kernel v4.7), + // the percpu usage information includes extra zero values for all additional + // possible CPUs. This is to allow statistic collection after CPU-hotplug. + // We intentionally ignore these extra zeroes. + numActual, err := numCpusFunc() + if err != nil { + glog.Errorf("unable to determine number of actual cpus; defaulting to maximum possible number: errno %v", err) + numActual = numPossible + } + if numActual > numPossible { + // The real number of cores should never be greater than the number of + // datapoints reported in cpu usage. + glog.Errorf("PercpuUsage had %v cpus, but the actual number is %v; ignoring extra CPUs", numPossible, numActual) + } + numActual = minUint32(numPossible, numActual) + ret.Cpu.Usage.PerCpu = make([]uint64, numActual) + + for i := uint32(0); i < numActual; i++ { + ret.Cpu.Usage.PerCpu[i] = s.CpuStats.CpuUsage.PercpuUsage[i] + } + +} + +// Copied from +// https://github.com/moby/moby/blob/8b1adf55c2af329a4334f21d9444d6a169000c81/daemon/stats/collector_unix.go#L73 +// Apache 2.0, Copyright Docker, Inc. +func getNumberOnlineCPUs() (uint32, error) { + i, err := C.sysconf(C._SC_NPROCESSORS_ONLN) + // According to POSIX - errno is undefined after successful + // sysconf, and can be non-zero in several cases, so look for + // error in returned value not in errno. + // (https://sourceware.org/bugzilla/show_bug.cgi?id=21536) + if i == -1 { + return 0, err + } + return uint32(i), nil +} + +func setDiskIoStats(s *cgroups.Stats, ret *info.ContainerStats) { + ret.DiskIo.IoServiceBytes = DiskStatsCopy(s.BlkioStats.IoServiceBytesRecursive) + ret.DiskIo.IoServiced = DiskStatsCopy(s.BlkioStats.IoServicedRecursive) + ret.DiskIo.IoQueued = DiskStatsCopy(s.BlkioStats.IoQueuedRecursive) + ret.DiskIo.Sectors = DiskStatsCopy(s.BlkioStats.SectorsRecursive) + ret.DiskIo.IoServiceTime = DiskStatsCopy(s.BlkioStats.IoServiceTimeRecursive) + ret.DiskIo.IoWaitTime = DiskStatsCopy(s.BlkioStats.IoWaitTimeRecursive) + ret.DiskIo.IoMerged = DiskStatsCopy(s.BlkioStats.IoMergedRecursive) + ret.DiskIo.IoTime = DiskStatsCopy(s.BlkioStats.IoTimeRecursive) +} + +func setMemoryStats(s *cgroups.Stats, ret *info.ContainerStats) { + ret.Memory.Usage = s.MemoryStats.Usage.Usage + ret.Memory.MaxUsage = s.MemoryStats.Usage.MaxUsage + ret.Memory.Failcnt = s.MemoryStats.Usage.Failcnt + ret.Memory.Cache = s.MemoryStats.Stats["cache"] + + if s.MemoryStats.UseHierarchy { + ret.Memory.RSS = s.MemoryStats.Stats["total_rss"] + ret.Memory.Swap = s.MemoryStats.Stats["total_swap"] + } else { + ret.Memory.RSS = s.MemoryStats.Stats["rss"] + ret.Memory.Swap = s.MemoryStats.Stats["swap"] + } + if v, ok := s.MemoryStats.Stats["pgfault"]; ok { + ret.Memory.ContainerData.Pgfault = v + ret.Memory.HierarchicalData.Pgfault = v + } + if v, ok := s.MemoryStats.Stats["pgmajfault"]; ok { + ret.Memory.ContainerData.Pgmajfault = v + ret.Memory.HierarchicalData.Pgmajfault = v + } + + workingSet := ret.Memory.Usage + if v, ok := s.MemoryStats.Stats["total_inactive_file"]; ok { + if workingSet < v { + workingSet = 0 + } else { + workingSet -= v + } + } + ret.Memory.WorkingSet = workingSet +} + +func setNetworkStats(libcontainerStats *libcontainer.Stats, ret *info.ContainerStats) { + ret.Network.Interfaces = make([]info.InterfaceStats, len(libcontainerStats.Interfaces)) + for i := range libcontainerStats.Interfaces { + ret.Network.Interfaces[i] = info.InterfaceStats{ + Name: libcontainerStats.Interfaces[i].Name, + RxBytes: libcontainerStats.Interfaces[i].RxBytes, + RxPackets: libcontainerStats.Interfaces[i].RxPackets, + RxErrors: libcontainerStats.Interfaces[i].RxErrors, + RxDropped: libcontainerStats.Interfaces[i].RxDropped, + TxBytes: libcontainerStats.Interfaces[i].TxBytes, + TxPackets: libcontainerStats.Interfaces[i].TxPackets, + TxErrors: libcontainerStats.Interfaces[i].TxErrors, + TxDropped: libcontainerStats.Interfaces[i].TxDropped, + } + } + + // Add to base struct for backwards compatibility. + if len(ret.Network.Interfaces) > 0 { + ret.Network.InterfaceStats = ret.Network.Interfaces[0] + } +} + +func newContainerStats(libcontainerStats *libcontainer.Stats, withPerCPU bool) *info.ContainerStats { + ret := &info.ContainerStats{ + Timestamp: time.Now(), + } + + if s := libcontainerStats.CgroupStats; s != nil { + setCpuStats(s, ret, withPerCPU) + setDiskIoStats(s, ret) + setMemoryStats(s, ret) + } + if len(libcontainerStats.Interfaces) > 0 { + setNetworkStats(libcontainerStats, ret) + } + return ret +} diff --git a/vendor/github.com/google/cadvisor/container/libcontainer/helpers.go b/vendor/github.com/google/cadvisor/container/libcontainer/helpers.go index 2f9270758b0..d033f7bfc50 100644 --- a/vendor/github.com/google/cadvisor/container/libcontainer/helpers.go +++ b/vendor/github.com/google/cadvisor/container/libcontainer/helpers.go @@ -15,29 +15,14 @@ package libcontainer import ( - "bufio" "fmt" - "io" - "io/ioutil" - "os" - "path" - "strconv" - "strings" - "time" - "github.com/google/cadvisor/container" info "github.com/google/cadvisor/info/v1" "github.com/golang/glog" - "github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer/cgroups" ) -/* -#include -*/ -import "C" - type CgroupSubsystems struct { // Cgroup subsystem mounts. // e.g.: "/sys/fs/cgroup/cpu" -> ["cpu", "cpuacct"] @@ -104,309 +89,6 @@ var supportedSubsystems map[string]struct{} = map[string]struct{}{ "devices": {}, } -// Get cgroup and networking stats of the specified container -func GetStats(cgroupManager cgroups.Manager, rootFs string, pid int, ignoreMetrics container.MetricSet) (*info.ContainerStats, error) { - cgroupStats, err := cgroupManager.GetStats() - if err != nil { - return nil, err - } - libcontainerStats := &libcontainer.Stats{ - CgroupStats: cgroupStats, - } - withPerCPU := !ignoreMetrics.Has(container.PerCpuUsageMetrics) - stats := newContainerStats(libcontainerStats, withPerCPU) - - // If we know the pid then get network stats from /proc//net/dev - if pid == 0 { - return stats, nil - } - if !ignoreMetrics.Has(container.NetworkUsageMetrics) { - netStats, err := networkStatsFromProc(rootFs, pid) - if err != nil { - glog.V(4).Infof("Unable to get network stats from pid %d: %v", pid, err) - } else { - stats.Network.Interfaces = append(stats.Network.Interfaces, netStats...) - } - } - if !ignoreMetrics.Has(container.NetworkTcpUsageMetrics) { - t, err := tcpStatsFromProc(rootFs, pid, "net/tcp") - if err != nil { - glog.V(4).Infof("Unable to get tcp stats from pid %d: %v", pid, err) - } else { - stats.Network.Tcp = t - } - - t6, err := tcpStatsFromProc(rootFs, pid, "net/tcp6") - if err != nil { - glog.V(4).Infof("Unable to get tcp6 stats from pid %d: %v", pid, err) - } else { - stats.Network.Tcp6 = t6 - } - } - if !ignoreMetrics.Has(container.NetworkUdpUsageMetrics) { - u, err := udpStatsFromProc(rootFs, pid, "net/udp") - if err != nil { - glog.V(4).Infof("Unable to get udp stats from pid %d: %v", pid, err) - } else { - stats.Network.Udp = u - } - - u6, err := udpStatsFromProc(rootFs, pid, "net/udp6") - if err != nil { - glog.V(4).Infof("Unable to get udp6 stats from pid %d: %v", pid, err) - } else { - stats.Network.Udp6 = u6 - } - } - - // For backwards compatibility. - if len(stats.Network.Interfaces) > 0 { - stats.Network.InterfaceStats = stats.Network.Interfaces[0] - } - - return stats, nil -} - -func networkStatsFromProc(rootFs string, pid int) ([]info.InterfaceStats, error) { - netStatsFile := path.Join(rootFs, "proc", strconv.Itoa(pid), "/net/dev") - - ifaceStats, err := scanInterfaceStats(netStatsFile) - if err != nil { - return []info.InterfaceStats{}, fmt.Errorf("couldn't read network stats: %v", err) - } - - return ifaceStats, nil -} - -var ( - ignoredDevicePrefixes = []string{"lo", "veth", "docker"} -) - -func isIgnoredDevice(ifName string) bool { - for _, prefix := range ignoredDevicePrefixes { - if strings.HasPrefix(strings.ToLower(ifName), prefix) { - return true - } - } - return false -} - -func scanInterfaceStats(netStatsFile string) ([]info.InterfaceStats, error) { - file, err := os.Open(netStatsFile) - if err != nil { - return nil, fmt.Errorf("failure opening %s: %v", netStatsFile, err) - } - defer file.Close() - - scanner := bufio.NewScanner(file) - - // Discard header lines - for i := 0; i < 2; i++ { - if b := scanner.Scan(); !b { - return nil, scanner.Err() - } - } - - stats := []info.InterfaceStats{} - for scanner.Scan() { - line := scanner.Text() - line = strings.Replace(line, ":", "", -1) - - fields := strings.Fields(line) - // If the format of the line is invalid then don't trust any of the stats - // in this file. - if len(fields) != 17 { - return nil, fmt.Errorf("invalid interface stats line: %v", line) - } - - devName := fields[0] - if isIgnoredDevice(devName) { - continue - } - - i := info.InterfaceStats{ - Name: devName, - } - - statFields := append(fields[1:5], fields[9:13]...) - statPointers := []*uint64{ - &i.RxBytes, &i.RxPackets, &i.RxErrors, &i.RxDropped, - &i.TxBytes, &i.TxPackets, &i.TxErrors, &i.TxDropped, - } - - err := setInterfaceStatValues(statFields, statPointers) - if err != nil { - return nil, fmt.Errorf("cannot parse interface stats (%v): %v", err, line) - } - - stats = append(stats, i) - } - - return stats, nil -} - -func setInterfaceStatValues(fields []string, pointers []*uint64) error { - for i, v := range fields { - val, err := strconv.ParseUint(v, 10, 64) - if err != nil { - return err - } - *pointers[i] = val - } - return nil -} - -func tcpStatsFromProc(rootFs string, pid int, file string) (info.TcpStat, error) { - tcpStatsFile := path.Join(rootFs, "proc", strconv.Itoa(pid), file) - - tcpStats, err := scanTcpStats(tcpStatsFile) - if err != nil { - return tcpStats, fmt.Errorf("couldn't read tcp stats: %v", err) - } - - return tcpStats, nil -} - -func scanTcpStats(tcpStatsFile string) (info.TcpStat, error) { - - var stats info.TcpStat - - data, err := ioutil.ReadFile(tcpStatsFile) - if err != nil { - return stats, fmt.Errorf("failure opening %s: %v", tcpStatsFile, err) - } - - tcpStateMap := map[string]uint64{ - "01": 0, //ESTABLISHED - "02": 0, //SYN_SENT - "03": 0, //SYN_RECV - "04": 0, //FIN_WAIT1 - "05": 0, //FIN_WAIT2 - "06": 0, //TIME_WAIT - "07": 0, //CLOSE - "08": 0, //CLOSE_WAIT - "09": 0, //LAST_ACK - "0A": 0, //LISTEN - "0B": 0, //CLOSING - } - - reader := strings.NewReader(string(data)) - scanner := bufio.NewScanner(reader) - - scanner.Split(bufio.ScanLines) - - // Discard header line - if b := scanner.Scan(); !b { - return stats, scanner.Err() - } - - for scanner.Scan() { - line := scanner.Text() - - state := strings.Fields(line) - // TCP state is the 4th field. - // Format: sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode - tcpState := state[3] - _, ok := tcpStateMap[tcpState] - if !ok { - return stats, fmt.Errorf("invalid TCP stats line: %v", line) - } - tcpStateMap[tcpState]++ - } - - stats = info.TcpStat{ - Established: tcpStateMap["01"], - SynSent: tcpStateMap["02"], - SynRecv: tcpStateMap["03"], - FinWait1: tcpStateMap["04"], - FinWait2: tcpStateMap["05"], - TimeWait: tcpStateMap["06"], - Close: tcpStateMap["07"], - CloseWait: tcpStateMap["08"], - LastAck: tcpStateMap["09"], - Listen: tcpStateMap["0A"], - Closing: tcpStateMap["0B"], - } - - return stats, nil -} - -func udpStatsFromProc(rootFs string, pid int, file string) (info.UdpStat, error) { - var err error - var udpStats info.UdpStat - - udpStatsFile := path.Join(rootFs, "proc", strconv.Itoa(pid), file) - - r, err := os.Open(udpStatsFile) - if err != nil { - return udpStats, fmt.Errorf("failure opening %s: %v", udpStatsFile, err) - } - - udpStats, err = scanUdpStats(r) - if err != nil { - return udpStats, fmt.Errorf("couldn't read udp stats: %v", err) - } - - return udpStats, nil -} - -func scanUdpStats(r io.Reader) (info.UdpStat, error) { - var stats info.UdpStat - - scanner := bufio.NewScanner(r) - scanner.Split(bufio.ScanLines) - - // Discard header line - if b := scanner.Scan(); !b { - return stats, scanner.Err() - } - - listening := uint64(0) - dropped := uint64(0) - rxQueued := uint64(0) - txQueued := uint64(0) - - for scanner.Scan() { - line := scanner.Text() - // Format: sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops - - listening++ - - fs := strings.Fields(line) - if len(fs) != 13 { - continue - } - - rx, tx := uint64(0), uint64(0) - fmt.Sscanf(fs[4], "%X:%X", &rx, &tx) - rxQueued += rx - txQueued += tx - - d, err := strconv.Atoi(string(fs[12])) - if err != nil { - continue - } - dropped += uint64(d) - } - - stats = info.UdpStat{ - Listen: listening, - Dropped: dropped, - RxQueued: rxQueued, - TxQueued: txQueued, - } - - return stats, nil -} - -func GetProcesses(cgroupManager cgroups.Manager) ([]int, error) { - pids, err := cgroupManager.GetPids() - if err != nil { - return nil, err - } - return pids, nil -} - func DiskStatsCopy0(major, minor uint64) *info.PerDiskStats { disk := info.PerDiskStats{ Major: major, @@ -456,152 +138,3 @@ func DiskStatsCopy(blkio_stats []cgroups.BlkioStatEntry) (stat []info.PerDiskSta } return DiskStatsCopy1(disk_stat) } - -func minUint32(x, y uint32) uint32 { - if x < y { - return x - } - return y -} - -// var to allow unit tests to stub it out -var numCpusFunc = getNumberOnlineCPUs - -// Convert libcontainer stats to info.ContainerStats. -func setCpuStats(s *cgroups.Stats, ret *info.ContainerStats, withPerCPU bool) { - ret.Cpu.Usage.User = s.CpuStats.CpuUsage.UsageInUsermode - ret.Cpu.Usage.System = s.CpuStats.CpuUsage.UsageInKernelmode - ret.Cpu.Usage.Total = s.CpuStats.CpuUsage.TotalUsage - ret.Cpu.CFS.Periods = s.CpuStats.ThrottlingData.Periods - ret.Cpu.CFS.ThrottledPeriods = s.CpuStats.ThrottlingData.ThrottledPeriods - ret.Cpu.CFS.ThrottledTime = s.CpuStats.ThrottlingData.ThrottledTime - - if !withPerCPU { - return - } - if len(s.CpuStats.CpuUsage.PercpuUsage) == 0 { - // libcontainer's 'GetStats' can leave 'PercpuUsage' nil if it skipped the - // cpuacct subsystem. - return - } - - numPossible := uint32(len(s.CpuStats.CpuUsage.PercpuUsage)) - // Note that as of https://patchwork.kernel.org/patch/8607101/ (kernel v4.7), - // the percpu usage information includes extra zero values for all additional - // possible CPUs. This is to allow statistic collection after CPU-hotplug. - // We intentionally ignore these extra zeroes. - numActual, err := numCpusFunc() - if err != nil { - glog.Errorf("unable to determine number of actual cpus; defaulting to maximum possible number: errno %v", err) - numActual = numPossible - } - if numActual > numPossible { - // The real number of cores should never be greater than the number of - // datapoints reported in cpu usage. - glog.Errorf("PercpuUsage had %v cpus, but the actual number is %v; ignoring extra CPUs", numPossible, numActual) - } - numActual = minUint32(numPossible, numActual) - ret.Cpu.Usage.PerCpu = make([]uint64, numActual) - - for i := uint32(0); i < numActual; i++ { - ret.Cpu.Usage.PerCpu[i] = s.CpuStats.CpuUsage.PercpuUsage[i] - } - -} - -// Copied from -// https://github.com/moby/moby/blob/8b1adf55c2af329a4334f21d9444d6a169000c81/daemon/stats/collector_unix.go#L73 -// Apache 2.0, Copyright Docker, Inc. -func getNumberOnlineCPUs() (uint32, error) { - i, err := C.sysconf(C._SC_NPROCESSORS_ONLN) - // According to POSIX - errno is undefined after successful - // sysconf, and can be non-zero in several cases, so look for - // error in returned value not in errno. - // (https://sourceware.org/bugzilla/show_bug.cgi?id=21536) - if i == -1 { - return 0, err - } - return uint32(i), nil -} - -func setDiskIoStats(s *cgroups.Stats, ret *info.ContainerStats) { - ret.DiskIo.IoServiceBytes = DiskStatsCopy(s.BlkioStats.IoServiceBytesRecursive) - ret.DiskIo.IoServiced = DiskStatsCopy(s.BlkioStats.IoServicedRecursive) - ret.DiskIo.IoQueued = DiskStatsCopy(s.BlkioStats.IoQueuedRecursive) - ret.DiskIo.Sectors = DiskStatsCopy(s.BlkioStats.SectorsRecursive) - ret.DiskIo.IoServiceTime = DiskStatsCopy(s.BlkioStats.IoServiceTimeRecursive) - ret.DiskIo.IoWaitTime = DiskStatsCopy(s.BlkioStats.IoWaitTimeRecursive) - ret.DiskIo.IoMerged = DiskStatsCopy(s.BlkioStats.IoMergedRecursive) - ret.DiskIo.IoTime = DiskStatsCopy(s.BlkioStats.IoTimeRecursive) -} - -func setMemoryStats(s *cgroups.Stats, ret *info.ContainerStats) { - ret.Memory.Usage = s.MemoryStats.Usage.Usage - ret.Memory.MaxUsage = s.MemoryStats.Usage.MaxUsage - ret.Memory.Failcnt = s.MemoryStats.Usage.Failcnt - ret.Memory.Cache = s.MemoryStats.Stats["cache"] - - if s.MemoryStats.UseHierarchy { - ret.Memory.RSS = s.MemoryStats.Stats["total_rss"] - ret.Memory.Swap = s.MemoryStats.Stats["total_swap"] - } else { - ret.Memory.RSS = s.MemoryStats.Stats["rss"] - ret.Memory.Swap = s.MemoryStats.Stats["swap"] - } - if v, ok := s.MemoryStats.Stats["pgfault"]; ok { - ret.Memory.ContainerData.Pgfault = v - ret.Memory.HierarchicalData.Pgfault = v - } - if v, ok := s.MemoryStats.Stats["pgmajfault"]; ok { - ret.Memory.ContainerData.Pgmajfault = v - ret.Memory.HierarchicalData.Pgmajfault = v - } - - workingSet := ret.Memory.Usage - if v, ok := s.MemoryStats.Stats["total_inactive_file"]; ok { - if workingSet < v { - workingSet = 0 - } else { - workingSet -= v - } - } - ret.Memory.WorkingSet = workingSet -} - -func setNetworkStats(libcontainerStats *libcontainer.Stats, ret *info.ContainerStats) { - ret.Network.Interfaces = make([]info.InterfaceStats, len(libcontainerStats.Interfaces)) - for i := range libcontainerStats.Interfaces { - ret.Network.Interfaces[i] = info.InterfaceStats{ - Name: libcontainerStats.Interfaces[i].Name, - RxBytes: libcontainerStats.Interfaces[i].RxBytes, - RxPackets: libcontainerStats.Interfaces[i].RxPackets, - RxErrors: libcontainerStats.Interfaces[i].RxErrors, - RxDropped: libcontainerStats.Interfaces[i].RxDropped, - TxBytes: libcontainerStats.Interfaces[i].TxBytes, - TxPackets: libcontainerStats.Interfaces[i].TxPackets, - TxErrors: libcontainerStats.Interfaces[i].TxErrors, - TxDropped: libcontainerStats.Interfaces[i].TxDropped, - } - } - - // Add to base struct for backwards compatibility. - if len(ret.Network.Interfaces) > 0 { - ret.Network.InterfaceStats = ret.Network.Interfaces[0] - } -} - -func newContainerStats(libcontainerStats *libcontainer.Stats, withPerCPU bool) *info.ContainerStats { - ret := &info.ContainerStats{ - Timestamp: time.Now(), - } - - if s := libcontainerStats.CgroupStats; s != nil { - setCpuStats(s, ret, withPerCPU) - setDiskIoStats(s, ret) - setMemoryStats(s, ret) - } - if len(libcontainerStats.Interfaces) > 0 { - setNetworkStats(libcontainerStats, ret) - } - return ret -} diff --git a/vendor/github.com/google/cadvisor/container/raw/BUILD b/vendor/github.com/google/cadvisor/container/raw/BUILD index fcf14378ca3..f745a7023e3 100644 --- a/vendor/github.com/google/cadvisor/container/raw/BUILD +++ b/vendor/github.com/google/cadvisor/container/raw/BUILD @@ -17,7 +17,6 @@ go_library( "//vendor/github.com/google/cadvisor/info/v1:go_default_library", "//vendor/github.com/google/cadvisor/machine:go_default_library", "//vendor/github.com/google/cadvisor/manager/watcher:go_default_library", - "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library", ], diff --git a/vendor/github.com/google/cadvisor/container/raw/handler.go b/vendor/github.com/google/cadvisor/container/raw/handler.go index 35614afd950..a04a7c89e42 100644 --- a/vendor/github.com/google/cadvisor/container/raw/handler.go +++ b/vendor/github.com/google/cadvisor/container/raw/handler.go @@ -26,7 +26,6 @@ import ( "github.com/google/cadvisor/machine" "github.com/golang/glog" - "github.com/opencontainers/runc/libcontainer/cgroups" cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -34,25 +33,16 @@ import ( type rawContainerHandler struct { // Name of the container for this handler. name string - cgroupSubsystems *libcontainer.CgroupSubsystems machineInfoFactory info.MachineInfoFactory // Absolute path to the cgroup hierarchies of this container. // (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test") cgroupPaths map[string]string - // Manager of this container's cgroups. - cgroupManager cgroups.Manager - fsInfo fs.FsInfo externalMounts []common.Mount - rootFs string - - // Metrics to be ignored. - ignoreMetrics container.MetricSet - - pid int + libcontainerHandler *libcontainer.Handler } func isRootCgroup(name string) bool { @@ -88,17 +78,15 @@ func newRawContainerHandler(name string, cgroupSubsystems *libcontainer.CgroupSu pid = 1 } + handler := libcontainer.NewHandler(cgroupManager, rootFs, pid, ignoreMetrics) + return &rawContainerHandler{ - name: name, - cgroupSubsystems: cgroupSubsystems, - machineInfoFactory: machineInfoFactory, - cgroupPaths: cgroupPaths, - cgroupManager: cgroupManager, - fsInfo: fsInfo, - externalMounts: externalMounts, - rootFs: rootFs, - ignoreMetrics: ignoreMetrics, - pid: pid, + name: name, + machineInfoFactory: machineInfoFactory, + cgroupPaths: cgroupPaths, + fsInfo: fsInfo, + externalMounts: externalMounts, + libcontainerHandler: handler, }, nil } @@ -231,7 +219,7 @@ func (self *rawContainerHandler) getFsStats(stats *info.ContainerStats) error { } func (self *rawContainerHandler) GetStats() (*info.ContainerStats, error) { - stats, err := libcontainer.GetStats(self.cgroupManager, self.rootFs, self.pid, self.ignoreMetrics) + stats, err := self.libcontainerHandler.GetStats() if err != nil { return stats, err } @@ -267,7 +255,7 @@ func (self *rawContainerHandler) ListContainers(listType container.ListType) ([] } func (self *rawContainerHandler) ListProcesses(listType container.ListType) ([]int, error) { - return libcontainer.GetProcesses(self.cgroupManager) + return self.libcontainerHandler.GetProcesses() } func (self *rawContainerHandler) Exists() bool { diff --git a/vendor/github.com/google/cadvisor/container/rkt/BUILD b/vendor/github.com/google/cadvisor/container/rkt/BUILD index 90d7151cb1e..b6252046756 100644 --- a/vendor/github.com/google/cadvisor/container/rkt/BUILD +++ b/vendor/github.com/google/cadvisor/container/rkt/BUILD @@ -20,7 +20,6 @@ go_library( "//vendor/github.com/google/cadvisor/fs:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library", "//vendor/github.com/google/cadvisor/manager/watcher:go_default_library", - "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library", "//vendor/golang.org/x/net/context:go_default_library", diff --git a/vendor/github.com/google/cadvisor/container/rkt/handler.go b/vendor/github.com/google/cadvisor/container/rkt/handler.go index 9caa0ce4d8b..86564a1ea93 100644 --- a/vendor/github.com/google/cadvisor/container/rkt/handler.go +++ b/vendor/github.com/google/cadvisor/container/rkt/handler.go @@ -28,48 +28,35 @@ import ( "golang.org/x/net/context" "github.com/golang/glog" - "github.com/opencontainers/runc/libcontainer/cgroups" cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs" "github.com/opencontainers/runc/libcontainer/configs" ) type rktContainerHandler struct { - rktClient rktapi.PublicAPIClient - // Name of the container for this handler. - name string - cgroupSubsystems *libcontainer.CgroupSubsystems machineInfoFactory info.MachineInfoFactory // Absolute path to the cgroup hierarchies of this container. // (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test") cgroupPaths map[string]string - // Manager of this container's cgroups. - cgroupManager cgroups.Manager - - // Whether this container has network isolation enabled. - hasNetwork bool - fsInfo fs.FsInfo - rootFs string - isPod bool - aliases []string - - pid int - rootfsStorageDir string - labels map[string]string - // Filesystem handler. fsHandler common.FsHandler ignoreMetrics container.MetricSet apiPod *rktapi.Pod + + labels map[string]string + + reference info.ContainerReference + + libcontainerHandler *libcontainer.Handler } func newRktContainerHandler(name string, rktClient rktapi.PublicAPIClient, rktPath string, cgroupSubsystems *libcontainer.CgroupSubsystems, machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, rootFs string, ignoreMetrics container.MetricSet) (container.ContainerHandler, error) { @@ -122,30 +109,27 @@ func newRktContainerHandler(name string, rktClient rktapi.PublicAPIClient, rktPa Paths: cgroupPaths, } - hasNetwork := false - if isPod { - hasNetwork = true - } + libcontainerHandler := libcontainer.NewHandler(cgroupManager, rootFs, pid, ignoreMetrics) rootfsStorageDir := getRootFs(rktPath, parsed) + containerReference := info.ContainerReference{ + Name: name, + Aliases: aliases, + Namespace: RktNamespace, + } + handler := &rktContainerHandler{ - name: name, - rktClient: rktClient, - cgroupSubsystems: cgroupSubsystems, - machineInfoFactory: machineInfoFactory, - cgroupPaths: cgroupPaths, - cgroupManager: cgroupManager, - fsInfo: fsInfo, - hasNetwork: hasNetwork, - rootFs: rootFs, - isPod: isPod, - aliases: aliases, - pid: pid, - labels: labels, - rootfsStorageDir: rootfsStorageDir, - ignoreMetrics: ignoreMetrics, - apiPod: apiPod, + machineInfoFactory: machineInfoFactory, + cgroupPaths: cgroupPaths, + fsInfo: fsInfo, + isPod: isPod, + rootfsStorageDir: rootfsStorageDir, + ignoreMetrics: ignoreMetrics, + apiPod: apiPod, + labels: labels, + reference: containerReference, + libcontainerHandler: libcontainerHandler, } if !ignoreMetrics.Has(container.DiskUsageMetrics) { @@ -174,12 +158,7 @@ func createLabels(annotations []*rktapi.KeyValue) map[string]string { } func (handler *rktContainerHandler) ContainerReference() (info.ContainerReference, error) { - return info.ContainerReference{ - Name: handler.name, - Aliases: handler.aliases, - Namespace: RktNamespace, - Labels: handler.labels, - }, nil + return handler.reference, nil } func (handler *rktContainerHandler) Start() { @@ -191,7 +170,7 @@ func (handler *rktContainerHandler) Cleanup() { } func (handler *rktContainerHandler) GetSpec() (info.ContainerSpec, error) { - hasNetwork := handler.hasNetwork && !handler.ignoreMetrics.Has(container.NetworkUsageMetrics) + hasNetwork := handler.isPod && !handler.ignoreMetrics.Has(container.NetworkUsageMetrics) hasFilesystem := !handler.ignoreMetrics.Has(container.DiskUsageMetrics) spec, err := common.GetSpec(handler.cgroupPaths, handler.machineInfoFactory, hasNetwork, hasFilesystem) @@ -243,7 +222,7 @@ func (handler *rktContainerHandler) getFsStats(stats *info.ContainerStats) error } func (handler *rktContainerHandler) GetStats() (*info.ContainerStats, error) { - stats, err := libcontainer.GetStats(handler.cgroupManager, handler.rootFs, handler.pid, handler.ignoreMetrics) + stats, err := handler.libcontainerHandler.GetStats() if err != nil { return stats, err } @@ -275,7 +254,7 @@ func (self *rktContainerHandler) GetContainerIPAddress() string { func (handler *rktContainerHandler) GetCgroupPath(resource string) (string, error) { path, ok := handler.cgroupPaths[resource] if !ok { - return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, handler.name) + return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, handler.reference.Name) } return path, nil } @@ -285,11 +264,11 @@ func (handler *rktContainerHandler) GetContainerLabels() map[string]string { } func (handler *rktContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) { - return common.ListContainers(handler.name, handler.cgroupPaths, listType) + return common.ListContainers(handler.reference.Name, handler.cgroupPaths, listType) } func (handler *rktContainerHandler) ListProcesses(listType container.ListType) ([]int, error) { - return libcontainer.GetProcesses(handler.cgroupManager) + return handler.libcontainerHandler.GetProcesses() } func (handler *rktContainerHandler) Exists() bool { diff --git a/vendor/github.com/google/cadvisor/fs/fs.go b/vendor/github.com/google/cadvisor/fs/fs.go index b86ec36efed..996f8577b4b 100644 --- a/vendor/github.com/google/cadvisor/fs/fs.go +++ b/vendor/github.com/google/cadvisor/fs/fs.go @@ -554,7 +554,7 @@ func GetDirDiskUsage(dir string, timeout time.Duration) (uint64, error) { if dir == "" { return 0, fmt.Errorf("invalid directory") } - cmd := exec.Command("nice", "-n", "19", "du", "-s", dir) + cmd := exec.Command("ionice", "-c3", "nice", "-n", "19", "du", "-s", dir) stdoutp, err := cmd.StdoutPipe() if err != nil { return 0, fmt.Errorf("failed to setup stdout for cmd %v - %v", cmd.Args, err) @@ -601,7 +601,7 @@ func GetDirInodeUsage(dir string, timeout time.Duration) (uint64, error) { } var counter byteCounter var stderr bytes.Buffer - findCmd := exec.Command("find", dir, "-xdev", "-printf", ".") + findCmd := exec.Command("ionice", "-c3", "nice", "-n", "19", "find", dir, "-xdev", "-printf", ".") findCmd.Stdout, findCmd.Stderr = &counter, &stderr if err := findCmd.Start(); err != nil { return 0, fmt.Errorf("failed to exec cmd %v - %v; stderr: %v", findCmd.Args, err, stderr.String()) diff --git a/vendor/github.com/google/cadvisor/info/v1/container.go b/vendor/github.com/google/cadvisor/info/v1/container.go index 8d0c28e0bb8..0d7b895bc01 100644 --- a/vendor/github.com/google/cadvisor/info/v1/container.go +++ b/vendor/github.com/google/cadvisor/info/v1/container.go @@ -85,8 +85,6 @@ type ContainerReference struct { // Namespace under which the aliases of a container are unique. // An example of a namespace is "docker" for Docker containers. Namespace string `json:"namespace,omitempty"` - - Labels map[string]string `json:"labels,omitempty"` } // Sorts by container name. @@ -295,10 +293,23 @@ type CpuCFS struct { ThrottledTime uint64 `json:"throttled_time"` } +// Cpu Aggregated scheduler statistics +type CpuSchedstat struct { + // https://www.kernel.org/doc/Documentation/scheduler/sched-stats.txt + + // time spent on the cpu + RunTime uint64 `json:"run_time"` + // time spent waiting on a runqueue + RunqueueTime uint64 `json:"runqueue_time"` + // # of timeslices run on this cpu + RunPeriods uint64 `json:"run_periods"` +} + // All CPU usage metrics are cumulative from the creation of the container type CpuStats struct { - Usage CpuUsage `json:"usage"` - CFS CpuCFS `json:"cfs"` + Usage CpuUsage `json:"usage"` + CFS CpuCFS `json:"cfs"` + Schedstat CpuSchedstat `json:"schedstat"` // Smoothed average of number of runnable threads x 1000. // We multiply by thousand to avoid using floats, but preserving precision. // Load is smoothed over the last 10 seconds. Instantaneous value can be read diff --git a/vendor/github.com/google/cadvisor/machine/BUILD b/vendor/github.com/google/cadvisor/machine/BUILD index 3a248ed5e58..620377540b3 100644 --- a/vendor/github.com/google/cadvisor/machine/BUILD +++ b/vendor/github.com/google/cadvisor/machine/BUILD @@ -9,6 +9,7 @@ go_library( importpath = "github.com/google/cadvisor/machine", visibility = ["//visibility:public"], deps = [ + "//vendor/github.com/docker/docker/pkg/parsers/operatingsystem:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/google/cadvisor/fs:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library", diff --git a/vendor/github.com/google/cadvisor/machine/info.go b/vendor/github.com/google/cadvisor/machine/info.go index be90f17e96c..bf4f595ab21 100644 --- a/vendor/github.com/google/cadvisor/machine/info.go +++ b/vendor/github.com/google/cadvisor/machine/info.go @@ -23,6 +23,7 @@ import ( "strconv" "strings" + "github.com/docker/docker/pkg/parsers/operatingsystem" "github.com/google/cadvisor/fs" info "github.com/google/cadvisor/info/v1" "github.com/google/cadvisor/utils/cloudinfo" @@ -173,20 +174,11 @@ func Info(sysFs sysfs.SysFs, fsInfo fs.FsInfo, inHostNamespace bool) (*info.Mach } func ContainerOsVersion() string { - container_os := "Unknown" - os_release, err := ioutil.ReadFile("/etc/os-release") - if err == nil { - // We might be running in a busybox or some hand-crafted image. - // It's useful to know why cadvisor didn't come up. - for _, line := range strings.Split(string(os_release), "\n") { - parsed := strings.Split(line, "\"") - if len(parsed) == 3 && parsed[0] == "PRETTY_NAME=" { - container_os = parsed[1] - break - } - } + os, err := operatingsystem.GetOperatingSystem() + if err != nil { + os = "Unknown" } - return container_os + return os } func KernelVersion() string { diff --git a/vendor/github.com/google/cadvisor/manager/container.go b/vendor/github.com/google/cadvisor/manager/container.go index 88dd7c15365..295479f092d 100644 --- a/vendor/github.com/google/cadvisor/manager/container.go +++ b/vendor/github.com/google/cadvisor/manager/container.go @@ -615,7 +615,12 @@ func (c *containerData) updateStats() error { } return err } - err = c.memoryCache.AddStats(ref, stats) + + cInfo := info.ContainerInfo{ + ContainerReference: ref, + } + + err = c.memoryCache.AddStats(&cInfo, stats) if err != nil { return err } diff --git a/vendor/github.com/google/cadvisor/manager/manager.go b/vendor/github.com/google/cadvisor/manager/manager.go index 10a725f7eb5..95054ae8b8b 100644 --- a/vendor/github.com/google/cadvisor/manager/manager.go +++ b/vendor/github.com/google/cadvisor/manager/manager.go @@ -242,7 +242,7 @@ func retryDockerStatus() info.DockerStatus { for { ctx, _ := context.WithTimeout(context.Background(), startupTimeout) dockerStatus, err := docker.StatusWithContext(ctx) - if err != nil { + if err == nil { return dockerStatus } diff --git a/vendor/github.com/google/cadvisor/manager/watcher/raw/raw.go b/vendor/github.com/google/cadvisor/manager/watcher/raw/raw.go index 103fa887afe..137cd9b9781 100644 --- a/vendor/github.com/google/cadvisor/manager/watcher/raw/raw.go +++ b/vendor/github.com/google/cadvisor/manager/watcher/raw/raw.go @@ -71,7 +71,7 @@ func NewRawContainerWatcher() (watcher.ContainerWatcher, error) { func (self *rawContainerWatcher) Start(events chan watcher.ContainerEvent) error { // Watch this container (all its cgroups) and all subdirectories. for _, cgroupPath := range self.cgroupPaths { - _, err := self.watchDirectory(cgroupPath, "/") + _, err := self.watchDirectory(events, cgroupPath, "/") if err != nil { return err } @@ -109,7 +109,7 @@ func (self *rawContainerWatcher) Stop() error { // Watches the specified directory and all subdirectories. Returns whether the path was // already being watched and an error (if any). -func (self *rawContainerWatcher) watchDirectory(dir string, containerName string) (bool, error) { +func (self *rawContainerWatcher) watchDirectory(events chan watcher.ContainerEvent, dir string, containerName string) (bool, error) { alreadyWatching, err := self.watcher.AddWatch(containerName, dir) if err != nil { return alreadyWatching, err @@ -135,7 +135,8 @@ func (self *rawContainerWatcher) watchDirectory(dir string, containerName string for _, entry := range entries { if entry.IsDir() { entryPath := path.Join(dir, entry.Name()) - _, err = self.watchDirectory(entryPath, path.Join(containerName, entry.Name())) + subcontainerName := path.Join(containerName, entry.Name()) + alreadyWatchingSubDir, err := self.watchDirectory(events, entryPath, subcontainerName) if err != nil { glog.Errorf("Failed to watch directory %q: %v", entryPath, err) if os.IsNotExist(err) { @@ -145,6 +146,16 @@ func (self *rawContainerWatcher) watchDirectory(dir string, containerName string } return alreadyWatching, err } + // since we already missed the creation event for this directory, publish an event here. + if !alreadyWatchingSubDir { + go func() { + events <- watcher.ContainerEvent{ + EventType: watcher.ContainerAdd, + Name: subcontainerName, + WatchSource: watcher.Raw, + } + }() + } } } @@ -186,7 +197,7 @@ func (self *rawContainerWatcher) processEvent(event *inotify.Event, events chan switch eventType { case watcher.ContainerAdd: // New container was created, watch it. - alreadyWatched, err := self.watchDirectory(event.Name, containerName) + alreadyWatched, err := self.watchDirectory(events, event.Name, containerName) if err != nil { return err } diff --git a/vendor/github.com/google/cadvisor/metrics/prometheus.go b/vendor/github.com/google/cadvisor/metrics/prometheus.go index 4354071b812..f0aaa0ede51 100644 --- a/vendor/github.com/google/cadvisor/metrics/prometheus.go +++ b/vendor/github.com/google/cadvisor/metrics/prometheus.go @@ -197,6 +197,27 @@ func NewPrometheusCollector(i infoProvider, f ContainerLabelsFunc) *PrometheusCo getValues: func(s *info.ContainerStats) metricValues { return metricValues{{value: float64(s.Cpu.CFS.ThrottledTime) / float64(time.Second)}} }, + }, { + name: "container_cpu_schedstat_run_seconds_total", + help: "Time duration the processes of the container have run on the CPU.", + valueType: prometheus.CounterValue, + getValues: func(s *info.ContainerStats) metricValues { + return metricValues{{value: float64(s.Cpu.Schedstat.RunTime) / float64(time.Second)}} + }, + }, { + name: "container_cpu_schedstat_runqueue_seconds_total", + help: "Time duration processes of the container have been waiting on a runqueue.", + valueType: prometheus.CounterValue, + getValues: func(s *info.ContainerStats) metricValues { + return metricValues{{value: float64(s.Cpu.Schedstat.RunqueueTime) / float64(time.Second)}} + }, + }, { + name: "container_cpu_schedstat_run_periods_total", + help: "Number of times processes of the cgroup have run on the cpu", + valueType: prometheus.CounterValue, + getValues: func(s *info.ContainerStats) metricValues { + return metricValues{{value: float64(s.Cpu.Schedstat.RunPeriods)}} + }, }, { name: "container_cpu_load_average_10s", help: "Value of container cpu load average over the last 10 seconds.", diff --git a/vendor/github.com/google/cadvisor/storage/storage.go b/vendor/github.com/google/cadvisor/storage/storage.go index b420d4b1355..dd950862b34 100644 --- a/vendor/github.com/google/cadvisor/storage/storage.go +++ b/vendor/github.com/google/cadvisor/storage/storage.go @@ -22,7 +22,7 @@ import ( ) type StorageDriver interface { - AddStats(ref info.ContainerReference, stats *info.ContainerStats) error + AddStats(cInfo *info.ContainerInfo, stats *info.ContainerStats) error // Close will clear the state of the storage driver. The elements // stored in the underlying storage may or may not be deleted depending diff --git a/vendor/github.com/google/cadvisor/validate/validate.go b/vendor/github.com/google/cadvisor/validate/validate.go index c73311cf64a..b2db558097a 100644 --- a/vendor/github.com/google/cadvisor/validate/validate.go +++ b/vendor/github.com/google/cadvisor/validate/validate.go @@ -22,6 +22,7 @@ import ( "io/ioutil" "log" "net/http" + "os" "path" "strings" @@ -133,6 +134,23 @@ func areCgroupsPresent(available map[string]int, desired []string) (bool, string return true, "" } +func validateCpuCfsBandwidth(available_cgroups map[string]int) string { + ok, _ := areCgroupsPresent(available_cgroups, []string{"cpu"}) + if !ok { + return "\tCpu cfs bandwidth status unknown: cpu cgroup not enabled.\n" + } + mnt, err := cgroups.FindCgroupMountpoint("cpu") + if err != nil { + return "\tCpu cfs bandwidth status unknown: cpu cgroup not mounted.\n" + } + _, err = os.Stat(path.Join(mnt, "cpu.cfs_period_us")) + if os.IsNotExist(err) { + return "\tCpu cfs bandwidth is disabled. Recompile kernel with \"CONFIG_CFS_BANDWIDTH\" enabled.\n" + } + + return "\tCpu cfs bandwidth is enabled.\n" +} + func validateMemoryAccounting(available_cgroups map[string]int) string { ok, _ := areCgroupsPresent(available_cgroups, []string{"memory"}) if !ok { @@ -181,6 +199,7 @@ func validateCgroups() (string, string) { out = fmt.Sprintf("Available cgroups: %v\n", available_cgroups) out += desc out += validateMemoryAccounting(available_cgroups) + out += validateCpuCfsBandwidth(available_cgroups) return Recommended, out } diff --git a/vendor/github.com/json-iterator/go/Gopkg.lock b/vendor/github.com/json-iterator/go/Gopkg.lock index 338f1c68a50..3719afe8e0d 100644 --- a/vendor/github.com/json-iterator/go/Gopkg.lock +++ b/vendor/github.com/json-iterator/go/Gopkg.lock @@ -1,6 +1,12 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + name = "github.com/json-iterator/go" + packages = ["."] + revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4" + version = "1.1.3" + [[projects]] name = "github.com/modern-go/concurrent" packages = ["."] @@ -16,6 +22,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "ac7003b5a981716353a43055ab7d4c5357403cb30a60de2dbdeb446c1544beaa" + inputs-digest = "56a0b9e9e61d2bc8af5e1b68537401b7f4d60805eda3d107058f3171aa5cf793" solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/json-iterator/go/config.go b/vendor/github.com/json-iterator/go/config.go index bd66947d7c8..835819129c5 100644 --- a/vendor/github.com/json-iterator/go/config.go +++ b/vendor/github.com/json-iterator/go/config.go @@ -2,12 +2,13 @@ package jsoniter import ( "encoding/json" - "github.com/modern-go/concurrent" - "github.com/modern-go/reflect2" "io" "reflect" "sync" "unsafe" + + "github.com/modern-go/concurrent" + "github.com/modern-go/reflect2" ) // Config customize how the API should behave. @@ -23,6 +24,7 @@ type Config struct { OnlyTaggedField bool ValidateJsonRawMessage bool ObjectFieldMustBeSimpleString bool + CaseSensitive bool } // API the public interface of this package. @@ -75,6 +77,7 @@ type frozenConfig struct { extensions []Extension streamPool *sync.Pool iteratorPool *sync.Pool + caseSensitive bool } func (cfg *frozenConfig) initCache() { @@ -128,6 +131,7 @@ func (cfg Config) Froze() API { objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString, onlyTaggedField: cfg.OnlyTaggedField, disallowUnknownFields: cfg.DisallowUnknownFields, + caseSensitive: cfg.CaseSensitive, } api.streamPool = &sync.Pool{ New: func() interface{} { diff --git a/vendor/github.com/json-iterator/go/iter_object.go b/vendor/github.com/json-iterator/go/iter_object.go index ebd3da8951d..6e7c370abec 100644 --- a/vendor/github.com/json-iterator/go/iter_object.go +++ b/vendor/github.com/json-iterator/go/iter_object.go @@ -60,7 +60,7 @@ func (iter *Iterator) readFieldHash() int64 { if b == '\\' { iter.head = i for _, b := range iter.readStringSlowPath() { - if 'A' <= b && b <= 'Z' { + if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive { b += 'a' - 'A' } hash ^= int64(b) @@ -82,7 +82,7 @@ func (iter *Iterator) readFieldHash() int64 { } return hash } - if 'A' <= b && b <= 'Z' { + if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive { b += 'a' - 'A' } hash ^= int64(b) @@ -95,10 +95,14 @@ func (iter *Iterator) readFieldHash() int64 { } } -func calcHash(str string) int64 { +func calcHash(str string, caseSensitive bool) int64 { hash := int64(0x811c9dc5) for _, b := range str { - hash ^= int64(unicode.ToLower(b)) + if caseSensitive { + hash ^= int64(b) + } else { + hash ^= int64(unicode.ToLower(b)) + } hash *= 0x1000193 } return int64(hash) diff --git a/vendor/github.com/json-iterator/go/reflect.go b/vendor/github.com/json-iterator/go/reflect.go index 5c7d3a8a030..be7a0e21880 100644 --- a/vendor/github.com/json-iterator/go/reflect.go +++ b/vendor/github.com/json-iterator/go/reflect.go @@ -2,9 +2,10 @@ package jsoniter import ( "fmt" - "github.com/modern-go/reflect2" "reflect" "unsafe" + + "github.com/modern-go/reflect2" ) // ValDecoder is an internal type registered to cache as needed. @@ -40,6 +41,14 @@ type ctx struct { decoders map[reflect2.Type]ValDecoder } +func (b *ctx) caseSensitive() bool { + if b.frozenConfig == nil { + // default is case-insensitive + return false + } + return b.frozenConfig.caseSensitive +} + func (b *ctx) append(prefix string) *ctx { return &ctx{ frozenConfig: b.frozenConfig, diff --git a/vendor/github.com/json-iterator/go/reflect_native.go b/vendor/github.com/json-iterator/go/reflect_native.go index fac4d9f775c..9042eb0cb98 100644 --- a/vendor/github.com/json-iterator/go/reflect_native.go +++ b/vendor/github.com/json-iterator/go/reflect_native.go @@ -1,7 +1,6 @@ package jsoniter import ( - "bytes" "encoding/base64" "reflect" "strconv" @@ -418,20 +417,11 @@ func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { } switch iter.WhatIsNext() { case StringValue: - encoding := base64.StdEncoding - src := iter.SkipAndReturnBytes() - // New line characters (\r and \n) are ignored. - // Refer to https://golang.org/pkg/encoding/base64/#Encoding.Decode - src = bytes.Replace(src, []byte(`\r`), []byte{}, -1) - src = bytes.Replace(src, []byte(`\n`), []byte{}, -1) - src = src[1 : len(src)-1] - decodedLen := encoding.DecodedLen(len(src)) - dst := make([]byte, decodedLen) - len, err := encoding.Decode(dst, src) + src := iter.ReadString() + dst, err := base64.StdEncoding.DecodeString(src) if err != nil { iter.ReportError("decode base64", err.Error()) } else { - dst = dst[:len] codec.sliceType.UnsafeSet(ptr, unsafe.Pointer(&dst)) } case ArrayValue: diff --git a/vendor/github.com/json-iterator/go/reflect_struct_decoder.go b/vendor/github.com/json-iterator/go/reflect_struct_decoder.go index fd76647863b..355d2d116b4 100644 --- a/vendor/github.com/json-iterator/go/reflect_struct_decoder.go +++ b/vendor/github.com/json-iterator/go/reflect_struct_decoder.go @@ -2,10 +2,11 @@ package jsoniter import ( "fmt" - "github.com/modern-go/reflect2" "io" "strings" "unsafe" + + "github.com/modern-go/reflect2" ) func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder { @@ -31,11 +32,15 @@ func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder { for k, binding := range bindings { fields[k] = binding.Decoder.(*structFieldDecoder) } - for k, binding := range bindings { - if _, found := fields[strings.ToLower(k)]; !found { - fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder) + + if !ctx.caseSensitive() { + for k, binding := range bindings { + if _, found := fields[strings.ToLower(k)]; !found { + fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder) + } } } + return createStructDecoder(ctx, typ, fields) } @@ -46,12 +51,13 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF knownHash := map[int64]struct{}{ 0: {}, } + switch len(fields) { case 0: return &skipObjectDecoder{typ} case 1: for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -65,7 +71,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -88,7 +94,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -119,7 +125,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -156,7 +162,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -199,7 +205,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -248,7 +254,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder6 *structFieldDecoder var fieldDecoder7 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -303,7 +309,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder7 *structFieldDecoder var fieldDecoder8 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -364,7 +370,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder8 *structFieldDecoder var fieldDecoder9 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -431,7 +437,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder9 *structFieldDecoder var fieldDecoder10 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -513,13 +519,13 @@ func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *It fieldBytes := iter.ReadStringAsSlice() field = *(*string)(unsafe.Pointer(&fieldBytes)) fieldDecoder = decoder.fields[field] - if fieldDecoder == nil { + if fieldDecoder == nil && !iter.cfg.caseSensitive { fieldDecoder = decoder.fields[strings.ToLower(field)] } } else { field = iter.ReadString() fieldDecoder = decoder.fields[field] - if fieldDecoder == nil { + if fieldDecoder == nil && !iter.cfg.caseSensitive { fieldDecoder = decoder.fields[strings.ToLower(field)] } } diff --git a/vendor/github.com/mattn/go-shellwords/.travis.yml b/vendor/github.com/mattn/go-shellwords/.travis.yml new file mode 100644 index 00000000000..16d1430aa22 --- /dev/null +++ b/vendor/github.com/mattn/go-shellwords/.travis.yml @@ -0,0 +1,8 @@ +language: go +go: + - tip +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -repotoken 2FMhp57u8LcstKL9B190fLTcEnBtAAiEL diff --git a/vendor/github.com/mattn/go-shellwords/BUILD b/vendor/github.com/mattn/go-shellwords/BUILD new file mode 100644 index 00000000000..9f11c41a466 --- /dev/null +++ b/vendor/github.com/mattn/go-shellwords/BUILD @@ -0,0 +1,60 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "shellwords.go", + "util_go15.go", + ] + select({ + "@io_bazel_rules_go//go/platform:android": [ + "util_posix.go", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "util_posix.go", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "util_posix.go", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "util_posix.go", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "util_posix.go", + ], + "@io_bazel_rules_go//go/platform:nacl": [ + "util_posix.go", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "util_posix.go", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "util_posix.go", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "util_posix.go", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "util_posix.go", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "util_windows.go", + ], + "//conditions:default": [], + }), + importpath = "github.com/mattn/go-shellwords", + 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/mattn/go-shellwords/LICENSE b/vendor/github.com/mattn/go-shellwords/LICENSE new file mode 100644 index 00000000000..740fa931322 --- /dev/null +++ b/vendor/github.com/mattn/go-shellwords/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Yasuhiro Matsumoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/mattn/go-shellwords/README.md b/vendor/github.com/mattn/go-shellwords/README.md new file mode 100644 index 00000000000..b1d235c78d3 --- /dev/null +++ b/vendor/github.com/mattn/go-shellwords/README.md @@ -0,0 +1,47 @@ +# go-shellwords + +[![Coverage Status](https://coveralls.io/repos/mattn/go-shellwords/badge.png?branch=master)](https://coveralls.io/r/mattn/go-shellwords?branch=master) +[![Build Status](https://travis-ci.org/mattn/go-shellwords.svg?branch=master)](https://travis-ci.org/mattn/go-shellwords) + +Parse line as shell words. + +## Usage + +```go +args, err := shellwords.Parse("./foo --bar=baz") +// args should be ["./foo", "--bar=baz"] +``` + +```go +os.Setenv("FOO", "bar") +p := shellwords.NewParser() +p.ParseEnv = true +args, err := p.Parse("./foo $FOO") +// args should be ["./foo", "bar"] +``` + +```go +p := shellwords.NewParser() +p.ParseBacktick = true +args, err := p.Parse("./foo `echo $SHELL`") +// args should be ["./foo", "/bin/bash"] +``` + +```go +shellwords.ParseBacktick = true +p := shellwords.NewParser() +args, err := p.Parse("./foo `echo $SHELL`") +// args should be ["./foo", "/bin/bash"] +``` + +# Thanks + +This is based on cpan module [Parse::CommandLine](https://metacpan.org/pod/Parse::CommandLine). + +# License + +under the MIT License: http://mattn.mit-license.org/2017 + +# Author + +Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/mattn/go-shellwords/shellwords.go b/vendor/github.com/mattn/go-shellwords/shellwords.go new file mode 100644 index 00000000000..bcd1e1f06ec --- /dev/null +++ b/vendor/github.com/mattn/go-shellwords/shellwords.go @@ -0,0 +1,178 @@ +package shellwords + +import ( + "errors" + "os" + "regexp" +) + +var ( + ParseEnv bool = false + ParseBacktick bool = false +) + +var envRe = regexp.MustCompile(`\$({[a-zA-Z0-9_]+}|[a-zA-Z0-9_]+)`) + +func isSpace(r rune) bool { + switch r { + case ' ', '\t', '\r', '\n': + return true + } + return false +} + +func replaceEnv(s string) string { + return envRe.ReplaceAllStringFunc(s, func(s string) string { + s = s[1:] + if s[0] == '{' { + s = s[1 : len(s)-1] + } + return os.Getenv(s) + }) +} + +type Parser struct { + ParseEnv bool + ParseBacktick bool + Position int +} + +func NewParser() *Parser { + return &Parser{ParseEnv, ParseBacktick, 0} +} + +func (p *Parser) Parse(line string) ([]string, error) { + args := []string{} + buf := "" + var escaped, doubleQuoted, singleQuoted, backQuote, dollarQuote bool + backtick := "" + + pos := -1 + got := false + +loop: + for i, r := range line { + if escaped { + buf += string(r) + escaped = false + continue + } + + if r == '\\' { + if singleQuoted { + buf += string(r) + } else { + escaped = true + } + continue + } + + if isSpace(r) { + if singleQuoted || doubleQuoted || backQuote || dollarQuote { + buf += string(r) + backtick += string(r) + } else if got { + if p.ParseEnv { + buf = replaceEnv(buf) + } + args = append(args, buf) + buf = "" + got = false + } + continue + } + + switch r { + case '`': + if !singleQuoted && !doubleQuoted && !dollarQuote { + if p.ParseBacktick { + if backQuote { + out, err := shellRun(backtick) + if err != nil { + return nil, err + } + buf = out + } + backtick = "" + backQuote = !backQuote + continue + } + backtick = "" + backQuote = !backQuote + } + case ')': + if !singleQuoted && !doubleQuoted && !backQuote { + if p.ParseBacktick { + if dollarQuote { + out, err := shellRun(backtick) + if err != nil { + return nil, err + } + buf = out + } + backtick = "" + dollarQuote = !dollarQuote + continue + } + backtick = "" + dollarQuote = !dollarQuote + } + case '(': + if !singleQuoted && !doubleQuoted && !backQuote { + if !dollarQuote && len(buf) > 0 && buf == "$" { + dollarQuote = true + buf += "(" + continue + } else { + return nil, errors.New("invalid command line string") + } + } + case '"': + if !singleQuoted && !dollarQuote { + doubleQuoted = !doubleQuoted + continue + } + case '\'': + if !doubleQuoted && !dollarQuote { + singleQuoted = !singleQuoted + continue + } + case ';', '&', '|', '<', '>': + if !(escaped || singleQuoted || doubleQuoted || backQuote) { + if r == '>' && len(buf) > 0 { + if c := buf[0]; '0' <= c && c <= '9' { + i -= 1 + got = false + } + } + pos = i + break loop + } + } + + got = true + buf += string(r) + if backQuote || dollarQuote { + backtick += string(r) + } + } + + if got { + if p.ParseEnv { + buf = replaceEnv(buf) + } + args = append(args, buf) + } + + if escaped || singleQuoted || doubleQuoted || backQuote || dollarQuote { + return nil, errors.New("invalid command line string") + } + + p.Position = pos + + return args, nil +} + +func Parse(line string) ([]string, error) { + return NewParser().Parse(line) +} diff --git a/vendor/github.com/mattn/go-shellwords/util_go15.go b/vendor/github.com/mattn/go-shellwords/util_go15.go new file mode 100644 index 00000000000..180f00f0bd6 --- /dev/null +++ b/vendor/github.com/mattn/go-shellwords/util_go15.go @@ -0,0 +1,24 @@ +// +build !go1.6 + +package shellwords + +import ( + "os" + "os/exec" + "runtime" + "strings" +) + +func shellRun(line string) (string, error) { + var b []byte + var err error + if runtime.GOOS == "windows" { + b, err = exec.Command(os.Getenv("COMSPEC"), "/c", line).Output() + } else { + b, err = exec.Command(os.Getenv("SHELL"), "-c", line).Output() + } + if err != nil { + return "", err + } + return strings.TrimSpace(string(b)), nil +} diff --git a/vendor/github.com/mattn/go-shellwords/util_posix.go b/vendor/github.com/mattn/go-shellwords/util_posix.go new file mode 100644 index 00000000000..eaf1011d60e --- /dev/null +++ b/vendor/github.com/mattn/go-shellwords/util_posix.go @@ -0,0 +1,22 @@ +// +build !windows,go1.6 + +package shellwords + +import ( + "errors" + "os" + "os/exec" + "strings" +) + +func shellRun(line string) (string, error) { + shell := os.Getenv("SHELL") + b, err := exec.Command(shell, "-c", line).Output() + if err != nil { + if eerr, ok := err.(*exec.ExitError); ok { + b = eerr.Stderr + } + return "", errors.New(err.Error() + ":" + string(b)) + } + return strings.TrimSpace(string(b)), nil +} diff --git a/vendor/github.com/mattn/go-shellwords/util_windows.go b/vendor/github.com/mattn/go-shellwords/util_windows.go new file mode 100644 index 00000000000..e46f89a1fed --- /dev/null +++ b/vendor/github.com/mattn/go-shellwords/util_windows.go @@ -0,0 +1,22 @@ +// +build windows,go1.6 + +package shellwords + +import ( + "errors" + "os" + "os/exec" + "strings" +) + +func shellRun(line string) (string, error) { + shell := os.Getenv("COMSPEC") + b, err := exec.Command(shell, "/c", line).Output() + if err != nil { + if eerr, ok := err.(*exec.ExitError); ok { + b = eerr.Stderr + } + return "", errors.New(err.Error() + ":" + string(b)) + } + return strings.TrimSpace(string(b)), nil +} 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 be9d128bef8..b60a8bfdc7c 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": "\"-iA1DTNe4s-I6JZXPt1t1Ypy8IU/N-OFBDyIh2rjB3cbDrFel2ULy4k\"", + "etag": "\"Zkyw9ACJZUvcYmlFaKGChzhmtnE/uu5Fb8xKeF9Z7ooFYwXgp7bFFJg\"", "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" @@ -74,12 +74,12 @@ "type": "boolean" }, "quotaUser": { - "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.", + "description": "An opaque string that represents a user for quota purposes. Must not exceed 40 characters.", "location": "query", "type": "string" }, "userIp": { - "description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.", + "description": "Deprecated. Please use quotaUser instead.", "location": "query", "type": "string" } @@ -97,7 +97,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -138,7 +138,7 @@ ] }, "get": { - "description": "Returns the specified accelerator type. Get a list of available accelerator types by making a list() request.", + "description": "Returns the specified accelerator type.", "httpMethod": "GET", "id": "compute.acceleratorTypes.get", "parameterOrder": [ @@ -189,7 +189,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -249,7 +249,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -428,7 +428,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -582,7 +582,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -669,7 +669,7 @@ ] }, "get": { - "description": "Returns the specified autoscaler resource. Get a list of available autoscalers by making a list() request.", + "description": "Returns the specified autoscaler resource. Gets a list of available autoscalers by making a list() request.", "httpMethod": "GET", "id": "compute.autoscalers.get", "parameterOrder": [ @@ -761,7 +761,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1074,7 +1074,7 @@ ] }, "get": { - "description": "Returns the specified BackendBucket resource. Get a list of available backend buckets by making a list() request.", + "description": "Returns the specified BackendBucket resource. Gets a list of available backend buckets by making a list() request.", "httpMethod": "GET", "id": "compute.backendBuckets.get", "parameterOrder": [ @@ -1183,7 +1183,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1290,7 +1290,7 @@ }, "path": "{project}/global/backendBuckets/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "GlobalSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -1431,7 +1431,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1554,7 +1554,7 @@ ] }, "get": { - "description": "Returns the specified BackendService resource. Get a list of available backend services by making a list() request.", + "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", "httpMethod": "GET", "id": "compute.backendServices.get", "parameterOrder": [ @@ -1665,7 +1665,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1866,47 +1866,6 @@ } } }, - "clientSslPolicies": { - "methods": { - "testIamPermissions": { - "description": "Returns permissions that a caller has on the specified resource.", - "httpMethod": "POST", - "id": "compute.clientSslPolicies.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 of the resource for this request.", - "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/global/clientSslPolicies/{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" - ] - } - } - }, "diskTypes": { "methods": { "aggregatedList": { @@ -1918,7 +1877,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1959,7 +1918,7 @@ ] }, "get": { - "description": "Returns the specified disk type. Get a list of available disk types by making a list() request.", + "description": "Returns the specified disk type. Gets a list of available disk types by making a list() request.", "httpMethod": "GET", "id": "compute.diskTypes.get", "parameterOrder": [ @@ -2010,7 +1969,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2061,6 +2020,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])?", + "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", @@ -2070,7 +2078,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2209,7 +2217,7 @@ ] }, "get": { - "description": "Returns a specified persistent disk. Get a list of available persistent disks by making a list() request.", + "description": "Returns a specified persistent disk. Gets a list of available persistent disks by making a list() request.", "httpMethod": "GET", "id": "compute.disks.get", "parameterOrder": [ @@ -2348,7 +2356,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2395,6 +2403,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])?", + "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", @@ -2478,7 +2535,7 @@ }, "path": "{project}/zones/{zone}/disks/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "ZoneSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -2700,7 +2757,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2872,7 +2929,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3051,7 +3108,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3333,7 +3390,7 @@ ] }, "get": { - "description": "Returns the specified address resource. Get a list of available addresses by making a list() request.", + "description": "Returns the specified address resource. Gets a list of available addresses by making a list() request.", "httpMethod": "GET", "id": "compute.globalAddresses.get", "parameterOrder": [ @@ -3408,7 +3465,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3564,7 +3621,7 @@ ] }, "get": { - "description": "Returns the specified GlobalForwardingRule resource. Get a list of available forwarding rules by making a list() request.", + "description": "Returns the specified GlobalForwardingRule resource. Gets a list of available forwarding rules by making a list() request.", "httpMethod": "GET", "id": "compute.globalForwardingRules.get", "parameterOrder": [ @@ -3639,7 +3696,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3847,7 +3904,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3918,7 +3975,7 @@ ] }, "get": { - "description": "Retrieves the specified Operations resource. Get a list of operations by making a list() request.", + "description": "Retrieves the specified Operations resource. Gets a list of operations by making a list() request.", "httpMethod": "GET", "id": "compute.globalOperations.get", "parameterOrder": [ @@ -3960,7 +4017,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3999,11 +4056,94 @@ "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.globalOperations.wait", + "parameterOrder": [ + "project", + "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" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{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/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": { + "description": "Retrieves the list of all HealthCheck resources, regional and global, available to the specified project.", + "httpMethod": "GET", + "id": "compute.healthChecks.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/healthChecks", + "response": { + "$ref": "HealthChecksAggregatedList" + }, + "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 HealthCheck resource.", "httpMethod": "DELETE", @@ -4043,7 +4183,7 @@ ] }, "get": { - "description": "Returns the specified HealthCheck resource. Get a list of available health checks by making a list() request.", + "description": "Returns the specified HealthCheck resource. Gets a list of available health checks by making a list() request.", "httpMethod": "GET", "id": "compute.healthChecks.get", "parameterOrder": [ @@ -4118,7 +4258,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4290,7 +4430,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4331,7 +4471,7 @@ ] }, "get": { - "description": "Returns the specified host type. Get a list of available host types by making a list() request.", + "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": [ @@ -4382,7 +4522,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4442,7 +4582,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4529,7 +4669,7 @@ ] }, "get": { - "description": "Returns the specified host. Get a list of available hosts by making a list() request.", + "description": "Returns the specified host. Gets a list of available hosts by making a list() request.", "httpMethod": "GET", "id": "compute.hosts.get", "parameterOrder": [ @@ -4663,7 +4803,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4744,7 +4884,7 @@ }, "path": "{project}/zones/{zone}/hosts/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "ZoneSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -4842,7 +4982,7 @@ ] }, "get": { - "description": "Returns the specified HttpHealthCheck resource. Get a list of available HTTP health checks by making a list() request.", + "description": "Returns the specified HttpHealthCheck resource. Gets a list of available HTTP health checks by making a list() request.", "httpMethod": "GET", "id": "compute.httpHealthChecks.get", "parameterOrder": [ @@ -4917,7 +5057,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5119,7 +5259,7 @@ ] }, "get": { - "description": "Returns the specified HttpsHealthCheck resource. Get a list of available HTTPS health checks by making a list() request.", + "description": "Returns the specified HttpsHealthCheck resource. Gets a list of available HTTPS health checks by making a list() request.", "httpMethod": "GET", "id": "compute.httpsHealthChecks.get", "parameterOrder": [ @@ -5194,7 +5334,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5437,7 +5577,7 @@ ] }, "get": { - "description": "Returns the specified image. Get a list of available images by making a list() request.", + "description": "Returns the specified image. Gets a list of available images by making a list() request.", "httpMethod": "GET", "id": "compute.images.get", "parameterOrder": [ @@ -5588,7 +5728,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5654,7 +5794,7 @@ }, "path": "{project}/global/images/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "GlobalSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -5797,7 +5937,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5971,7 +6111,7 @@ ] }, "deletePerInstanceConfigs": { - "description": "Delete selected per-instance configs for the managed instance group.", + "description": "Deletes selected per-instance configs for the managed instance group.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.deletePerInstanceConfigs", "parameterOrder": [ @@ -6013,7 +6153,7 @@ ] }, "get": { - "description": "Returns all of the details about the specified managed instance group. Get a list of available managed instance groups by making a list() request.", + "description": "Returns all of the details about the specified managed instance group. Gets a list of available managed instance groups by making a list() request.", "httpMethod": "GET", "id": "compute.instanceGroupManagers.get", "parameterOrder": [ @@ -6102,7 +6242,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -6218,7 +6358,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -6803,7 +6943,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -6888,7 +7028,7 @@ ] }, "get": { - "description": "Returns the specified instance group. Get a list of available instance groups by making a list() request.", + "description": "Returns the specified instance group. Gets a list of available instance groups by making a list() request.", "httpMethod": "GET", "id": "compute.instanceGroups.get", "parameterOrder": [ @@ -6977,7 +7117,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -7034,7 +7174,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -7271,7 +7411,7 @@ ] }, "get": { - "description": "Returns the specified instance template. Get a list of available instance templates by making a list() request.", + "description": "Returns the specified instance template. Gets a list of available instance templates by making a list() request.", "httpMethod": "GET", "id": "compute.instanceTemplates.get", "parameterOrder": [ @@ -7346,7 +7486,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -7483,10 +7623,10 @@ "https://www.googleapis.com/auth/compute" ] }, - "addMaintenancePolicies": { - "description": "Adds existing maintenance policies to an instance. You can only add one policy right now which will be applied to this instance for scheduling live migrations.", + "addResourcePolicies": { + "description": "Adds existing resource policies to an instance. You can only add one policy right now which will be applied to this instance for scheduling live migrations.", "httpMethod": "POST", - "id": "compute.instances.addMaintenancePolicies", + "id": "compute.instances.addResourcePolicies", "parameterOrder": [ "project", "zone", @@ -7520,9 +7660,9 @@ "type": "string" } }, - "path": "{project}/zones/{zone}/instances/{instance}/addMaintenancePolicies", + "path": "{project}/zones/{zone}/instances/{instance}/addResourcePolicies", "request": { - "$ref": "InstancesAddMaintenancePoliciesRequest" + "$ref": "InstancesAddResourcePoliciesRequest" }, "response": { "$ref": "Operation" @@ -7541,7 +7681,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -7795,7 +7935,7 @@ ] }, "get": { - "description": "Returns the specified Instance resource. Get a list of available instances by making a list() request.", + "description": "Returns the specified Instance resource. Gets a list of available instances by making a list() request.", "httpMethod": "GET", "id": "compute.instances.get", "parameterOrder": [ @@ -8038,7 +8178,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8096,7 +8236,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8150,10 +8290,10 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, - "removeMaintenancePolicies": { - "description": "Removes maintenance policies from an instance.", + "removeResourcePolicies": { + "description": "Removes resource policies from an instance.", "httpMethod": "POST", - "id": "compute.instances.removeMaintenancePolicies", + "id": "compute.instances.removeResourcePolicies", "parameterOrder": [ "project", "zone", @@ -8187,9 +8327,9 @@ "type": "string" } }, - "path": "{project}/zones/{zone}/instances/{instance}/removeMaintenancePolicies", + "path": "{project}/zones/{zone}/instances/{instance}/removeResourcePolicies", "request": { - "$ref": "InstancesRemoveMaintenancePoliciesRequest" + "$ref": "InstancesRemoveResourcePoliciesRequest" }, "response": { "$ref": "Operation" @@ -8441,7 +8581,7 @@ }, "path": "{project}/zones/{zone}/instances/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "ZoneSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -8794,6 +8934,55 @@ "https://www.googleapis.com/auth/compute" ] }, + "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.", + "httpMethod": "PATCH", + "id": "compute.instances.setShieldedVmIntegrityPolicy", + "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}/setShieldedVmIntegrityPolicy", + "request": { + "$ref": "ShieldedVmIntegrityPolicy" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setTags": { "description": "Sets tags for the specified instance to the data included in the request.", "httpMethod": "POST", @@ -8885,7 +9074,7 @@ ] }, "start": { - "description": "Starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance.", + "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", "httpMethod": "POST", "id": "compute.instances.start", "parameterOrder": [ @@ -8931,7 +9120,7 @@ ] }, "startWithEncryptionKey": { - "description": "Starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance.", + "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", "httpMethod": "POST", "id": "compute.instances.startWithEncryptionKey", "parameterOrder": [ @@ -9300,7 +9489,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -9521,7 +9710,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -9651,7 +9840,7 @@ }, "path": "{project}/regions/{region}/interconnectAttachments/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "RegionSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -9760,7 +9949,7 @@ "interconnectLocations": { "methods": { "get": { - "description": "Returns the details for the specified interconnect location. Get a list of available interconnect locations by making a list() request.", + "description": "Returns the details for the specified interconnect location. Gets a list of available interconnect locations by making a list() request.", "httpMethod": "GET", "id": "compute.interconnectLocations.get", "parameterOrder": [ @@ -9802,7 +9991,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10031,7 +10220,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10138,7 +10327,7 @@ }, "path": "{project}/global/interconnects/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "GlobalSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -10319,7 +10508,7 @@ }, "path": "{project}/global/licenseCodes/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "GlobalSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -10513,7 +10702,7 @@ ] }, "list": { - "description": "Retrieves the list of licenses available in the specified project. This method does not get any licenses that belong to other projects, including licenses attached to publicly-available images, like Debian 8. If you want to get a list of publicly-available licenses, use this method to make a request to the respective image project, such as debian-cloud or windows-cloud.", + "description": "Retrieves the list of licenses available in the specified project. This method does not get any licenses that belong to other projects, including licenses attached to publicly-available images, like Debian 9. If you want to get a list of publicly-available licenses, use this method to make a request to the respective image project, such as debian-cloud or windows-cloud.", "httpMethod": "GET", "id": "compute.licenses.list", "parameterOrder": [ @@ -10521,7 +10710,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10587,7 +10776,7 @@ }, "path": "{project}/global/licenses/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "GlobalSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -10647,7 +10836,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10688,7 +10877,7 @@ ] }, "get": { - "description": "Returns the specified machine type. Get a list of available machine types by making a list() request.", + "description": "Returns the specified machine type. Gets a list of available machine types by making a list() request.", "httpMethod": "GET", "id": "compute.machineTypes.get", "parameterOrder": [ @@ -10739,7 +10928,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10788,376 +10977,6 @@ } } }, - "maintenancePolicies": { - "methods": { - "aggregatedList": { - "description": "Retrieves an aggregated list of maintenance policies.", - "httpMethod": "GET", - "id": "compute.maintenancePolicies.aggregatedList", - "parameterOrder": [ - "project" - ], - "parameters": { - "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", - "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/maintenancePolicies", - "response": { - "$ref": "MaintenancePolicyAggregatedList" - }, - "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 maintenance policy.", - "httpMethod": "DELETE", - "id": "compute.maintenancePolicies.delete", - "parameterOrder": [ - "project", - "region", - "maintenancePolicy" - ], - "parameters": { - "maintenancePolicy": { - "description": "Name of the maintenance policy 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": "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}/maintenancePolicies/{maintenancePolicy}", - "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 maintenance policy.", - "httpMethod": "GET", - "id": "compute.maintenancePolicies.get", - "parameterOrder": [ - "project", - "region", - "maintenancePolicy" - ], - "parameters": { - "maintenancePolicy": { - "description": "Name of the maintenance policy 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" - }, - "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}/maintenancePolicies/{maintenancePolicy}", - "response": { - "$ref": "MaintenancePolicy" - }, - "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.maintenancePolicies.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 of the resource for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/regions/{region}/maintenancePolicies/{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 maintenance policy.", - "httpMethod": "POST", - "id": "compute.maintenancePolicies.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}/maintenancePolicies", - "request": { - "$ref": "MaintenancePolicy" - }, - "response": { - "$ref": "Operation" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute" - ] - }, - "list": { - "description": "List all the maintenance policies that have been configured for the specified project in specified region.", - "httpMethod": "GET", - "id": "compute.maintenancePolicies.list", - "parameterOrder": [ - "project", - "region" - ], - "parameters": { - "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", - "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}/maintenancePolicies", - "response": { - "$ref": "MaintenancePoliciesList" - }, - "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.maintenancePolicies.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 of the resource for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/regions/{region}/maintenancePolicies/{resource}/setIamPolicy", - "request": { - "$ref": "Policy" - }, - "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.maintenancePolicies.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 of the resource for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/regions/{region}/maintenancePolicies/{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" - ] - } - } - }, "networkEndpointGroups": { "methods": { "aggregatedList": { @@ -11169,7 +10988,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11348,7 +11167,7 @@ ] }, "get": { - "description": "Returns the specified network endpoint group. Get a list of available network endpoint groups by making a list() request.", + "description": "Returns the specified network endpoint group. Gets a list of available network endpoint groups by making a list() request.", "httpMethod": "GET", "id": "compute.networkEndpointGroups.get", "parameterOrder": [ @@ -11437,7 +11256,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11484,7 +11303,7 @@ ] }, "listNetworkEndpoints": { - "description": "List the network endpoints in the specified network endpoint group.", + "description": "Lists the network endpoints in the specified network endpoint group.", "httpMethod": "POST", "id": "compute.networkEndpointGroups.listNetworkEndpoints", "parameterOrder": [ @@ -11494,7 +11313,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11678,7 +11497,7 @@ ] }, "get": { - "description": "Returns the specified network. Get a list of available networks by making a list() request.", + "description": "Returns the specified network. Gets a list of available networks by making a list() request.", "httpMethod": "GET", "id": "compute.networks.get", "parameterOrder": [ @@ -11753,7 +11572,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11794,7 +11613,7 @@ ] }, "listIpOwners": { - "description": "List the internal IP owners in the specified network.", + "description": "Lists the internal IP owners in the specified network.", "httpMethod": "GET", "id": "compute.networks.listIpOwners", "parameterOrder": [ @@ -11803,7 +11622,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -12038,6 +11857,241 @@ }, "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 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}/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.", + "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.", + "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", @@ -12080,6 +12134,112 @@ "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.", + "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" + ] + }, "setIamPolicy": { "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", "httpMethod": "POST", @@ -12114,7 +12274,7 @@ }, "path": "{project}/zones/{zone}/nodeGroups/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "ZoneSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -12124,6 +12284,55 @@ "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", @@ -12173,6 +12382,143 @@ }, "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", @@ -12215,6 +12561,104 @@ "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", @@ -12249,7 +12693,7 @@ }, "path": "{project}/regions/{region}/nodeTemplates/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "RegionSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -12306,6 +12750,158 @@ } } }, + "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": { @@ -12461,7 +13057,7 @@ ] }, "getXpnHost": { - "description": "Get the shared VPC host project that this project links to. May be empty if no link exists.", + "description": "Gets the shared VPC host project that this project links to. May be empty if no link exists.", "httpMethod": "GET", "id": "compute.projects.getXpnHost", "parameterOrder": [ @@ -12486,7 +13082,7 @@ ] }, "getXpnResources": { - "description": "Get service resources (a.k.a service project) associated with this host project.", + "description": "Gets service resources (a.k.a service project) associated with this host project.", "httpMethod": "GET", "id": "compute.projects.getXpnResources", "parameterOrder": [ @@ -12530,7 +13126,7 @@ ] }, "listXpnHosts": { - "description": "List all shared VPC host projects visible to the user in an organization.", + "description": "Lists all shared VPC host projects visible to the user in an organization.", "httpMethod": "POST", "id": "compute.projects.listXpnHosts", "parameterOrder": [ @@ -12920,7 +13516,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13293,7 +13889,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13496,7 +14092,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13537,7 +14133,7 @@ ] }, "get": { - "description": "Returns the specified commitment resource. Get a list of available commitments by making a list() request.", + "description": "Returns the specified commitment resource. Gets a list of available commitments by making a list() request.", "httpMethod": "GET", "id": "compute.regionCommitments.get", "parameterOrder": [ @@ -13629,7 +14225,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13726,7 +14322,7 @@ "regionDiskTypes": { "methods": { "get": { - "description": "Returns the specified regional disk type. Get a list of available disk types by making a list() request.", + "description": "Returns the specified regional disk type. Gets a list of available disk types by making a list() request.", "httpMethod": "GET", "id": "compute.regionDiskTypes.get", "parameterOrder": [ @@ -13777,7 +14373,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -14024,7 +14620,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -14216,6 +14812,339 @@ } } }, + "regionHealthChecks": { + "methods": { + "delete": { + "description": "Deletes the specified HealthCheck resource.", + "httpMethod": "DELETE", + "id": "compute.regionHealthChecks.delete", + "parameterOrder": [ + "project", + "region", + "healthCheck" + ], + "parameters": { + "healthCheck": { + "description": "Name of the HealthCheck 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": "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}/healthChecks/{healthCheck}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Returns the specified HealthCheck resource. Gets a list of available health checks by making a list() request.", + "httpMethod": "GET", + "id": "compute.regionHealthChecks.get", + "parameterOrder": [ + "project", + "region", + "healthCheck" + ], + "parameters": { + "healthCheck": { + "description": "Name of the HealthCheck resource 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": "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}/healthChecks/{healthCheck}", + "response": { + "$ref": "HealthCheck" + }, + "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 HealthCheck resource in the specified project using the data included in the request.", + "httpMethod": "POST", + "id": "compute.regionHealthChecks.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}/healthChecks", + "request": { + "$ref": "HealthCheck" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "Retrieves the list of HealthCheck resources available to the specified project.", + "httpMethod": "GET", + "id": "compute.regionHealthChecks.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}/healthChecks", + "response": { + "$ref": "HealthCheckList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "patch": { + "description": "Updates a HealthCheck resource in the specified project using the data included in the request. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + "httpMethod": "PATCH", + "id": "compute.regionHealthChecks.patch", + "parameterOrder": [ + "project", + "region", + "healthCheck" + ], + "parameters": { + "healthCheck": { + "description": "Name of the HealthCheck resource to patch.", + "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": "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}/healthChecks/{healthCheck}", + "request": { + "$ref": "HealthCheck" + }, + "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.regionHealthChecks.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 of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/healthChecks/{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" + ] + }, + "update": { + "description": "Updates a HealthCheck resource in the specified project using the data included in the request.", + "httpMethod": "PUT", + "id": "compute.regionHealthChecks.update", + "parameterOrder": [ + "project", + "region", + "healthCheck" + ], + "parameters": { + "healthCheck": { + "description": "Name of the HealthCheck resource 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" + }, + "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}/healthChecks/{healthCheck}", + "request": { + "$ref": "HealthCheck" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + } + } + }, "regionInstanceGroupManagers": { "methods": { "abandonInstances": { @@ -14399,7 +15328,7 @@ ] }, "deletePerInstanceConfigs": { - "description": "Delete selected per-instance configs for the managed instance group.", + "description": "Deletes selected per-instance configs for the managed instance group.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.deletePerInstanceConfigs", "parameterOrder": [ @@ -14530,7 +15459,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -14646,7 +15575,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -15174,7 +16103,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -15231,7 +16160,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -15472,7 +16401,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -15518,13 +16447,716 @@ "https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/compute.readonly" ] + }, + "wait": { + "description": "Waits for the specified region-specific 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.regionOperations.wait", + "parameterOrder": [ + "project", + "region", + "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" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{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}/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" + ] + } + } + }, + "regionTargetHttpProxies": { + "methods": { + "delete": { + "description": "Deletes the specified TargetHttpProxy resource.", + "httpMethod": "DELETE", + "id": "compute.regionTargetHttpProxies.delete", + "parameterOrder": [ + "project", + "region", + "targetHttpProxy" + ], + "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" + }, + "targetHttpProxy": { + "description": "Name of the TargetHttpProxy 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/{targetHttpProxy}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Returns the specified TargetHttpProxy resource in the specified region. Gets a list of available target HTTP proxies by making a list() request.", + "httpMethod": "GET", + "id": "compute.regionTargetHttpProxies.get", + "parameterOrder": [ + "project", + "region", + "targetHttpProxy" + ], + "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" + }, + "targetHttpProxy": { + "description": "Name of the TargetHttpProxy resource to return.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/targetHttpProxies/{targetHttpProxy}", + "response": { + "$ref": "TargetHttpProxy" + }, + "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 TargetHttpProxy resource in the specified project and region using the data included in the request.", + "httpMethod": "POST", + "id": "compute.regionTargetHttpProxies.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}/targetHttpProxies", + "request": { + "$ref": "TargetHttpProxy" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "Retrieves the list of TargetHttpProxy resources available to the specified project in the specified region.", + "httpMethod": "GET", + "id": "compute.regionTargetHttpProxies.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}/targetHttpProxies", + "response": { + "$ref": "TargetHttpProxyList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "setUrlMap": { + "description": "Changes the URL map for TargetHttpProxy.", + "httpMethod": "POST", + "id": "compute.regionTargetHttpProxies.setUrlMap", + "parameterOrder": [ + "project", + "region", + "targetHttpProxy" + ], + "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" + }, + "targetHttpProxy": { + "description": "Name of the TargetHttpProxy 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}/targetHttpProxies/{targetHttpProxy}/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.regionTargetHttpProxies.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 of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "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" + ] + } + } + }, + "regionUrlMaps": { + "methods": { + "delete": { + "description": "Deletes the specified UrlMap resource.", + "httpMethod": "DELETE", + "id": "compute.regionUrlMaps.delete", + "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 resource to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/urlMaps/{urlMap}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Returns the specified UrlMap resource. Gets a list of available URL maps by making a list() request.", + "httpMethod": "GET", + "id": "compute.regionUrlMaps.get", + "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" + }, + "urlMap": { + "description": "Name of the UrlMap resource to return.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/urlMaps/{urlMap}", + "response": { + "$ref": "UrlMap" + }, + "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 UrlMap resource in the specified project using the data included in the request.", + "httpMethod": "POST", + "id": "compute.regionUrlMaps.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": "begin_interface: MixerMutationRequestBuilder Request ID to support idempotency.", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/urlMaps", + "request": { + "$ref": "UrlMap" + }, + "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", + "id": "compute.regionUrlMaps.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}/urlMaps", + "response": { + "$ref": "UrlMapList" + }, + "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 UrlMap resource with the data included in the request. This method supports PATCH semantics and uses JSON merge patch format and processing rules.", + "httpMethod": "PATCH", + "id": "compute.regionUrlMaps.patch", + "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 resource to patch.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/urlMaps/{urlMap}", + "request": { + "$ref": "UrlMap" + }, + "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.regionUrlMaps.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 of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/urlMaps/{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" + ] + }, + "update": { + "description": "Updates the specified UrlMap resource with the data included in the request.", + "httpMethod": "PUT", + "id": "compute.regionUrlMaps.update", + "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 resource to update.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/urlMaps/{urlMap}", + "request": { + "$ref": "UrlMap" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "validate": { + "description": "Runs static validation for the UrlMap. In particular, the tests of the provided UrlMap will be run. Calling this method does NOT create the UrlMap.", + "httpMethod": "POST", + "id": "compute.regionUrlMaps.validate", + "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" + }, + "urlMap": { + "description": "Name of the UrlMap resource to be validated as.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/urlMaps/{urlMap}/validate", + "request": { + "$ref": "RegionUrlMapsValidateRequest" + }, + "response": { + "$ref": "UrlMapsValidateResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] } } }, "regions": { "methods": { "get": { - "description": "Returns the specified Region resource. Get a list of available regions by making a list() request.", + "description": "Returns the specified Region resource. Gets a list of available regions by making a list() request.", "httpMethod": "GET", "id": "compute.regions.get", "parameterOrder": [ @@ -15566,7 +17198,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -15608,6 +17240,376 @@ } } }, + "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" + ] + }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.resourcePolicies.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 of the resource 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/{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 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": "ResourcePoliciesList" + }, + "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.resourcePolicies.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 of the resource 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/{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.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 of the resource 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/{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": { @@ -15619,7 +17621,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -15706,7 +17708,7 @@ ] }, "get": { - "description": "Returns the specified Router resource. Get a list of available routers by making a list() request.", + "description": "Returns the specified Router resource. Gets a list of available routers by making a list() request.", "httpMethod": "GET", "id": "compute.routers.get", "parameterOrder": [ @@ -15840,7 +17842,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -16118,7 +18120,7 @@ ] }, "get": { - "description": "Returns the specified Route resource. Get a list of available routes by making a list() request.", + "description": "Returns the specified Route resource. Gets a list of available routes by making a list() request.", "httpMethod": "GET", "id": "compute.routes.get", "parameterOrder": [ @@ -16193,7 +18195,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -16446,6 +18448,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", @@ -16469,7 +18476,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -16509,6 +18516,54 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "listPreconfiguredExpressionSets": { + "description": "Gets the current list of preconfigured Web Application Firewall (WAF) expressions.", + "httpMethod": "GET", + "id": "compute.securityPolicies.listPreconfiguredExpressionSets", + "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/listPreconfiguredExpressionSets", + "response": { + "$ref": "SecurityPoliciesListPreconfiguredExpressionSetsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "patch": { "description": "Patches the specified policy with the data included in the request.", "httpMethod": "PATCH", @@ -16636,6 +18691,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 of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "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", @@ -16716,7 +18807,7 @@ ] }, "get": { - "description": "Returns the specified Snapshot resource. Get a list of available snapshots by making a list() request.", + "description": "Returns the specified Snapshot resource. Gets a list of available snapshots by making a list() request.", "httpMethod": "GET", "id": "compute.snapshots.get", "parameterOrder": [ @@ -16792,7 +18883,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -16858,7 +18949,7 @@ }, "path": "{project}/global/snapshots/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "GlobalSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -16984,7 +19075,7 @@ ] }, "get": { - "description": "Returns the specified SslCertificate resource. Get a list of available SSL certificates by making a list() request.", + "description": "Returns the specified SslCertificate resource. Gets a list of available SSL certificates by making a list() request.", "httpMethod": "GET", "id": "compute.sslCertificates.get", "parameterOrder": [ @@ -17059,7 +19150,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -17178,7 +19269,7 @@ ] }, "get": { - "description": "List all of the ordered rules present in a single specified policy.", + "description": "Lists all of the ordered rules present in a single specified policy.", "httpMethod": "GET", "id": "compute.sslPolicies.get", "parameterOrder": [ @@ -17211,7 +19302,7 @@ ] }, "insert": { - "description": "Returns the specified SSL policy resource. Get a list of available SSL policies by making a list() request.", + "description": "Returns the specified SSL policy resource. Gets a list of available SSL policies by making a list() request.", "httpMethod": "POST", "id": "compute.sslPolicies.insert", "parameterOrder": [ @@ -17244,7 +19335,7 @@ ] }, "list": { - "description": "List all the SSL policies that have been configured for the specified project.", + "description": "Lists all the SSL policies that have been configured for the specified project.", "httpMethod": "GET", "id": "compute.sslPolicies.list", "parameterOrder": [ @@ -17252,7 +19343,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -17301,7 +19392,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -17431,7 +19522,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -17567,7 +19658,7 @@ ] }, "get": { - "description": "Returns the specified subnetwork. Get a list of available subnetworks list() request.", + "description": "Returns the specified subnetwork. Gets a list of available subnetworks list() request.", "httpMethod": "GET", "id": "compute.subnetworks.get", "parameterOrder": [ @@ -17701,7 +19792,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -17757,7 +19848,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -17798,7 +19889,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 and allow_subnet_cidr_routes_overlap. 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 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.", "httpMethod": "PATCH", "id": "compute.subnetworks.patch", "parameterOrder": [ @@ -17880,7 +19971,7 @@ }, "path": "{project}/regions/{region}/subnetworks/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "RegionSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -17988,6 +20079,55 @@ }, "targetHttpProxies": { "methods": { + "aggregatedList": { + "description": "Retrieves the list of all TargetHttpProxy resources, regional and global, available to the specified project.", + "httpMethod": "GET", + "id": "compute.targetHttpProxies.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/targetHttpProxies", + "response": { + "$ref": "TargetHttpProxyAggregatedList" + }, + "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 TargetHttpProxy resource.", "httpMethod": "DELETE", @@ -18027,7 +20167,7 @@ ] }, "get": { - "description": "Returns the specified TargetHttpProxy resource. Get a list of available target HTTP proxies by making a list() request.", + "description": "Returns the specified TargetHttpProxy resource. Gets a list of available target HTTP proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetHttpProxies.get", "parameterOrder": [ @@ -18102,7 +20242,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -18263,7 +20403,7 @@ ] }, "get": { - "description": "Returns the specified TargetHttpsProxy resource. Get a list of available target HTTPS proxies by making a list() request.", + "description": "Returns the specified TargetHttpsProxy resource. Gets a list of available target HTTPS proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetHttpsProxies.get", "parameterOrder": [ @@ -18338,7 +20478,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -18590,7 +20730,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -18677,7 +20817,7 @@ ] }, "get": { - "description": "Returns the specified TargetInstance resource. Get a list of available target instances by making a list() request.", + "description": "Returns the specified TargetInstance resource. Gets a list of available target instances by making a list() request.", "httpMethod": "GET", "id": "compute.targetInstances.get", "parameterOrder": [ @@ -18769,7 +20909,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -18972,7 +21112,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -19059,7 +21199,7 @@ ] }, "get": { - "description": "Returns the specified target pool. Get a list of available target pools by making a list() request.", + "description": "Returns the specified target pool. Gets a list of available target pools by making a list() request.", "httpMethod": "GET", "id": "compute.targetPools.get", "parameterOrder": [ @@ -19196,7 +21336,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -19484,7 +21624,7 @@ ] }, "get": { - "description": "Returns the specified TargetSslProxy resource. Get a list of available target SSL proxies by making a list() request.", + "description": "Returns the specified TargetSslProxy resource. Gets a list of available target SSL proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetSslProxies.get", "parameterOrder": [ @@ -19559,7 +21699,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -19842,7 +21982,7 @@ ] }, "get": { - "description": "Returns the specified TargetTcpProxy resource. Get a list of available target TCP proxies by making a list() request.", + "description": "Returns the specified TargetTcpProxy resource. Gets a list of available target TCP proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetTcpProxies.get", "parameterOrder": [ @@ -19917,7 +22057,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -20089,7 +22229,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -20176,7 +22316,7 @@ ] }, "get": { - "description": "Returns the specified target VPN gateway. Get a list of available target VPN gateways by making a list() request.", + "description": "Returns the specified target VPN gateway. Gets a list of available target VPN gateways by making a list() request.", "httpMethod": "GET", "id": "compute.targetVpnGateways.get", "parameterOrder": [ @@ -20268,7 +22408,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -20452,7 +22592,7 @@ ] }, "get": { - "description": "Returns the specified UrlMap resource. Get a list of available URL maps by making a list() request.", + "description": "Returns the specified UrlMap resource. Gets a list of available URL maps by making a list() request.", "httpMethod": "GET", "id": "compute.urlMaps.get", "parameterOrder": [ @@ -20568,7 +22708,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -20765,6 +22905,339 @@ } } }, + "vpnGateways": { + "methods": { + "aggregatedList": { + "description": "Retrieves an aggregated list of VPN gateways.", + "httpMethod": "GET", + "id": "compute.vpnGateways.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/vpnGateways", + "response": { + "$ref": "VpnGatewayAggregatedList" + }, + "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 VPN gateway.", + "httpMethod": "DELETE", + "id": "compute.vpnGateways.delete", + "parameterOrder": [ + "project", + "region", + "vpnGateway" + ], + "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" + }, + "vpnGateway": { + "description": "Name of the VPN gateway to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/vpnGateways/{vpnGateway}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Returns the specified VPN gateway. Gets a list of available VPN gateways by making a list() request.", + "httpMethod": "GET", + "id": "compute.vpnGateways.get", + "parameterOrder": [ + "project", + "region", + "vpnGateway" + ], + "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" + }, + "vpnGateway": { + "description": "Name of the VPN gateway to return.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/vpnGateways/{vpnGateway}", + "response": { + "$ref": "VpnGateway" + }, + "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 VPN gateway in the specified project and region using the data included in the request.", + "httpMethod": "POST", + "id": "compute.vpnGateways.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}/vpnGateways", + "request": { + "$ref": "VpnGateway" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "Retrieves a list of VPN gateways available to the specified project and region.", + "httpMethod": "GET", + "id": "compute.vpnGateways.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}/vpnGateways", + "response": { + "$ref": "VpnGatewayList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "setLabels": { + "description": "Sets the labels on a VpnGateway. To learn more about labels, read the Labeling Resources documentation.", + "httpMethod": "POST", + "id": "compute.vpnGateways.setLabels", + "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 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" + }, + "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" + } + }, + "path": "{project}/regions/{region}/vpnGateways/{resource}/setLabels", + "request": { + "$ref": "RegionSetLabelsRequest" + }, + "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.vpnGateways.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 of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/vpnGateways/{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" + ] + } + } + }, "vpnTunnels": { "methods": { "aggregatedList": { @@ -20776,7 +23249,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -20863,7 +23336,7 @@ ] }, "get": { - "description": "Returns the specified VpnTunnel resource. Get a list of available VPN tunnels by making a list() request.", + "description": "Returns the specified VpnTunnel resource. Gets a list of available VPN tunnels by making a list() request.", "httpMethod": "GET", "id": "compute.vpnTunnels.get", "parameterOrder": [ @@ -20955,7 +23428,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -21190,7 +23663,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -21236,13 +23709,55 @@ "https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/compute.readonly" ] + }, + "wait": { + "description": "Waits for the specified zone-specific 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.zoneOperations.wait", + "parameterOrder": [ + "project", + "zone", + "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" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{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}/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" + ] } } }, "zones": { "methods": { "get": { - "description": "Returns the specified Zone resource. Get a list of available zones by making a list() request.", + "description": "Returns the specified Zone resource. Gets a list of available zones by making a list() request.", "httpMethod": "GET", "id": "compute.zones.get", "parameterOrder": [ @@ -21284,7 +23799,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -21327,7 +23842,7 @@ } } }, - "revision": "20180220", + "revision": "20180518", "rootUrl": "https://www.googleapis.com/", "schemas": { "AcceleratorConfig": { @@ -21621,7 +24136,7 @@ "id": "AcceleratorTypesScopedList", "properties": { "acceleratorTypes": { - "description": "[Output Only] List of accelerator types contained in this scope.", + "description": "[Output Only] A list of accelerator types contained in this scope.", "items": { "$ref": "AcceleratorType" }, @@ -22151,7 +24666,7 @@ "id": "AddressesScopedList", "properties": { "addresses": { - "description": "[Output Only] List of addresses contained in this scope.", + "description": "[Output Only] A list of addresses contained in this scope.", "items": { "$ref": "Address" }, @@ -22334,7 +24849,7 @@ "type": "string" }, "savedState": { - "description": "For LocalSSD disks on VM Instances in STOPPED or SUSPENDED state, this field is set to PRESERVED iff 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.", + "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" @@ -22407,6 +24922,10 @@ "sourceImageEncryptionKey": { "$ref": "CustomerEncryptionKey", "description": "The customer-supplied encryption key of the source image. Required if the source image is protected by a customer-supplied encryption key.\n\nInstance templates do not store customer-supplied encryption keys, so you cannot create disks for instances in a managed instance group if the source images are encrypted with your own keys." + }, + "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" } }, "type": "object" @@ -22528,7 +25047,7 @@ "type": "string" }, "recommendedSize": { - "description": "[Output Only] Target recommended MIG size computed by autoscaler. Autoscaler calculates recommended MIG size even when autoscaling policy mode is different from ON. This field is empty when autoscaler is not connected to the existing managed instance group or autoscaler did not generate its first prediction.", + "description": "[Output Only] Target recommended MIG size (number of instances) computed by autoscaler. Autoscaler calculates recommended MIG size even when autoscaling policy mode is different from ON. This field is empty when autoscaler is not connected to the existing managed instance group or autoscaler did not generate its prediction.", "format": "int32", "type": "integer" }, @@ -22850,7 +25369,7 @@ "id": "AutoscalersScopedList", "properties": { "autoscalers": { - "description": "[Output Only] List of autoscalers contained in this scope.", + "description": "[Output Only] A list of autoscalers contained in this scope.", "items": { "$ref": "Autoscaler" }, @@ -23429,9 +25948,11 @@ "enum": [ "EXTERNAL", "INTERNAL", + "INTERNAL_SELF_MANAGED", "INVALID_LOAD_BALANCING_SCHEME" ], "enumDescriptions": [ + "", "", "", "" @@ -23726,6 +26247,10 @@ "oauth2ClientId": { "type": "string" }, + "oauth2ClientInfo": { + "$ref": "BackendServiceIAPOAuth2ClientInfo", + "description": "[Input Only] OAuth client info required to generate client id to be used for IAP." + }, "oauth2ClientSecret": { "type": "string" }, @@ -23736,6 +26261,24 @@ }, "type": "object" }, + "BackendServiceIAPOAuth2ClientInfo": { + "id": "BackendServiceIAPOAuth2ClientInfo", + "properties": { + "applicationName": { + "description": "Application name to be used in OAuth consent screen.", + "type": "string" + }, + "clientName": { + "description": "Name of the client to be generated. Optional - If not provided, the name will be autogenerated by the backend.", + "type": "string" + }, + "developerEmailAddress": { + "description": "Developer's information to be used in OAuth consent screen.", + "type": "string" + } + }, + "type": "object" + }, "BackendServiceList": { "description": "Contains a list of BackendService resources.", "id": "BackendServiceList", @@ -23861,7 +26404,7 @@ "id": "BackendServicesScopedList", "properties": { "backendServices": { - "description": "List of BackendServices contained in this scope.", + "description": "A list of BackendServices contained in this scope.", "items": { "$ref": "BackendService" }, @@ -23960,7 +26503,7 @@ "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." }, "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` or `joe@example.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`.", + "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" }, @@ -24069,7 +26612,7 @@ "type": "string" }, "resources": { - "description": "List of commitment amounts for particular resources. Note that VCPU and MEMORY resource commitments must occur together.", + "description": "A list of commitment amounts for particular resources. Note that VCPU and MEMORY resource commitments must occur together.", "items": { "$ref": "ResourceCommitment" }, @@ -24102,6 +26645,20 @@ "statusMessage": { "description": "[Output Only] An optional, human-readable explanation of the status.", "type": "string" + }, + "type": { + "description": "The type of commitment, which affects the discount rate and the eligible resources. Type MEMORY_OPTIMIZED specifies a commitment that will only apply to memory optimized machines.", + "enum": [ + "GENERAL_PURPOSE", + "MEMORY_OPTIMIZED", + "TYPE_UNSPECIFIED" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" } }, "type": "object" @@ -24334,7 +26891,7 @@ "id": "CommitmentsScopedList", "properties": { "commitments": { - "description": "[Output Only] List of commitments contained in this scope.", + "description": "[Output Only] A list of commitments contained in this scope.", "items": { "$ref": "Commitment" }, @@ -24531,7 +27088,7 @@ "type": "string" }, "rsaEncryptedKey": { - "description": "Specifies an RFC 4648 base64 encoded, RSA-wrapped 2048-bit customer-supplied encryption key to either encrypt or decrypt this resource.\n\nThe key must meet the following requirements before you can provide it to Compute Engine: \n- The key is wrapped using a RSA public key certificate provided by Google. \n- After being wrapped, the key must be encoded in RFC 4648 base64 encoding. Get the RSA public key certificate provided by Google at:\nhttps://cloud-certs.storage.googleapis.com/google-cloud-csek-ingress.pem", + "description": "Specifies an RFC 4648 base64 encoded, RSA-wrapped 2048-bit customer-supplied encryption key to either encrypt or decrypt this resource.\n\nThe key must meet the following requirements before you can provide it to Compute Engine: \n- The key is wrapped using a RSA public key certificate provided by Google. \n- After being wrapped, the key must be encoded in RFC 4648 base64 encoding. Gets the RSA public key certificate provided by Google at:\nhttps://cloud-certs.storage.googleapis.com/google-cloud-csek-ingress.pem", "type": "string" }, "sha256": { @@ -24555,26 +27112,6 @@ }, "type": "object" }, - "DailyMaintenanceWindow": { - "description": "Time window specified for daily maintenance operations.", - "id": "DailyMaintenanceWindow", - "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 maintenance window to start the maintenance operations. It must be in format \"HH:MM?, where HH : [00-23] and MM : [00-59] GMT.", - "type": "string" - } - }, - "type": "object" - }, "DeprecationStatus": { "description": "Deprecation status for a public resource.", "id": "DeprecationStatus", @@ -24710,6 +27247,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" @@ -25104,6 +27648,10 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, + "region": { + "description": "[Output Only] URL of the region where the disk type 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" + }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" @@ -25347,7 +27895,7 @@ "id": "DiskTypesScopedList", "properties": { "diskTypes": { - "description": "[Output Only] List of disk types contained in this scope.", + "description": "[Output Only] A list of disk types contained in this scope.", "items": { "$ref": "DiskType" }, @@ -25437,6 +27985,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": { @@ -25452,7 +28026,7 @@ "id": "DisksScopedList", "properties": { "disks": { - "description": "[Output Only] List of disks contained in this scope.", + "description": "[Output Only] A list of disks contained in this scope.", "items": { "$ref": "Disk" }, @@ -25669,7 +28243,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 the configured export destination for all firewall logs in the network. Logs may be exported to BigQuery or Pub/Sub.", + "description": "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": { @@ -26274,7 +28848,7 @@ "id": "ForwardingRulesScopedList", "properties": { "forwardingRules": { - "description": "List of forwarding rules contained in this scope.", + "description": "A list of forwarding rules contained in this scope.", "items": { "$ref": "ForwardingRule" }, @@ -26382,6 +28956,28 @@ }, "type": "object" }, + "GlobalSetPolicyRequest": { + "id": "GlobalSetPolicyRequest", + "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" + }, "GuestAttributes": { "description": "A guest attributes entry.", "id": "GuestAttributes", @@ -26638,6 +29234,10 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, + "region": { + "description": "[Output Only] Region where the health check resides. Not applicable to global health checks.", + "type": "string" + }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" @@ -26808,6 +29408,212 @@ }, "type": "object" }, + "HealthChecksAggregatedList": { + "id": "HealthChecksAggregatedList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "HealthChecksScopedList", + "description": "Name of the scope containing this set of HealthChecks." + }, + "description": "A list of HealthChecksScopedList resources.", + "type": "object" + }, + "kind": { + "default": "compute#healthChecksAggregatedList", + "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" + }, + "HealthChecksScopedList": { + "id": "HealthChecksScopedList", + "properties": { + "healthChecks": { + "description": "A list of HealthChecks contained in this scope.", + "items": { + "$ref": "HealthCheck" + }, + "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" + }, "HealthStatus": { "id": "HealthStatus", "properties": { @@ -27489,7 +30295,7 @@ "id": "HostTypesScopedList", "properties": { "hostTypes": { - "description": "[Output Only] List of host types contained in this scope.", + "description": "[Output Only] A list of host types contained in this scope.", "items": { "$ref": "HostType" }, @@ -27583,7 +30389,7 @@ "id": "HostsScopedList", "properties": { "hosts": { - "description": "[Output Only] List of hosts contained in this scope.", + "description": "[Output Only] A list of hosts contained in this scope.", "items": { "$ref": "Host" }, @@ -27673,26 +30479,6 @@ }, "type": "object" }, - "HourlyMaintenanceWindow": { - "description": "Time window specified for hourly maintenance operations.", - "id": "HourlyMaintenanceWindow", - "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 maintenance window to start the maintenance operations. It must be in format \"HH:MM?, where HH : [00-23] and MM : [00-59] GMT.", - "type": "string" - } - }, - "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", @@ -28381,7 +31167,7 @@ "type": "array" }, "guestAccelerators": { - "description": "List of the type and count of accelerator cards attached to the instance.", + "description": "A list of the type and count of accelerator cards attached to the instance.", "items": { "$ref": "AcceleratorConfig" }, @@ -28406,7 +31192,7 @@ "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 instance.", + "description": "A fingerprint for this request, which is essentially a hash of the label's contents and 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 instance.", "format": "byte", "type": "string" }, @@ -28426,13 +31212,6 @@ "description": "Full or partial URL of the machine type resource to use for this instance, in the format: zones/zone/machineTypes/machine-type. This is provided by the client when the instance is created. For example, the following is a valid partial url to a predefined machine type:\nzones/us-central1-f/machineTypes/n1-standard-1\n\n\nTo create a custom machine type, provide a URL to a machine type in the following format, where CPUS is 1 or an even number up to 32 (2, 4, 6, ... 24, etc), and MEMORY is the total memory for this instance. Memory must be a multiple of 256 MB and must be supplied in MB (e.g. 5 GB of memory is 5120 MB):\nzones/zone/machineTypes/custom-CPUS-MEMORY\n\n\nFor example: zones/us-central1-f/machineTypes/custom-4-5120 \n\nFor a full list of restrictions, read the Specifications for custom machine types.", "type": "string" }, - "maintenancePolicies": { - "description": "Maintenance policies applied to this instance.", - "items": { - "type": "string" - }, - "type": "array" - }, "metadata": { "$ref": "Metadata", "description": "The metadata key/value pairs assigned to this instance. This includes custom metadata and predefined keys." @@ -28463,6 +31242,13 @@ "format": "int64", "type": "string" }, + "resourcePolicies": { + "description": "Resource policies applied to this instance.", + "items": { + "type": "string" + }, + "type": "array" + }, "scheduling": { "$ref": "Scheduling", "description": "Sets the scheduling options for this instance." @@ -28481,6 +31267,13 @@ "shieldedVmConfig": { "$ref": "ShieldedVmConfig" }, + "shieldedVmIntegrityPolicy": { + "$ref": "ShieldedVmIntegrityPolicy" + }, + "sourceMachineImage": { + "description": "Source machine image", + "type": "string" + }, "startRestricted": { "description": "[Output Only] Whether a VM has been restricted for start because Compute Engine has detected suspicious activity.", "type": "boolean" @@ -28685,7 +31478,7 @@ "type": "string" }, "region": { - "description": "The URL of the region where the instance group is located (for regional resources).", + "description": "[Output Only] The URL of the region where the instance group is located (for regional resources).", "type": "string" }, "selfLink": { @@ -28698,7 +31491,7 @@ "type": "integer" }, "subnetwork": { - "description": "The URL of the subnetwork to which all instances in the instance group belong.", + "description": "[Output Only] The URL of the subnetwork to which all instances in the instance group belong.", "type": "string" }, "zone": { @@ -28985,7 +31778,7 @@ "type": "string" }, "fingerprint": { - "description": "[Output Only] The fingerprint of the resource data. You can use this optional field for optimistic locking when you update the resource.", + "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.", "format": "byte", "type": "string" }, @@ -29038,7 +31831,7 @@ "type": "string" }, "serviceAccount": { - "description": "[Output Only] 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.", + "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" }, "statefulPolicy": { @@ -29499,6 +32292,19 @@ "InstanceGroupManagerUpdatePolicy": { "id": "InstanceGroupManagerUpdatePolicy", "properties": { + "instanceRedistributionType": { + "enum": [ + "NONE", + "PROACTIVE", + "UNSPECIFIED_TYPE" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, "maxSurge": { "$ref": "FixedOrPercent", "description": "The maximum number of instances that can be created above the specified targetSize during the update process. By default, a fixed value of 1 is used. This value can be either a fixed number or a percentage if the instance group has 10 or more instances. If you set a percentage, the number of instances will be rounded up if necessary.\n\nAt least one of either maxSurge or maxUnavailable must be greater than 0. Learn more about maxSurge." @@ -30738,11 +33544,11 @@ }, "type": "object" }, - "InstancesAddMaintenancePoliciesRequest": { - "id": "InstancesAddMaintenancePoliciesRequest", + "InstancesAddResourcePoliciesRequest": { + "id": "InstancesAddResourcePoliciesRequest", "properties": { - "maintenancePolicies": { - "description": "Maintenance policies to be added to this instance.", + "resourcePolicies": { + "description": "Resource policies to be added to this instance.", "items": { "type": "string" }, @@ -30751,11 +33557,11 @@ }, "type": "object" }, - "InstancesRemoveMaintenancePoliciesRequest": { - "id": "InstancesRemoveMaintenancePoliciesRequest", + "InstancesRemoveResourcePoliciesRequest": { + "id": "InstancesRemoveResourcePoliciesRequest", "properties": { - "maintenancePolicies": { - "description": "Maintenance policies to be removed from this instance.", + "resourcePolicies": { + "description": "Resource policies to be removed from this instance.", "items": { "type": "string" }, @@ -30785,7 +33591,7 @@ "id": "InstancesScopedList", "properties": { "instances": { - "description": "[Output Only] List of instances contained in this scope.", + "description": "[Output Only] A list of instances contained in this scope.", "items": { "$ref": "Instance" }, @@ -30896,7 +33702,7 @@ "id": "InstancesSetMachineResourcesRequest", "properties": { "guestAccelerators": { - "description": "List of the type and count of accelerator cards attached to the instance.", + "description": "A list of the type and count of accelerator cards attached to the instance.", "items": { "$ref": "AcceleratorConfig" }, @@ -30968,7 +33774,7 @@ "type": "boolean" }, "circuitInfos": { - "description": "[Output Only] List of CircuitInfo objects, that describe the individual circuits in this LAG.", + "description": "[Output Only] A list of CircuitInfo objects, that describe the individual circuits in this LAG.", "items": { "$ref": "InterconnectCircuitInfo" }, @@ -30987,7 +33793,7 @@ "type": "string" }, "expectedOutages": { - "description": "[Output Only] List of outages expected for this Interconnect.", + "description": "[Output Only] A list of outages expected for this Interconnect.", "items": { "$ref": "InterconnectOutageNotification" }, @@ -31126,6 +33932,7 @@ "type": "boolean" }, "availabilityZone": { + "description": "[Deprecated] Replaced by edge_availability_domain.", "enum": [ "ZONE_1", "ZONE_2", @@ -31139,6 +33946,7 @@ "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.", "enum": [ "BPS_100M", "BPS_10G", @@ -31189,7 +33997,7 @@ "type": "string" }, "edgeAvailabilityDomain": { - "description": "Desired availability domain for the attachment. Can only be specified when creating PARTNER-type InterconnectAttachments.\n\nFor improved reliability, customers should configure a pair of attachments with one per availability domain. The selected availability domain will be provided to the Partner via the pairing key so that the provisioned circuit will lie in the specified domain. If not specified, the value will default to AVAILABILITY_DOMAIN_ANY.", + "description": "Desired availability domain for the attachment. Only available for type PARTNER, at creation time. For improved reliability, customers should configure a pair of attachments with one per availability domain. The selected availability domain will be provided to the Partner via the pairing key so that the provisioned circuit will lie in the specified domain. If not specified, the value will default to AVAILABILITY_DOMAIN_ANY.", "enum": [ "AVAILABILITY_DOMAIN_1", "AVAILABILITY_DOMAIN_2", @@ -31250,16 +34058,17 @@ "type": "string" }, "pairingKey": { - "description": "[Output only for type PARTNER. Input only for PARTNER_PROVIDER. Not present for DEDICATED]. Opaque string identifying an PARTNER attachment. Of the form ?cloud-region/XXXXXX?.", + "description": "[Output only for type PARTNER. Input only for PARTNER_PROVIDER. Not present for DEDICATED]. The opaque identifier of an PARTNER attachment used to initiate provisioning with a selected partner. Of the form \"XXXXX/region/domain\"", "type": "string" }, "partnerAsn": { - "description": "[Output only for PARTNER. Input for PARTNER_PROVIDER. Not present for DEDICATED] BGP ASN of the Partner. A layer 3 Partner should supply this if they configured BGP on behalf of the customer.", + "description": "Optional BGP ASN for the router that should be supplied by a layer 3 Partner if they configured BGP on behalf of the customer. Output only for PARTNER type, input only for PARTNER_PROVIDER, not available for DEDICATED.", "format": "int64", "type": "string" }, "partnerMetadata": { - "$ref": "InterconnectAttachmentPartnerMetadata" + "$ref": "InterconnectAttachmentPartnerMetadata", + "description": "Informational metadata about Partner attachments from Partners to display to customers. Output only for for PARTNER type, mutable for PARTNER_PROVIDER, not available for DEDICATED." }, "privateInterconnectInfo": { "$ref": "InterconnectAttachmentPrivateInfo", @@ -31278,7 +34087,7 @@ "type": "string" }, "state": { - "description": "[Output Only] The current state of whether or not this interconnect attachment is functional.", + "description": "[Output Only] The current state of this attachment's functionality.", "enum": [ "ACTIVE", "DEFUNCT", @@ -31545,7 +34354,7 @@ "type": "object" }, "InterconnectAttachmentPartnerMetadata": { - "description": "Informational metadata about Partner attachments from Partners to display to customers. These fields are propagated from PARTNER_PROVIDER attachments to their corresponding PARTNER attachments. Only mutable for PARTNER_PROVIDER type, output-only for PARTNER, not available for DEDICATED.", + "description": "Informational metadata about Partner attachments from Partners to display to customers. These fields are propagated from PARTNER_PROVIDER attachments to their corresponding PARTNER attachments.", "id": "InterconnectAttachmentPartnerMetadata", "properties": { "interconnectName": { @@ -31579,7 +34388,7 @@ "id": "InterconnectAttachmentsScopedList", "properties": { "interconnectAttachments": { - "description": "List of interconnect attachments contained in this scope.", + "description": "A list of interconnect attachments contained in this scope.", "items": { "$ref": "InterconnectAttachment" }, @@ -32041,7 +34850,7 @@ "id": "InterconnectOutageNotification", "properties": { "affectedCircuits": { - "description": "Iff issue_type is IT_PARTIAL_OUTAGE, a list of the Google-side circuit IDs that will be affected.", + "description": "If issue_type is IT_PARTIAL_OUTAGE, a list of the Google-side circuit IDs that will be affected.", "items": { "type": "string" }, @@ -32875,7 +35684,7 @@ "id": "MachineTypesScopedList", "properties": { "machineTypes": { - "description": "[Output Only] List of machine types contained in this scope.", + "description": "[Output Only] A list of machine types contained in this scope.", "items": { "$ref": "MachineType" }, @@ -32965,382 +35774,6 @@ }, "type": "object" }, - "MaintenancePoliciesList": { - "id": "MaintenancePoliciesList", - "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 MaintenancePolicy resources.", - "items": { - "$ref": "MaintenancePolicy" - }, - "type": "array" - }, - "kind": { - "default": "compute#maintenancePoliciesList", - "description": "[Output Only] Type of resource.Always compute#maintenancePoliciesList for listsof maintenancePolicies", - "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" - }, - "MaintenancePoliciesScopedList": { - "id": "MaintenancePoliciesScopedList", - "properties": { - "maintenancePolicies": { - "description": "List of maintenancePolicies contained in this scope.", - "items": { - "$ref": "MaintenancePolicy" - }, - "type": "array" - }, - "warning": { - "description": "Informational warning which replaces the list of maintenancePolicies 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" - }, - "MaintenancePolicy": { - "description": "A maintenance policy for an instance. This specifies what kind of maintenance operations our infrastructure may perform on this instance and when.", - "id": "MaintenancePolicy", - "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#maintenancePolicy", - "description": "[Output Only] Type of the resource. Always compute#maintenance_policies for maintenance 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" - }, - "vmMaintenancePolicy": { - "$ref": "VmMaintenancePolicy", - "description": "Maintenance policy applicable to VMs for infrastructure maintenance." - } - }, - "type": "object" - }, - "MaintenancePolicyAggregatedList": { - "description": "Contains a list of maintenancePolicies.", - "id": "MaintenancePolicyAggregatedList", - "properties": { - "id": { - "description": "[Output Only] Unique identifier for the resource; defined by the server.", - "type": "string" - }, - "items": { - "additionalProperties": { - "$ref": "MaintenancePoliciesScopedList", - "description": "Name of the scope containing this set of maintenancePolicies." - }, - "description": "A list of MaintenancePolicy resources.", - "type": "object" - }, - "kind": { - "default": "compute#maintenancePolicyAggregatedList", - "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" - }, - "MaintenanceWindow": { - "description": "A maintenance window for VMs and disks. When set, we restrict our maintenance operations to this window.", - "id": "MaintenanceWindow", - "properties": { - "dailyMaintenanceWindow": { - "$ref": "DailyMaintenanceWindow" - }, - "hourlyMaintenanceWindow": { - "$ref": "HourlyMaintenanceWindow" - } - }, - "type": "object" - }, "ManagedInstance": { "description": "Next available tag: 12", "id": "ManagedInstance", @@ -33690,7 +36123,7 @@ "type": "string" }, "peerings": { - "description": "[Output Only] List of network peerings for the resource.", + "description": "[Output Only] A list of network peerings for the resource.", "items": { "$ref": "NetworkPeering" }, @@ -34472,6 +36905,14 @@ "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.", "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": { "description": "Name of this peering. Provided by the client when the peering is created. The name must comply with RFC1035. Specifically, the name must be 1-63 characters long and match regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all the following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", "type": "string" @@ -34525,6 +36966,14 @@ "description": "Whether Google Compute Engine manages the routes automatically.", "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": { "annotations": { "required": [ @@ -34551,12 +37000,1243 @@ }, "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" + }, + "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" + }, + "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": { + "index": { + "format": "int32", + "type": "integer" + }, + "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" + } + }, + "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": { + "nodeIndexes": { + "description": "Indexes of the nodes to be deleted from the node group.", + "items": { + "format": "int32", + "type": "integer" + }, + "type": "array" + }, + "nodes": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "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 charaicter, 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", "properties": { "clientOperationId": { - "description": "[Output Only] Reserved for future use.", + "description": "[Output Only] The value of `requestId` if you provided it in the request. Not present otherwise.", "type": "string" }, "creationTimestamp": { @@ -34996,7 +38676,7 @@ "id": "OperationsScopedList", "properties": { "operations": { - "description": "[Output Only] List of operations contained in this scope.", + "description": "[Output Only] A list of operations contained in this scope.", "items": { "$ref": "Operation" }, @@ -35133,8 +38813,13 @@ "PerInstanceConfig": { "id": "PerInstanceConfig", "properties": { + "fingerprint": { + "description": "Fingerprint of this per-instance config. This field may be used in optimistic locking. It will be ignored when inserting a per-instance config. An up-to-date fingerprint must be provided in order to update an existing per-instance config or the field needs to be unset.", + "format": "byte", + "type": "string" + }, "instance": { - "description": "The URL of the instance. Serves as a merge key during UpdatePerInstanceConfigs operation.", + "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" }, "override": { @@ -35144,7 +38829,7 @@ "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**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\nFor a description of IAM and its features, see the [IAM developer's guide](https://cloud.google.com/iam/docs).", + "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": { @@ -35185,6 +38870,19 @@ }, "type": "object" }, + "PreconfiguredWafSet": { + "id": "PreconfiguredWafSet", + "properties": { + "expressionSets": { + "description": "List of entities that are currently supported for WAF rules.", + "items": { + "$ref": "WafExpressionSet" + }, + "type": "array" + } + }, + "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", @@ -35381,10 +39079,12 @@ "INSTANCE_GROUP_MANAGERS", "INSTANCE_TEMPLATES", "INTERCONNECTS", + "INTERCONNECT_ATTACHMENTS_PER_REGION", + "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS", "INTERNAL_ADDRESSES", "IN_USE_ADDRESSES", + "IN_USE_MAINTENANCE_WINDOWS", "LOCAL_SSD_TOTAL_GB", - "MAINTENANCE_POLICIES", "NETWORKS", "NVIDIA_K80_GPUS", "NVIDIA_P100_GPUS", @@ -35394,8 +39094,11 @@ "PREEMPTIBLE_LOCAL_SSD_GB", "PREEMPTIBLE_NVIDIA_K80_GPUS", "PREEMPTIBLE_NVIDIA_P100_GPUS", + "PREEMPTIBLE_NVIDIA_V100_GPUS", + "PRIVATE_V6_ACCESS_SUBNETWORKS", "REGIONAL_AUTOSCALERS", "REGIONAL_INSTANCE_GROUP_MANAGERS", + "RESOURCE_POLICIES", "ROUTERS", "ROUTES", "SECURITY_POLICIES", @@ -35465,6 +39168,11 @@ "", "", "", + "", + "", + "", + "", + "", "" ], "type": "string" @@ -36224,7 +39932,7 @@ "id": "RegionInstanceGroupManagersListInstancesResponse", "properties": { "managedInstances": { - "description": "List of managed instances.", + "description": "A list of managed instances.", "items": { "$ref": "ManagedInstance" }, @@ -36572,6 +40280,38 @@ }, "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" + }, + "RegionUrlMapsValidateRequest": { + "id": "RegionUrlMapsValidateRequest", + "properties": { + "resource": { + "$ref": "UrlMap", + "description": "Content of the UrlMap to be validated." + } + }, + "type": "object" + }, "ResourceCommitment": { "description": "Commitment for a particular resource (a Commitment is composed of one or more of these).", "id": "ResourceCommitment", @@ -36610,6 +40350,572 @@ }, "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": { + "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" + }, + "vmMaintenancePolicy": { + "$ref": "ResourcePolicyVmMaintenancePolicy", + "description": "Resource policy applicable to VMs for infrastructure maintenance." + } + }, + "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 automatically created snapshot 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 lables, encryption keys." + } + }, + "type": "object" + }, + "ResourcePolicyBackupSchedulePolicyRetentionPolicy": { + "description": "Policy for retention of automatically created snapshots.", + "id": "ResourcePolicyBackupSchedulePolicyRetentionPolicy", + "properties": { + "maxRetentionDays": { + "description": "Maximum age of the snapshot that is allowed to be kept.", + "format": "int32", + "type": "integer" + } + }, + "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 automatic 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 automatic 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-59] 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-59] GMT.", + "type": "string" + } + }, + "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." + } + }, + "type": "object" + }, + "ResourcePolicyVmMaintenancePolicyMaintenanceWindow": { + "description": "A maintenance window for VMs. When set, we restrict our maintenance operations to this window.", + "id": "ResourcePolicyVmMaintenancePolicyMaintenanceWindow", + "properties": { + "dailyMaintenanceWindow": { + "$ref": "ResourcePolicyDailyCycle" + }, + "weeklyMaintenanceWindow": { + "$ref": "ResourcePolicyWeeklyCycle" + } + }, + "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-59] GMT.", + "type": "string" + } + }, + "type": "object" + }, "Route": { "description": "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 called its routing table.\n\nFor each packet leaving an instance, the system searches that instance's routing table for a single best matching route. Routes match packets by destination IP address, preferring smaller or more specific ranges over larger ones. If there is a tie, the system selects the route with the smallest priority value. If there is still a tie, it uses the layer three and four packet headers to select just one of the remaining matching routes. The packet is then forwarded as specified by the nextHop field of the winning route - either to another instance destination, an instance gateway, or a Google Compute Engine-operated gateway.\n\nPackets that do not match any route in the sending instance's routing table are dropped. (== resource_for beta.routes ==) (== resource_for v1.routes ==)", "id": "Route", @@ -36664,6 +40970,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" @@ -36960,7 +41270,7 @@ "type": "string" }, "nats": { - "description": "List of Nat services created in this router. The maximum number of Nat services within a Router is 3 for Alpha.", + "description": "A list of Nat services created in this router.", "items": { "$ref": "RouterNat" }, @@ -37001,21 +41311,6 @@ }, "type": "object" }, - "RouterAdvertisedPrefix": { - "description": "Description-tagged prefixes for the router to advertise.", - "id": "RouterAdvertisedPrefix", - "properties": { - "description": { - "description": "User-specified description for the prefix.", - "type": "string" - }, - "prefix": { - "description": "The prefix to advertise. The value must be a CIDR-formatted string.", - "type": "string" - } - }, - "type": "object" - }, "RouterAggregatedList": { "description": "Contains a list of routers.", "id": "RouterAggregatedList", @@ -37164,13 +41459,6 @@ }, "type": "array" }, - "advertisedPrefixs": { - "description": "User-specified list of individual prefixes 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 prefixes will be advertised in addition to any specified groups. Leave this field blank to advertise no custom prefixes.", - "items": { - "$ref": "RouterAdvertisedPrefix" - }, - "type": "array" - }, "asn": { "description": "Local BGP Autonomous System Number (ASN). Must be an RFC6996 private ASN, either 16-bit or 32-bit. The value will be fixed for this router resource. All VPN tunnels that link to this router will have the same local ASN.", "format": "uint32", @@ -37214,13 +41502,6 @@ }, "type": "array" }, - "advertisedPrefixs": { - "description": "User-specified list of individual prefixes 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 prefixes will be advertised in addition to any specified groups. Leave this field blank to advertise no custom prefixes.", - "items": { - "$ref": "RouterAdvertisedPrefix" - }, - "type": "array" - }, "advertisedRoutePriority": { "description": "The priority of routes advertised to this BGP peer. In the case where there is more than one matching route of maximum length, the routes with lowest priority value win.", "format": "uint32", @@ -37234,6 +41515,18 @@ "description": "IP address of the interface inside Google Cloud Platform. Only IPv4 is supported.", "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.", + "enum": [ + "MANAGED_BY_ATTACHMENT", + "MANAGED_BY_USER" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, "name": { "description": "Name of this BGP peer. The name must be 1-63 characters long and comply with RFC1035.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", @@ -37266,6 +41559,18 @@ "description": "URI of the linked VPN tunnel. It must be in the same region as the router. Each interface can have at most one linked resource and it could either be a VPN Tunnel or an interconnect attachment.", "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.", + "enum": [ + "MANAGED_BY_ATTACHMENT", + "MANAGED_BY_USER" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, "name": { "description": "Name of this interface entry. The name must be 1-63 characters long and comply with RFC1035.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", @@ -37391,7 +41696,7 @@ "id": "RouterNat", "properties": { "autoAllocatedNatIps": { - "description": "[Output Only] 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.", + "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" }, @@ -37415,7 +41720,7 @@ "type": "string" }, "natIps": { - "description": "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.", + "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" }, @@ -37436,7 +41741,7 @@ "type": "string" }, "subnetworks": { - "description": "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.", + "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" }, @@ -37454,7 +41759,7 @@ "type": "string" }, "secondaryIpRangeNames": { - "description": "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.", + "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" }, @@ -37581,7 +41886,7 @@ "id": "RouterStatusNatStatus", "properties": { "autoAllocatedNatIps": { - "description": "List of IPs auto-allocated for NAT. Example: [\"1.1.1.1\", \"129.2.16.89\"]", + "description": "A list of IPs auto-allocated for NAT. Example: [\"1.1.1.1\", \"129.2.16.89\"]", "items": { "type": "string" }, @@ -37602,14 +41907,14 @@ "type": "integer" }, "userAllocatedNatIpResources": { - "description": "List of fully qualified URLs of reserved IP address resources.", + "description": "A list of fully qualified URLs of reserved IP address resources.", "items": { "type": "string" }, "type": "array" }, "userAllocatedNatIps": { - "description": "List of IPs user-allocated for NAT. They will be raw IP strings like \"179.12.26.133\".", + "description": "A list of IPs user-allocated for NAT. They will be raw IP strings like \"179.12.26.133\".", "items": { "type": "string" }, @@ -37646,7 +41951,7 @@ "id": "RoutersScopedList", "properties": { "routers": { - "description": "List of routers contained in this scope.", + "description": "A list of routers contained in this scope.", "items": { "$ref": "Router" }, @@ -37917,8 +42222,26 @@ }, "type": "object" }, + "SecurityPoliciesListPreconfiguredExpressionSetsResponse": { + "id": "SecurityPoliciesListPreconfiguredExpressionSetsResponse", + "properties": { + "preconfiguredExpressionSets": { + "$ref": "SecurityPoliciesWafConfig" + } + }, + "type": "object" + }, + "SecurityPoliciesWafConfig": { + "id": "SecurityPoliciesWafConfig", + "properties": { + "wafRules": { + "$ref": "PreconfiguredWafSet" + } + }, + "type": "object" + }, "SecurityPolicy": { - "description": "A security policy is comprised of one or more rules. It can also be associated with one or more 'targets'.", + "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", "id": "SecurityPolicy", "properties": { "creationTimestamp": { @@ -37944,13 +42267,25 @@ "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])?", "type": "string" }, "rules": { - "description": "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.", + "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" }, @@ -38226,6 +42561,17 @@ }, "type": "object" }, + "ShieldedVmIntegrityPolicy": { + "description": "The policy describes how boot integrity measurements are evaluated.", + "id": "ShieldedVmIntegrityPolicy", + "properties": { + "updateAutoLearnPolicy": { + "description": "Triggers an auto relearn event: the integrity monitoring module copies existing guest measurements to the baseline.", + "type": "boolean" + } + }, + "type": "object" + }, "SignedUrlKey": { "description": "Represents a customer-supplied Signing Key used by Cloud CDN Signed URLs", "id": "SignedUrlKey", @@ -38246,6 +42592,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 autoamtically by applying resource policy on the target disk.", + "type": "boolean" + }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" @@ -38289,7 +42639,7 @@ "type": "object" }, "licenseCodes": { - "description": "Integer license codes indicating which licenses are attached to this snapshot.", + "description": "[Output Only] Integer license codes indicating which licenses are attached to this snapshot.", "items": { "format": "int64", "type": "string" @@ -38744,7 +43094,7 @@ "type": "object" }, "SslCertificateSelfManagedSslCertificate": { - "description": "Configuration and status of a self-managed SSL certificate..", + "description": "Configuration and status of a self-managed SSL certificate.", "id": "SslCertificateSelfManagedSslCertificate", "properties": { "certificate": { @@ -38890,7 +43240,7 @@ "type": "string" }, "customFeatures": { - "description": "List of features enabled when the selected profile is CUSTOM. The\n- method returns the set of features that can be specified in this list. This field must be empty if the profile is not CUSTOM.", + "description": "A list of features enabled when the selected profile is CUSTOM. The\n- method returns the set of features that can be specified in this list. This field must be empty if the profile is not CUSTOM.", "items": { "type": "string" }, @@ -38923,15 +43273,13 @@ "type": "string" }, "minTlsVersion": { - "description": "The minimum version of SSL protocol that can be used by the clients to establish a connection with the load balancer. This can be one of TLS_1_0, TLS_1_1, TLS_1_2, TLS_1_3.", + "description": "The minimum version of SSL protocol that can be used by the clients to establish a connection with the load balancer. This can be one of TLS_1_0, TLS_1_1, TLS_1_2.", "enum": [ "TLS_1_0", "TLS_1_1", - "TLS_1_2", - "TLS_1_3" + "TLS_1_2" ], "enumDescriptions": [ - "", "", "", "" @@ -39157,10 +43505,34 @@ "description": "Whether the VMs in this subnet can access Google services without assigned external IP addresses. This field can be both set at resource creation time and updated using setPrivateIpGoogleAccess.", "type": "boolean" }, + "purpose": { + "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_RFC_1918" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, "region": { "description": "URL of the region where the Subnetwork resides. This field can be set only at resource creation time.", "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.", + "enum": [ + "ACTIVE", + "BACKUP" + ], + "enumDescriptions": [ + "", + "" + ], + "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.", "items": { @@ -39428,7 +43800,7 @@ "id": "SubnetworksScopedList", "properties": { "subnetworks": { - "description": "List of subnetworks contained in this scope.", + "description": "A list of subnetworks contained in this scope.", "items": { "$ref": "Subnetwork" }, @@ -39581,7 +43953,7 @@ "id": "Tags", "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.\n\nTo see the latest fingerprint, make get() request to the instance.", + "description": "Specifies a fingerprint for this request, which is essentially a hash of the tags' contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update tags. You must always provide an up-to-date fingerprint hash in order to update or change tags.\n\nTo see the latest fingerprint, make get() request to the instance.", "format": "byte", "type": "string" }, @@ -39595,6 +43967,100 @@ }, "type": "object" }, + "TargetHttpProxiesScopedList": { + "id": "TargetHttpProxiesScopedList", + "properties": { + "targetHttpProxies": { + "description": "A list of TargetHttpProxies contained in this scope.", + "items": { + "$ref": "TargetHttpProxy" + }, + "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" + }, "TargetHttpProxy": { "description": "A TargetHttpProxy resource. This resource defines an HTTP proxy. (== resource_for beta.targetHttpProxies ==) (== resource_for v1.targetHttpProxies ==)", "id": "TargetHttpProxy", @@ -39622,6 +44088,10 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, + "region": { + "description": "[Output Only] URL of the region where the regional Target HTTP Proxy resides. This field is not applicable to global Target HTTP Proxies.", + "type": "string" + }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" @@ -39633,6 +44103,118 @@ }, "type": "object" }, + "TargetHttpProxyAggregatedList": { + "id": "TargetHttpProxyAggregatedList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "TargetHttpProxiesScopedList", + "description": "Name of the scope containing this set of TargetHttpProxies." + }, + "description": "A list of TargetHttpProxiesScopedList resources.", + "type": "object" + }, + "kind": { + "default": "compute#targetHttpProxyAggregatedList", + "description": "[Output Only] Type of resource. Always compute#targetHttpProxyAggregatedList 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" + }, "TargetHttpProxyList": { "description": "A list of TargetHttpProxy resources.", "id": "TargetHttpProxyList", @@ -39782,10 +44364,6 @@ "description": "A TargetHttpsProxy resource. This resource defines an HTTPS proxy. (== resource_for beta.targetHttpsProxies ==) (== resource_for v1.targetHttpsProxies ==)", "id": "TargetHttpsProxy", "properties": { - "clientSslPolicy": { - "description": "URL to ClientSslPolicy resource which controls the set of allowed SSL versions and ciphers.", - "type": "string" - }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" @@ -40237,7 +44815,7 @@ "id": "TargetInstancesScopedList", "properties": { "targetInstances": { - "description": "List of target instances contained in this scope.", + "description": "A list of target instances contained in this scope.", "items": { "$ref": "TargetInstance" }, @@ -40703,7 +45281,7 @@ "id": "TargetPoolsScopedList", "properties": { "targetPools": { - "description": "List of target pools contained in this scope.", + "description": "A list of target pools contained in this scope.", "items": { "$ref": "TargetPool" }, @@ -40847,10 +45425,6 @@ "description": "A TargetSslProxy resource. This resource defines an SSL proxy. (== resource_for beta.targetSslProxies ==) (== resource_for v1.targetSslProxies ==)", "id": "TargetSslProxy", "properties": { - "clientSslPolicy": { - "description": "URL to ClientSslPolicy resource which controls the set of allowed SSL versions and ciphers.", - "type": "string" - }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" @@ -41532,7 +46106,7 @@ "id": "TargetVpnGatewaysScopedList", "properties": { "targetVpnGateways": { - "description": "[Output Only] List of target vpn gateways contained in this scope.", + "description": "[Output Only] A list of target vpn gateways contained in this scope.", "items": { "$ref": "TargetVpnGateway" }, @@ -41739,6 +46313,10 @@ }, "type": "array" }, + "region": { + "description": "[Output Only] URL of the region where the regional URL map resides. This field is not applicable to global URL maps. 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" + }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" @@ -41955,6 +46533,13 @@ "description": "Network URL.", "type": "string" }, + "secondaryIpRanges": { + "description": "Secondary IP ranges.", + "items": { + "$ref": "UsableSubnetworkSecondaryRange" + }, + "type": "array" + }, "subnetwork": { "description": "Subnetwork URL.", "type": "string" @@ -41962,6 +46547,21 @@ }, "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": { @@ -42088,13 +46688,421 @@ }, "type": "object" }, - "VmMaintenancePolicy": { - "description": "A Vm Maintenance Policy specifies what kind of infrastructure maintenance we are allowed to perform on this VM and when.", - "id": "VmMaintenancePolicy", + "VpnGateway": { + "description": "Represents a VPN gateway resource.", + "id": "VpnGateway", "properties": { - "maintenanceWindow": { - "$ref": "MaintenanceWindow", - "description": "Maintenance windows that are applied to VMs covered by this policy." + "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#vpnGateway", + "description": "[Output Only] Type of resource. Always compute#vpnGateway for VPN gateways.", + "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.", + "format": "byte", + "type": "string" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "Labels to apply to this VpnGateway 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": { + "annotations": { + "required": [ + "compute.vpnGateways.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" + }, + "network": { + "annotations": { + "required": [ + "compute.vpnGateways.insert" + ] + }, + "description": "URL of the network to which this VPN gateway is attached. Provided by the client when the VPN gateway is created.", + "type": "string" + }, + "redundancy": { + "description": "The redundancy mode configured for this VPN gateway. Possible values are ACTIVE_ACTIVE and NONE. If set to ACTIVE_ACTIVE, two VPN interfaces are created thereby providing higher availability. If set to NONE, only one interface is created with a lower availability SLA.\n\nIf this field is specified, either 2 or 1 external IP addresses (depending on the value of specified redundancy) are automatically allocated for use with this VPN gateway, and incoming traffic on the external addresses to ports ESP, UDP:500 and UDP:4500 are automatically forwarded to this gateway.", + "enum": [ + "ACTIVE_ACTIVE", + "NONE", + "REDUNDANCY_UNSPECIFIED" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, + "region": { + "description": "[Output Only] URL of the region where the VPN gateway resides.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for the resource.", + "type": "string" + }, + "vpnInterfaces": { + "description": "[Output Only] A list of interfaces on this VPN gateway.", + "items": { + "$ref": "VpnGatewayVpnGatewayInterface" + }, + "type": "array" + } + }, + "type": "object" + }, + "VpnGatewayAggregatedList": { + "id": "VpnGatewayAggregatedList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "VpnGatewaysScopedList", + "description": "[Output Only] Name of the scope containing this set of VPN gateways." + }, + "description": "A list of VpnGateway resources.", + "type": "object" + }, + "kind": { + "default": "compute#vpnGatewayAggregatedList", + "description": "[Output Only] Type of resource. Always compute#vpnGateway for VPN gateways.", + "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" + }, + "VpnGatewayList": { + "description": "Contains a list of VpnGateway resources.", + "id": "VpnGatewayList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of VpnGateway resources.", + "items": { + "$ref": "VpnGateway" + }, + "type": "array" + }, + "kind": { + "default": "compute#vpnGatewayList", + "description": "[Output Only] Type of resource. Always compute#vpnGateway for VPN gateways.", + "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" + }, + "VpnGatewayVpnGatewayInterface": { + "description": "A VPN gateway interface.", + "id": "VpnGatewayVpnGatewayInterface", + "properties": { + "id": { + "description": "The numeric ID of this VPN gateway interface.", + "format": "uint32", + "type": "integer" + }, + "ipAddress": { + "description": "The external IP address for this VPN gateway interface.", + "type": "string" + } + }, + "type": "object" + }, + "VpnGatewaysScopedList": { + "id": "VpnGatewaysScopedList", + "properties": { + "vpnGateways": { + "description": "[Output Only] A list of VPN gateways contained in this scope.", + "items": { + "$ref": "VpnGateway" + }, + "type": "array" + }, + "warning": { + "description": "[Output Only] Informational warning which replaces the list of addresses 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" @@ -42225,6 +47233,15 @@ "targetVpnGateway": { "description": "URL of the Target VPN gateway with which this VPN tunnel is associated. Provided by the client when the VPN tunnel is created.", "type": "string" + }, + "vpnGateway": { + "description": "URL of the VPN gateway with which this VPN tunnel is associated. Provided by the client when the VPN tunnel is created. This must be used (instead of target_vpn_gateway) if a VPN gateway resource is created with redundancy.\n\nVPN gateway resource provides a way to create a highly available VPN setup.", + "type": "string" + }, + "vpnGatewayInterface": { + "description": "The interface ID of the VPN gateway with which this VPN tunnel is associated. If the VPN gateway has redundancy other than NONE, this field is required to identify which interface of the VPN gateway to use.", + "format": "int32", + "type": "integer" } }, "type": "object" @@ -42457,7 +47474,7 @@ "id": "VpnTunnelsScopedList", "properties": { "vpnTunnels": { - "description": "List of vpn tunnels contained in this scope.", + "description": "A list of vpn tunnels contained in this scope.", "items": { "$ref": "VpnTunnel" }, @@ -42547,6 +47564,40 @@ }, "type": "object" }, + "WafExpressionSet": { + "id": "WafExpressionSet", + "properties": { + "aliases": { + "description": "A list of alternate IDs. The format should be: - E.g. XSS-stable Generic suffix like \"stable\" is particularly useful if a policy likes to avail newer set of expressions without having to change the policy. A given alias name can't be used for more than one entity set.", + "items": { + "type": "string" + }, + "type": "array" + }, + "expressions": { + "description": "List of available expressions.", + "items": { + "$ref": "WafExpressionSetExpression" + }, + "type": "array" + }, + "id": { + "description": "Google specified expression set ID. The format should be: - E.g. XSS-20170329", + "type": "string" + } + }, + "type": "object" + }, + "WafExpressionSetExpression": { + "id": "WafExpressionSetExpression", + "properties": { + "id": { + "description": "Expression ID should uniquely identify the origin of the expression. E.g. owasp-crs-v020901-id973337 identifies Owasp core rule set version 2.9.1 rule id 973337. The ID could be used to determine the individual attack definition that has been detected. It could also be used to exclude it from the policy in case of false positive.", + "type": "string" + } + }, + "type": "object" + }, "XpnHostList": { "id": "XpnHostList", "properties": { @@ -42870,6 +47921,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/alpha/projects/", 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 497ac423ba9..50c4ab5587c 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 @@ -76,7 +76,6 @@ func New(client *http.Client) (*Service, error) { s.Autoscalers = NewAutoscalersService(s) s.BackendBuckets = NewBackendBucketsService(s) s.BackendServices = NewBackendServicesService(s) - s.ClientSslPolicies = NewClientSslPoliciesService(s) s.DiskTypes = NewDiskTypesService(s) s.Disks = NewDisksService(s) s.Firewalls = NewFirewallsService(s) @@ -100,21 +99,25 @@ func New(client *http.Client) (*Service, error) { s.LicenseCodes = NewLicenseCodesService(s) s.Licenses = NewLicensesService(s) s.MachineTypes = NewMachineTypesService(s) - s.MaintenancePolicies = NewMaintenancePoliciesService(s) s.NetworkEndpointGroups = NewNetworkEndpointGroupsService(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) s.RegionCommitments = NewRegionCommitmentsService(s) s.RegionDiskTypes = NewRegionDiskTypesService(s) s.RegionDisks = NewRegionDisksService(s) + s.RegionHealthChecks = NewRegionHealthChecksService(s) s.RegionInstanceGroupManagers = NewRegionInstanceGroupManagersService(s) s.RegionInstanceGroups = NewRegionInstanceGroupsService(s) s.RegionOperations = NewRegionOperationsService(s) + s.RegionTargetHttpProxies = NewRegionTargetHttpProxiesService(s) + s.RegionUrlMaps = NewRegionUrlMapsService(s) s.Regions = NewRegionsService(s) + s.ResourcePolicies = NewResourcePoliciesService(s) s.Routers = NewRoutersService(s) s.Routes = NewRoutesService(s) s.SecurityPolicies = NewSecurityPoliciesService(s) @@ -130,6 +133,7 @@ func New(client *http.Client) (*Service, error) { s.TargetTcpProxies = NewTargetTcpProxiesService(s) s.TargetVpnGateways = NewTargetVpnGatewaysService(s) s.UrlMaps = NewUrlMapsService(s) + s.VpnGateways = NewVpnGatewaysService(s) s.VpnTunnels = NewVpnTunnelsService(s) s.ZoneOperations = NewZoneOperationsService(s) s.Zones = NewZonesService(s) @@ -151,8 +155,6 @@ type Service struct { BackendServices *BackendServicesService - ClientSslPolicies *ClientSslPoliciesService - DiskTypes *DiskTypesService Disks *DisksService @@ -199,8 +201,6 @@ type Service struct { MachineTypes *MachineTypesService - MaintenancePolicies *MaintenancePoliciesService - NetworkEndpointGroups *NetworkEndpointGroupsService Networks *NetworksService @@ -209,6 +209,8 @@ type Service struct { NodeTemplates *NodeTemplatesService + NodeTypes *NodeTypesService + Projects *ProjectsService RegionAutoscalers *RegionAutoscalersService @@ -221,14 +223,22 @@ type Service struct { RegionDisks *RegionDisksService + RegionHealthChecks *RegionHealthChecksService + RegionInstanceGroupManagers *RegionInstanceGroupManagersService RegionInstanceGroups *RegionInstanceGroupsService RegionOperations *RegionOperationsService + RegionTargetHttpProxies *RegionTargetHttpProxiesService + + RegionUrlMaps *RegionUrlMapsService + Regions *RegionsService + ResourcePolicies *ResourcePoliciesService + Routers *RoutersService Routes *RoutesService @@ -259,6 +269,8 @@ type Service struct { UrlMaps *UrlMapsService + VpnGateways *VpnGatewaysService + VpnTunnels *VpnTunnelsService ZoneOperations *ZoneOperationsService @@ -318,15 +330,6 @@ type BackendServicesService struct { s *Service } -func NewClientSslPoliciesService(s *Service) *ClientSslPoliciesService { - rs := &ClientSslPoliciesService{s: s} - return rs -} - -type ClientSslPoliciesService struct { - s *Service -} - func NewDiskTypesService(s *Service) *DiskTypesService { rs := &DiskTypesService{s: s} return rs @@ -534,15 +537,6 @@ type MachineTypesService struct { s *Service } -func NewMaintenancePoliciesService(s *Service) *MaintenancePoliciesService { - rs := &MaintenancePoliciesService{s: s} - return rs -} - -type MaintenancePoliciesService struct { - s *Service -} - func NewNetworkEndpointGroupsService(s *Service) *NetworkEndpointGroupsService { rs := &NetworkEndpointGroupsService{s: s} return rs @@ -579,6 +573,15 @@ 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 @@ -633,6 +636,15 @@ type RegionDisksService struct { s *Service } +func NewRegionHealthChecksService(s *Service) *RegionHealthChecksService { + rs := &RegionHealthChecksService{s: s} + return rs +} + +type RegionHealthChecksService struct { + s *Service +} + func NewRegionInstanceGroupManagersService(s *Service) *RegionInstanceGroupManagersService { rs := &RegionInstanceGroupManagersService{s: s} return rs @@ -660,6 +672,24 @@ type RegionOperationsService struct { s *Service } +func NewRegionTargetHttpProxiesService(s *Service) *RegionTargetHttpProxiesService { + rs := &RegionTargetHttpProxiesService{s: s} + return rs +} + +type RegionTargetHttpProxiesService struct { + s *Service +} + +func NewRegionUrlMapsService(s *Service) *RegionUrlMapsService { + rs := &RegionUrlMapsService{s: s} + return rs +} + +type RegionUrlMapsService struct { + s *Service +} + func NewRegionsService(s *Service) *RegionsService { rs := &RegionsService{s: s} return rs @@ -669,6 +699,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 @@ -804,6 +843,15 @@ type UrlMapsService struct { s *Service } +func NewVpnGatewaysService(s *Service) *VpnGatewaysService { + rs := &VpnGatewaysService{s: s} + return rs +} + +type VpnGatewaysService struct { + s *Service +} + func NewVpnTunnelsService(s *Service) *VpnTunnelsService { rs := &VpnTunnelsService{s: s} return rs @@ -1248,7 +1296,7 @@ func (s *AcceleratorTypeListWarningData) MarshalJSON() ([]byte, error) { } type AcceleratorTypesScopedList struct { - // AcceleratorTypes: [Output Only] List of accelerator types contained + // AcceleratorTypes: [Output Only] A list of accelerator types contained // in this scope. AcceleratorTypes []*AcceleratorType `json:"acceleratorTypes,omitempty"` @@ -1930,7 +1978,7 @@ func (s *AddressListWarningData) MarshalJSON() ([]byte, error) { } type AddressesScopedList struct { - // Addresses: [Output Only] List of addresses contained in this scope. + // Addresses: [Output Only] A list of addresses contained in this scope. Addresses []*Address `json:"addresses,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -2199,7 +2247,7 @@ type AttachedDisk struct { Mode string `json:"mode,omitempty"` // SavedState: For LocalSSD disks on VM Instances in STOPPED or - // SUSPENDED state, this field is set to PRESERVED iff the LocalSSD data + // 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. // @@ -2340,6 +2388,19 @@ type AttachedDiskInitializeParams struct { // the source images are encrypted with your own keys. SourceImageEncryptionKey *CustomerEncryptionKey `json:"sourceImageEncryptionKey,omitempty"` + // SourceSnapshot: 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. + // + // To create a disk with a snapshot that you created, specify the + // snapshot name in the following + // format: + // global/snapshots/my-backup + // + // + // 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 // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -2549,11 +2610,11 @@ type Autoscaler struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` - // RecommendedSize: [Output Only] Target recommended MIG size computed - // by autoscaler. Autoscaler calculates recommended MIG size even when - // autoscaling policy mode is different from ON. This field is empty - // when autoscaler is not connected to the existing managed instance - // group or autoscaler did not generate its first prediction. + // RecommendedSize: [Output Only] Target recommended MIG size (number of + // instances) computed by autoscaler. Autoscaler calculates recommended + // MIG size even when autoscaling policy mode is different from ON. This + // field is empty when autoscaler is not connected to the existing + // managed instance group or autoscaler did not generate its prediction. RecommendedSize int64 `json:"recommendedSize,omitempty"` // Region: [Output Only] URL of the region where the instance group @@ -2971,7 +3032,7 @@ func (s *AutoscalerStatusDetails) MarshalJSON() ([]byte, error) { } type AutoscalersScopedList struct { - // Autoscalers: [Output Only] List of autoscalers contained in this + // Autoscalers: [Output Only] A list of autoscalers contained in this // scope. Autoscalers []*Autoscaler `json:"autoscalers,omitempty"` @@ -3997,6 +4058,7 @@ type BackendService struct { // Possible values: // "EXTERNAL" // "INTERNAL" + // "INTERNAL_SELF_MANAGED" // "INVALID_LOAD_BALANCING_SCHEME" LoadBalancingScheme string `json:"loadBalancingScheme,omitempty"` @@ -4493,6 +4555,10 @@ type BackendServiceIAP struct { Oauth2ClientId string `json:"oauth2ClientId,omitempty"` + // Oauth2ClientInfo: [Input Only] OAuth client info required to generate + // client id to be used for IAP. + Oauth2ClientInfo *BackendServiceIAPOAuth2ClientInfo `json:"oauth2ClientInfo,omitempty"` + Oauth2ClientSecret string `json:"oauth2ClientSecret,omitempty"` // Oauth2ClientSecretSha256: [Output Only] SHA256 hash value for the @@ -4522,6 +4588,42 @@ func (s *BackendServiceIAP) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type BackendServiceIAPOAuth2ClientInfo struct { + // ApplicationName: Application name to be used in OAuth consent screen. + ApplicationName string `json:"applicationName,omitempty"` + + // ClientName: Name of the client to be generated. Optional - If not + // provided, the name will be autogenerated by the backend. + ClientName string `json:"clientName,omitempty"` + + // DeveloperEmailAddress: Developer's information to be used in OAuth + // consent screen. + DeveloperEmailAddress string `json:"developerEmailAddress,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ApplicationName") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ApplicationName") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *BackendServiceIAPOAuth2ClientInfo) MarshalJSON() ([]byte, error) { + type NoMethod BackendServiceIAPOAuth2ClientInfo + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // BackendServiceList: Contains a list of BackendService resources. type BackendServiceList struct { // Id: [Output Only] Unique identifier for the resource; defined by the @@ -4706,7 +4808,7 @@ func (s *BackendServiceReference) MarshalJSON() ([]byte, error) { } type BackendServicesScopedList struct { - // BackendServices: List of BackendServices contained in this scope. + // BackendServices: A list of BackendServices contained in this scope. BackendServices []*BackendService `json:"backendServices,omitempty"` // Warning: Informational warning which replaces the list of backend @@ -4859,8 +4961,7 @@ type Binding struct { // account. // // * `user:{emailid}`: An email address that represents a specific - // Google account. For example, `alice@gmail.com` or - // `joe@example.com`. + // Google account. For example, `alice@gmail.com` . // // // @@ -5042,8 +5143,8 @@ type Commitment struct { // used. Region string `json:"region,omitempty"` - // Resources: List of commitment amounts for particular resources. Note - // that VCPU and MEMORY resource commitments must occur together. + // Resources: A list of commitment amounts for particular resources. + // Note that VCPU and MEMORY resource commitments must occur together. Resources []*ResourceCommitment `json:"resources,omitempty"` // SelfLink: [Output Only] Server-defined URL for the resource. @@ -5068,6 +5169,16 @@ type Commitment struct { // of the status. StatusMessage string `json:"statusMessage,omitempty"` + // Type: The type of commitment, which affects the discount rate and the + // eligible resources. Type MEMORY_OPTIMIZED specifies a commitment that + // will only apply to memory optimized machines. + // + // Possible values: + // "GENERAL_PURPOSE" + // "MEMORY_OPTIMIZED" + // "TYPE_UNSPECIFIED" + Type string `json:"type,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -5407,7 +5518,7 @@ func (s *CommitmentListWarningData) MarshalJSON() ([]byte, error) { } type CommitmentsScopedList struct { - // Commitments: [Output Only] List of commitments contained in this + // Commitments: [Output Only] A list of commitments contained in this // scope. Commitments []*Commitment `json:"commitments,omitempty"` @@ -5659,7 +5770,7 @@ type CustomerEncryptionKey struct { // - The key is wrapped using a RSA public key certificate provided by // Google. // - After being wrapped, the key must be encoded in RFC 4648 base64 - // encoding. Get the RSA public key certificate provided by Google + // encoding. Gets the RSA public key certificate provided by Google // at: // https://cloud-certs.storage.googleapis.com/google-cloud-csek-ingre // ss.pem @@ -5726,45 +5837,6 @@ func (s *CustomerEncryptionKeyProtectedDisk) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// DailyMaintenanceWindow: Time window specified for daily maintenance -// operations. -type DailyMaintenanceWindow 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 maintenance window to start the - // maintenance operations. It must be in format "HH:MM?, where HH : - // [00-23] and MM : [00-59] 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 *DailyMaintenanceWindow) MarshalJSON() ([]byte, error) { - type NoMethod DailyMaintenanceWindow - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - // DeprecationStatus: Deprecation status for a public resource. type DeprecationStatus struct { // Deleted: An optional RFC3339 timestamp on or after which the state of @@ -5926,6 +5998,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"` @@ -6511,6 +6587,12 @@ type DiskType struct { // Name: [Output Only] Name of the resource. Name string `json:"name,omitempty"` + // Region: [Output Only] URL of the region where the disk type 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. + Region string `json:"region,omitempty"` + // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` @@ -6862,7 +6944,8 @@ func (s *DiskTypeListWarningData) MarshalJSON() ([]byte, error) { } type DiskTypesScopedList struct { - // DiskTypes: [Output Only] List of disk types contained in this scope. + // DiskTypes: [Output Only] A list of disk types contained in this + // scope. DiskTypes []*DiskType `json:"diskTypes,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -6994,6 +7077,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. @@ -7023,7 +7162,7 @@ func (s *DisksResizeRequest) MarshalJSON() ([]byte, error) { } type DisksScopedList struct { - // Disks: [Output Only] List of disks contained in this scope. + // Disks: [Output Only] A list of disks contained in this scope. Disks []*Disk `json:"disks,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -7304,8 +7443,7 @@ type Firewall struct { // EnableLogging: This field denotes whether to enable logging for a // particular firewall rule. If logging is enabled, logs will be - // exported to the configured export destination for all firewall logs - // in the network. Logs may be exported to BigQuery or Pub/Sub. + // exported to Stackdriver. EnableLogging bool `json:"enableLogging,omitempty"` // Id: [Output Only] The unique identifier for the resource. This @@ -8312,7 +8450,7 @@ func (s *ForwardingRuleReference) MarshalJSON() ([]byte, error) { } type ForwardingRulesScopedList struct { - // ForwardingRules: List of forwarding rules contained in this scope. + // ForwardingRules: A list of forwarding rules contained in this scope. ForwardingRules []*ForwardingRule `json:"forwardingRules,omitempty"` // Warning: Informational warning which replaces the list of forwarding @@ -8488,6 +8626,44 @@ func (s *GlobalSetLabelsRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type GlobalSetPolicyRequest 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 *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 @@ -8855,6 +9031,10 @@ type HealthCheck struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` + // Region: [Output Only] Region where the health check resides. Not + // applicable to global health checks. + Region string `json:"region,omitempty"` + // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` @@ -9103,6 +9283,293 @@ func (s *HealthCheckReference) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type HealthChecksAggregatedList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of HealthChecksScopedList resources. + Items map[string]HealthChecksScopedList `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 *HealthChecksAggregatedListWarning `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 *HealthChecksAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod HealthChecksAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// HealthChecksAggregatedListWarning: [Output Only] Informational +// warning message. +type HealthChecksAggregatedListWarning 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 []*HealthChecksAggregatedListWarningData `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 *HealthChecksAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod HealthChecksAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type HealthChecksAggregatedListWarningData 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 *HealthChecksAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod HealthChecksAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type HealthChecksScopedList struct { + // HealthChecks: A list of HealthChecks contained in this scope. + HealthChecks []*HealthCheck `json:"healthChecks,omitempty"` + + // Warning: Informational warning which replaces the list of backend + // services when the list is empty. + Warning *HealthChecksScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "HealthChecks") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "HealthChecks") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *HealthChecksScopedList) MarshalJSON() ([]byte, error) { + type NoMethod HealthChecksScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// HealthChecksScopedListWarning: Informational warning which replaces +// the list of backend services when the list is empty. +type HealthChecksScopedListWarning 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 []*HealthChecksScopedListWarningData `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 *HealthChecksScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod HealthChecksScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type HealthChecksScopedListWarningData 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 *HealthChecksScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod HealthChecksScopedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type HealthStatus struct { // HealthState: Health state of the instance. // @@ -10028,7 +10495,8 @@ func (s *HostTypeListWarningData) MarshalJSON() ([]byte, error) { } type HostTypesScopedList struct { - // HostTypes: [Output Only] List of host types contained in this scope. + // 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 @@ -10161,7 +10629,7 @@ func (s *HostTypesScopedListWarningData) MarshalJSON() ([]byte, error) { } type HostsScopedList struct { - // Hosts: [Output Only] List of hosts contained in this scope. + // 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 @@ -10293,44 +10761,6 @@ func (s *HostsScopedListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// HourlyMaintenanceWindow: Time window specified for hourly maintenance -// operations. -type HourlyMaintenanceWindow 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 maintenance window to start the - // maintenance operations. It must be in format "HH:MM?, where HH : - // [00-23] and MM : [00-59] 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 *HourlyMaintenanceWindow) MarshalJSON() ([]byte, error) { - type NoMethod HourlyMaintenanceWindow - 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. @@ -11245,7 +11675,7 @@ type Instance struct { // must be created before you can assign them. Disks []*AttachedDisk `json:"disks,omitempty"` - // GuestAccelerators: List of the type and count of accelerator cards + // GuestAccelerators: A list of the type and count of accelerator cards // attached to the instance. GuestAccelerators []*AcceleratorConfig `json:"guestAccelerators,omitempty"` @@ -11291,11 +11721,11 @@ type Instance struct { 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 + // essentially a hash of the label'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 + // 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 metadata. + // change labels. // // To see the latest fingerprint, make get() request to the instance. LabelFingerprint string `json:"labelFingerprint,omitempty"` @@ -11328,9 +11758,6 @@ type Instance struct { // machine types. MachineType string `json:"machineType,omitempty"` - // MaintenancePolicies: Maintenance policies applied to this instance. - MaintenancePolicies []string `json:"maintenancePolicies,omitempty"` - // Metadata: The metadata key/value pairs assigned to this instance. // This includes custom metadata and predefined keys. Metadata *Metadata `json:"metadata,omitempty"` @@ -11361,6 +11788,9 @@ type Instance struct { // instances. Read-only in the api. PreservedStateSizeGb int64 `json:"preservedStateSizeGb,omitempty,string"` + // ResourcePolicies: Resource policies applied to this instance. + ResourcePolicies []string `json:"resourcePolicies,omitempty"` + // Scheduling: Sets the scheduling options for this instance. Scheduling *Scheduling `json:"scheduling,omitempty"` @@ -11378,6 +11808,11 @@ type Instance struct { ShieldedVmConfig *ShieldedVmConfig `json:"shieldedVmConfig,omitempty"` + ShieldedVmIntegrityPolicy *ShieldedVmIntegrityPolicy `json:"shieldedVmIntegrityPolicy,omitempty"` + + // SourceMachineImage: Source machine image + SourceMachineImage string `json:"sourceMachineImage,omitempty"` + // StartRestricted: [Output Only] Whether a VM has been restricted for // start because Compute Engine has detected suspicious activity. StartRestricted bool `json:"startRestricted,omitempty"` @@ -11641,8 +12076,8 @@ type InstanceGroup struct { // instance group belong. Network string `json:"network,omitempty"` - // Region: The URL of the region where the instance group is located - // (for regional resources). + // Region: [Output Only] The URL of the region where the instance group + // is located (for regional resources). Region string `json:"region,omitempty"` // SelfLink: [Output Only] The URL for this instance group. The server @@ -11653,8 +12088,8 @@ type InstanceGroup struct { // group. Size int64 `json:"size,omitempty"` - // Subnetwork: The URL of the subnetwork to which all instances in the - // instance group belong. + // Subnetwork: [Output Only] The URL of the subnetwork to which all + // instances in the instance group belong. Subnetwork string `json:"subnetwork,omitempty"` // Zone: [Output Only] The URL of the zone where the instance group is @@ -12044,9 +12479,10 @@ type InstanceGroupManager struct { // "UNKNOWN" FailoverAction string `json:"failoverAction,omitempty"` - // Fingerprint: [Output Only] The fingerprint of the resource data. You - // can use this optional field for optimistic locking when you update - // the resource. + // 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. Fingerprint string `json:"fingerprint,omitempty"` // Id: [Output Only] A unique identifier for this resource type. The @@ -12086,11 +12522,11 @@ type InstanceGroupManager struct { // server defines this URL. SelfLink string `json:"selfLink,omitempty"` - // ServiceAccount: [Output Only] 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. + // ServiceAccount: 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. ServiceAccount string `json:"serviceAccount,omitempty"` // StatefulPolicy: Stateful configuration for this Instanced Group @@ -12696,6 +13132,12 @@ func (s *InstanceGroupManagerPendingActionsSummary) MarshalJSON() ([]byte, error } 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 // the specified targetSize during the update process. By default, a // fixed value of 1 is used. This value can be either a fixed number or @@ -12751,20 +13193,22 @@ type InstanceGroupManagerUpdatePolicy struct { // "PROACTIVE" Type string `json:"type,omitempty"` - // ForceSendFields is a list of field names (e.g. "MaxSurge") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent 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. + // "InstanceRedistributionType") to unconditionally include in API + // requests. By default, fields with empty values are omitted from API + // requests. However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "MaxSurge") to include in - // API requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an 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. + // "InstanceRedistributionType") to include in API requests with the + // JSON null value. By default, fields with empty values are omitted + // from API requests. However, any field with an empty value appearing + // in NullFields will be sent to the server as null. It is an error if a + // field in this list has a non-empty value. This may be used to include + // null fields in Patch requests. NullFields []string `json:"-"` } @@ -14656,20 +15100,19 @@ func (s *InstanceWithNamedPorts) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -type InstancesAddMaintenancePoliciesRequest struct { - // MaintenancePolicies: Maintenance policies to be added to this - // instance. - MaintenancePolicies []string `json:"maintenancePolicies,omitempty"` +type InstancesAddResourcePoliciesRequest struct { + // ResourcePolicies: Resource policies to be added to this instance. + ResourcePolicies []string `json:"resourcePolicies,omitempty"` - // ForceSendFields is a list of field names (e.g. "MaintenancePolicies") - // to unconditionally include in API requests. By default, fields with + // 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. "MaintenancePolicies") to + // 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 @@ -14679,26 +15122,25 @@ type InstancesAddMaintenancePoliciesRequest struct { NullFields []string `json:"-"` } -func (s *InstancesAddMaintenancePoliciesRequest) MarshalJSON() ([]byte, error) { - type NoMethod InstancesAddMaintenancePoliciesRequest +func (s *InstancesAddResourcePoliciesRequest) MarshalJSON() ([]byte, error) { + type NoMethod InstancesAddResourcePoliciesRequest raw := NoMethod(*s) return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -type InstancesRemoveMaintenancePoliciesRequest struct { - // MaintenancePolicies: Maintenance policies to be removed from this - // instance. - MaintenancePolicies []string `json:"maintenancePolicies,omitempty"` +type InstancesRemoveResourcePoliciesRequest struct { + // ResourcePolicies: Resource policies to be removed from this instance. + ResourcePolicies []string `json:"resourcePolicies,omitempty"` - // ForceSendFields is a list of field names (e.g. "MaintenancePolicies") - // to unconditionally include in API requests. By default, fields with + // 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. "MaintenancePolicies") to + // 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 @@ -14708,8 +15150,8 @@ type InstancesRemoveMaintenancePoliciesRequest struct { NullFields []string `json:"-"` } -func (s *InstancesRemoveMaintenancePoliciesRequest) MarshalJSON() ([]byte, error) { - type NoMethod InstancesRemoveMaintenancePoliciesRequest +func (s *InstancesRemoveResourcePoliciesRequest) MarshalJSON() ([]byte, error) { + type NoMethod InstancesRemoveResourcePoliciesRequest raw := NoMethod(*s) return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } @@ -14757,7 +15199,7 @@ func (s *InstancesResumeRequest) MarshalJSON() ([]byte, error) { } type InstancesScopedList struct { - // Instances: [Output Only] List of instances contained in this scope. + // Instances: [Output Only] A list of instances contained in this scope. Instances []*Instance `json:"instances,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -14922,7 +15364,7 @@ func (s *InstancesSetLabelsRequest) MarshalJSON() ([]byte, error) { } type InstancesSetMachineResourcesRequest struct { - // GuestAccelerators: List of the type and count of accelerator cards + // GuestAccelerators: A list of the type and count of accelerator cards // attached to the instance. GuestAccelerators []*AcceleratorConfig `json:"guestAccelerators,omitempty"` @@ -15094,7 +15536,7 @@ type Interconnect struct { // set to true. AdminEnabled bool `json:"adminEnabled,omitempty"` - // CircuitInfos: [Output Only] List of CircuitInfo objects, that + // CircuitInfos: [Output Only] A list of CircuitInfo objects, that // describe the individual circuits in this LAG. CircuitInfos []*InterconnectCircuitInfo `json:"circuitInfos,omitempty"` @@ -15110,7 +15552,7 @@ type Interconnect struct { // property when you create the resource. Description string `json:"description,omitempty"` - // ExpectedOutages: [Output Only] List of outages expected for this + // ExpectedOutages: [Output Only] A list of outages expected for this // Interconnect. ExpectedOutages []*InterconnectOutageNotification `json:"expectedOutages,omitempty"` @@ -15257,12 +15699,19 @@ 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. + // // Possible values: // "BPS_100M" // "BPS_10G" @@ -15304,10 +15753,8 @@ type InterconnectAttachment struct { Description string `json:"description,omitempty"` // EdgeAvailabilityDomain: Desired availability domain for the - // attachment. Can only be specified when creating PARTNER-type - // InterconnectAttachments. - // - // For improved reliability, customers should configure a pair of + // attachment. Only available for type PARTNER, at creation time. For + // improved reliability, customers should configure a pair of // attachments with one per availability domain. The selected // availability domain will be provided to the Partner via the pairing // key so that the provisioned circuit will lie in the specified domain. @@ -15370,15 +15817,20 @@ type InterconnectAttachment struct { OperationalStatus string `json:"operationalStatus,omitempty"` // PairingKey: [Output only for type PARTNER. Input only for - // PARTNER_PROVIDER. Not present for DEDICATED]. Opaque string - // identifying an PARTNER attachment. Of the form ?cloud-region/XXXXXX?. + // PARTNER_PROVIDER. Not present for DEDICATED]. The opaque identifier + // of an PARTNER attachment used to initiate provisioning with a + // selected partner. Of the form "XXXXX/region/domain" PairingKey string `json:"pairingKey,omitempty"` - // PartnerAsn: [Output only for PARTNER. Input for PARTNER_PROVIDER. Not - // present for DEDICATED] BGP ASN of the Partner. A layer 3 Partner - // should supply this if they configured BGP on behalf of the customer. + // PartnerAsn: Optional BGP ASN for the router that should be supplied + // by a layer 3 Partner if they configured BGP on behalf of the + // customer. Output only for PARTNER type, input only for + // PARTNER_PROVIDER, not available for DEDICATED. PartnerAsn int64 `json:"partnerAsn,omitempty,string"` + // PartnerMetadata: Informational metadata about Partner attachments + // from Partners to display to customers. Output only for for PARTNER + // type, mutable for PARTNER_PROVIDER, not available for DEDICATED. PartnerMetadata *InterconnectAttachmentPartnerMetadata `json:"partnerMetadata,omitempty"` // PrivateInterconnectInfo: [Output Only] Information specific to an @@ -15401,8 +15853,8 @@ type InterconnectAttachment struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` - // State: [Output Only] The current state of whether or not this - // interconnect attachment is functional. + // State: [Output Only] The current state of this attachment's + // functionality. // // Possible values: // "ACTIVE" @@ -15770,8 +16222,7 @@ func (s *InterconnectAttachmentListWarningData) MarshalJSON() ([]byte, error) { // InterconnectAttachmentPartnerMetadata: Informational metadata about // Partner attachments from Partners to display to customers. These // fields are propagated from PARTNER_PROVIDER attachments to their -// corresponding PARTNER attachments. Only mutable for PARTNER_PROVIDER -// type, output-only for PARTNER, not available for DEDICATED. +// corresponding PARTNER attachments. type InterconnectAttachmentPartnerMetadata struct { // InterconnectName: Plain text name of the Interconnect this attachment // is connected to, as displayed in the Partner?s portal. For instance @@ -15846,7 +16297,7 @@ func (s *InterconnectAttachmentPrivateInfo) MarshalJSON() ([]byte, error) { } type InterconnectAttachmentsScopedList struct { - // InterconnectAttachments: List of interconnect attachments contained + // InterconnectAttachments: A list of interconnect attachments contained // in this scope. InterconnectAttachments []*InterconnectAttachment `json:"interconnectAttachments,omitempty"` @@ -16479,7 +16930,7 @@ func (s *InterconnectLocationRegionInfo) MarshalJSON() ([]byte, error) { // InterconnectOutageNotification: Description of a planned outage on // this Interconnect. Next id: 9 type InterconnectOutageNotification struct { - // AffectedCircuits: Iff issue_type is IT_PARTIAL_OUTAGE, a list of the + // AffectedCircuits: If issue_type is IT_PARTIAL_OUTAGE, a list of the // Google-side circuit IDs that will be affected. AffectedCircuits []string `json:"affectedCircuits,omitempty"` @@ -17643,7 +18094,7 @@ func (s *MachineTypeListWarningData) MarshalJSON() ([]byte, error) { } type MachineTypesScopedList struct { - // MachineTypes: [Output Only] List of machine types contained in this + // MachineTypes: [Output Only] A list of machine types contained in this // scope. MachineTypes []*MachineType `json:"machineTypes,omitempty"` @@ -17776,550 +18227,6 @@ func (s *MachineTypesScopedListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -type MaintenancePoliciesList 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 MaintenancePolicy resources. - Items []*MaintenancePolicy `json:"items,omitempty"` - - // Kind: [Output Only] Type of resource.Always - // compute#maintenancePoliciesList for listsof maintenancePolicies - 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 *MaintenancePoliciesListWarning `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 *MaintenancePoliciesList) MarshalJSON() ([]byte, error) { - type NoMethod MaintenancePoliciesList - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// MaintenancePoliciesListWarning: [Output Only] Informational warning -// message. -type MaintenancePoliciesListWarning 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 []*MaintenancePoliciesListWarningData `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 *MaintenancePoliciesListWarning) MarshalJSON() ([]byte, error) { - type NoMethod MaintenancePoliciesListWarning - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type MaintenancePoliciesListWarningData 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 *MaintenancePoliciesListWarningData) MarshalJSON() ([]byte, error) { - type NoMethod MaintenancePoliciesListWarningData - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type MaintenancePoliciesScopedList struct { - // MaintenancePolicies: List of maintenancePolicies contained in this - // scope. - MaintenancePolicies []*MaintenancePolicy `json:"maintenancePolicies,omitempty"` - - // Warning: Informational warning which replaces the list of - // maintenancePolicies when the list is empty. - Warning *MaintenancePoliciesScopedListWarning `json:"warning,omitempty"` - - // ForceSendFields is a list of field names (e.g. "MaintenancePolicies") - // to unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "MaintenancePolicies") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an error if a field in this list has a - // non-empty value. This may be used to include null fields in Patch - // requests. - NullFields []string `json:"-"` -} - -func (s *MaintenancePoliciesScopedList) MarshalJSON() ([]byte, error) { - type NoMethod MaintenancePoliciesScopedList - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// MaintenancePoliciesScopedListWarning: Informational warning which -// replaces the list of maintenancePolicies when the list is empty. -type MaintenancePoliciesScopedListWarning 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 []*MaintenancePoliciesScopedListWarningData `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 *MaintenancePoliciesScopedListWarning) MarshalJSON() ([]byte, error) { - type NoMethod MaintenancePoliciesScopedListWarning - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type MaintenancePoliciesScopedListWarningData 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 *MaintenancePoliciesScopedListWarningData) MarshalJSON() ([]byte, error) { - type NoMethod MaintenancePoliciesScopedListWarningData - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// MaintenancePolicy: A maintenance policy for an instance. This -// specifies what kind of maintenance operations our infrastructure may -// perform on this instance and when. -type MaintenancePolicy 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#maintenance_policies for maintenance 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"` - - // VmMaintenancePolicy: Maintenance policy applicable to VMs for - // infrastructure maintenance. - VmMaintenancePolicy *VmMaintenancePolicy `json:"vmMaintenancePolicy,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 *MaintenancePolicy) MarshalJSON() ([]byte, error) { - type NoMethod MaintenancePolicy - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// MaintenancePolicyAggregatedList: Contains a list of -// maintenancePolicies. -type MaintenancePolicyAggregatedList struct { - // Id: [Output Only] Unique identifier for the resource; defined by the - // server. - Id string `json:"id,omitempty"` - - // Items: A list of MaintenancePolicy resources. - Items map[string]MaintenancePoliciesScopedList `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 *MaintenancePolicyAggregatedListWarning `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 *MaintenancePolicyAggregatedList) MarshalJSON() ([]byte, error) { - type NoMethod MaintenancePolicyAggregatedList - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// MaintenancePolicyAggregatedListWarning: [Output Only] Informational -// warning message. -type MaintenancePolicyAggregatedListWarning 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 []*MaintenancePolicyAggregatedListWarningData `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 *MaintenancePolicyAggregatedListWarning) MarshalJSON() ([]byte, error) { - type NoMethod MaintenancePolicyAggregatedListWarning - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type MaintenancePolicyAggregatedListWarningData 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 *MaintenancePolicyAggregatedListWarningData) MarshalJSON() ([]byte, error) { - type NoMethod MaintenancePolicyAggregatedListWarningData - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// MaintenanceWindow: A maintenance window for VMs and disks. When set, -// we restrict our maintenance operations to this window. -type MaintenanceWindow struct { - DailyMaintenanceWindow *DailyMaintenanceWindow `json:"dailyMaintenanceWindow,omitempty"` - - HourlyMaintenanceWindow *HourlyMaintenanceWindow `json:"hourlyMaintenanceWindow,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. - // However, any non-pointer, non-interface field appearing in - // ForceSendFields will be sent to the server regardless of whether the - // field is empty or not. This may be used to include empty fields in - // Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "DailyMaintenanceWindow") - // to include in API requests with the JSON null value. By default, - // fields with empty values are omitted from API requests. However, any - // field with an empty value appearing in NullFields will be sent to the - // server as null. It is an error if a field in this list has a - // non-empty value. This may be used to include null fields in Patch - // requests. - NullFields []string `json:"-"` -} - -func (s *MaintenanceWindow) MarshalJSON() ([]byte, error) { - type NoMethod MaintenanceWindow - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - // ManagedInstance: Next available tag: 12 type ManagedInstance struct { // CurrentAction: [Output Only] The current action that the managed @@ -18842,7 +18749,7 @@ type Network struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` - // Peerings: [Output Only] List of network peerings for the resource. + // Peerings: [Output Only] A list of network peerings for the resource. Peerings []*NetworkPeering `json:"peerings,omitempty"` // RoutingConfig: The network-level routing configuration for this @@ -20027,6 +19934,14 @@ type NetworkPeering struct { // manually to route packets to peer network. AutoCreateRoutes bool `json:"autoCreateRoutes,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 // must be 1-63 characters long and match regular expression @@ -20121,6 +20036,14 @@ type NetworksAddPeeringRequest struct { // automatically. AutoCreateRoutes bool `json:"autoCreateRoutes,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 the peering, which should conform to RFC1035. Name string `json:"name,omitempty"` @@ -20181,13 +20104,1742 @@ 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"` + + // 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"` + + // 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 { + Index int64 `json:"index,omitempty"` + + // 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"` + + // ForceSendFields is a list of field names (e.g. "Index") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // 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 + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field 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 { + // 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 + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // 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 + // null. It is an error if a field 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 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 charaicter, 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 ==) // (== resource_for beta.regionOperations ==) (== resource_for // v1.zoneOperations ==) (== resource_for beta.zoneOperations ==) type Operation struct { - // ClientOperationId: [Output Only] Reserved for future use. + // ClientOperationId: [Output Only] The value of `requestId` if you + // provided it in the request. Not present otherwise. ClientOperationId string `json:"clientOperationId,omitempty"` // CreationTimestamp: [Deprecated] This field is deprecated. @@ -20792,7 +22444,8 @@ func (s *OperationListWarningData) MarshalJSON() ([]byte, error) { } type OperationsScopedList struct { - // Operations: [Output Only] List of operations contained in this scope. + // Operations: [Output Only] A list of operations contained in this + // scope. Operations []*Operation `json:"operations,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -21010,13 +22663,22 @@ func (s *PathRule) MarshalJSON() ([]byte, error) { } type PerInstanceConfig struct { + // Fingerprint: Fingerprint of this per-instance config. This field may + // be used in optimistic locking. It will be ignored when inserting a + // per-instance config. An up-to-date fingerprint must be provided in + // order to update an existing per-instance config or the field needs to + // be unset. + Fingerprint string `json:"fingerprint,omitempty"` + // Instance: The URL of the instance. Serves as a merge key during - // UpdatePerInstanceConfigs operation. + // 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. Instance string `json:"instance,omitempty"` Override *ManagedInstanceOverride `json:"override,omitempty"` - // ForceSendFields is a list of field names (e.g. "Instance") to + // 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, // non-interface field appearing in ForceSendFields will be sent to the @@ -21024,10 +22686,10 @@ type PerInstanceConfig 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. "Fingerprint") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` @@ -21045,20 +22707,30 @@ func (s *PerInstanceConfig) MarshalJSON() ([]byte, error) { // // // -// A `Policy` consists of a list of `bindings`. A `Binding` binds a list +// 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. // -// **Example** +// **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", ] }, { +// "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 { @@ -21125,6 +22797,35 @@ func (s *Policy) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type PreconfiguredWafSet struct { + // ExpressionSets: List of entities that are currently supported for WAF + // rules. + ExpressionSets []*WafExpressionSet `json:"expressionSets,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ExpressionSets") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ExpressionSets") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *PreconfiguredWafSet) MarshalJSON() ([]byte, error) { + type NoMethod PreconfiguredWafSet + 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 ==) @@ -21431,10 +23132,12 @@ type Quota struct { // "INSTANCE_GROUP_MANAGERS" // "INSTANCE_TEMPLATES" // "INTERCONNECTS" + // "INTERCONNECT_ATTACHMENTS_PER_REGION" + // "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS" // "INTERNAL_ADDRESSES" // "IN_USE_ADDRESSES" + // "IN_USE_MAINTENANCE_WINDOWS" // "LOCAL_SSD_TOTAL_GB" - // "MAINTENANCE_POLICIES" // "NETWORKS" // "NVIDIA_K80_GPUS" // "NVIDIA_P100_GPUS" @@ -21444,8 +23147,11 @@ type Quota struct { // "PREEMPTIBLE_LOCAL_SSD_GB" // "PREEMPTIBLE_NVIDIA_K80_GPUS" // "PREEMPTIBLE_NVIDIA_P100_GPUS" + // "PREEMPTIBLE_NVIDIA_V100_GPUS" + // "PRIVATE_V6_ACCESS_SUBNETWORKS" // "REGIONAL_AUTOSCALERS" // "REGIONAL_INSTANCE_GROUP_MANAGERS" + // "RESOURCE_POLICIES" // "ROUTERS" // "ROUTES" // "SECURITY_POLICIES" @@ -22583,7 +24289,7 @@ func (s *RegionInstanceGroupManagersListInstanceConfigsRespWarningData) MarshalJ } type RegionInstanceGroupManagersListInstancesResponse struct { - // ManagedInstances: List of managed instances. + // ManagedInstances: A list of managed instances. ManagedInstances []*ManagedInstance `json:"managedInstances,omitempty"` // NextPageToken: [Output Only] This token allows you to get the next @@ -23159,6 +24865,71 @@ 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) +} + +type RegionUrlMapsValidateRequest struct { + // Resource: Content of the UrlMap to be validated. + Resource *UrlMap `json:"resource,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Resource") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Resource") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *RegionUrlMapsValidateRequest) MarshalJSON() ([]byte, error) { + type NoMethod RegionUrlMapsValidateRequest + 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 { @@ -23229,6 +25000,880 @@ 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"` + + // 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"` + + // VmMaintenancePolicy: Resource policy applicable to VMs for + // infrastructure maintenance. + VmMaintenancePolicy *ResourcePolicyVmMaintenancePolicy `json:"vmMaintenancePolicy,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 automatically +// created snapshot 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 lables, 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 automatically created snapshots. +type ResourcePolicyBackupSchedulePolicyRetentionPolicy struct { + // MaxRetentionDays: Maximum age of the snapshot that is allowed to be + // kept. + MaxRetentionDays int64 `json:"maxRetentionDays,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 automatic 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 + // 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-59] 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-59] 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 ResourcePolicyVmMaintenancePolicy struct { + // MaintenanceEnvironment: A hint about the environment this VM belongs + // to (production vs develoment) + // + // Possible values: + // "DEVELOPMENT" + // "MAINTENANCE_ENVIRONMENT_UNSPECIFIED" + // "PRODUCTION" + MaintenanceEnvironment string `json:"maintenanceEnvironment,omitempty"` + + // 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 []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 + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyVmMaintenancePolicy) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyVmMaintenancePolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyVmMaintenancePolicyMaintenanceWindow: A maintenance +// window for VMs. When set, we restrict our maintenance operations to +// this window. +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. + // However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "DailyMaintenanceWindow") + // to include in API requests with the JSON null value. By default, + // fields with empty values are omitted from API requests. However, any + // field with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyVmMaintenancePolicyMaintenanceWindow) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyVmMaintenancePolicyMaintenanceWindow + 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-59] 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 @@ -23288,6 +25933,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: @@ -23651,8 +26307,7 @@ type Router struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` - // Nats: List of Nat services created in this router. The maximum number - // of Nat services within a Router is 3 for Alpha. + // 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. @@ -23726,39 +26381,6 @@ func (s *RouterAdvertisedIpRange) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// RouterAdvertisedPrefix: Description-tagged prefixes for the router to -// advertise. -type RouterAdvertisedPrefix struct { - // Description: User-specified description for the prefix. - Description string `json:"description,omitempty"` - - // Prefix: The prefix to advertise. The value must be a CIDR-formatted - // string. - Prefix string `json:"prefix,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 *RouterAdvertisedPrefix) MarshalJSON() ([]byte, error) { - type NoMethod RouterAdvertisedPrefix - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - // RouterAggregatedList: Contains a list of routers. type RouterAggregatedList struct { // Id: [Output Only] Unique identifier for the resource; defined by the @@ -23941,14 +26563,6 @@ type RouterBgp struct { // ranges. AdvertisedIpRanges []*RouterAdvertisedIpRange `json:"advertisedIpRanges,omitempty"` - // AdvertisedPrefixs: User-specified list of individual prefixes 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 prefixes will be advertised in addition to any - // specified groups. Leave this field blank to advertise no custom - // prefixes. - AdvertisedPrefixs []*RouterAdvertisedPrefix `json:"advertisedPrefixs,omitempty"` - // Asn: Local BGP Autonomous System Number (ASN). Must be an RFC6996 // private ASN, either 16-bit or 32-bit. The value will be fixed for // this router resource. All VPN tunnels that link to this router will @@ -24006,14 +26620,6 @@ type RouterBgpPeer struct { // no custom IP ranges. AdvertisedIpRanges []*RouterAdvertisedIpRange `json:"advertisedIpRanges,omitempty"` - // AdvertisedPrefixs: User-specified list of individual prefixes 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 prefixes will be advertised in - // addition to any specified groups. Leave this field blank to advertise - // no custom prefixes. - AdvertisedPrefixs []*RouterAdvertisedPrefix `json:"advertisedPrefixs,omitempty"` - // AdvertisedRoutePriority: The priority of routes advertised to this // BGP peer. In the case where there is more than one matching route of // maximum length, the routes with lowest priority value win. @@ -24026,6 +26632,18 @@ 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. + // + // Possible values: + // "MANAGED_BY_ATTACHMENT" + // "MANAGED_BY_USER" + ManagementType string `json:"managementType,omitempty"` + // Name: Name of this BGP peer. The name must be 1-63 characters long // and comply with RFC1035. Name string `json:"name,omitempty"` @@ -24081,6 +26699,18 @@ 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. + // + // Possible values: + // "MANAGED_BY_ATTACHMENT" + // "MANAGED_BY_USER" + ManagementType string `json:"managementType,omitempty"` + // Name: Name of this interface entry. The name must be 1-63 characters // long and comply with RFC1035. Name string `json:"name,omitempty"` @@ -24270,7 +26900,7 @@ 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] List of IPs allocated + // 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 @@ -24289,7 +26919,7 @@ type RouterNat struct { // "MANUAL_ONLY" NatIpAllocateOption string `json:"natIpAllocateOption,omitempty"` - // NatIps: List of URLs of the IP resources used for this Nat service. + // 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"` @@ -24306,7 +26936,7 @@ type RouterNat struct { // "LIST_OF_SUBNETWORKS" SourceSubnetworkIpRangesToNat string `json:"sourceSubnetworkIpRangesToNat,omitempty"` - // Subnetworks: List of Subnetwork resources whose traffic should be + // 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"` @@ -24341,8 +26971,8 @@ type RouterNatSubnetworkToNat struct { // Name: URL for the subnetwork resource to use NAT. Name string `json:"name,omitempty"` - // SecondaryIpRangeNames: List of the secondary ranges of the Subnetwork - // that are allowed to use NAT. This can be populated only if + // 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"` @@ -24482,7 +27112,7 @@ func (s *RouterStatusBgpPeerStatus) MarshalJSON() ([]byte, error) { // RouterStatusNatStatus: Status of a NAT contained in this router. type RouterStatusNatStatus struct { - // AutoAllocatedNatIps: List of IPs auto-allocated for NAT. Example: + // AutoAllocatedNatIps: A list of IPs auto-allocated for NAT. Example: // ["1.1.1.1", "129.2.16.89"] AutoAllocatedNatIps []string `json:"autoAllocatedNatIps,omitempty"` @@ -24499,12 +27129,12 @@ type RouterStatusNatStatus struct { // that can use NAT. NumVmEndpointsWithNatMappings int64 `json:"numVmEndpointsWithNatMappings,omitempty"` - // UserAllocatedNatIpResources: List of fully qualified URLs of reserved - // IP address resources. + // UserAllocatedNatIpResources: A list of fully qualified URLs of + // reserved IP address resources. UserAllocatedNatIpResources []string `json:"userAllocatedNatIpResources,omitempty"` - // UserAllocatedNatIps: List of IPs user-allocated for NAT. They will be - // raw IP strings like "179.12.26.133". + // 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") @@ -24596,7 +27226,7 @@ func (s *RoutersPreviewResponse) MarshalJSON() ([]byte, error) { } type RoutersScopedList struct { - // Routers: List of routers contained in this scope. + // Routers: A list of routers contained in this scope. Routers []*Router `json:"routers,omitempty"` // Warning: Informational warning which replaces the list of routers @@ -24963,8 +27593,67 @@ func (s *SchedulingNodeAffinity) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type SecurityPoliciesListPreconfiguredExpressionSetsResponse struct { + PreconfiguredExpressionSets *SecurityPoliciesWafConfig `json:"preconfiguredExpressionSets,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. + // "PreconfiguredExpressionSets") to unconditionally include in API + // requests. By default, fields with empty values are omitted from API + // requests. However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. + // "PreconfiguredExpressionSets") to include in API requests with the + // JSON null value. By default, fields with empty values are omitted + // from API requests. However, any field with an empty value appearing + // in NullFields will be sent to the server as null. It is an error if a + // field in this list has a non-empty value. This may be used to include + // null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPoliciesListPreconfiguredExpressionSetsResponse) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPoliciesListPreconfiguredExpressionSetsResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SecurityPoliciesWafConfig struct { + WafRules *PreconfiguredWafSet `json:"wafRules,omitempty"` + + // ForceSendFields is a list of field names (e.g. "WafRules") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "WafRules") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPoliciesWafConfig) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPoliciesWafConfig + 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'. +// It can also be associated with one or more 'targets'. Next available +// tag: 11 type SecurityPolicy struct { // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text // format. @@ -24993,6 +27682,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 @@ -25002,9 +27707,9 @@ type SecurityPolicy struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` - // Rules: 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 + // 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"` @@ -25471,6 +28176,38 @@ func (s *ShieldedVmConfig) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// ShieldedVmIntegrityPolicy: The policy describes how boot integrity +// measurements are evaluated. +type ShieldedVmIntegrityPolicy struct { + // UpdateAutoLearnPolicy: Triggers an auto relearn event: the integrity + // monitoring module copies existing guest measurements to the baseline. + UpdateAutoLearnPolicy bool `json:"updateAutoLearnPolicy,omitempty"` + + // ForceSendFields is a list of field names (e.g. + // "UpdateAutoLearnPolicy") to unconditionally include in API requests. + // By default, fields with empty values are omitted from API requests. + // However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "UpdateAutoLearnPolicy") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *ShieldedVmIntegrityPolicy) MarshalJSON() ([]byte, error) { + type NoMethod ShieldedVmIntegrityPolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // SignedUrlKey: Represents a customer-supplied Signing Key used by // Cloud CDN Signed URLs type SignedUrlKey struct { @@ -25512,6 +28249,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 autoamtically + // 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"` @@ -25552,8 +28293,8 @@ type Snapshot struct { // by the setLabels method. Label values may be empty. Labels map[string]string `json:"labels,omitempty"` - // LicenseCodes: Integer license codes indicating which licenses are - // attached to this snapshot. + // LicenseCodes: [Output Only] Integer license codes indicating which + // licenses are attached to this snapshot. LicenseCodes googleapi.Int64s `json:"licenseCodes,omitempty"` // Licenses: [Output Only] A list of public visible licenses that apply @@ -25639,21 +28380,20 @@ type Snapshot 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. "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:"-"` } @@ -26144,7 +28884,7 @@ func (s *SslCertificateManagedSslCertificate) MarshalJSON() ([]byte, error) { } // SslCertificateSelfManagedSslCertificate: Configuration and status of -// a self-managed SSL certificate.. +// 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. @@ -26372,8 +29112,8 @@ type SslPolicy struct { // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` - // CustomFeatures: List of features enabled when the selected profile is - // CUSTOM. The + // CustomFeatures: A list of features enabled when the selected profile + // is CUSTOM. The // - method returns the set of features that can be specified in this // list. This field must be empty if the profile is not CUSTOM. CustomFeatures []string `json:"customFeatures,omitempty"` @@ -26402,13 +29142,12 @@ type SslPolicy struct { // MinTlsVersion: The minimum version of SSL protocol that can be used // by the clients to establish a connection with the load balancer. This - // can be one of TLS_1_0, TLS_1_1, TLS_1_2, TLS_1_3. + // can be one of TLS_1_0, TLS_1_1, TLS_1_2. // // Possible values: // "TLS_1_0" // "TLS_1_1" // "TLS_1_2" - // "TLS_1_3" MinTlsVersion string `json:"minTlsVersion,omitempty"` // Name: Name of the resource. The name must be 1-63 characters long, @@ -26769,10 +29508,32 @@ type Subnetwork struct { // setPrivateIpGoogleAccess. PrivateIpGoogleAccess bool `json:"privateIpGoogleAccess,omitempty"` + // Purpose: 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. + // + // Possible values: + // "INTERNAL_HTTPS_LOAD_BALANCER" + // "PRIVATE_RFC_1918" + Purpose string `json:"purpose,omitempty"` + // Region: URL of the region where the Subnetwork resides. This field // can be set only at resource creation time. Region string `json:"region,omitempty"` + // Role: 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. + // + // Possible values: + // "ACTIVE" + // "BACKUP" + Role string `json:"role,omitempty"` + // 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 @@ -27192,7 +29953,7 @@ func (s *SubnetworksExpandIpCidrRangeRequest) MarshalJSON() ([]byte, error) { } type SubnetworksScopedList struct { - // Subnetworks: List of subnetworks contained in this scope. + // Subnetworks: A list of subnetworks contained in this scope. Subnetworks []*Subnetwork `json:"subnetworks,omitempty"` // Warning: An informational warning that appears when the list of @@ -27434,11 +30195,11 @@ func (s *TCPHealthCheck) MarshalJSON() ([]byte, error) { // Tags: A set of instance tags. type Tags struct { // Fingerprint: Specifies a fingerprint for this request, which is - // essentially a hash of the metadata's contents and used for optimistic + // essentially a hash of the tags' 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. + // changes after every request to modify or update tags. You must always + // provide an up-to-date fingerprint hash in order to update or change + // tags. // // To see the latest fingerprint, make get() request to the instance. Fingerprint string `json:"fingerprint,omitempty"` @@ -27470,6 +30231,141 @@ func (s *Tags) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type TargetHttpProxiesScopedList struct { + // TargetHttpProxies: A list of TargetHttpProxies contained in this + // scope. + TargetHttpProxies []*TargetHttpProxy `json:"targetHttpProxies,omitempty"` + + // Warning: Informational warning which replaces the list of backend + // services when the list is empty. + Warning *TargetHttpProxiesScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "TargetHttpProxies") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "TargetHttpProxies") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *TargetHttpProxiesScopedList) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpProxiesScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// TargetHttpProxiesScopedListWarning: Informational warning which +// replaces the list of backend services when the list is empty. +type TargetHttpProxiesScopedListWarning 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 []*TargetHttpProxiesScopedListWarningData `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 *TargetHttpProxiesScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpProxiesScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type TargetHttpProxiesScopedListWarningData 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 *TargetHttpProxiesScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpProxiesScopedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // TargetHttpProxy: A TargetHttpProxy resource. This resource defines an // HTTP proxy. (== resource_for beta.targetHttpProxies ==) (== // resource_for v1.targetHttpProxies ==) @@ -27499,6 +30395,11 @@ type TargetHttpProxy struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` + // Region: [Output Only] URL of the region where the regional Target + // HTTP Proxy resides. This field is not applicable to global Target + // HTTP Proxies. + Region string `json:"region,omitempty"` + // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` @@ -27534,6 +30435,162 @@ func (s *TargetHttpProxy) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type TargetHttpProxyAggregatedList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of TargetHttpProxiesScopedList resources. + Items map[string]TargetHttpProxiesScopedList `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource. Always + // compute#targetHttpProxyAggregatedList 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 *TargetHttpProxyAggregatedListWarning `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 *TargetHttpProxyAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpProxyAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// TargetHttpProxyAggregatedListWarning: [Output Only] Informational +// warning message. +type TargetHttpProxyAggregatedListWarning 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 []*TargetHttpProxyAggregatedListWarningData `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 *TargetHttpProxyAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpProxyAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type TargetHttpProxyAggregatedListWarningData 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 *TargetHttpProxyAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpProxyAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // TargetHttpProxyList: A list of TargetHttpProxy resources. type TargetHttpProxyList struct { // Id: [Output Only] Unique identifier for the resource; defined by the @@ -27756,10 +30813,6 @@ func (s *TargetHttpsProxiesSetSslCertificatesRequest) MarshalJSON() ([]byte, err // an HTTPS proxy. (== resource_for beta.targetHttpsProxies ==) (== // resource_for v1.targetHttpsProxies ==) type TargetHttpsProxy struct { - // ClientSslPolicy: URL to ClientSslPolicy resource which controls the - // set of allowed SSL versions and ciphers. - ClientSslPolicy string `json:"clientSslPolicy,omitempty"` - // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` @@ -27826,15 +30879,15 @@ type TargetHttpsProxy struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "ClientSslPolicy") to - // unconditionally include in API requests. By default, fields with + // 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. "ClientSslPolicy") to + // 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 @@ -28399,7 +31452,7 @@ func (s *TargetInstanceListWarningData) MarshalJSON() ([]byte, error) { } type TargetInstancesScopedList struct { - // TargetInstances: List of target instances contained in this scope. + // TargetInstances: A list of target instances contained in this scope. TargetInstances []*TargetInstance `json:"targetInstances,omitempty"` // Warning: Informational warning which replaces the list of addresses @@ -29142,7 +32195,7 @@ func (s *TargetPoolsRemoveInstanceRequest) MarshalJSON() ([]byte, error) { } type TargetPoolsScopedList struct { - // TargetPools: List of target pools contained in this scope. + // TargetPools: A list of target pools contained in this scope. TargetPools []*TargetPool `json:"targetPools,omitempty"` // Warning: Informational warning which replaces the list of addresses @@ -29394,10 +32447,6 @@ func (s *TargetSslProxiesSetSslCertificatesRequest) MarshalJSON() ([]byte, error // SSL proxy. (== resource_for beta.targetSslProxies ==) (== // resource_for v1.targetSslProxies ==) type TargetSslProxy struct { - // ClientSslPolicy: URL to ClientSslPolicy resource which controls the - // set of allowed SSL versions and ciphers. - ClientSslPolicy string `json:"clientSslPolicy,omitempty"` - // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` @@ -29452,15 +32501,15 @@ type TargetSslProxy struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "ClientSslPolicy") to - // unconditionally include in API requests. By default, fields with + // 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. "ClientSslPolicy") to + // 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 @@ -30334,7 +33383,7 @@ func (s *TargetVpnGatewayListWarningData) MarshalJSON() ([]byte, error) { } type TargetVpnGatewaysScopedList struct { - // TargetVpnGateways: [Output Only] List of target vpn gateways + // TargetVpnGateways: [Output Only] A list of target vpn gateways // contained in this scope. TargetVpnGateways []*TargetVpnGateway `json:"targetVpnGateways,omitempty"` @@ -30647,6 +33696,12 @@ type UrlMap struct { // PathMatchers: The list of named PathMatchers to use against the URL. PathMatchers []*PathMatcher `json:"pathMatchers,omitempty"` + // Region: [Output Only] URL of the region where the regional URL map + // resides. This field is not applicable to global URL maps. You must + // specify this field as part of the HTTP request URL. It is not + // settable as a field in the request body. + Region string `json:"region,omitempty"` + // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` @@ -31007,6 +34062,9 @@ type UsableSubnetwork struct { // 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"` @@ -31033,6 +34091,42 @@ func (s *UsableSubnetwork) MarshalJSON() ([]byte, error) { 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. @@ -31232,15 +34326,87 @@ func (s *UsageExportLocation) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// VmMaintenancePolicy: A Vm Maintenance Policy specifies what kind of -// infrastructure maintenance we are allowed to perform on this VM and -// when. -type VmMaintenancePolicy struct { - // MaintenanceWindow: Maintenance windows that are applied to VMs - // covered by this policy. - MaintenanceWindow *MaintenanceWindow `json:"maintenanceWindow,omitempty"` +// VpnGateway: Represents a VPN gateway resource. +type VpnGateway struct { + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text + // format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` - // ForceSendFields is a list of field names (e.g. "MaintenanceWindow") + // 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] Type of resource. Always compute#vpnGateway for + // VPN gateways. + Kind string `json:"kind,omitempty"` + + // LabelFingerprint: 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. + // + // To see the latest fingerprint, make a get() request to retrieve an + // VpnGateway. + LabelFingerprint string `json:"labelFingerprint,omitempty"` + + // Labels: Labels to apply to this VpnGateway 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 + // 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"` + + // Network: URL of the network to which this VPN gateway is attached. + // Provided by the client when the VPN gateway is created. + Network string `json:"network,omitempty"` + + // Redundancy: The redundancy mode configured for this VPN gateway. + // Possible values are ACTIVE_ACTIVE and NONE. If set to ACTIVE_ACTIVE, + // two VPN interfaces are created thereby providing higher availability. + // If set to NONE, only one interface is created with a lower + // availability SLA. + // + // If this field is specified, either 2 or 1 external IP addresses + // (depending on the value of specified redundancy) are automatically + // allocated for use with this VPN gateway, and incoming traffic on the + // external addresses to ports ESP, UDP:500 and UDP:4500 are + // automatically forwarded to this gateway. + // + // Possible values: + // "ACTIVE_ACTIVE" + // "NONE" + // "REDUNDANCY_UNSPECIFIED" + Redundancy string `json:"redundancy,omitempty"` + + // Region: [Output Only] URL of the region where the VPN gateway + // resides. + Region string `json:"region,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for the resource. + SelfLink string `json:"selfLink,omitempty"` + + // VpnInterfaces: [Output Only] A list of interfaces on this VPN + // gateway. + VpnInterfaces []*VpnGatewayVpnGatewayInterface `json:"vpnInterfaces,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 @@ -31248,7 +34414,7 @@ type VmMaintenancePolicy struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "MaintenanceWindow") to + // 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 @@ -31258,8 +34424,483 @@ type VmMaintenancePolicy struct { NullFields []string `json:"-"` } -func (s *VmMaintenancePolicy) MarshalJSON() ([]byte, error) { - type NoMethod VmMaintenancePolicy +func (s *VpnGateway) MarshalJSON() ([]byte, error) { + type NoMethod VpnGateway + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type VpnGatewayAggregatedList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of VpnGateway resources. + Items map[string]VpnGatewaysScopedList `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource. Always compute#vpnGateway for + // VPN gateways. + 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 *VpnGatewayAggregatedListWarning `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 *VpnGatewayAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod VpnGatewayAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// VpnGatewayAggregatedListWarning: [Output Only] Informational warning +// message. +type VpnGatewayAggregatedListWarning 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 []*VpnGatewayAggregatedListWarningData `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 *VpnGatewayAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod VpnGatewayAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type VpnGatewayAggregatedListWarningData 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 *VpnGatewayAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod VpnGatewayAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// VpnGatewayList: Contains a list of VpnGateway resources. +type VpnGatewayList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of VpnGateway resources. + Items []*VpnGateway `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource. Always compute#vpnGateway for + // VPN gateways. + 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 *VpnGatewayListWarning `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 *VpnGatewayList) MarshalJSON() ([]byte, error) { + type NoMethod VpnGatewayList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// VpnGatewayListWarning: [Output Only] Informational warning message. +type VpnGatewayListWarning 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 []*VpnGatewayListWarningData `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 *VpnGatewayListWarning) MarshalJSON() ([]byte, error) { + type NoMethod VpnGatewayListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type VpnGatewayListWarningData 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 *VpnGatewayListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod VpnGatewayListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// VpnGatewayVpnGatewayInterface: A VPN gateway interface. +type VpnGatewayVpnGatewayInterface struct { + // Id: The numeric ID of this VPN gateway interface. + Id int64 `json:"id,omitempty"` + + // IpAddress: The external IP address for this VPN gateway interface. + IpAddress string `json:"ipAddress,omitempty"` + + // 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 *VpnGatewayVpnGatewayInterface) MarshalJSON() ([]byte, error) { + type NoMethod VpnGatewayVpnGatewayInterface + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type VpnGatewaysScopedList struct { + // VpnGateways: [Output Only] A list of VPN gateways contained in this + // scope. + VpnGateways []*VpnGateway `json:"vpnGateways,omitempty"` + + // Warning: [Output Only] Informational warning which replaces the list + // of addresses when the list is empty. + Warning *VpnGatewaysScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "VpnGateways") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "VpnGateways") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *VpnGatewaysScopedList) MarshalJSON() ([]byte, error) { + type NoMethod VpnGatewaysScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// VpnGatewaysScopedListWarning: [Output Only] Informational warning +// which replaces the list of addresses when the list is empty. +type VpnGatewaysScopedListWarning 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 []*VpnGatewaysScopedListWarningData `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 *VpnGatewaysScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod VpnGatewaysScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type VpnGatewaysScopedListWarningData 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 *VpnGatewaysScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod VpnGatewaysScopedListWarningData raw := NoMethod(*s) return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } @@ -31372,6 +35013,21 @@ type VpnTunnel struct { // created. TargetVpnGateway string `json:"targetVpnGateway,omitempty"` + // VpnGateway: URL of the VPN gateway with which this VPN tunnel is + // associated. Provided by the client when the VPN tunnel is created. + // This must be used (instead of target_vpn_gateway) if a VPN gateway + // resource is created with redundancy. + // + // VPN gateway resource provides a way to create a highly available VPN + // setup. + VpnGateway string `json:"vpnGateway,omitempty"` + + // VpnGatewayInterface: The interface ID of the VPN gateway with which + // this VPN tunnel is associated. If the VPN gateway has redundancy + // other than NONE, this field is required to identify which interface + // of the VPN gateway to use. + VpnGatewayInterface int64 `json:"vpnGatewayInterface,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -31711,7 +35367,7 @@ func (s *VpnTunnelListWarningData) MarshalJSON() ([]byte, error) { } type VpnTunnelsScopedList struct { - // VpnTunnels: List of vpn tunnels contained in this scope. + // VpnTunnels: A list of vpn tunnels contained in this scope. VpnTunnels []*VpnTunnel `json:"vpnTunnels,omitempty"` // Warning: Informational warning which replaces the list of addresses @@ -31843,6 +35499,76 @@ func (s *VpnTunnelsScopedListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type WafExpressionSet struct { + // Aliases: A list of alternate IDs. The format should be: - E.g. + // XSS-stable Generic suffix like "stable" is particularly useful if a + // policy likes to avail newer set of expressions without having to + // change the policy. A given alias name can't be used for more than one + // entity set. + Aliases []string `json:"aliases,omitempty"` + + // Expressions: List of available expressions. + Expressions []*WafExpressionSetExpression `json:"expressions,omitempty"` + + // Id: Google specified expression set ID. The format should be: - E.g. + // XSS-20170329 + Id string `json:"id,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Aliases") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Aliases") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *WafExpressionSet) MarshalJSON() ([]byte, error) { + type NoMethod WafExpressionSet + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type WafExpressionSetExpression struct { + // Id: Expression ID should uniquely identify the origin of the + // expression. E.g. owasp-crs-v020901-id973337 identifies Owasp core + // rule set version 2.9.1 rule id 973337. The ID could be used to + // determine the individual attack definition that has been detected. It + // could also be used to exclude it from the policy in case of false + // positive. + Id string `json:"id,omitempty"` + + // 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 *WafExpressionSetExpression) MarshalJSON() ([]byte, error) { + type NoMethod WafExpressionSetExpression + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type XpnHostList struct { // Id: [Output Only] Unique identifier for the resource; defined by the // server. @@ -32296,6 +36022,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 { @@ -32314,32 +36078,28 @@ func (r *AcceleratorTypesService) AggregatedList(project string) *AcceleratorTyp return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AcceleratorTypesAggregatedListCall) Filter(filter string) *AcceleratorTypesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -32483,7 +36243,7 @@ func (c *AcceleratorTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (* // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -32560,8 +36320,7 @@ type AcceleratorTypesGetCall struct { header_ http.Header } -// Get: Returns the specified accelerator type. Get a list of available -// accelerator types by making a list() request. +// Get: Returns the specified accelerator type. func (r *AcceleratorTypesService) Get(project string, zone string, acceleratorType string) *AcceleratorTypesGetCall { c := &AcceleratorTypesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -32666,7 +36425,7 @@ func (c *AcceleratorTypesGetCall) Do(opts ...googleapi.CallOption) (*Accelerator } return ret, nil // { - // "description": "Returns the specified accelerator type. Get a list of available accelerator types by making a list() request.", + // "description": "Returns the specified accelerator type.", // "httpMethod": "GET", // "id": "compute.acceleratorTypes.get", // "parameterOrder": [ @@ -32731,32 +36490,28 @@ func (r *AcceleratorTypesService) List(project string, zone string) *Accelerator return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AcceleratorTypesListCall) Filter(filter string) *AcceleratorTypesListCall { c.urlParams_.Set("filter", filter) return c @@ -32902,7 +36657,7 @@ func (c *AcceleratorTypesListCall) Do(opts ...googleapi.CallOption) (*Accelerato // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -32992,32 +36747,28 @@ func (r *AddressesService) AggregatedList(project string) *AddressesAggregatedLi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AddressesAggregatedListCall) Filter(filter string) *AddressesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -33161,7 +36912,7 @@ func (c *AddressesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Address // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -33754,32 +37505,28 @@ func (r *AddressesService) List(project string, region string) *AddressesListCal return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AddressesListCall) Filter(filter string) *AddressesListCall { c.urlParams_.Set("filter", filter) return c @@ -33925,7 +37672,7 @@ func (c *AddressesListCall) Do(opts ...googleapi.CallOption) (*AddressList, erro // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -34355,32 +38102,28 @@ func (r *AutoscalersService) AggregatedList(project string) *AutoscalersAggregat return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AutoscalersAggregatedListCall) Filter(filter string) *AutoscalersAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -34524,7 +38267,7 @@ func (c *AutoscalersAggregatedListCall) Do(opts ...googleapi.CallOption) (*Autos // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -34772,7 +38515,7 @@ type AutoscalersGetCall struct { header_ http.Header } -// Get: Returns the specified autoscaler resource. Get a list of +// Get: Returns the specified autoscaler resource. Gets a list of // available autoscalers by making a list() request. func (r *AutoscalersService) Get(project string, zone string, autoscaler string) *AutoscalersGetCall { c := &AutoscalersGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -34878,7 +38621,7 @@ func (c *AutoscalersGetCall) Do(opts ...googleapi.CallOption) (*Autoscaler, erro } return ret, nil // { - // "description": "Returns the specified autoscaler resource. Get a list of available autoscalers by making a list() request.", + // "description": "Returns the specified autoscaler resource. Gets a list of available autoscalers by making a list() request.", // "httpMethod": "GET", // "id": "compute.autoscalers.get", // "parameterOrder": [ @@ -35114,32 +38857,28 @@ func (r *AutoscalersService) List(project string, zone string) *AutoscalersListC return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AutoscalersListCall) Filter(filter string) *AutoscalersListCall { c.urlParams_.Set("filter", filter) return c @@ -35285,7 +39024,7 @@ func (c *AutoscalersListCall) Do(opts ...googleapi.CallOption) (*AutoscalerList, // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -36393,7 +40132,7 @@ type BackendBucketsGetCall struct { header_ http.Header } -// Get: Returns the specified BackendBucket resource. Get a list of +// Get: Returns the specified BackendBucket resource. Gets a list of // available backend buckets by making a list() request. func (r *BackendBucketsService) Get(project string, backendBucket string) *BackendBucketsGetCall { c := &BackendBucketsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -36497,7 +40236,7 @@ func (c *BackendBucketsGetCall) Do(opts ...googleapi.CallOption) (*BackendBucket } return ret, nil // { - // "description": "Returns the specified BackendBucket resource. Get a list of available backend buckets by making a list() request.", + // "description": "Returns the specified BackendBucket resource. Gets a list of available backend buckets by making a list() request.", // "httpMethod": "GET", // "id": "compute.backendBuckets.get", // "parameterOrder": [ @@ -36864,32 +40603,28 @@ func (r *BackendBucketsService) List(project string) *BackendBucketsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *BackendBucketsListCall) Filter(filter string) *BackendBucketsListCall { c.urlParams_.Set("filter", filter) return c @@ -37033,7 +40768,7 @@ func (c *BackendBucketsListCall) Do(opts ...googleapi.CallOption) (*BackendBucke // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -37272,22 +41007,22 @@ func (c *BackendBucketsPatchCall) Do(opts ...googleapi.CallOption) (*Operation, // method id "compute.backendBuckets.setIamPolicy": type BackendBucketsSetIamPolicyCall struct { - s *Service - project string - resource string - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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 *BackendBucketsService) SetIamPolicy(project string, resource string, policy *Policy) *BackendBucketsSetIamPolicyCall { +func (r *BackendBucketsService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *BackendBucketsSetIamPolicyCall { c := &BackendBucketsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project c.resource = resource - c.policy = policy + c.globalsetpolicyrequest = globalsetpolicyrequest return c } @@ -37323,7 +41058,7 @@ func (c *BackendBucketsSetIamPolicyCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) if err != nil { return nil, err } @@ -37403,7 +41138,7 @@ func (c *BackendBucketsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Poli // }, // "path": "{project}/global/backendBuckets/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "GlobalSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -37924,32 +41659,28 @@ func (r *BackendServicesService) AggregatedList(project string) *BackendServices return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *BackendServicesAggregatedListCall) Filter(filter string) *BackendServicesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -38093,7 +41824,7 @@ func (c *BackendServicesAggregatedListCall) Do(opts ...googleapi.CallOption) (*B // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -38498,7 +42229,7 @@ type BackendServicesGetCall struct { header_ http.Header } -// Get: Returns the specified BackendService resource. Get a list of +// Get: Returns the specified BackendService resource. Gets a list of // available backend services by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/backendServices/get func (r *BackendServicesService) Get(project string, backendService string) *BackendServicesGetCall { @@ -38603,7 +42334,7 @@ func (c *BackendServicesGetCall) Do(opts ...googleapi.CallOption) (*BackendServi } return ret, nil // { - // "description": "Returns the specified BackendService resource. Get a list of available backend services by making a list() request.", + // "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", // "httpMethod": "GET", // "id": "compute.backendServices.get", // "parameterOrder": [ @@ -38970,32 +42701,28 @@ func (r *BackendServicesService) List(project string) *BackendServicesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *BackendServicesListCall) Filter(filter string) *BackendServicesListCall { c.urlParams_.Set("filter", filter) return c @@ -39139,7 +42866,7 @@ func (c *BackendServicesListCall) Do(opts ...googleapi.CallOption) (*BackendServ // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -39871,154 +43598,6 @@ func (c *BackendServicesUpdateCall) Do(opts ...googleapi.CallOption) (*Operation } -// method id "compute.clientSslPolicies.testIamPermissions": - -type ClientSslPoliciesTestIamPermissionsCall 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 *ClientSslPoliciesService) TestIamPermissions(project string, resource string, testpermissionsrequest *TestPermissionsRequest) *ClientSslPoliciesTestIamPermissionsCall { - c := &ClientSslPoliciesTestIamPermissionsCall{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 *ClientSslPoliciesTestIamPermissionsCall) Fields(s ...googleapi.Field) *ClientSslPoliciesTestIamPermissionsCall { - 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 *ClientSslPoliciesTestIamPermissionsCall) Context(ctx context.Context) *ClientSslPoliciesTestIamPermissionsCall { - 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 *ClientSslPoliciesTestIamPermissionsCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *ClientSslPoliciesTestIamPermissionsCall) 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}/global/clientSslPolicies/{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, - "resource": c.resource, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.clientSslPolicies.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 *ClientSslPoliciesTestIamPermissionsCall) 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.clientSslPolicies.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 of the resource for this request.", - // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/global/clientSslPolicies/{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.diskTypes.aggregatedList": type DiskTypesAggregatedListCall struct { @@ -40038,32 +43617,28 @@ func (r *DiskTypesService) AggregatedList(project string) *DiskTypesAggregatedLi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DiskTypesAggregatedListCall) Filter(filter string) *DiskTypesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -40207,7 +43782,7 @@ func (c *DiskTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (*DiskTyp // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -40284,7 +43859,7 @@ type DiskTypesGetCall struct { header_ http.Header } -// Get: Returns the specified disk type. Get a list of available disk +// Get: Returns the specified disk type. Gets a list of available disk // types by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/diskTypes/get func (r *DiskTypesService) Get(project string, zone string, diskType string) *DiskTypesGetCall { @@ -40391,7 +43966,7 @@ func (c *DiskTypesGetCall) Do(opts ...googleapi.CallOption) (*DiskType, error) { } return ret, nil // { - // "description": "Returns the specified disk type. Get a list of available disk types by making a list() request.", + // "description": "Returns the specified disk type. Gets a list of available disk types by making a list() request.", // "httpMethod": "GET", // "id": "compute.diskTypes.get", // "parameterOrder": [ @@ -40457,32 +44032,28 @@ func (r *DiskTypesService) List(project string, zone string) *DiskTypesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DiskTypesListCall) Filter(filter string) *DiskTypesListCall { c.urlParams_.Set("filter", filter) return c @@ -40628,7 +44199,7 @@ func (c *DiskTypesListCall) Do(opts ...googleapi.CallOption) (*DiskTypeList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -40699,6 +44270,189 @@ 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/addResourcePolicies") + 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, + "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])?", + // "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 { @@ -40718,32 +44472,28 @@ func (r *DisksService) AggregatedList(project string) *DisksAggregatedListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DisksAggregatedListCall) Filter(filter string) *DisksAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -40887,7 +44637,7 @@ func (c *DisksAggregatedListCall) Do(opts ...googleapi.CallOption) (*DiskAggrega // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -41330,7 +45080,7 @@ type DisksGetCall struct { header_ http.Header } -// Get: Returns a specified persistent disk. Get a list of available +// Get: Returns a specified persistent disk. Gets a list of available // persistent disks by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/disks/get func (r *DisksService) Get(project string, zone string, disk string) *DisksGetCall { @@ -41437,7 +45187,7 @@ func (c *DisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, error) { } return ret, nil // { - // "description": "Returns a specified persistent disk. Get a list of available persistent disks by making a list() request.", + // "description": "Returns a specified persistent disk. Gets a list of available persistent disks by making a list() request.", // "httpMethod": "GET", // "id": "compute.disks.get", // "parameterOrder": [ @@ -41853,32 +45603,28 @@ func (r *DisksService) List(project string, zone string) *DisksListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DisksListCall) Filter(filter string) *DisksListCall { c.urlParams_.Set("filter", filter) return c @@ -42024,7 +45770,7 @@ func (c *DisksListCall) Do(opts ...googleapi.CallOption) (*DiskList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -42095,6 +45841,187 @@ 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/removeResourcePolicies") + 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, + "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])?", + // "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 { @@ -42280,24 +46207,24 @@ 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 - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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, policy *Policy) *DisksSetIamPolicyCall { +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.policy = policy + c.zonesetpolicyrequest = zonesetpolicyrequest return c } @@ -42333,7 +46260,7 @@ func (c *DisksSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) if err != nil { return nil, err } @@ -42422,7 +46349,7 @@ func (c *DisksSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error // }, // "path": "{project}/zones/{zone}/disks/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "ZoneSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -43270,32 +47197,28 @@ func (r *FirewallsService) List(project string) *FirewallsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *FirewallsListCall) Filter(filter string) *FirewallsListCall { c.urlParams_.Set("filter", filter) return c @@ -43439,7 +47362,7 @@ func (c *FirewallsListCall) Do(opts ...googleapi.CallOption) (*FirewallList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -44017,32 +47940,28 @@ func (r *ForwardingRulesService) AggregatedList(project string) *ForwardingRules return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ForwardingRulesAggregatedListCall) Filter(filter string) *ForwardingRulesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -44186,7 +48105,7 @@ func (c *ForwardingRulesAggregatedListCall) Do(opts ...googleapi.CallOption) (*F // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -44779,32 +48698,28 @@ func (r *ForwardingRulesService) List(project string, region string) *Forwarding return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ForwardingRulesListCall) Filter(filter string) *ForwardingRulesListCall { c.urlParams_.Set("filter", filter) return c @@ -44950,7 +48865,7 @@ func (c *ForwardingRulesListCall) Do(opts ...googleapi.CallOption) (*ForwardingR // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -45902,7 +49817,7 @@ type GlobalAddressesGetCall struct { header_ http.Header } -// Get: Returns the specified address resource. Get a list of available +// Get: Returns the specified address resource. Gets a list of available // addresses by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/globalAddresses/get func (r *GlobalAddressesService) Get(project string, address string) *GlobalAddressesGetCall { @@ -46007,7 +49922,7 @@ func (c *GlobalAddressesGetCall) Do(opts ...googleapi.CallOption) (*Address, err } return ret, nil // { - // "description": "Returns the specified address resource. Get a list of available addresses by making a list() request.", + // "description": "Returns the specified address resource. Gets a list of available addresses by making a list() request.", // "httpMethod": "GET", // "id": "compute.globalAddresses.get", // "parameterOrder": [ @@ -46223,32 +50138,28 @@ func (r *GlobalAddressesService) List(project string) *GlobalAddressesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalAddressesListCall) Filter(filter string) *GlobalAddressesListCall { c.urlParams_.Set("filter", filter) return c @@ -46392,7 +50303,7 @@ func (c *GlobalAddressesListCall) Do(opts ...googleapi.CallOption) (*AddressList // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -46924,7 +50835,7 @@ type GlobalForwardingRulesGetCall struct { header_ http.Header } -// Get: Returns the specified GlobalForwardingRule resource. Get a list +// Get: Returns the specified GlobalForwardingRule resource. Gets a list // of available forwarding rules by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/globalForwardingRules/get func (r *GlobalForwardingRulesService) Get(project string, forwardingRule string) *GlobalForwardingRulesGetCall { @@ -47029,7 +50940,7 @@ func (c *GlobalForwardingRulesGetCall) Do(opts ...googleapi.CallOption) (*Forwar } return ret, nil // { - // "description": "Returns the specified GlobalForwardingRule resource. Get a list of available forwarding rules by making a list() request.", + // "description": "Returns the specified GlobalForwardingRule resource. Gets a list of available forwarding rules by making a list() request.", // "httpMethod": "GET", // "id": "compute.globalForwardingRules.get", // "parameterOrder": [ @@ -47246,32 +51157,28 @@ func (r *GlobalForwardingRulesService) List(project string) *GlobalForwardingRul return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalForwardingRulesListCall) Filter(filter string) *GlobalForwardingRulesListCall { c.urlParams_.Set("filter", filter) return c @@ -47415,7 +51322,7 @@ func (c *GlobalForwardingRulesListCall) Do(opts ...googleapi.CallOption) (*Forwa // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -48138,32 +52045,28 @@ func (r *GlobalOperationsService) AggregatedList(project string) *GlobalOperatio return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalOperationsAggregatedListCall) Filter(filter string) *GlobalOperationsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -48307,7 +52210,7 @@ func (c *GlobalOperationsAggregatedListCall) Do(opts ...googleapi.CallOption) (* // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -48492,7 +52395,7 @@ type GlobalOperationsGetCall struct { header_ http.Header } -// Get: Retrieves the specified Operations resource. Get a list of +// Get: Retrieves the specified Operations resource. Gets a list of // operations by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/globalOperations/get func (r *GlobalOperationsService) Get(project string, operation string) *GlobalOperationsGetCall { @@ -48597,7 +52500,7 @@ func (c *GlobalOperationsGetCall) Do(opts ...googleapi.CallOption) (*Operation, } return ret, nil // { - // "description": "Retrieves the specified Operations resource. Get a list of operations by making a list() request.", + // "description": "Retrieves the specified Operations resource. Gets a list of operations by making a list() request.", // "httpMethod": "GET", // "id": "compute.globalOperations.get", // "parameterOrder": [ @@ -48653,32 +52556,28 @@ func (r *GlobalOperationsService) List(project string) *GlobalOperationsListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalOperationsListCall) Filter(filter string) *GlobalOperationsListCall { c.urlParams_.Set("filter", filter) return c @@ -48822,7 +52721,7 @@ func (c *GlobalOperationsListCall) Do(opts ...googleapi.CallOption) (*OperationL // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -48886,6 +52785,400 @@ func (c *GlobalOperationsListCall) Pages(ctx context.Context, f func(*OperationL } } +// method id "compute.globalOperations.wait": + +type GlobalOperationsWaitCall struct { + s *Service + project string + 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 *GlobalOperationsService) Wait(project string, operation string) *GlobalOperationsWaitCall { + c := &GlobalOperationsWaitCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.operation = operation + 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 *GlobalOperationsWaitCall) Fields(s ...googleapi.Field) *GlobalOperationsWaitCall { + 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 *GlobalOperationsWaitCall) Context(ctx context.Context) *GlobalOperationsWaitCall { + 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 *GlobalOperationsWaitCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *GlobalOperationsWaitCall) 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}/global/operations/{operation}/wait") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "operation": c.operation, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.globalOperations.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 *GlobalOperationsWaitCall) 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.globalOperations.wait", + // "parameterOrder": [ + // "project", + // "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" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{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/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 { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves the list of all HealthCheck resources, +// regional and global, available to the specified project. +func (r *HealthChecksService) AggregatedList(project string) *HealthChecksAggregatedListCall { + c := &HealthChecksAggregatedListCall{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 *HealthChecksAggregatedListCall) Filter(filter string) *HealthChecksAggregatedListCall { + 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 *HealthChecksAggregatedListCall) MaxResults(maxResults int64) *HealthChecksAggregatedListCall { + 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 *HealthChecksAggregatedListCall) OrderBy(orderBy string) *HealthChecksAggregatedListCall { + 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 *HealthChecksAggregatedListCall) PageToken(pageToken string) *HealthChecksAggregatedListCall { + 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 *HealthChecksAggregatedListCall) Fields(s ...googleapi.Field) *HealthChecksAggregatedListCall { + 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 *HealthChecksAggregatedListCall) IfNoneMatch(entityTag string) *HealthChecksAggregatedListCall { + 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 *HealthChecksAggregatedListCall) Context(ctx context.Context) *HealthChecksAggregatedListCall { + 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 *HealthChecksAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *HealthChecksAggregatedListCall) 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/healthChecks") + 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.healthChecks.aggregatedList" call. +// Exactly one of *HealthChecksAggregatedList or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *HealthChecksAggregatedList.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 *HealthChecksAggregatedListCall) Do(opts ...googleapi.CallOption) (*HealthChecksAggregatedList, 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 := &HealthChecksAggregatedList{ + 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 HealthCheck resources, regional and global, available to the specified project.", + // "httpMethod": "GET", + // "id": "compute.healthChecks.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/healthChecks", + // "response": { + // "$ref": "HealthChecksAggregatedList" + // }, + // "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 *HealthChecksAggregatedListCall) Pages(ctx context.Context, f func(*HealthChecksAggregatedList) 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.healthChecks.delete": type HealthChecksDeleteCall struct { @@ -49058,7 +53351,7 @@ type HealthChecksGetCall struct { header_ http.Header } -// Get: Returns the specified HealthCheck resource. Get a list of +// Get: Returns the specified HealthCheck resource. Gets a list of // available health checks by making a list() request. func (r *HealthChecksService) Get(project string, healthCheck string) *HealthChecksGetCall { c := &HealthChecksGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -49162,7 +53455,7 @@ func (c *HealthChecksGetCall) Do(opts ...googleapi.CallOption) (*HealthCheck, er } return ret, nil // { - // "description": "Returns the specified HealthCheck resource. Get a list of available health checks by making a list() request.", + // "description": "Returns the specified HealthCheck resource. Gets a list of available health checks by making a list() request.", // "httpMethod": "GET", // "id": "compute.healthChecks.get", // "parameterOrder": [ @@ -49377,32 +53670,28 @@ func (r *HealthChecksService) List(project string) *HealthChecksListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *HealthChecksListCall) Filter(filter string) *HealthChecksListCall { c.urlParams_.Set("filter", filter) return c @@ -49546,7 +53835,7 @@ func (c *HealthChecksListCall) Do(opts ...googleapi.CallOption) (*HealthCheckLis // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -50119,32 +54408,28 @@ func (r *HostTypesService) AggregatedList(project string) *HostTypesAggregatedLi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 @@ -50288,7 +54573,7 @@ func (c *HostTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (*HostTyp // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -50365,7 +54650,7 @@ type HostTypesGetCall struct { header_ http.Header } -// Get: Returns the specified host type. Get a list of available host +// 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)} @@ -50471,7 +54756,7 @@ func (c *HostTypesGetCall) Do(opts ...googleapi.CallOption) (*HostType, error) { } return ret, nil // { - // "description": "Returns the specified host type. Get a list of available host types by making a list() request.", + // "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": [ @@ -50536,32 +54821,28 @@ func (r *HostTypesService) List(project string, zone string) *HostTypesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 @@ -50707,7 +54988,7 @@ func (c *HostTypesListCall) Do(opts ...googleapi.CallOption) (*HostTypeList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -50796,32 +55077,28 @@ func (r *HostsService) AggregatedList(project string) *HostsAggregatedListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 @@ -50965,7 +55242,7 @@ func (c *HostsAggregatedListCall) Do(opts ...googleapi.CallOption) (*HostAggrega // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -51213,7 +55490,7 @@ type HostsGetCall struct { header_ http.Header } -// Get: Returns the specified host. Get a list of available hosts by +// 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)} @@ -51319,7 +55596,7 @@ func (c *HostsGetCall) Do(opts ...googleapi.CallOption) (*Host, error) { } return ret, nil // { - // "description": "Returns the specified host. Get a list of available hosts by making a list() request.", + // "description": "Returns the specified host. Gets a list of available hosts by making a list() request.", // "httpMethod": "GET", // "id": "compute.hosts.get", // "parameterOrder": [ @@ -51717,32 +55994,28 @@ func (r *HostsService) List(project string, zone string) *HostsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 @@ -51888,7 +56161,7 @@ func (c *HostsListCall) Do(opts ...googleapi.CallOption) (*HostList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -51962,24 +56235,24 @@ func (c *HostsListCall) Pages(ctx context.Context, f func(*HostList) error) erro // method id "compute.hosts.setIamPolicy": type HostsSetIamPolicyCall struct { - s *Service - project string - zone string - resource string - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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, policy *Policy) *HostsSetIamPolicyCall { +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.policy = policy + c.zonesetpolicyrequest = zonesetpolicyrequest return c } @@ -52015,7 +56288,7 @@ func (c *HostsSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) if err != nil { return nil, err } @@ -52104,7 +56377,7 @@ func (c *HostsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error // }, // "path": "{project}/zones/{zone}/hosts/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "ZoneSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -52449,7 +56722,7 @@ type HttpHealthChecksGetCall struct { header_ http.Header } -// Get: Returns the specified HttpHealthCheck resource. Get a list of +// Get: Returns the specified HttpHealthCheck resource. Gets a list of // available HTTP health checks by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/httpHealthChecks/get func (r *HttpHealthChecksService) Get(project string, httpHealthCheck string) *HttpHealthChecksGetCall { @@ -52554,7 +56827,7 @@ func (c *HttpHealthChecksGetCall) Do(opts ...googleapi.CallOption) (*HttpHealthC } return ret, nil // { - // "description": "Returns the specified HttpHealthCheck resource. Get a list of available HTTP health checks by making a list() request.", + // "description": "Returns the specified HttpHealthCheck resource. Gets a list of available HTTP health checks by making a list() request.", // "httpMethod": "GET", // "id": "compute.httpHealthChecks.get", // "parameterOrder": [ @@ -52771,32 +57044,28 @@ func (r *HttpHealthChecksService) List(project string) *HttpHealthChecksListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *HttpHealthChecksListCall) Filter(filter string) *HttpHealthChecksListCall { c.urlParams_.Set("filter", filter) return c @@ -52940,7 +57209,7 @@ func (c *HttpHealthChecksListCall) Do(opts ...googleapi.CallOption) (*HttpHealth // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -53669,7 +57938,7 @@ type HttpsHealthChecksGetCall struct { header_ http.Header } -// Get: Returns the specified HttpsHealthCheck resource. Get a list of +// Get: Returns the specified HttpsHealthCheck resource. Gets a list of // available HTTPS health checks by making a list() request. func (r *HttpsHealthChecksService) Get(project string, httpsHealthCheck string) *HttpsHealthChecksGetCall { c := &HttpsHealthChecksGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -53773,7 +58042,7 @@ func (c *HttpsHealthChecksGetCall) Do(opts ...googleapi.CallOption) (*HttpsHealt } return ret, nil // { - // "description": "Returns the specified HttpsHealthCheck resource. Get a list of available HTTPS health checks by making a list() request.", + // "description": "Returns the specified HttpsHealthCheck resource. Gets a list of available HTTPS health checks by making a list() request.", // "httpMethod": "GET", // "id": "compute.httpsHealthChecks.get", // "parameterOrder": [ @@ -53988,32 +58257,28 @@ func (r *HttpsHealthChecksService) List(project string) *HttpsHealthChecksListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *HttpsHealthChecksListCall) Filter(filter string) *HttpsHealthChecksListCall { c.urlParams_.Set("filter", filter) return c @@ -54157,7 +58422,7 @@ func (c *HttpsHealthChecksListCall) Do(opts ...googleapi.CallOption) (*HttpsHeal // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -55059,7 +59324,7 @@ type ImagesGetCall struct { header_ http.Header } -// Get: Returns the specified image. Get a list of available images by +// Get: Returns the specified image. Gets a list of available images by // making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/images/get func (r *ImagesService) Get(project string, image string) *ImagesGetCall { @@ -55164,7 +59429,7 @@ func (c *ImagesGetCall) Do(opts ...googleapi.CallOption) (*Image, error) { } return ret, nil // { - // "description": "Returns the specified image. Get a list of available images by making a list() request.", + // "description": "Returns the specified image. Gets a list of available images by making a list() request.", // "httpMethod": "GET", // "id": "compute.images.get", // "parameterOrder": [ @@ -55705,32 +59970,28 @@ func (r *ImagesService) List(project string) *ImagesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ImagesListCall) Filter(filter string) *ImagesListCall { c.urlParams_.Set("filter", filter) return c @@ -55874,7 +60135,7 @@ func (c *ImagesListCall) Do(opts ...googleapi.CallOption) (*ImageList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -55941,22 +60202,22 @@ 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 - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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, policy *Policy) *ImagesSetIamPolicyCall { +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.policy = policy + c.globalsetpolicyrequest = globalsetpolicyrequest return c } @@ -55992,7 +60253,7 @@ func (c *ImagesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) if err != nil { return nil, err } @@ -56072,7 +60333,7 @@ func (c *ImagesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, erro // }, // "path": "{project}/global/images/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "GlobalSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -56594,32 +60855,28 @@ func (r *InstanceGroupManagersService) AggregatedList(project string) *InstanceG return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupManagersAggregatedListCall) Filter(filter string) *InstanceGroupManagersAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -56764,7 +61021,7 @@ func (c *InstanceGroupManagersAggregatedListCall) Do(opts ...googleapi.CallOptio // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -57364,7 +61621,7 @@ type InstanceGroupManagersDeletePerInstanceConfigsCall struct { header_ http.Header } -// DeletePerInstanceConfigs: Delete selected per-instance configs for +// DeletePerInstanceConfigs: Deletes selected per-instance configs for // the managed instance group. func (r *InstanceGroupManagersService) DeletePerInstanceConfigs(project string, zone string, instanceGroupManager string, instancegroupmanagersdeleteperinstanceconfigsreq *InstanceGroupManagersDeletePerInstanceConfigsReq) *InstanceGroupManagersDeletePerInstanceConfigsCall { c := &InstanceGroupManagersDeletePerInstanceConfigsCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -57463,7 +61720,7 @@ func (c *InstanceGroupManagersDeletePerInstanceConfigsCall) Do(opts ...googleapi } return ret, nil // { - // "description": "Delete selected per-instance configs for the managed instance group.", + // "description": "Deletes selected per-instance configs for the managed instance group.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.deletePerInstanceConfigs", // "parameterOrder": [ @@ -57521,7 +61778,7 @@ type InstanceGroupManagersGetCall struct { } // Get: Returns all of the details about the specified managed instance -// group. Get a list of available managed instance groups by making a +// group. Gets a list of available managed instance groups by making a // list() request. func (r *InstanceGroupManagersService) Get(project string, zone string, instanceGroupManager string) *InstanceGroupManagersGetCall { c := &InstanceGroupManagersGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -57627,7 +61884,7 @@ func (c *InstanceGroupManagersGetCall) Do(opts ...googleapi.CallOption) (*Instan } return ret, nil // { - // "description": "Returns all of the details about the specified managed instance group. Get a list of available managed instance groups by making a list() request.", + // "description": "Returns all of the details about the specified managed instance group. Gets a list of available managed instance groups by making a list() request.", // "httpMethod": "GET", // "id": "compute.instanceGroupManagers.get", // "parameterOrder": [ @@ -57868,32 +62125,28 @@ func (r *InstanceGroupManagersService) List(project string, zone string) *Instan return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupManagersListCall) Filter(filter string) *InstanceGroupManagersListCall { c.urlParams_.Set("filter", filter) return c @@ -58039,7 +62292,7 @@ func (c *InstanceGroupManagersListCall) Do(opts ...googleapi.CallOption) (*Insta // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -58348,32 +62601,28 @@ func (r *InstanceGroupManagersService) ListPerInstanceConfigs(project string, zo return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupManagersListPerInstanceConfigsCall) Filter(filter string) *InstanceGroupManagersListPerInstanceConfigsCall { c.urlParams_.Set("filter", filter) return c @@ -58510,7 +62759,7 @@ func (c *InstanceGroupManagersListPerInstanceConfigsCall) Do(opts ...googleapi.C // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -60614,32 +64863,28 @@ func (r *InstanceGroupsService) AggregatedList(project string) *InstanceGroupsAg return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupsAggregatedListCall) Filter(filter string) *InstanceGroupsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -60783,7 +65028,7 @@ func (c *InstanceGroupsAggregatedListCall) Do(opts ...googleapi.CallOption) (*In // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -61032,7 +65277,7 @@ type InstanceGroupsGetCall struct { header_ http.Header } -// Get: Returns the specified instance group. Get a list of available +// Get: Returns the specified instance group. Gets a list of available // instance groups by making a list() request. func (r *InstanceGroupsService) Get(project string, zone string, instanceGroup string) *InstanceGroupsGetCall { c := &InstanceGroupsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -61138,7 +65383,7 @@ func (c *InstanceGroupsGetCall) Do(opts ...googleapi.CallOption) (*InstanceGroup } return ret, nil // { - // "description": "Returns the specified instance group. Get a list of available instance groups by making a list() request.", + // "description": "Returns the specified instance group. Gets a list of available instance groups by making a list() request.", // "httpMethod": "GET", // "id": "compute.instanceGroups.get", // "parameterOrder": [ @@ -61371,32 +65616,28 @@ func (r *InstanceGroupsService) List(project string, zone string) *InstanceGroup return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupsListCall) Filter(filter string) *InstanceGroupsListCall { c.urlParams_.Set("filter", filter) return c @@ -61542,7 +65783,7 @@ func (c *InstanceGroupsListCall) Do(opts ...googleapi.CallOption) (*InstanceGrou // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -61635,32 +65876,28 @@ func (r *InstanceGroupsService) ListInstances(project string, zone string, insta return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupsListInstancesCall) Filter(filter string) *InstanceGroupsListInstancesCall { c.urlParams_.Set("filter", filter) return c @@ -61800,7 +66037,7 @@ func (c *InstanceGroupsListInstancesCall) Do(opts ...googleapi.CallOption) (*Ins // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -62576,8 +66813,8 @@ type InstanceTemplatesGetCall struct { header_ http.Header } -// Get: Returns the specified instance template. Get a list of available -// instance templates by making a list() request. +// Get: Returns the specified instance template. Gets a list of +// available instance templates by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/instanceTemplates/get func (r *InstanceTemplatesService) Get(project string, instanceTemplate string) *InstanceTemplatesGetCall { c := &InstanceTemplatesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -62681,7 +66918,7 @@ func (c *InstanceTemplatesGetCall) Do(opts ...googleapi.CallOption) (*InstanceTe } return ret, nil // { - // "description": "Returns the specified instance template. Get a list of available instance templates by making a list() request.", + // "description": "Returns the specified instance template. Gets a list of available instance templates by making a list() request.", // "httpMethod": "GET", // "id": "compute.instanceTemplates.get", // "parameterOrder": [ @@ -62901,32 +67138,28 @@ func (r *InstanceTemplatesService) List(project string) *InstanceTemplatesListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceTemplatesListCall) Filter(filter string) *InstanceTemplatesListCall { c.urlParams_.Set("filter", filter) return c @@ -63070,7 +67303,7 @@ func (c *InstanceTemplatesListCall) Do(opts ...googleapi.CallOption) (*InstanceT // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -63473,28 +67706,28 @@ func (c *InstancesAddAccessConfigCall) Do(opts ...googleapi.CallOption) (*Operat } -// method id "compute.instances.addMaintenancePolicies": +// method id "compute.instances.addResourcePolicies": -type InstancesAddMaintenancePoliciesCall struct { - s *Service - project string - zone string - instance string - instancesaddmaintenancepoliciesrequest *InstancesAddMaintenancePoliciesRequest - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header +type InstancesAddResourcePoliciesCall struct { + s *Service + project string + zone string + instance string + instancesaddresourcepoliciesrequest *InstancesAddResourcePoliciesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header } -// AddMaintenancePolicies: Adds existing maintenance policies to an -// instance. You can only add one policy right now which will be applied -// to this instance for scheduling live migrations. -func (r *InstancesService) AddMaintenancePolicies(project string, zone string, instance string, instancesaddmaintenancepoliciesrequest *InstancesAddMaintenancePoliciesRequest) *InstancesAddMaintenancePoliciesCall { - c := &InstancesAddMaintenancePoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// AddResourcePolicies: Adds existing resource policies to an instance. +// You can only add one policy right now which will be applied to this +// instance for scheduling live migrations. +func (r *InstancesService) AddResourcePolicies(project string, zone string, instance string, instancesaddresourcepoliciesrequest *InstancesAddResourcePoliciesRequest) *InstancesAddResourcePoliciesCall { + c := &InstancesAddResourcePoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project c.zone = zone c.instance = instance - c.instancesaddmaintenancepoliciesrequest = instancesaddmaintenancepoliciesrequest + c.instancesaddresourcepoliciesrequest = instancesaddresourcepoliciesrequest return c } @@ -63512,7 +67745,7 @@ func (r *InstancesService) AddMaintenancePolicies(project string, zone string, i // // The request ID must be a valid UUID with the exception that zero UUID // is not supported (00000000-0000-0000-0000-000000000000). -func (c *InstancesAddMaintenancePoliciesCall) RequestId(requestId string) *InstancesAddMaintenancePoliciesCall { +func (c *InstancesAddResourcePoliciesCall) RequestId(requestId string) *InstancesAddResourcePoliciesCall { c.urlParams_.Set("requestId", requestId) return c } @@ -63520,7 +67753,7 @@ func (c *InstancesAddMaintenancePoliciesCall) RequestId(requestId string) *Insta // Fields allows partial responses to be retrieved. See // https://developers.google.com/gdata/docs/2.0/basics#PartialResponse // for more information. -func (c *InstancesAddMaintenancePoliciesCall) Fields(s ...googleapi.Field) *InstancesAddMaintenancePoliciesCall { +func (c *InstancesAddResourcePoliciesCall) Fields(s ...googleapi.Field) *InstancesAddResourcePoliciesCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } @@ -63528,34 +67761,34 @@ func (c *InstancesAddMaintenancePoliciesCall) Fields(s ...googleapi.Field) *Inst // 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 *InstancesAddMaintenancePoliciesCall) Context(ctx context.Context) *InstancesAddMaintenancePoliciesCall { +func (c *InstancesAddResourcePoliciesCall) Context(ctx context.Context) *InstancesAddResourcePoliciesCall { 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 *InstancesAddMaintenancePoliciesCall) Header() http.Header { +func (c *InstancesAddResourcePoliciesCall) Header() http.Header { if c.header_ == nil { c.header_ = make(http.Header) } return c.header_ } -func (c *InstancesAddMaintenancePoliciesCall) doRequest(alt string) (*http.Response, error) { +func (c *InstancesAddResourcePoliciesCall) 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.instancesaddmaintenancepoliciesrequest) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.instancesaddresourcepoliciesrequest) 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}/instances/{instance}/addMaintenancePolicies") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/addResourcePolicies") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("POST", urls, body) req.Header = reqHeaders @@ -63567,14 +67800,14 @@ func (c *InstancesAddMaintenancePoliciesCall) doRequest(alt string) (*http.Respo return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "compute.instances.addMaintenancePolicies" call. +// Do executes the "compute.instances.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 *InstancesAddMaintenancePoliciesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { +func (c *InstancesAddResourcePoliciesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { @@ -63605,9 +67838,9 @@ func (c *InstancesAddMaintenancePoliciesCall) Do(opts ...googleapi.CallOption) ( } return ret, nil // { - // "description": "Adds existing maintenance policies to an instance. You can only add one policy right now which will be applied to this instance for scheduling live migrations.", + // "description": "Adds existing resource policies to an instance. You can only add one policy right now which will be applied to this instance for scheduling live migrations.", // "httpMethod": "POST", - // "id": "compute.instances.addMaintenancePolicies", + // "id": "compute.instances.addResourcePolicies", // "parameterOrder": [ // "project", // "zone", @@ -63641,9 +67874,9 @@ func (c *InstancesAddMaintenancePoliciesCall) Do(opts ...googleapi.CallOption) ( // "type": "string" // } // }, - // "path": "{project}/zones/{zone}/instances/{instance}/addMaintenancePolicies", + // "path": "{project}/zones/{zone}/instances/{instance}/addResourcePolicies", // "request": { - // "$ref": "InstancesAddMaintenancePoliciesRequest" + // "$ref": "InstancesAddResourcePoliciesRequest" // }, // "response": { // "$ref": "Operation" @@ -63675,32 +67908,28 @@ func (r *InstancesService) AggregatedList(project string) *InstancesAggregatedLi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstancesAggregatedListCall) Filter(filter string) *InstancesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -63844,7 +68073,7 @@ func (c *InstancesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Instanc // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -64661,8 +68890,8 @@ type InstancesGetCall struct { header_ http.Header } -// Get: Returns the specified Instance resource. Get a list of available -// instances by making a list() request. +// Get: Returns the specified Instance resource. Gets a list of +// available instances by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/get func (r *InstancesService) Get(project string, zone string, instance string) *InstancesGetCall { c := &InstancesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -64768,7 +68997,7 @@ func (c *InstancesGetCall) Do(opts ...googleapi.CallOption) (*Instance, error) { } return ret, nil // { - // "description": "Returns the specified Instance resource. Get a list of available instances by making a list() request.", + // "description": "Returns the specified Instance resource. Gets a list of available instances by making a list() request.", // "httpMethod": "GET", // "id": "compute.instances.get", // "parameterOrder": [ @@ -65561,32 +69790,28 @@ func (r *InstancesService) List(project string, zone string) *InstancesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstancesListCall) Filter(filter string) *InstancesListCall { c.urlParams_.Set("filter", filter) return c @@ -65732,7 +69957,7 @@ func (c *InstancesListCall) Do(opts ...googleapi.CallOption) (*InstanceList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -65826,32 +70051,28 @@ func (r *InstancesService) ListReferrers(project string, zone string, instance s return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstancesListReferrersCall) Filter(filter string) *InstancesListReferrersCall { c.urlParams_.Set("filter", filter) return c @@ -65999,7 +70220,7 @@ func (c *InstancesListReferrersCall) Do(opts ...googleapi.CallOption) (*Instance // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -66077,27 +70298,26 @@ func (c *InstancesListReferrersCall) Pages(ctx context.Context, f func(*Instance } } -// method id "compute.instances.removeMaintenancePolicies": +// method id "compute.instances.removeResourcePolicies": -type InstancesRemoveMaintenancePoliciesCall struct { - s *Service - project string - zone string - instance string - instancesremovemaintenancepoliciesrequest *InstancesRemoveMaintenancePoliciesRequest - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header +type InstancesRemoveResourcePoliciesCall struct { + s *Service + project string + zone string + instance string + instancesremoveresourcepoliciesrequest *InstancesRemoveResourcePoliciesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header } -// RemoveMaintenancePolicies: Removes maintenance policies from an -// instance. -func (r *InstancesService) RemoveMaintenancePolicies(project string, zone string, instance string, instancesremovemaintenancepoliciesrequest *InstancesRemoveMaintenancePoliciesRequest) *InstancesRemoveMaintenancePoliciesCall { - c := &InstancesRemoveMaintenancePoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// RemoveResourcePolicies: Removes resource policies from an instance. +func (r *InstancesService) RemoveResourcePolicies(project string, zone string, instance string, instancesremoveresourcepoliciesrequest *InstancesRemoveResourcePoliciesRequest) *InstancesRemoveResourcePoliciesCall { + c := &InstancesRemoveResourcePoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project c.zone = zone c.instance = instance - c.instancesremovemaintenancepoliciesrequest = instancesremovemaintenancepoliciesrequest + c.instancesremoveresourcepoliciesrequest = instancesremoveresourcepoliciesrequest return c } @@ -66115,7 +70335,7 @@ func (r *InstancesService) RemoveMaintenancePolicies(project string, zone string // // The request ID must be a valid UUID with the exception that zero UUID // is not supported (00000000-0000-0000-0000-000000000000). -func (c *InstancesRemoveMaintenancePoliciesCall) RequestId(requestId string) *InstancesRemoveMaintenancePoliciesCall { +func (c *InstancesRemoveResourcePoliciesCall) RequestId(requestId string) *InstancesRemoveResourcePoliciesCall { c.urlParams_.Set("requestId", requestId) return c } @@ -66123,7 +70343,7 @@ func (c *InstancesRemoveMaintenancePoliciesCall) RequestId(requestId string) *In // Fields allows partial responses to be retrieved. See // https://developers.google.com/gdata/docs/2.0/basics#PartialResponse // for more information. -func (c *InstancesRemoveMaintenancePoliciesCall) Fields(s ...googleapi.Field) *InstancesRemoveMaintenancePoliciesCall { +func (c *InstancesRemoveResourcePoliciesCall) Fields(s ...googleapi.Field) *InstancesRemoveResourcePoliciesCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } @@ -66131,34 +70351,34 @@ func (c *InstancesRemoveMaintenancePoliciesCall) Fields(s ...googleapi.Field) *I // 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 *InstancesRemoveMaintenancePoliciesCall) Context(ctx context.Context) *InstancesRemoveMaintenancePoliciesCall { +func (c *InstancesRemoveResourcePoliciesCall) Context(ctx context.Context) *InstancesRemoveResourcePoliciesCall { 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 *InstancesRemoveMaintenancePoliciesCall) Header() http.Header { +func (c *InstancesRemoveResourcePoliciesCall) Header() http.Header { if c.header_ == nil { c.header_ = make(http.Header) } return c.header_ } -func (c *InstancesRemoveMaintenancePoliciesCall) doRequest(alt string) (*http.Response, error) { +func (c *InstancesRemoveResourcePoliciesCall) 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.instancesremovemaintenancepoliciesrequest) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.instancesremoveresourcepoliciesrequest) 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}/instances/{instance}/removeMaintenancePolicies") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/removeResourcePolicies") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("POST", urls, body) req.Header = reqHeaders @@ -66170,14 +70390,14 @@ func (c *InstancesRemoveMaintenancePoliciesCall) doRequest(alt string) (*http.Re return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "compute.instances.removeMaintenancePolicies" call. +// Do executes the "compute.instances.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 *InstancesRemoveMaintenancePoliciesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { +func (c *InstancesRemoveResourcePoliciesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { @@ -66208,9 +70428,9 @@ func (c *InstancesRemoveMaintenancePoliciesCall) Do(opts ...googleapi.CallOption } return ret, nil // { - // "description": "Removes maintenance policies from an instance.", + // "description": "Removes resource policies from an instance.", // "httpMethod": "POST", - // "id": "compute.instances.removeMaintenancePolicies", + // "id": "compute.instances.removeResourcePolicies", // "parameterOrder": [ // "project", // "zone", @@ -66244,9 +70464,9 @@ func (c *InstancesRemoveMaintenancePoliciesCall) Do(opts ...googleapi.CallOption // "type": "string" // } // }, - // "path": "{project}/zones/{zone}/instances/{instance}/removeMaintenancePolicies", + // "path": "{project}/zones/{zone}/instances/{instance}/removeResourcePolicies", // "request": { - // "$ref": "InstancesRemoveMaintenancePoliciesRequest" + // "$ref": "InstancesRemoveResourcePoliciesRequest" // }, // "response": { // "$ref": "Operation" @@ -66991,24 +71211,24 @@ func (c *InstancesSetDiskAutoDeleteCall) Do(opts ...googleapi.CallOption) (*Oper // method id "compute.instances.setIamPolicy": type InstancesSetIamPolicyCall struct { - s *Service - project string - zone string - resource string - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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, policy *Policy) *InstancesSetIamPolicyCall { +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.policy = policy + c.zonesetpolicyrequest = zonesetpolicyrequest return c } @@ -67044,7 +71264,7 @@ func (c *InstancesSetIamPolicyCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) if err != nil { return nil, err } @@ -67133,7 +71353,7 @@ func (c *InstancesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, e // }, // "path": "{project}/zones/{zone}/instances/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "ZoneSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -68424,6 +72644,189 @@ func (c *InstancesSetServiceAccountCall) Do(opts ...googleapi.CallOption) (*Oper } +// method id "compute.instances.setShieldedVmIntegrityPolicy": + +type InstancesSetShieldedVmIntegrityPolicyCall struct { + s *Service + project string + zone string + instance string + shieldedvmintegritypolicy *ShieldedVmIntegrityPolicy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// 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. +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 + c.zone = zone + c.instance = instance + c.shieldedvmintegritypolicy = shieldedvmintegritypolicy + 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 *InstancesSetShieldedVmIntegrityPolicyCall) RequestId(requestId string) *InstancesSetShieldedVmIntegrityPolicyCall { + 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 *InstancesSetShieldedVmIntegrityPolicyCall) Fields(s ...googleapi.Field) *InstancesSetShieldedVmIntegrityPolicyCall { + 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 *InstancesSetShieldedVmIntegrityPolicyCall) Context(ctx context.Context) *InstancesSetShieldedVmIntegrityPolicyCall { + 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 *InstancesSetShieldedVmIntegrityPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesSetShieldedVmIntegrityPolicyCall) 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.shieldedvmintegritypolicy) + 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}/instances/{instance}/setShieldedVmIntegrityPolicy") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PATCH", urls, body) + 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.setShieldedVmIntegrityPolicy" 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 *InstancesSetShieldedVmIntegrityPolicyCall) 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 Shielded VM integrity policy for an instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "httpMethod": "PATCH", + // "id": "compute.instances.setShieldedVmIntegrityPolicy", + // "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}/setShieldedVmIntegrityPolicy", + // "request": { + // "$ref": "ShieldedVmIntegrityPolicy" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instances.setTags": type InstancesSetTagsCall struct { @@ -68767,9 +73170,8 @@ type InstancesStartCall struct { header_ http.Header } -// Start: Starts an instance that was stopped using the using the -// instances().stop method. For more information, see Restart an -// instance. +// Start: Starts an instance that was stopped using the instances().stop +// method. For more information, see Restart an instance. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/start func (r *InstancesService) Start(project string, zone string, instance string) *InstancesStartCall { c := &InstancesStartCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -68881,7 +73283,7 @@ func (c *InstancesStartCall) Do(opts ...googleapi.CallOption) (*Operation, error } return ret, nil // { - // "description": "Starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance.", + // "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", // "httpMethod": "POST", // "id": "compute.instances.start", // "parameterOrder": [ @@ -68943,8 +73345,8 @@ type InstancesStartWithEncryptionKeyCall struct { } // StartWithEncryptionKey: Starts an instance that was stopped using the -// using the instances().stop method. For more information, see Restart -// an instance. +// instances().stop method. For more information, see Restart an +// instance. func (r *InstancesService) StartWithEncryptionKey(project string, zone string, instance string, instancesstartwithencryptionkeyrequest *InstancesStartWithEncryptionKeyRequest) *InstancesStartWithEncryptionKeyCall { c := &InstancesStartWithEncryptionKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -69061,7 +73463,7 @@ func (c *InstancesStartWithEncryptionKeyCall) Do(opts ...googleapi.CallOption) ( } return ret, nil // { - // "description": "Starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance.", + // "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", // "httpMethod": "POST", // "id": "compute.instances.startWithEncryptionKey", // "parameterOrder": [ @@ -70234,32 +74636,28 @@ func (r *InterconnectAttachmentsService) AggregatedList(project string) *Interco return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectAttachmentsAggregatedListCall) Filter(filter string) *InterconnectAttachmentsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -70404,7 +74802,7 @@ func (c *InterconnectAttachmentsAggregatedListCall) Do(opts ...googleapi.CallOpt // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -71156,32 +75554,28 @@ func (r *InterconnectAttachmentsService) List(project string, region string) *In return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectAttachmentsListCall) Filter(filter string) *InterconnectAttachmentsListCall { c.urlParams_.Set("filter", filter) return c @@ -71327,7 +75721,7 @@ func (c *InterconnectAttachmentsListCall) Do(opts ...googleapi.CallOption) (*Int // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -71584,24 +75978,24 @@ func (c *InterconnectAttachmentsPatchCall) Do(opts ...googleapi.CallOption) (*Op // method id "compute.interconnectAttachments.setIamPolicy": type InterconnectAttachmentsSetIamPolicyCall struct { - s *Service - project string - region string - resource string - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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 *InterconnectAttachmentsService) SetIamPolicy(project string, region string, resource string, policy *Policy) *InterconnectAttachmentsSetIamPolicyCall { +func (r *InterconnectAttachmentsService) SetIamPolicy(project string, region string, resource string, regionsetpolicyrequest *RegionSetPolicyRequest) *InterconnectAttachmentsSetIamPolicyCall { c := &InterconnectAttachmentsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project c.region = region c.resource = resource - c.policy = policy + c.regionsetpolicyrequest = regionsetpolicyrequest return c } @@ -71637,7 +76031,7 @@ func (c *InterconnectAttachmentsSetIamPolicyCall) doRequest(alt string) (*http.R } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.regionsetpolicyrequest) if err != nil { return nil, err } @@ -71726,7 +76120,7 @@ func (c *InterconnectAttachmentsSetIamPolicyCall) Do(opts ...googleapi.CallOptio // }, // "path": "{project}/regions/{region}/interconnectAttachments/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "RegionSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -72092,8 +76486,8 @@ type InterconnectLocationsGetCall struct { header_ http.Header } -// Get: Returns the details for the specified interconnect location. Get -// a list of available interconnect locations by making a list() +// Get: Returns the details for the specified interconnect location. +// Gets a list of available interconnect locations by making a list() // request. func (r *InterconnectLocationsService) Get(project string, interconnectLocation string) *InterconnectLocationsGetCall { c := &InterconnectLocationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -72197,7 +76591,7 @@ func (c *InterconnectLocationsGetCall) Do(opts ...googleapi.CallOption) (*Interc } return ret, nil // { - // "description": "Returns the details for the specified interconnect location. Get a list of available interconnect locations by making a list() request.", + // "description": "Returns the details for the specified interconnect location. Gets a list of available interconnect locations by making a list() request.", // "httpMethod": "GET", // "id": "compute.interconnectLocations.get", // "parameterOrder": [ @@ -72252,32 +76646,28 @@ func (r *InterconnectLocationsService) List(project string) *InterconnectLocatio return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectLocationsListCall) Filter(filter string) *InterconnectLocationsListCall { c.urlParams_.Set("filter", filter) return c @@ -72421,7 +76811,7 @@ func (c *InterconnectLocationsListCall) Do(opts ...googleapi.CallOption) (*Inter // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -73276,32 +77666,28 @@ func (r *InterconnectsService) List(project string) *InterconnectsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectsListCall) Filter(filter string) *InterconnectsListCall { c.urlParams_.Set("filter", filter) return c @@ -73445,7 +77831,7 @@ func (c *InterconnectsListCall) Do(opts ...googleapi.CallOption) (*InterconnectL // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -73684,22 +78070,22 @@ func (c *InterconnectsPatchCall) Do(opts ...googleapi.CallOption) (*Operation, e // method id "compute.interconnects.setIamPolicy": type InterconnectsSetIamPolicyCall struct { - s *Service - project string - resource string - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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 *InterconnectsService) SetIamPolicy(project string, resource string, policy *Policy) *InterconnectsSetIamPolicyCall { +func (r *InterconnectsService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *InterconnectsSetIamPolicyCall { c := &InterconnectsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project c.resource = resource - c.policy = policy + c.globalsetpolicyrequest = globalsetpolicyrequest return c } @@ -73735,7 +78121,7 @@ func (c *InterconnectsSetIamPolicyCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) if err != nil { return nil, err } @@ -73815,7 +78201,7 @@ func (c *InterconnectsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Polic // }, // "path": "{project}/global/interconnects/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "GlobalSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -74430,22 +78816,22 @@ func (c *LicenseCodesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy // method id "compute.licenseCodes.setIamPolicy": type LicenseCodesSetIamPolicyCall struct { - s *Service - project string - resource string - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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 *LicenseCodesService) SetIamPolicy(project string, resource string, policy *Policy) *LicenseCodesSetIamPolicyCall { +func (r *LicenseCodesService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *LicenseCodesSetIamPolicyCall { c := &LicenseCodesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project c.resource = resource - c.policy = policy + c.globalsetpolicyrequest = globalsetpolicyrequest return c } @@ -74481,7 +78867,7 @@ func (c *LicenseCodesSetIamPolicyCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) if err != nil { return nil, err } @@ -74561,7 +78947,7 @@ func (c *LicenseCodesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy // }, // "path": "{project}/global/licenseCodes/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "GlobalSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -75362,7 +79748,7 @@ type LicensesListCall struct { // List: Retrieves the list of licenses available in the specified // project. This method does not get any licenses that belong to other // projects, including licenses attached to publicly-available images, -// like Debian 8. If you want to get a list of publicly-available +// like Debian 9. If you want to get a list of publicly-available // licenses, use this method to make a request to the respective image // project, such as debian-cloud or windows-cloud. func (r *LicensesService) List(project string) *LicensesListCall { @@ -75371,32 +79757,28 @@ func (r *LicensesService) List(project string) *LicensesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *LicensesListCall) Filter(filter string) *LicensesListCall { c.urlParams_.Set("filter", filter) return c @@ -75532,7 +79914,7 @@ func (c *LicensesListCall) Do(opts ...googleapi.CallOption) (*LicensesListRespon } return ret, nil // { - // "description": "Retrieves the list of licenses available in the specified project. This method does not get any licenses that belong to other projects, including licenses attached to publicly-available images, like Debian 8. If you want to get a list of publicly-available licenses, use this method to make a request to the respective image project, such as debian-cloud or windows-cloud.", + // "description": "Retrieves the list of licenses available in the specified project. This method does not get any licenses that belong to other projects, including licenses attached to publicly-available images, like Debian 9. If you want to get a list of publicly-available licenses, use this method to make a request to the respective image project, such as debian-cloud or windows-cloud.", // "httpMethod": "GET", // "id": "compute.licenses.list", // "parameterOrder": [ @@ -75540,7 +79922,7 @@ func (c *LicensesListCall) Do(opts ...googleapi.CallOption) (*LicensesListRespon // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -75607,22 +79989,22 @@ func (c *LicensesListCall) Pages(ctx context.Context, f func(*LicensesListRespon // method id "compute.licenses.setIamPolicy": type LicensesSetIamPolicyCall struct { - s *Service - project string - resource string - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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, policy *Policy) *LicensesSetIamPolicyCall { +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.policy = policy + c.globalsetpolicyrequest = globalsetpolicyrequest return c } @@ -75658,7 +80040,7 @@ func (c *LicensesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) if err != nil { return nil, err } @@ -75738,7 +80120,7 @@ func (c *LicensesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, er // }, // "path": "{project}/global/licenses/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "GlobalSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -75918,32 +80300,28 @@ func (r *MachineTypesService) AggregatedList(project string) *MachineTypesAggreg return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *MachineTypesAggregatedListCall) Filter(filter string) *MachineTypesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -76087,7 +80465,7 @@ func (c *MachineTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Mach // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -76164,7 +80542,7 @@ type MachineTypesGetCall struct { header_ http.Header } -// Get: Returns the specified machine type. Get a list of available +// Get: Returns the specified machine type. Gets a list of available // machine types by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/machineTypes/get func (r *MachineTypesService) Get(project string, zone string, machineType string) *MachineTypesGetCall { @@ -76271,7 +80649,7 @@ func (c *MachineTypesGetCall) Do(opts ...googleapi.CallOption) (*MachineType, er } return ret, nil // { - // "description": "Returns the specified machine type. Get a list of available machine types by making a list() request.", + // "description": "Returns the specified machine type. Gets a list of available machine types by making a list() request.", // "httpMethod": "GET", // "id": "compute.machineTypes.get", // "parameterOrder": [ @@ -76337,32 +80715,28 @@ func (r *MachineTypesService) List(project string, zone string) *MachineTypesLis return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *MachineTypesListCall) Filter(filter string) *MachineTypesListCall { c.urlParams_.Set("filter", filter) return c @@ -76508,7 +80882,7 @@ func (c *MachineTypesListCall) Do(opts ...googleapi.CallOption) (*MachineTypeLis // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -76579,1503 +80953,6 @@ func (c *MachineTypesListCall) Pages(ctx context.Context, f func(*MachineTypeLis } } -// method id "compute.maintenancePolicies.aggregatedList": - -type MaintenancePoliciesAggregatedListCall struct { - s *Service - project string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// AggregatedList: Retrieves an aggregated list of maintenance policies. -func (r *MaintenancePoliciesService) AggregatedList(project string) *MaintenancePoliciesAggregatedListCall { - c := &MaintenancePoliciesAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - return c -} - -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. -// -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. -// -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. -// -// To filter on multiple expressions, provide each separate expression -// within parentheses. For example, (scheduling.automaticRestart eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. -func (c *MaintenancePoliciesAggregatedListCall) Filter(filter string) *MaintenancePoliciesAggregatedListCall { - 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 *MaintenancePoliciesAggregatedListCall) MaxResults(maxResults int64) *MaintenancePoliciesAggregatedListCall { - 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 *MaintenancePoliciesAggregatedListCall) OrderBy(orderBy string) *MaintenancePoliciesAggregatedListCall { - 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 *MaintenancePoliciesAggregatedListCall) PageToken(pageToken string) *MaintenancePoliciesAggregatedListCall { - 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 *MaintenancePoliciesAggregatedListCall) Fields(s ...googleapi.Field) *MaintenancePoliciesAggregatedListCall { - 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 *MaintenancePoliciesAggregatedListCall) IfNoneMatch(entityTag string) *MaintenancePoliciesAggregatedListCall { - 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 *MaintenancePoliciesAggregatedListCall) Context(ctx context.Context) *MaintenancePoliciesAggregatedListCall { - 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 *MaintenancePoliciesAggregatedListCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *MaintenancePoliciesAggregatedListCall) 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/maintenancePolicies") - 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.maintenancePolicies.aggregatedList" call. -// Exactly one of *MaintenancePolicyAggregatedList or error will be -// non-nil. Any non-2xx status code is an error. Response headers are in -// either *MaintenancePolicyAggregatedList.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 *MaintenancePoliciesAggregatedListCall) Do(opts ...googleapi.CallOption) (*MaintenancePolicyAggregatedList, 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 := &MaintenancePolicyAggregatedList{ - 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 maintenance policies.", - // "httpMethod": "GET", - // "id": "compute.maintenancePolicies.aggregatedList", - // "parameterOrder": [ - // "project" - // ], - // "parameters": { - // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", - // "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/maintenancePolicies", - // "response": { - // "$ref": "MaintenancePolicyAggregatedList" - // }, - // "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 *MaintenancePoliciesAggregatedListCall) Pages(ctx context.Context, f func(*MaintenancePolicyAggregatedList) 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.maintenancePolicies.delete": - -type MaintenancePoliciesDeleteCall struct { - s *Service - project string - region string - maintenancePolicy string - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header -} - -// Delete: Deletes the specified maintenance policy. -func (r *MaintenancePoliciesService) Delete(project string, region string, maintenancePolicy string) *MaintenancePoliciesDeleteCall { - c := &MaintenancePoliciesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.region = region - c.maintenancePolicy = maintenancePolicy - 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 *MaintenancePoliciesDeleteCall) RequestId(requestId string) *MaintenancePoliciesDeleteCall { - 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 *MaintenancePoliciesDeleteCall) Fields(s ...googleapi.Field) *MaintenancePoliciesDeleteCall { - 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 *MaintenancePoliciesDeleteCall) Context(ctx context.Context) *MaintenancePoliciesDeleteCall { - 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 *MaintenancePoliciesDeleteCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *MaintenancePoliciesDeleteCall) 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}/regions/{region}/maintenancePolicies/{maintenancePolicy}") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - "region": c.region, - "maintenancePolicy": c.maintenancePolicy, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.maintenancePolicies.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 *MaintenancePoliciesDeleteCall) 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 maintenance policy.", - // "httpMethod": "DELETE", - // "id": "compute.maintenancePolicies.delete", - // "parameterOrder": [ - // "project", - // "region", - // "maintenancePolicy" - // ], - // "parameters": { - // "maintenancePolicy": { - // "description": "Name of the maintenance policy 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": "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}/maintenancePolicies/{maintenancePolicy}", - // "response": { - // "$ref": "Operation" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute" - // ] - // } - -} - -// method id "compute.maintenancePolicies.get": - -type MaintenancePoliciesGetCall struct { - s *Service - project string - region string - maintenancePolicy string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// Get: Retrieves all information of the specified maintenance policy. -func (r *MaintenancePoliciesService) Get(project string, region string, maintenancePolicy string) *MaintenancePoliciesGetCall { - c := &MaintenancePoliciesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.region = region - c.maintenancePolicy = maintenancePolicy - 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 *MaintenancePoliciesGetCall) Fields(s ...googleapi.Field) *MaintenancePoliciesGetCall { - 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 *MaintenancePoliciesGetCall) IfNoneMatch(entityTag string) *MaintenancePoliciesGetCall { - 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 *MaintenancePoliciesGetCall) Context(ctx context.Context) *MaintenancePoliciesGetCall { - 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 *MaintenancePoliciesGetCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *MaintenancePoliciesGetCall) 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}/regions/{region}/maintenancePolicies/{maintenancePolicy}") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - "region": c.region, - "maintenancePolicy": c.maintenancePolicy, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.maintenancePolicies.get" call. -// Exactly one of *MaintenancePolicy or error will be non-nil. Any -// non-2xx status code is an error. Response headers are in either -// *MaintenancePolicy.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 *MaintenancePoliciesGetCall) Do(opts ...googleapi.CallOption) (*MaintenancePolicy, 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 := &MaintenancePolicy{ - 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 maintenance policy.", - // "httpMethod": "GET", - // "id": "compute.maintenancePolicies.get", - // "parameterOrder": [ - // "project", - // "region", - // "maintenancePolicy" - // ], - // "parameters": { - // "maintenancePolicy": { - // "description": "Name of the maintenance policy 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" - // }, - // "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}/maintenancePolicies/{maintenancePolicy}", - // "response": { - // "$ref": "MaintenancePolicy" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute", - // "https://www.googleapis.com/auth/compute.readonly" - // ] - // } - -} - -// method id "compute.maintenancePolicies.getIamPolicy": - -type MaintenancePoliciesGetIamPolicyCall 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 *MaintenancePoliciesService) GetIamPolicy(project string, region string, resource string) *MaintenancePoliciesGetIamPolicyCall { - c := &MaintenancePoliciesGetIamPolicyCall{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 *MaintenancePoliciesGetIamPolicyCall) Fields(s ...googleapi.Field) *MaintenancePoliciesGetIamPolicyCall { - 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 *MaintenancePoliciesGetIamPolicyCall) IfNoneMatch(entityTag string) *MaintenancePoliciesGetIamPolicyCall { - 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 *MaintenancePoliciesGetIamPolicyCall) Context(ctx context.Context) *MaintenancePoliciesGetIamPolicyCall { - 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 *MaintenancePoliciesGetIamPolicyCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *MaintenancePoliciesGetIamPolicyCall) 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}/regions/{region}/maintenancePolicies/{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, - "region": c.region, - "resource": c.resource, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.maintenancePolicies.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 *MaintenancePoliciesGetIamPolicyCall) 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.maintenancePolicies.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 of the resource for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/regions/{region}/maintenancePolicies/{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.maintenancePolicies.insert": - -type MaintenancePoliciesInsertCall struct { - s *Service - project string - region string - maintenancepolicy *MaintenancePolicy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header -} - -// Insert: Creates a new maintenance policy. -func (r *MaintenancePoliciesService) Insert(project string, region string, maintenancepolicy *MaintenancePolicy) *MaintenancePoliciesInsertCall { - c := &MaintenancePoliciesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.region = region - c.maintenancepolicy = maintenancepolicy - 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 *MaintenancePoliciesInsertCall) RequestId(requestId string) *MaintenancePoliciesInsertCall { - 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 *MaintenancePoliciesInsertCall) Fields(s ...googleapi.Field) *MaintenancePoliciesInsertCall { - 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 *MaintenancePoliciesInsertCall) Context(ctx context.Context) *MaintenancePoliciesInsertCall { - 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 *MaintenancePoliciesInsertCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *MaintenancePoliciesInsertCall) 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.maintenancepolicy) - if err != nil { - return nil, err - } - reqHeaders.Set("Content-Type", "application/json") - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/maintenancePolicies") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) - 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.maintenancePolicies.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 *MaintenancePoliciesInsertCall) 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 maintenance policy.", - // "httpMethod": "POST", - // "id": "compute.maintenancePolicies.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}/maintenancePolicies", - // "request": { - // "$ref": "MaintenancePolicy" - // }, - // "response": { - // "$ref": "Operation" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute" - // ] - // } - -} - -// method id "compute.maintenancePolicies.list": - -type MaintenancePoliciesListCall struct { - s *Service - project string - region string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// List: List all the maintenance policies that have been configured for -// the specified project in specified region. -func (r *MaintenancePoliciesService) List(project string, region string) *MaintenancePoliciesListCall { - c := &MaintenancePoliciesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.region = region - return c -} - -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. -// -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. -// -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. -// -// To filter on multiple expressions, provide each separate expression -// within parentheses. For example, (scheduling.automaticRestart eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. -func (c *MaintenancePoliciesListCall) Filter(filter string) *MaintenancePoliciesListCall { - 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 *MaintenancePoliciesListCall) MaxResults(maxResults int64) *MaintenancePoliciesListCall { - 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 *MaintenancePoliciesListCall) OrderBy(orderBy string) *MaintenancePoliciesListCall { - 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 *MaintenancePoliciesListCall) PageToken(pageToken string) *MaintenancePoliciesListCall { - 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 *MaintenancePoliciesListCall) Fields(s ...googleapi.Field) *MaintenancePoliciesListCall { - 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 *MaintenancePoliciesListCall) IfNoneMatch(entityTag string) *MaintenancePoliciesListCall { - 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 *MaintenancePoliciesListCall) Context(ctx context.Context) *MaintenancePoliciesListCall { - 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 *MaintenancePoliciesListCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *MaintenancePoliciesListCall) 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}/regions/{region}/maintenancePolicies") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - 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.maintenancePolicies.list" call. -// Exactly one of *MaintenancePoliciesList or error will be non-nil. Any -// non-2xx status code is an error. Response headers are in either -// *MaintenancePoliciesList.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 *MaintenancePoliciesListCall) Do(opts ...googleapi.CallOption) (*MaintenancePoliciesList, 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 := &MaintenancePoliciesList{ - 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 maintenance policies that have been configured for the specified project in specified region.", - // "httpMethod": "GET", - // "id": "compute.maintenancePolicies.list", - // "parameterOrder": [ - // "project", - // "region" - // ], - // "parameters": { - // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", - // "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}/maintenancePolicies", - // "response": { - // "$ref": "MaintenancePoliciesList" - // }, - // "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 *MaintenancePoliciesListCall) Pages(ctx context.Context, f func(*MaintenancePoliciesList) 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.maintenancePolicies.setIamPolicy": - -type MaintenancePoliciesSetIamPolicyCall struct { - s *Service - project string - region string - resource string - policy *Policy - 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 *MaintenancePoliciesService) SetIamPolicy(project string, region string, resource string, policy *Policy) *MaintenancePoliciesSetIamPolicyCall { - c := &MaintenancePoliciesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.region = region - c.resource = resource - c.policy = policy - 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 *MaintenancePoliciesSetIamPolicyCall) Fields(s ...googleapi.Field) *MaintenancePoliciesSetIamPolicyCall { - 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 *MaintenancePoliciesSetIamPolicyCall) Context(ctx context.Context) *MaintenancePoliciesSetIamPolicyCall { - 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 *MaintenancePoliciesSetIamPolicyCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *MaintenancePoliciesSetIamPolicyCall) 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.policy) - if err != nil { - return nil, err - } - reqHeaders.Set("Content-Type", "application/json") - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/maintenancePolicies/{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, - "region": c.region, - "resource": c.resource, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.maintenancePolicies.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 *MaintenancePoliciesSetIamPolicyCall) 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.maintenancePolicies.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 of the resource for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/regions/{region}/maintenancePolicies/{resource}/setIamPolicy", - // "request": { - // "$ref": "Policy" - // }, - // "response": { - // "$ref": "Policy" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute" - // ] - // } - -} - -// method id "compute.maintenancePolicies.testIamPermissions": - -type MaintenancePoliciesTestIamPermissionsCall 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 *MaintenancePoliciesService) TestIamPermissions(project string, region string, resource string, testpermissionsrequest *TestPermissionsRequest) *MaintenancePoliciesTestIamPermissionsCall { - c := &MaintenancePoliciesTestIamPermissionsCall{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 *MaintenancePoliciesTestIamPermissionsCall) Fields(s ...googleapi.Field) *MaintenancePoliciesTestIamPermissionsCall { - 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 *MaintenancePoliciesTestIamPermissionsCall) Context(ctx context.Context) *MaintenancePoliciesTestIamPermissionsCall { - 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 *MaintenancePoliciesTestIamPermissionsCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *MaintenancePoliciesTestIamPermissionsCall) 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}/regions/{region}/maintenancePolicies/{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, - "region": c.region, - "resource": c.resource, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.maintenancePolicies.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 *MaintenancePoliciesTestIamPermissionsCall) 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.maintenancePolicies.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 of the resource for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/regions/{region}/maintenancePolicies/{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.networkEndpointGroups.aggregatedList": type NetworkEndpointGroupsAggregatedListCall struct { @@ -78095,32 +80972,28 @@ func (r *NetworkEndpointGroupsService) AggregatedList(project string) *NetworkEn return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *NetworkEndpointGroupsAggregatedListCall) Filter(filter string) *NetworkEndpointGroupsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -78265,7 +81138,7 @@ func (c *NetworkEndpointGroupsAggregatedListCall) Do(opts ...googleapi.CallOptio // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -78874,7 +81747,7 @@ type NetworkEndpointGroupsGetCall struct { header_ http.Header } -// Get: Returns the specified network endpoint group. Get a list of +// Get: Returns the specified network endpoint group. Gets a list of // available network endpoint groups by making a list() request. func (r *NetworkEndpointGroupsService) Get(project string, zone string, networkEndpointGroup string) *NetworkEndpointGroupsGetCall { c := &NetworkEndpointGroupsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -78980,7 +81853,7 @@ func (c *NetworkEndpointGroupsGetCall) Do(opts ...googleapi.CallOption) (*Networ } return ret, nil // { - // "description": "Returns the specified network endpoint group. Get a list of available network endpoint groups by making a list() request.", + // "description": "Returns the specified network endpoint group. Gets a list of available network endpoint groups by making a list() request.", // "httpMethod": "GET", // "id": "compute.networkEndpointGroups.get", // "parameterOrder": [ @@ -79213,32 +82086,28 @@ func (r *NetworkEndpointGroupsService) List(project string, zone string) *Networ return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *NetworkEndpointGroupsListCall) Filter(filter string) *NetworkEndpointGroupsListCall { c.urlParams_.Set("filter", filter) return c @@ -79384,7 +82253,7 @@ func (c *NetworkEndpointGroupsListCall) Do(opts ...googleapi.CallOption) (*Netwo // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -79467,7 +82336,7 @@ type NetworkEndpointGroupsListNetworkEndpointsCall struct { header_ http.Header } -// ListNetworkEndpoints: List the network endpoints in the specified +// ListNetworkEndpoints: Lists the network endpoints in the specified // network endpoint group. func (r *NetworkEndpointGroupsService) ListNetworkEndpoints(project string, zone string, networkEndpointGroup string, networkendpointgroupslistendpointsrequest *NetworkEndpointGroupsListEndpointsRequest) *NetworkEndpointGroupsListNetworkEndpointsCall { c := &NetworkEndpointGroupsListNetworkEndpointsCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -79478,32 +82347,28 @@ func (r *NetworkEndpointGroupsService) ListNetworkEndpoints(project string, zone return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *NetworkEndpointGroupsListNetworkEndpointsCall) Filter(filter string) *NetworkEndpointGroupsListNetworkEndpointsCall { c.urlParams_.Set("filter", filter) return c @@ -79635,7 +82500,7 @@ func (c *NetworkEndpointGroupsListNetworkEndpointsCall) Do(opts ...googleapi.Cal } return ret, nil // { - // "description": "List the network endpoints in the specified network endpoint group.", + // "description": "Lists the network endpoints in the specified network endpoint group.", // "httpMethod": "POST", // "id": "compute.networkEndpointGroups.listNetworkEndpoints", // "parameterOrder": [ @@ -79645,7 +82510,7 @@ func (c *NetworkEndpointGroupsListNetworkEndpointsCall) Do(opts ...googleapi.Cal // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -80226,7 +83091,7 @@ type NetworksGetCall struct { header_ http.Header } -// Get: Returns the specified network. Get a list of available networks +// Get: Returns the specified network. Gets a list of available networks // by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/networks/get func (r *NetworksService) Get(project string, network string) *NetworksGetCall { @@ -80331,7 +83196,7 @@ func (c *NetworksGetCall) Do(opts ...googleapi.CallOption) (*Network, error) { } return ret, nil // { - // "description": "Returns the specified network. Get a list of available networks by making a list() request.", + // "description": "Returns the specified network. Gets a list of available networks by making a list() request.", // "httpMethod": "GET", // "id": "compute.networks.get", // "parameterOrder": [ @@ -80548,32 +83413,28 @@ func (r *NetworksService) List(project string) *NetworksListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *NetworksListCall) Filter(filter string) *NetworksListCall { c.urlParams_.Set("filter", filter) return c @@ -80717,7 +83578,7 @@ func (c *NetworksListCall) Do(opts ...googleapi.CallOption) (*NetworkList, error // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -80793,7 +83654,7 @@ type NetworksListIpOwnersCall struct { header_ http.Header } -// ListIpOwners: List the internal IP owners in the specified network. +// ListIpOwners: Lists the internal IP owners in the specified network. func (r *NetworksService) ListIpOwners(project string, network string) *NetworksListIpOwnersCall { c := &NetworksListIpOwnersCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -80801,32 +83662,28 @@ func (r *NetworksService) ListIpOwners(project string, network string) *Networks return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *NetworksListIpOwnersCall) Filter(filter string) *NetworksListIpOwnersCall { c.urlParams_.Set("filter", filter) return c @@ -80998,7 +83855,7 @@ func (c *NetworksListIpOwnersCall) Do(opts ...googleapi.CallOption) (*IpOwnerLis } return ret, nil // { - // "description": "List the internal IP owners in the specified network.", + // "description": "Lists the internal IP owners in the specified network.", // "httpMethod": "GET", // "id": "compute.networks.listIpOwners", // "parameterOrder": [ @@ -81007,7 +83864,7 @@ func (c *NetworksListIpOwnersCall) Do(opts ...googleapi.CallOption) (*IpOwnerLis // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -81756,6 +84613,949 @@ func (c *NetworksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Test } +// 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/addNodes") + 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, + "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 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}/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. +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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeGroups") + 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.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.", + // "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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}") + 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, + "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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/deleteNodes") + 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, + "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. +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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}") + 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, + "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.", + // "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 { @@ -81919,27 +85719,466 @@ func (c *NodeGroupsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, } -// method id "compute.nodeGroups.setIamPolicy": +// method id "compute.nodeGroups.insert": -type NodeGroupsSetIamPolicyCall struct { +type NodeGroupsInsertCall struct { s *Service project string zone string - resource string - policy *Policy + 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups") + 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.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. +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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups") + 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.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.", + // "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.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, policy *Policy) *NodeGroupsSetIamPolicyCall { +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.policy = policy + c.zonesetpolicyrequest = zonesetpolicyrequest return c } @@ -81975,7 +86214,7 @@ func (c *NodeGroupsSetIamPolicyCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) if err != nil { return nil, err } @@ -82064,7 +86303,7 @@ func (c *NodeGroupsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, // }, // "path": "{project}/zones/{zone}/nodeGroups/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "ZoneSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -82077,6 +86316,187 @@ func (c *NodeGroupsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, } +// 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/setNodeTemplate") + 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, + "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 { @@ -82236,6 +86656,587 @@ func (c *NodeGroupsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Te } +// 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeTemplates") + 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.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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{nodeTemplate}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", urls, body) + 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{nodeTemplate}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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 { @@ -82399,27 +87400,457 @@ func (c *NodeTemplatesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Polic } +// 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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 - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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, policy *Policy) *NodeTemplatesSetIamPolicyCall { +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.policy = policy + c.regionsetpolicyrequest = regionsetpolicyrequest return c } @@ -82455,7 +87886,7 @@ func (c *NodeTemplatesSetIamPolicyCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.regionsetpolicyrequest) if err != nil { return nil, err } @@ -82544,7 +87975,7 @@ func (c *NodeTemplatesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Polic // }, // "path": "{project}/regions/{region}/nodeTemplates/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "RegionSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -82716,6 +88147,675 @@ func (c *NodeTemplatesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) ( } +// 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeTypes") + 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.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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeTypes/{nodeType}") + 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, + "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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeTypes") + 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.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 { @@ -83487,7 +89587,7 @@ type ProjectsGetXpnHostCall struct { header_ http.Header } -// GetXpnHost: Get the shared VPC host project that this project links +// GetXpnHost: Gets the shared VPC host project that this project links // to. May be empty if no link exists. func (r *ProjectsService) GetXpnHost(project string) *ProjectsGetXpnHostCall { c := &ProjectsGetXpnHostCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -83589,7 +89689,7 @@ func (c *ProjectsGetXpnHostCall) Do(opts ...googleapi.CallOption) (*Project, err } return ret, nil // { - // "description": "Get the shared VPC host project that this project links to. May be empty if no link exists.", + // "description": "Gets the shared VPC host project that this project links to. May be empty if no link exists.", // "httpMethod": "GET", // "id": "compute.projects.getXpnHost", // "parameterOrder": [ @@ -83627,7 +89727,7 @@ type ProjectsGetXpnResourcesCall struct { header_ http.Header } -// GetXpnResources: Get service resources (a.k.a service project) +// GetXpnResources: Gets service resources (a.k.a service project) // associated with this host project. func (r *ProjectsService) GetXpnResources(project string) *ProjectsGetXpnResourcesCall { c := &ProjectsGetXpnResourcesCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -83753,7 +89853,7 @@ func (c *ProjectsGetXpnResourcesCall) Do(opts ...googleapi.CallOption) (*Project } return ret, nil // { - // "description": "Get service resources (a.k.a service project) associated with this host project.", + // "description": "Gets service resources (a.k.a service project) associated with this host project.", // "httpMethod": "GET", // "id": "compute.projects.getXpnResources", // "parameterOrder": [ @@ -83831,7 +89931,7 @@ type ProjectsListXpnHostsCall struct { header_ http.Header } -// ListXpnHosts: List all shared VPC host projects visible to the user +// ListXpnHosts: Lists all shared VPC host projects visible to the user // in an organization. func (r *ProjectsService) ListXpnHosts(project string, projectslistxpnhostsrequest *ProjectsListXpnHostsRequest) *ProjectsListXpnHostsCall { c := &ProjectsListXpnHostsCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -83950,7 +90050,7 @@ func (c *ProjectsListXpnHostsCall) Do(opts ...googleapi.CallOption) (*XpnHostLis } return ret, nil // { - // "description": "List all shared VPC host projects visible to the user in an organization.", + // "description": "Lists all shared VPC host projects visible to the user in an organization.", // "httpMethod": "POST", // "id": "compute.projects.listXpnHosts", // "parameterOrder": [ @@ -85514,32 +91614,28 @@ func (r *RegionAutoscalersService) List(project string, region string) *RegionAu return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionAutoscalersListCall) Filter(filter string) *RegionAutoscalersListCall { c.urlParams_.Set("filter", filter) return c @@ -85685,7 +91781,7 @@ func (c *RegionAutoscalersListCall) Do(opts ...googleapi.CallOption) (*RegionAut // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -86970,32 +93066,28 @@ func (r *RegionBackendServicesService) List(project string, region string) *Regi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionBackendServicesListCall) Filter(filter string) *RegionBackendServicesListCall { c.urlParams_.Set("filter", filter) return c @@ -87141,7 +93233,7 @@ func (c *RegionBackendServicesListCall) Do(opts ...googleapi.CallOption) (*Backe // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -87759,32 +93851,28 @@ func (r *RegionCommitmentsService) AggregatedList(project string) *RegionCommitm return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionCommitmentsAggregatedListCall) Filter(filter string) *RegionCommitmentsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -87928,7 +94016,7 @@ func (c *RegionCommitmentsAggregatedListCall) Do(opts ...googleapi.CallOption) ( // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -88005,7 +94093,7 @@ type RegionCommitmentsGetCall struct { header_ http.Header } -// Get: Returns the specified commitment resource. Get a list of +// Get: Returns the specified commitment resource. Gets a list of // available commitments by making a list() request. func (r *RegionCommitmentsService) Get(project string, region string, commitment string) *RegionCommitmentsGetCall { c := &RegionCommitmentsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -88111,7 +94199,7 @@ func (c *RegionCommitmentsGetCall) Do(opts ...googleapi.CallOption) (*Commitment } return ret, nil // { - // "description": "Returns the specified commitment resource. Get a list of available commitments by making a list() request.", + // "description": "Returns the specified commitment resource. Gets a list of available commitments by making a list() request.", // "httpMethod": "GET", // "id": "compute.regionCommitments.get", // "parameterOrder": [ @@ -88347,32 +94435,28 @@ func (r *RegionCommitmentsService) List(project string, region string) *RegionCo return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionCommitmentsListCall) Filter(filter string) *RegionCommitmentsListCall { c.urlParams_.Set("filter", filter) return c @@ -88518,7 +94602,7 @@ func (c *RegionCommitmentsListCall) Do(opts ...googleapi.CallOption) (*Commitmen // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -88761,7 +94845,7 @@ type RegionDiskTypesGetCall struct { header_ http.Header } -// Get: Returns the specified regional disk type. Get a list of +// Get: Returns the specified regional disk type. Gets a list of // available disk types by making a list() request. func (r *RegionDiskTypesService) Get(project string, region string, diskType string) *RegionDiskTypesGetCall { c := &RegionDiskTypesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -88867,7 +94951,7 @@ func (c *RegionDiskTypesGetCall) Do(opts ...googleapi.CallOption) (*DiskType, er } return ret, nil // { - // "description": "Returns the specified regional disk type. Get a list of available disk types by making a list() request.", + // "description": "Returns the specified regional disk type. Gets a list of available disk types by making a list() request.", // "httpMethod": "GET", // "id": "compute.regionDiskTypes.get", // "parameterOrder": [ @@ -88932,32 +95016,28 @@ func (r *RegionDiskTypesService) List(project string, region string) *RegionDisk return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionDiskTypesListCall) Filter(filter string) *RegionDiskTypesListCall { c.urlParams_.Set("filter", filter) return c @@ -89103,7 +95183,7 @@ func (c *RegionDiskTypesListCall) Do(opts ...googleapi.CallOption) (*RegionDiskT // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -89904,32 +95984,28 @@ func (r *RegionDisksService) List(project string, region string) *RegionDisksLis return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionDisksListCall) Filter(filter string) *RegionDisksListCall { c.urlParams_.Set("filter", filter) return c @@ -90075,7 +96151,7 @@ func (c *RegionDisksListCall) Do(opts ...googleapi.CallOption) (*DiskList, error // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -90667,6 +96743,1294 @@ func (c *RegionDisksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T } +// method id "compute.regionHealthChecks.delete": + +type RegionHealthChecksDeleteCall struct { + s *Service + project string + region string + healthCheck string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified HealthCheck resource. +func (r *RegionHealthChecksService) Delete(project string, region string, healthCheck string) *RegionHealthChecksDeleteCall { + c := &RegionHealthChecksDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.healthCheck = healthCheck + 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 *RegionHealthChecksDeleteCall) RequestId(requestId string) *RegionHealthChecksDeleteCall { + 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 *RegionHealthChecksDeleteCall) Fields(s ...googleapi.Field) *RegionHealthChecksDeleteCall { + 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 *RegionHealthChecksDeleteCall) Context(ctx context.Context) *RegionHealthChecksDeleteCall { + 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 *RegionHealthChecksDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionHealthChecksDeleteCall) 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}/regions/{region}/healthChecks/{healthCheck}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "healthCheck": c.healthCheck, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionHealthChecks.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 *RegionHealthChecksDeleteCall) 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 HealthCheck resource.", + // "httpMethod": "DELETE", + // "id": "compute.regionHealthChecks.delete", + // "parameterOrder": [ + // "project", + // "region", + // "healthCheck" + // ], + // "parameters": { + // "healthCheck": { + // "description": "Name of the HealthCheck 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": "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}/healthChecks/{healthCheck}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionHealthChecks.get": + +type RegionHealthChecksGetCall struct { + s *Service + project string + region string + healthCheck string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns the specified HealthCheck resource. Gets a list of +// available health checks by making a list() request. +func (r *RegionHealthChecksService) Get(project string, region string, healthCheck string) *RegionHealthChecksGetCall { + c := &RegionHealthChecksGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.healthCheck = healthCheck + 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 *RegionHealthChecksGetCall) Fields(s ...googleapi.Field) *RegionHealthChecksGetCall { + 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 *RegionHealthChecksGetCall) IfNoneMatch(entityTag string) *RegionHealthChecksGetCall { + 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 *RegionHealthChecksGetCall) Context(ctx context.Context) *RegionHealthChecksGetCall { + 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 *RegionHealthChecksGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionHealthChecksGetCall) 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}/regions/{region}/healthChecks/{healthCheck}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "healthCheck": c.healthCheck, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionHealthChecks.get" call. +// Exactly one of *HealthCheck or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *HealthCheck.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 *RegionHealthChecksGetCall) Do(opts ...googleapi.CallOption) (*HealthCheck, 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 := &HealthCheck{ + 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 HealthCheck resource. Gets a list of available health checks by making a list() request.", + // "httpMethod": "GET", + // "id": "compute.regionHealthChecks.get", + // "parameterOrder": [ + // "project", + // "region", + // "healthCheck" + // ], + // "parameters": { + // "healthCheck": { + // "description": "Name of the HealthCheck resource 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": "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}/healthChecks/{healthCheck}", + // "response": { + // "$ref": "HealthCheck" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.regionHealthChecks.insert": + +type RegionHealthChecksInsertCall struct { + s *Service + project string + region string + healthcheck *HealthCheck + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a HealthCheck resource in the specified project using +// the data included in the request. +func (r *RegionHealthChecksService) Insert(project string, region string, healthcheck *HealthCheck) *RegionHealthChecksInsertCall { + c := &RegionHealthChecksInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.healthcheck = healthcheck + 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 *RegionHealthChecksInsertCall) RequestId(requestId string) *RegionHealthChecksInsertCall { + 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 *RegionHealthChecksInsertCall) Fields(s ...googleapi.Field) *RegionHealthChecksInsertCall { + 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 *RegionHealthChecksInsertCall) Context(ctx context.Context) *RegionHealthChecksInsertCall { + 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 *RegionHealthChecksInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionHealthChecksInsertCall) 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.healthcheck) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/healthChecks") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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.regionHealthChecks.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 *RegionHealthChecksInsertCall) 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 HealthCheck resource in the specified project using the data included in the request.", + // "httpMethod": "POST", + // "id": "compute.regionHealthChecks.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}/healthChecks", + // "request": { + // "$ref": "HealthCheck" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionHealthChecks.list": + +type RegionHealthChecksListCall struct { + s *Service + project string + region string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves the list of HealthCheck resources available to the +// specified project. +func (r *RegionHealthChecksService) List(project string, region string) *RegionHealthChecksListCall { + c := &RegionHealthChecksListCall{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 *RegionHealthChecksListCall) Filter(filter string) *RegionHealthChecksListCall { + 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 *RegionHealthChecksListCall) MaxResults(maxResults int64) *RegionHealthChecksListCall { + 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 *RegionHealthChecksListCall) OrderBy(orderBy string) *RegionHealthChecksListCall { + 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 *RegionHealthChecksListCall) PageToken(pageToken string) *RegionHealthChecksListCall { + 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 *RegionHealthChecksListCall) Fields(s ...googleapi.Field) *RegionHealthChecksListCall { + 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 *RegionHealthChecksListCall) IfNoneMatch(entityTag string) *RegionHealthChecksListCall { + 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 *RegionHealthChecksListCall) Context(ctx context.Context) *RegionHealthChecksListCall { + 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 *RegionHealthChecksListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionHealthChecksListCall) 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}/regions/{region}/healthChecks") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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.regionHealthChecks.list" call. +// Exactly one of *HealthCheckList or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *HealthCheckList.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 *RegionHealthChecksListCall) Do(opts ...googleapi.CallOption) (*HealthCheckList, 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 := &HealthCheckList{ + 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 HealthCheck resources available to the specified project.", + // "httpMethod": "GET", + // "id": "compute.regionHealthChecks.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}/healthChecks", + // "response": { + // "$ref": "HealthCheckList" + // }, + // "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 *RegionHealthChecksListCall) Pages(ctx context.Context, f func(*HealthCheckList) 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.regionHealthChecks.patch": + +type RegionHealthChecksPatchCall struct { + s *Service + project string + region string + healthCheck string + healthcheck *HealthCheck + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Updates a HealthCheck resource in the specified project using +// the data included in the request. This method supports PATCH +// semantics and uses the JSON merge patch format and processing rules. +func (r *RegionHealthChecksService) Patch(project string, region string, healthCheck string, healthcheck *HealthCheck) *RegionHealthChecksPatchCall { + c := &RegionHealthChecksPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.healthCheck = healthCheck + c.healthcheck = healthcheck + 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 *RegionHealthChecksPatchCall) RequestId(requestId string) *RegionHealthChecksPatchCall { + 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 *RegionHealthChecksPatchCall) Fields(s ...googleapi.Field) *RegionHealthChecksPatchCall { + 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 *RegionHealthChecksPatchCall) Context(ctx context.Context) *RegionHealthChecksPatchCall { + 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 *RegionHealthChecksPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionHealthChecksPatchCall) 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.healthcheck) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/healthChecks/{healthCheck}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PATCH", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "healthCheck": c.healthCheck, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionHealthChecks.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 *RegionHealthChecksPatchCall) 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 HealthCheck resource in the specified project using the data included in the request. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "httpMethod": "PATCH", + // "id": "compute.regionHealthChecks.patch", + // "parameterOrder": [ + // "project", + // "region", + // "healthCheck" + // ], + // "parameters": { + // "healthCheck": { + // "description": "Name of the HealthCheck resource to patch.", + // "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": "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}/healthChecks/{healthCheck}", + // "request": { + // "$ref": "HealthCheck" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionHealthChecks.testIamPermissions": + +type RegionHealthChecksTestIamPermissionsCall 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 *RegionHealthChecksService) TestIamPermissions(project string, region string, resource string, testpermissionsrequest *TestPermissionsRequest) *RegionHealthChecksTestIamPermissionsCall { + c := &RegionHealthChecksTestIamPermissionsCall{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 *RegionHealthChecksTestIamPermissionsCall) Fields(s ...googleapi.Field) *RegionHealthChecksTestIamPermissionsCall { + 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 *RegionHealthChecksTestIamPermissionsCall) Context(ctx context.Context) *RegionHealthChecksTestIamPermissionsCall { + 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 *RegionHealthChecksTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionHealthChecksTestIamPermissionsCall) 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}/regions/{region}/healthChecks/{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, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionHealthChecks.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 *RegionHealthChecksTestIamPermissionsCall) 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.regionHealthChecks.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 of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/healthChecks/{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.regionHealthChecks.update": + +type RegionHealthChecksUpdateCall struct { + s *Service + project string + region string + healthCheck string + healthcheck *HealthCheck + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Update: Updates a HealthCheck resource in the specified project using +// the data included in the request. +func (r *RegionHealthChecksService) Update(project string, region string, healthCheck string, healthcheck *HealthCheck) *RegionHealthChecksUpdateCall { + c := &RegionHealthChecksUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.healthCheck = healthCheck + c.healthcheck = healthcheck + 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 *RegionHealthChecksUpdateCall) RequestId(requestId string) *RegionHealthChecksUpdateCall { + 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 *RegionHealthChecksUpdateCall) Fields(s ...googleapi.Field) *RegionHealthChecksUpdateCall { + 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 *RegionHealthChecksUpdateCall) Context(ctx context.Context) *RegionHealthChecksUpdateCall { + 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 *RegionHealthChecksUpdateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionHealthChecksUpdateCall) 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.healthcheck) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/healthChecks/{healthCheck}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PUT", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "healthCheck": c.healthCheck, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionHealthChecks.update" 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 *RegionHealthChecksUpdateCall) 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 HealthCheck resource in the specified project using the data included in the request.", + // "httpMethod": "PUT", + // "id": "compute.regionHealthChecks.update", + // "parameterOrder": [ + // "project", + // "region", + // "healthCheck" + // ], + // "parameters": { + // "healthCheck": { + // "description": "Name of the HealthCheck resource 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" + // }, + // "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}/healthChecks/{healthCheck}", + // "request": { + // "$ref": "HealthCheck" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.regionInstanceGroupManagers.abandonInstances": type RegionInstanceGroupManagersAbandonInstancesCall struct { @@ -91395,7 +98759,7 @@ type RegionInstanceGroupManagersDeletePerInstanceConfigsCall struct { header_ http.Header } -// DeletePerInstanceConfigs: Delete selected per-instance configs for +// DeletePerInstanceConfigs: Deletes selected per-instance configs for // the managed instance group. func (r *RegionInstanceGroupManagersService) DeletePerInstanceConfigs(project string, region string, instanceGroupManager string, regioninstancegroupmanagerdeleteinstanceconfigreq *RegionInstanceGroupManagerDeleteInstanceConfigReq) *RegionInstanceGroupManagersDeletePerInstanceConfigsCall { c := &RegionInstanceGroupManagersDeletePerInstanceConfigsCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -91494,7 +98858,7 @@ func (c *RegionInstanceGroupManagersDeletePerInstanceConfigsCall) Do(opts ...goo } return ret, nil // { - // "description": "Delete selected per-instance configs for the managed instance group.", + // "description": "Deletes selected per-instance configs for the managed instance group.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.deletePerInstanceConfigs", // "parameterOrder": [ @@ -91897,32 +99261,28 @@ func (r *RegionInstanceGroupManagersService) List(project string, region string) return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionInstanceGroupManagersListCall) Filter(filter string) *RegionInstanceGroupManagersListCall { c.urlParams_.Set("filter", filter) return c @@ -92068,7 +99428,7 @@ func (c *RegionInstanceGroupManagersListCall) Do(opts ...googleapi.CallOption) ( // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -92375,32 +99735,28 @@ func (r *RegionInstanceGroupManagersService) ListPerInstanceConfigs(project stri return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionInstanceGroupManagersListPerInstanceConfigsCall) Filter(filter string) *RegionInstanceGroupManagersListPerInstanceConfigsCall { c.urlParams_.Set("filter", filter) return c @@ -92537,7 +99893,7 @@ func (c *RegionInstanceGroupManagersListPerInstanceConfigsCall) Do(opts ...googl // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -94404,32 +101760,28 @@ func (r *RegionInstanceGroupsService) List(project string, region string) *Regio return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionInstanceGroupsListCall) Filter(filter string) *RegionInstanceGroupsListCall { c.urlParams_.Set("filter", filter) return c @@ -94575,7 +101927,7 @@ func (c *RegionInstanceGroupsListCall) Do(opts ...googleapi.CallOption) (*Region // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -94671,32 +102023,28 @@ func (r *RegionInstanceGroupsService) ListInstances(project string, region strin return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionInstanceGroupsListInstancesCall) Filter(filter string) *RegionInstanceGroupsListInstancesCall { c.urlParams_.Set("filter", filter) return c @@ -94837,7 +102185,7 @@ func (c *RegionInstanceGroupsListInstancesCall) Do(opts ...googleapi.CallOption) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -95560,32 +102908,28 @@ func (r *RegionOperationsService) List(project string, region string) *RegionOpe return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionOperationsListCall) Filter(filter string) *RegionOperationsListCall { c.urlParams_.Set("filter", filter) return c @@ -95731,7 +103075,7 @@ func (c *RegionOperationsListCall) Do(opts ...googleapi.CallOption) (*OperationL // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -95802,6 +103146,2667 @@ func (c *RegionOperationsListCall) Pages(ctx context.Context, f func(*OperationL } } +// method id "compute.regionOperations.wait": + +type RegionOperationsWaitCall struct { + s *Service + project string + region string + operation string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Wait: Waits for the specified region-specific 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 *RegionOperationsService) Wait(project string, region string, operation string) *RegionOperationsWaitCall { + c := &RegionOperationsWaitCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.operation = operation + 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 *RegionOperationsWaitCall) Fields(s ...googleapi.Field) *RegionOperationsWaitCall { + 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 *RegionOperationsWaitCall) Context(ctx context.Context) *RegionOperationsWaitCall { + 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 *RegionOperationsWaitCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionOperationsWaitCall) 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}/regions/{region}/operations/{operation}/wait") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "operation": c.operation, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionOperations.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 *RegionOperationsWaitCall) 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 region-specific 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.regionOperations.wait", + // "parameterOrder": [ + // "project", + // "region", + // "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" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{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}/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.regionTargetHttpProxies.delete": + +type RegionTargetHttpProxiesDeleteCall struct { + s *Service + project string + region string + targetHttpProxy string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified TargetHttpProxy resource. +func (r *RegionTargetHttpProxiesService) Delete(project string, region string, targetHttpProxy string) *RegionTargetHttpProxiesDeleteCall { + c := &RegionTargetHttpProxiesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.targetHttpProxy = targetHttpProxy + 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 *RegionTargetHttpProxiesDeleteCall) RequestId(requestId string) *RegionTargetHttpProxiesDeleteCall { + 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 *RegionTargetHttpProxiesDeleteCall) Fields(s ...googleapi.Field) *RegionTargetHttpProxiesDeleteCall { + 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 *RegionTargetHttpProxiesDeleteCall) Context(ctx context.Context) *RegionTargetHttpProxiesDeleteCall { + 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 *RegionTargetHttpProxiesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpProxiesDeleteCall) 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}/regions/{region}/targetHttpProxies/{targetHttpProxy}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "targetHttpProxy": c.targetHttpProxy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionTargetHttpProxies.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 *RegionTargetHttpProxiesDeleteCall) 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 TargetHttpProxy resource.", + // "httpMethod": "DELETE", + // "id": "compute.regionTargetHttpProxies.delete", + // "parameterOrder": [ + // "project", + // "region", + // "targetHttpProxy" + // ], + // "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" + // }, + // "targetHttpProxy": { + // "description": "Name of the TargetHttpProxy 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/{targetHttpProxy}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionTargetHttpProxies.get": + +type RegionTargetHttpProxiesGetCall struct { + s *Service + project string + region string + targetHttpProxy string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns the specified TargetHttpProxy resource in the specified +// region. Gets a list of available target HTTP proxies by making a +// list() request. +func (r *RegionTargetHttpProxiesService) Get(project string, region string, targetHttpProxy string) *RegionTargetHttpProxiesGetCall { + c := &RegionTargetHttpProxiesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.targetHttpProxy = targetHttpProxy + 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 *RegionTargetHttpProxiesGetCall) Fields(s ...googleapi.Field) *RegionTargetHttpProxiesGetCall { + 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 *RegionTargetHttpProxiesGetCall) IfNoneMatch(entityTag string) *RegionTargetHttpProxiesGetCall { + 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 *RegionTargetHttpProxiesGetCall) Context(ctx context.Context) *RegionTargetHttpProxiesGetCall { + 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 *RegionTargetHttpProxiesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpProxiesGetCall) 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}/regions/{region}/targetHttpProxies/{targetHttpProxy}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "targetHttpProxy": c.targetHttpProxy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionTargetHttpProxies.get" call. +// Exactly one of *TargetHttpProxy or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *TargetHttpProxy.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 *RegionTargetHttpProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetHttpProxy, 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 := &TargetHttpProxy{ + 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 TargetHttpProxy resource in the specified region. Gets a list of available target HTTP proxies by making a list() request.", + // "httpMethod": "GET", + // "id": "compute.regionTargetHttpProxies.get", + // "parameterOrder": [ + // "project", + // "region", + // "targetHttpProxy" + // ], + // "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" + // }, + // "targetHttpProxy": { + // "description": "Name of the TargetHttpProxy resource to return.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/targetHttpProxies/{targetHttpProxy}", + // "response": { + // "$ref": "TargetHttpProxy" + // }, + // "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.insert": + +type RegionTargetHttpProxiesInsertCall struct { + s *Service + project string + region string + targethttpproxy *TargetHttpProxy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a TargetHttpProxy resource in the specified project +// and region using the data included in the request. +func (r *RegionTargetHttpProxiesService) Insert(project string, region string, targethttpproxy *TargetHttpProxy) *RegionTargetHttpProxiesInsertCall { + c := &RegionTargetHttpProxiesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.targethttpproxy = targethttpproxy + 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 *RegionTargetHttpProxiesInsertCall) RequestId(requestId string) *RegionTargetHttpProxiesInsertCall { + 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 *RegionTargetHttpProxiesInsertCall) Fields(s ...googleapi.Field) *RegionTargetHttpProxiesInsertCall { + 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 *RegionTargetHttpProxiesInsertCall) Context(ctx context.Context) *RegionTargetHttpProxiesInsertCall { + 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 *RegionTargetHttpProxiesInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpProxiesInsertCall) 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.targethttpproxy) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpProxies") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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.regionTargetHttpProxies.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 *RegionTargetHttpProxiesInsertCall) 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 TargetHttpProxy resource in the specified project and region using the data included in the request.", + // "httpMethod": "POST", + // "id": "compute.regionTargetHttpProxies.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}/targetHttpProxies", + // "request": { + // "$ref": "TargetHttpProxy" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionTargetHttpProxies.list": + +type RegionTargetHttpProxiesListCall struct { + s *Service + project string + region string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves the list of TargetHttpProxy resources available to +// the specified project in the specified region. +func (r *RegionTargetHttpProxiesService) List(project string, region string) *RegionTargetHttpProxiesListCall { + c := &RegionTargetHttpProxiesListCall{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 *RegionTargetHttpProxiesListCall) Filter(filter string) *RegionTargetHttpProxiesListCall { + 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 *RegionTargetHttpProxiesListCall) MaxResults(maxResults int64) *RegionTargetHttpProxiesListCall { + 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 *RegionTargetHttpProxiesListCall) OrderBy(orderBy string) *RegionTargetHttpProxiesListCall { + 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 *RegionTargetHttpProxiesListCall) PageToken(pageToken string) *RegionTargetHttpProxiesListCall { + 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 *RegionTargetHttpProxiesListCall) Fields(s ...googleapi.Field) *RegionTargetHttpProxiesListCall { + 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 *RegionTargetHttpProxiesListCall) IfNoneMatch(entityTag string) *RegionTargetHttpProxiesListCall { + 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 *RegionTargetHttpProxiesListCall) Context(ctx context.Context) *RegionTargetHttpProxiesListCall { + 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 *RegionTargetHttpProxiesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpProxiesListCall) 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}/regions/{region}/targetHttpProxies") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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.regionTargetHttpProxies.list" call. +// Exactly one of *TargetHttpProxyList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TargetHttpProxyList.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 *RegionTargetHttpProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetHttpProxyList, 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 := &TargetHttpProxyList{ + 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 TargetHttpProxy resources available to the specified project in the specified region.", + // "httpMethod": "GET", + // "id": "compute.regionTargetHttpProxies.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}/targetHttpProxies", + // "response": { + // "$ref": "TargetHttpProxyList" + // }, + // "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 *RegionTargetHttpProxiesListCall) Pages(ctx context.Context, f func(*TargetHttpProxyList) 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.regionTargetHttpProxies.setUrlMap": + +type RegionTargetHttpProxiesSetUrlMapCall struct { + s *Service + project string + region string + targetHttpProxy string + urlmapreference *UrlMapReference + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetUrlMap: Changes the URL map for TargetHttpProxy. +func (r *RegionTargetHttpProxiesService) SetUrlMap(project string, region string, targetHttpProxy string, urlmapreference *UrlMapReference) *RegionTargetHttpProxiesSetUrlMapCall { + c := &RegionTargetHttpProxiesSetUrlMapCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.targetHttpProxy = targetHttpProxy + 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 *RegionTargetHttpProxiesSetUrlMapCall) RequestId(requestId string) *RegionTargetHttpProxiesSetUrlMapCall { + 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 *RegionTargetHttpProxiesSetUrlMapCall) Fields(s ...googleapi.Field) *RegionTargetHttpProxiesSetUrlMapCall { + 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 *RegionTargetHttpProxiesSetUrlMapCall) Context(ctx context.Context) *RegionTargetHttpProxiesSetUrlMapCall { + 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 *RegionTargetHttpProxiesSetUrlMapCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpProxiesSetUrlMapCall) 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpProxies/{targetHttpProxy}/setUrlMap") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "targetHttpProxy": c.targetHttpProxy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionTargetHttpProxies.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 *RegionTargetHttpProxiesSetUrlMapCall) 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 TargetHttpProxy.", + // "httpMethod": "POST", + // "id": "compute.regionTargetHttpProxies.setUrlMap", + // "parameterOrder": [ + // "project", + // "region", + // "targetHttpProxy" + // ], + // "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" + // }, + // "targetHttpProxy": { + // "description": "Name of the TargetHttpProxy 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}/targetHttpProxies/{targetHttpProxy}/setUrlMap", + // "request": { + // "$ref": "UrlMapReference" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionTargetHttpProxies.testIamPermissions": + +type RegionTargetHttpProxiesTestIamPermissionsCall 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 *RegionTargetHttpProxiesService) TestIamPermissions(project string, region string, resource string, testpermissionsrequest *TestPermissionsRequest) *RegionTargetHttpProxiesTestIamPermissionsCall { + c := &RegionTargetHttpProxiesTestIamPermissionsCall{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 *RegionTargetHttpProxiesTestIamPermissionsCall) Fields(s ...googleapi.Field) *RegionTargetHttpProxiesTestIamPermissionsCall { + 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 *RegionTargetHttpProxiesTestIamPermissionsCall) Context(ctx context.Context) *RegionTargetHttpProxiesTestIamPermissionsCall { + 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 *RegionTargetHttpProxiesTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpProxiesTestIamPermissionsCall) 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}/regions/{region}/targetHttpProxies/{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, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionTargetHttpProxies.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 *RegionTargetHttpProxiesTestIamPermissionsCall) 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.regionTargetHttpProxies.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 of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "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.regionUrlMaps.delete": + +type RegionUrlMapsDeleteCall struct { + s *Service + project string + region string + urlMap string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified UrlMap resource. +func (r *RegionUrlMapsService) Delete(project string, region string, urlMap string) *RegionUrlMapsDeleteCall { + c := &RegionUrlMapsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.urlMap = urlMap + return c +} + +// RequestId sets the optional parameter "requestId": begin_interface: +// MixerMutationRequestBuilder Request ID to support idempotency. +func (c *RegionUrlMapsDeleteCall) RequestId(requestId string) *RegionUrlMapsDeleteCall { + 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 *RegionUrlMapsDeleteCall) Fields(s ...googleapi.Field) *RegionUrlMapsDeleteCall { + 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 *RegionUrlMapsDeleteCall) Context(ctx context.Context) *RegionUrlMapsDeleteCall { + 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 *RegionUrlMapsDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionUrlMapsDeleteCall) 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}/regions/{region}/urlMaps/{urlMap}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", urls, body) + 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.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 *RegionUrlMapsDeleteCall) 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 UrlMap resource.", + // "httpMethod": "DELETE", + // "id": "compute.regionUrlMaps.delete", + // "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 resource to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/urlMaps/{urlMap}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionUrlMaps.get": + +type RegionUrlMapsGetCall struct { + s *Service + project string + region string + urlMap string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns the specified UrlMap resource. Gets a list of available +// URL maps by making a list() request. +func (r *RegionUrlMapsService) Get(project string, region string, urlMap string) *RegionUrlMapsGetCall { + c := &RegionUrlMapsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.urlMap = urlMap + 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 *RegionUrlMapsGetCall) Fields(s ...googleapi.Field) *RegionUrlMapsGetCall { + 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 *RegionUrlMapsGetCall) IfNoneMatch(entityTag string) *RegionUrlMapsGetCall { + 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 *RegionUrlMapsGetCall) Context(ctx context.Context) *RegionUrlMapsGetCall { + 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 *RegionUrlMapsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionUrlMapsGetCall) 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}/regions/{region}/urlMaps/{urlMap}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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.get" call. +// Exactly one of *UrlMap or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *UrlMap.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 *RegionUrlMapsGetCall) Do(opts ...googleapi.CallOption) (*UrlMap, 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 := &UrlMap{ + 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 UrlMap resource. Gets a list of available URL maps by making a list() request.", + // "httpMethod": "GET", + // "id": "compute.regionUrlMaps.get", + // "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" + // }, + // "urlMap": { + // "description": "Name of the UrlMap resource to return.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/urlMaps/{urlMap}", + // "response": { + // "$ref": "UrlMap" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.regionUrlMaps.insert": + +type RegionUrlMapsInsertCall struct { + s *Service + project string + region string + urlmap *UrlMap + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a UrlMap resource in the specified project using the +// data included in the request. +func (r *RegionUrlMapsService) Insert(project string, region string, urlmap *UrlMap) *RegionUrlMapsInsertCall { + c := &RegionUrlMapsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.urlmap = urlmap + return c +} + +// RequestId sets the optional parameter "requestId": begin_interface: +// MixerMutationRequestBuilder Request ID to support idempotency. +func (c *RegionUrlMapsInsertCall) RequestId(requestId string) *RegionUrlMapsInsertCall { + 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 *RegionUrlMapsInsertCall) Fields(s ...googleapi.Field) *RegionUrlMapsInsertCall { + 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 *RegionUrlMapsInsertCall) Context(ctx context.Context) *RegionUrlMapsInsertCall { + 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 *RegionUrlMapsInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionUrlMapsInsertCall) 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.urlmap) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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.regionUrlMaps.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 *RegionUrlMapsInsertCall) 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 UrlMap resource in the specified project using the data included in the request.", + // "httpMethod": "POST", + // "id": "compute.regionUrlMaps.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": "begin_interface: MixerMutationRequestBuilder Request ID to support idempotency.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/urlMaps", + // "request": { + // "$ref": "UrlMap" + // }, + // "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 { + s *Service + project string + region string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves the list of UrlMap resources available to the +// specified project in the specified region. +func (r *RegionUrlMapsService) List(project string, region string) *RegionUrlMapsListCall { + c := &RegionUrlMapsListCall{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 *RegionUrlMapsListCall) Filter(filter string) *RegionUrlMapsListCall { + 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 *RegionUrlMapsListCall) MaxResults(maxResults int64) *RegionUrlMapsListCall { + 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 *RegionUrlMapsListCall) OrderBy(orderBy string) *RegionUrlMapsListCall { + 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 *RegionUrlMapsListCall) PageToken(pageToken string) *RegionUrlMapsListCall { + 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 *RegionUrlMapsListCall) Fields(s ...googleapi.Field) *RegionUrlMapsListCall { + 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 *RegionUrlMapsListCall) IfNoneMatch(entityTag string) *RegionUrlMapsListCall { + 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 *RegionUrlMapsListCall) Context(ctx context.Context) *RegionUrlMapsListCall { + 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 *RegionUrlMapsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionUrlMapsListCall) 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}/regions/{region}/urlMaps") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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.regionUrlMaps.list" call. +// Exactly one of *UrlMapList or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *UrlMapList.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 *RegionUrlMapsListCall) Do(opts ...googleapi.CallOption) (*UrlMapList, 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 := &UrlMapList{ + 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 UrlMap resources available to the specified project in the specified region.", + // "httpMethod": "GET", + // "id": "compute.regionUrlMaps.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}/urlMaps", + // "response": { + // "$ref": "UrlMapList" + // }, + // "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 *RegionUrlMapsListCall) Pages(ctx context.Context, f func(*UrlMapList) 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.regionUrlMaps.patch": + +type RegionUrlMapsPatchCall struct { + s *Service + project string + region string + urlMap string + urlmap *UrlMap + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Patches the specified UrlMap resource with the data included +// in the request. This method supports PATCH semantics and uses JSON +// merge patch format and processing rules. +func (r *RegionUrlMapsService) Patch(project string, region string, urlMap string, urlmap *UrlMap) *RegionUrlMapsPatchCall { + c := &RegionUrlMapsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.urlMap = urlMap + c.urlmap = urlmap + return c +} + +// RequestId sets the optional parameter "requestId": begin_interface: +// MixerMutationRequestBuilder Request ID to support idempotency. +func (c *RegionUrlMapsPatchCall) RequestId(requestId string) *RegionUrlMapsPatchCall { + 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 *RegionUrlMapsPatchCall) Fields(s ...googleapi.Field) *RegionUrlMapsPatchCall { + 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 *RegionUrlMapsPatchCall) Context(ctx context.Context) *RegionUrlMapsPatchCall { + 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 *RegionUrlMapsPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionUrlMapsPatchCall) 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.urlmap) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps/{urlMap}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PATCH", urls, body) + 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.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 *RegionUrlMapsPatchCall) 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 UrlMap resource with the data included in the request. This method supports PATCH semantics and uses JSON merge patch format and processing rules.", + // "httpMethod": "PATCH", + // "id": "compute.regionUrlMaps.patch", + // "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 resource to patch.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/urlMaps/{urlMap}", + // "request": { + // "$ref": "UrlMap" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionUrlMaps.testIamPermissions": + +type RegionUrlMapsTestIamPermissionsCall 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 *RegionUrlMapsService) TestIamPermissions(project string, region string, resource string, testpermissionsrequest *TestPermissionsRequest) *RegionUrlMapsTestIamPermissionsCall { + c := &RegionUrlMapsTestIamPermissionsCall{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 *RegionUrlMapsTestIamPermissionsCall) Fields(s ...googleapi.Field) *RegionUrlMapsTestIamPermissionsCall { + 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 *RegionUrlMapsTestIamPermissionsCall) Context(ctx context.Context) *RegionUrlMapsTestIamPermissionsCall { + 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 *RegionUrlMapsTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionUrlMapsTestIamPermissionsCall) 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}/regions/{region}/urlMaps/{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, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionUrlMaps.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 *RegionUrlMapsTestIamPermissionsCall) 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.regionUrlMaps.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 of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/urlMaps/{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.regionUrlMaps.update": + +type RegionUrlMapsUpdateCall struct { + s *Service + project string + region string + urlMap string + urlmap *UrlMap + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Update: Updates the specified UrlMap resource with the data included +// in the request. +func (r *RegionUrlMapsService) Update(project string, region string, urlMap string, urlmap *UrlMap) *RegionUrlMapsUpdateCall { + c := &RegionUrlMapsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.urlMap = urlMap + c.urlmap = urlmap + return c +} + +// RequestId sets the optional parameter "requestId": begin_interface: +// MixerMutationRequestBuilder Request ID to support idempotency. +func (c *RegionUrlMapsUpdateCall) RequestId(requestId string) *RegionUrlMapsUpdateCall { + 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 *RegionUrlMapsUpdateCall) Fields(s ...googleapi.Field) *RegionUrlMapsUpdateCall { + 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 *RegionUrlMapsUpdateCall) Context(ctx context.Context) *RegionUrlMapsUpdateCall { + 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 *RegionUrlMapsUpdateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionUrlMapsUpdateCall) 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.urlmap) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps/{urlMap}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PUT", urls, body) + 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.update" 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 *RegionUrlMapsUpdateCall) 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 UrlMap resource with the data included in the request.", + // "httpMethod": "PUT", + // "id": "compute.regionUrlMaps.update", + // "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 resource to update.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/urlMaps/{urlMap}", + // "request": { + // "$ref": "UrlMap" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionUrlMaps.validate": + +type RegionUrlMapsValidateCall struct { + s *Service + project string + region string + urlMap string + regionurlmapsvalidaterequest *RegionUrlMapsValidateRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Validate: Runs static validation for the UrlMap. In particular, the +// tests of the provided UrlMap will be run. Calling this method does +// NOT create the UrlMap. +func (r *RegionUrlMapsService) Validate(project string, region string, urlMap string, regionurlmapsvalidaterequest *RegionUrlMapsValidateRequest) *RegionUrlMapsValidateCall { + c := &RegionUrlMapsValidateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.urlMap = urlMap + c.regionurlmapsvalidaterequest = regionurlmapsvalidaterequest + 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 *RegionUrlMapsValidateCall) Fields(s ...googleapi.Field) *RegionUrlMapsValidateCall { + 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 *RegionUrlMapsValidateCall) Context(ctx context.Context) *RegionUrlMapsValidateCall { + 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 *RegionUrlMapsValidateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionUrlMapsValidateCall) 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.regionurlmapsvalidaterequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps/{urlMap}/validate") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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.validate" call. +// Exactly one of *UrlMapsValidateResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *UrlMapsValidateResponse.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 *RegionUrlMapsValidateCall) Do(opts ...googleapi.CallOption) (*UrlMapsValidateResponse, 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 := &UrlMapsValidateResponse{ + 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": "Runs static validation for the UrlMap. In particular, the tests of the provided UrlMap will be run. Calling this method does NOT create the UrlMap.", + // "httpMethod": "POST", + // "id": "compute.regionUrlMaps.validate", + // "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" + // }, + // "urlMap": { + // "description": "Name of the UrlMap resource to be validated as.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/urlMaps/{urlMap}/validate", + // "request": { + // "$ref": "RegionUrlMapsValidateRequest" + // }, + // "response": { + // "$ref": "UrlMapsValidateResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.regions.get": type RegionsGetCall struct { @@ -95814,7 +105819,7 @@ type RegionsGetCall struct { header_ http.Header } -// Get: Returns the specified Region resource. Get a list of available +// Get: Returns the specified Region resource. Gets a list of available // regions by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/regions/get func (r *RegionsService) Get(project string, region string) *RegionsGetCall { @@ -95919,7 +105924,7 @@ func (c *RegionsGetCall) Do(opts ...googleapi.CallOption) (*Region, error) { } return ret, nil // { - // "description": "Returns the specified Region resource. Get a list of available regions by making a list() request.", + // "description": "Returns the specified Region resource. Gets a list of available regions by making a list() request.", // "httpMethod": "GET", // "id": "compute.regions.get", // "parameterOrder": [ @@ -95975,32 +105980,28 @@ func (r *RegionsService) List(project string) *RegionsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionsListCall) Filter(filter string) *RegionsListCall { c.urlParams_.Set("filter", filter) return c @@ -96144,7 +106145,7 @@ func (c *RegionsListCall) Do(opts ...googleapi.CallOption) (*RegionList, error) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -96208,6 +106209,1495 @@ 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/resourcePolicies") + 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.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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{resourcePolicy}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", urls, body) + 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{resourcePolicy}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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.getIamPolicy": + +type ResourcePoliciesGetIamPolicyCall 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 *ResourcePoliciesService) GetIamPolicy(project string, region string, resource string) *ResourcePoliciesGetIamPolicyCall { + c := &ResourcePoliciesGetIamPolicyCall{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 *ResourcePoliciesGetIamPolicyCall) Fields(s ...googleapi.Field) *ResourcePoliciesGetIamPolicyCall { + 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 *ResourcePoliciesGetIamPolicyCall) IfNoneMatch(entityTag string) *ResourcePoliciesGetIamPolicyCall { + 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 *ResourcePoliciesGetIamPolicyCall) Context(ctx context.Context) *ResourcePoliciesGetIamPolicyCall { + 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 *ResourcePoliciesGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ResourcePoliciesGetIamPolicyCall) 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}/regions/{region}/resourcePolicies/{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, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.resourcePolicies.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 *ResourcePoliciesGetIamPolicyCall) 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.resourcePolicies.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 of the resource 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/{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.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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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 *ResourcePoliciesList 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 +// 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) { + 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 := &ResourcePoliciesList{ + 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": "ResourcePoliciesList" + // }, + // "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(*ResourcePoliciesList) 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.setIamPolicy": + +type ResourcePoliciesSetIamPolicyCall 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 *ResourcePoliciesService) SetIamPolicy(project string, region string, resource string, regionsetpolicyrequest *RegionSetPolicyRequest) *ResourcePoliciesSetIamPolicyCall { + c := &ResourcePoliciesSetIamPolicyCall{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 *ResourcePoliciesSetIamPolicyCall) Fields(s ...googleapi.Field) *ResourcePoliciesSetIamPolicyCall { + 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 *ResourcePoliciesSetIamPolicyCall) Context(ctx context.Context) *ResourcePoliciesSetIamPolicyCall { + 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 *ResourcePoliciesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ResourcePoliciesSetIamPolicyCall) 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{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, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.resourcePolicies.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 *ResourcePoliciesSetIamPolicyCall) 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.resourcePolicies.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 of the resource 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/{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.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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{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, + "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 of the resource 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/{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 { @@ -96226,32 +107716,28 @@ func (r *RoutersService) AggregatedList(project string) *RoutersAggregatedListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RoutersAggregatedListCall) Filter(filter string) *RoutersAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -96395,7 +107881,7 @@ func (c *RoutersAggregatedListCall) Do(opts ...googleapi.CallOption) (*RouterAgg // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -96643,7 +108129,7 @@ type RoutersGetCall struct { header_ http.Header } -// Get: Returns the specified Router resource. Get a list of available +// Get: Returns the specified Router resource. Gets a list of available // routers by making a list() request. func (r *RoutersService) Get(project string, region string, router string) *RoutersGetCall { c := &RoutersGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -96749,7 +108235,7 @@ func (c *RoutersGetCall) Do(opts ...googleapi.CallOption) (*Router, error) { } return ret, nil // { - // "description": "Returns the specified Router resource. Get a list of available routers by making a list() request.", + // "description": "Returns the specified Router resource. Gets a list of available routers by making a list() request.", // "httpMethod": "GET", // "id": "compute.routers.get", // "parameterOrder": [ @@ -97148,32 +108634,28 @@ func (r *RoutersService) List(project string, region string) *RoutersListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RoutersListCall) Filter(filter string) *RoutersListCall { c.urlParams_.Set("filter", filter) return c @@ -97319,7 +108801,7 @@ func (c *RoutersListCall) Do(opts ...googleapi.CallOption) (*RouterList, error) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -98247,7 +109729,7 @@ type RoutesGetCall struct { header_ http.Header } -// Get: Returns the specified Route resource. Get a list of available +// Get: Returns the specified Route resource. Gets a list of available // routes by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/routes/get func (r *RoutesService) Get(project string, route string) *RoutesGetCall { @@ -98352,7 +109834,7 @@ func (c *RoutesGetCall) Do(opts ...googleapi.CallOption) (*Route, error) { } return ret, nil // { - // "description": "Returns the specified Route resource. Get a list of available routes by making a list() request.", + // "description": "Returns the specified Route resource. Gets a list of available routes by making a list() request.", // "httpMethod": "GET", // "id": "compute.routes.get", // "parameterOrder": [ @@ -98569,32 +110051,28 @@ func (r *RoutesService) List(project string) *RoutesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RoutesListCall) Filter(filter string) *RoutesListCall { c.urlParams_.Set("filter", filter) return c @@ -98738,7 +110216,7 @@ func (c *RoutesListCall) Do(opts ...googleapi.CallOption) (*RouteList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -99623,6 +111101,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. @@ -99727,6 +111212,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", @@ -99763,32 +111253,28 @@ func (r *SecurityPoliciesService) List(project string) *SecurityPoliciesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 @@ -99932,7 +111418,7 @@ func (c *SecurityPoliciesListCall) Do(opts ...googleapi.CallOption) (*SecurityPo // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -99996,6 +111482,235 @@ func (c *SecurityPoliciesListCall) Pages(ctx context.Context, f func(*SecurityPo } } +// method id "compute.securityPolicies.listPreconfiguredExpressionSets": + +type SecurityPoliciesListPreconfiguredExpressionSetsCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// ListPreconfiguredExpressionSets: Gets the current list of +// preconfigured Web Application Firewall (WAF) expressions. +func (r *SecurityPoliciesService) ListPreconfiguredExpressionSets(project string) *SecurityPoliciesListPreconfiguredExpressionSetsCall { + c := &SecurityPoliciesListPreconfiguredExpressionSetsCall{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 *SecurityPoliciesListPreconfiguredExpressionSetsCall) Filter(filter string) *SecurityPoliciesListPreconfiguredExpressionSetsCall { + 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 *SecurityPoliciesListPreconfiguredExpressionSetsCall) MaxResults(maxResults int64) *SecurityPoliciesListPreconfiguredExpressionSetsCall { + 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 *SecurityPoliciesListPreconfiguredExpressionSetsCall) OrderBy(orderBy string) *SecurityPoliciesListPreconfiguredExpressionSetsCall { + 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 *SecurityPoliciesListPreconfiguredExpressionSetsCall) PageToken(pageToken string) *SecurityPoliciesListPreconfiguredExpressionSetsCall { + 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 *SecurityPoliciesListPreconfiguredExpressionSetsCall) Fields(s ...googleapi.Field) *SecurityPoliciesListPreconfiguredExpressionSetsCall { + 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 *SecurityPoliciesListPreconfiguredExpressionSetsCall) IfNoneMatch(entityTag string) *SecurityPoliciesListPreconfiguredExpressionSetsCall { + 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 *SecurityPoliciesListPreconfiguredExpressionSetsCall) Context(ctx context.Context) *SecurityPoliciesListPreconfiguredExpressionSetsCall { + 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 *SecurityPoliciesListPreconfiguredExpressionSetsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SecurityPoliciesListPreconfiguredExpressionSetsCall) 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}/global/securityPolicies/listPreconfiguredExpressionSets") + 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.securityPolicies.listPreconfiguredExpressionSets" call. +// Exactly one of +// *SecurityPoliciesListPreconfiguredExpressionSetsResponse or error +// will be non-nil. Any non-2xx status code is an error. Response +// headers are in either +// *SecurityPoliciesListPreconfiguredExpressionSetsResponse.ServerRespons +// e.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 *SecurityPoliciesListPreconfiguredExpressionSetsCall) Do(opts ...googleapi.CallOption) (*SecurityPoliciesListPreconfiguredExpressionSetsResponse, 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 := &SecurityPoliciesListPreconfiguredExpressionSetsResponse{ + 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 current list of preconfigured Web Application Firewall (WAF) expressions.", + // "httpMethod": "GET", + // "id": "compute.securityPolicies.listPreconfiguredExpressionSets", + // "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/listPreconfiguredExpressionSets", + // "response": { + // "$ref": "SecurityPoliciesListPreconfiguredExpressionSetsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.securityPolicies.patch": type SecurityPoliciesPatchCall struct { @@ -100487,6 +112202,153 @@ 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{resource}/setLabels") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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 of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "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 { @@ -100814,8 +112676,8 @@ type SnapshotsGetCall struct { header_ http.Header } -// Get: Returns the specified Snapshot resource. Get a list of available -// snapshots by making a list() request. +// Get: Returns the specified Snapshot resource. Gets a list of +// available snapshots by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/snapshots/get func (r *SnapshotsService) Get(project string, snapshot string) *SnapshotsGetCall { c := &SnapshotsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -100919,7 +112781,7 @@ func (c *SnapshotsGetCall) Do(opts ...googleapi.CallOption) (*Snapshot, error) { } return ret, nil // { - // "description": "Returns the specified Snapshot resource. Get a list of available snapshots by making a list() request.", + // "description": "Returns the specified Snapshot resource. Gets a list of available snapshots by making a list() request.", // "httpMethod": "GET", // "id": "compute.snapshots.get", // "parameterOrder": [ @@ -101127,32 +112989,28 @@ func (r *SnapshotsService) List(project string) *SnapshotsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SnapshotsListCall) Filter(filter string) *SnapshotsListCall { c.urlParams_.Set("filter", filter) return c @@ -101296,7 +113154,7 @@ func (c *SnapshotsListCall) Do(opts ...googleapi.CallOption) (*SnapshotList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -101363,22 +113221,22 @@ 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 - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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, policy *Policy) *SnapshotsSetIamPolicyCall { +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.policy = policy + c.globalsetpolicyrequest = globalsetpolicyrequest return c } @@ -101414,7 +113272,7 @@ func (c *SnapshotsSetIamPolicyCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) if err != nil { return nil, err } @@ -101494,7 +113352,7 @@ func (c *SnapshotsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, e // }, // "path": "{project}/global/snapshots/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "GlobalSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -101974,7 +113832,7 @@ type SslCertificatesGetCall struct { header_ http.Header } -// Get: Returns the specified SslCertificate resource. Get a list of +// Get: Returns the specified SslCertificate resource. Gets a list of // available SSL certificates by making a list() request. func (r *SslCertificatesService) Get(project string, sslCertificate string) *SslCertificatesGetCall { c := &SslCertificatesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -102078,7 +113936,7 @@ func (c *SslCertificatesGetCall) Do(opts ...googleapi.CallOption) (*SslCertifica } return ret, nil // { - // "description": "Returns the specified SslCertificate resource. Get a list of available SSL certificates by making a list() request.", + // "description": "Returns the specified SslCertificate resource. Gets a list of available SSL certificates by making a list() request.", // "httpMethod": "GET", // "id": "compute.sslCertificates.get", // "parameterOrder": [ @@ -102293,32 +114151,28 @@ func (r *SslCertificatesService) List(project string) *SslCertificatesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SslCertificatesListCall) Filter(filter string) *SslCertificatesListCall { c.urlParams_.Set("filter", filter) return c @@ -102462,7 +114316,7 @@ func (c *SslCertificatesListCall) Do(opts ...googleapi.CallOption) (*SslCertific // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -102847,7 +114701,7 @@ type SslPoliciesGetCall struct { header_ http.Header } -// Get: List all of the ordered rules present in a single specified +// Get: Lists all of the ordered rules present in a single specified // policy. func (r *SslPoliciesService) Get(project string, sslPolicy string) *SslPoliciesGetCall { c := &SslPoliciesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -102951,7 +114805,7 @@ func (c *SslPoliciesGetCall) Do(opts ...googleapi.CallOption) (*SslPolicy, error } return ret, nil // { - // "description": "List all of the ordered rules present in a single specified policy.", + // "description": "Lists all of the ordered rules present in a single specified policy.", // "httpMethod": "GET", // "id": "compute.sslPolicies.get", // "parameterOrder": [ @@ -102997,7 +114851,7 @@ type SslPoliciesInsertCall struct { header_ http.Header } -// Insert: Returns the specified SSL policy resource. Get a list of +// Insert: Returns the specified SSL policy resource. Gets a list of // available SSL policies by making a list() request. func (r *SslPoliciesService) Insert(project string, sslpolicy *SslPolicy) *SslPoliciesInsertCall { c := &SslPoliciesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -103111,7 +114965,7 @@ func (c *SslPoliciesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, er } return ret, nil // { - // "description": "Returns the specified SSL policy resource. Get a list of available SSL policies by making a list() request.", + // "description": "Returns the specified SSL policy resource. Gets a list of available SSL policies by making a list() request.", // "httpMethod": "POST", // "id": "compute.sslPolicies.insert", // "parameterOrder": [ @@ -103157,7 +115011,7 @@ type SslPoliciesListCall struct { header_ http.Header } -// List: List all the SSL policies that have been configured for the +// List: Lists all the SSL policies that have been configured for the // specified project. func (r *SslPoliciesService) List(project string) *SslPoliciesListCall { c := &SslPoliciesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -103165,32 +115019,28 @@ func (r *SslPoliciesService) List(project string) *SslPoliciesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SslPoliciesListCall) Filter(filter string) *SslPoliciesListCall { c.urlParams_.Set("filter", filter) return c @@ -103326,7 +115176,7 @@ func (c *SslPoliciesListCall) Do(opts ...googleapi.CallOption) (*SslPoliciesList } return ret, nil // { - // "description": "List all the SSL policies that have been configured for the specified project.", + // "description": "Lists all the SSL policies that have been configured for the specified project.", // "httpMethod": "GET", // "id": "compute.sslPolicies.list", // "parameterOrder": [ @@ -103334,7 +115184,7 @@ func (c *SslPoliciesListCall) Do(opts ...googleapi.CallOption) (*SslPoliciesList // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -103417,32 +115267,28 @@ func (r *SslPoliciesService) ListAvailableFeatures(project string) *SslPoliciesL return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SslPoliciesListAvailableFeaturesCall) Filter(filter string) *SslPoliciesListAvailableFeaturesCall { c.urlParams_.Set("filter", filter) return c @@ -103588,7 +115434,7 @@ func (c *SslPoliciesListAvailableFeaturesCall) Do(opts ...googleapi.CallOption) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -103967,32 +115813,28 @@ func (r *SubnetworksService) AggregatedList(project string) *SubnetworksAggregat return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SubnetworksAggregatedListCall) Filter(filter string) *SubnetworksAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -104136,7 +115978,7 @@ func (c *SubnetworksAggregatedListCall) Do(opts ...googleapi.CallOption) (*Subne // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -104566,7 +116408,7 @@ type SubnetworksGetCall struct { header_ http.Header } -// Get: Returns the specified subnetwork. Get a list of available +// Get: Returns the specified subnetwork. Gets a list of available // subnetworks list() request. func (r *SubnetworksService) Get(project string, region string, subnetwork string) *SubnetworksGetCall { c := &SubnetworksGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -104672,7 +116514,7 @@ func (c *SubnetworksGetCall) Do(opts ...googleapi.CallOption) (*Subnetwork, erro } return ret, nil // { - // "description": "Returns the specified subnetwork. Get a list of available subnetworks list() request.", + // "description": "Returns the specified subnetwork. Gets a list of available subnetworks list() request.", // "httpMethod": "GET", // "id": "compute.subnetworks.get", // "parameterOrder": [ @@ -105071,32 +116913,28 @@ func (r *SubnetworksService) List(project string, region string) *SubnetworksLis return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SubnetworksListCall) Filter(filter string) *SubnetworksListCall { c.urlParams_.Set("filter", filter) return c @@ -105242,7 +117080,7 @@ func (c *SubnetworksListCall) Do(opts ...googleapi.CallOption) (*SubnetworkList, // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -105331,32 +117169,28 @@ func (r *SubnetworksService) ListUsable(project string) *SubnetworksListUsableCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 @@ -105500,7 +117334,7 @@ func (c *SubnetworksListUsableCall) Do(opts ...googleapi.CallOption) (*UsableSub // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -105579,9 +117413,10 @@ 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 and -// allow_subnet_cidr_routes_overlap. It is also mandatory to specify the -// current fingeprint of the subnetwork resource being patched. +// 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. 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 @@ -105698,7 +117533,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 and allow_subnet_cidr_routes_overlap. 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 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.", // "httpMethod": "PATCH", // "id": "compute.subnetworks.patch", // "parameterOrder": [ @@ -105752,24 +117587,24 @@ 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 - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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, policy *Policy) *SubnetworksSetIamPolicyCall { +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.policy = policy + c.regionsetpolicyrequest = regionsetpolicyrequest return c } @@ -105805,7 +117640,7 @@ func (c *SubnetworksSetIamPolicyCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.regionsetpolicyrequest) if err != nil { return nil, err } @@ -105894,7 +117729,7 @@ func (c *SubnetworksSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, // }, // "path": "{project}/regions/{region}/subnetworks/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "RegionSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -106249,6 +118084,254 @@ func (c *SubnetworksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T } +// method id "compute.targetHttpProxies.aggregatedList": + +type TargetHttpProxiesAggregatedListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves the list of all TargetHttpProxy resources, +// regional and global, available to the specified project. +func (r *TargetHttpProxiesService) AggregatedList(project string) *TargetHttpProxiesAggregatedListCall { + c := &TargetHttpProxiesAggregatedListCall{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 *TargetHttpProxiesAggregatedListCall) Filter(filter string) *TargetHttpProxiesAggregatedListCall { + 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 *TargetHttpProxiesAggregatedListCall) MaxResults(maxResults int64) *TargetHttpProxiesAggregatedListCall { + 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 *TargetHttpProxiesAggregatedListCall) OrderBy(orderBy string) *TargetHttpProxiesAggregatedListCall { + 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 *TargetHttpProxiesAggregatedListCall) PageToken(pageToken string) *TargetHttpProxiesAggregatedListCall { + 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 *TargetHttpProxiesAggregatedListCall) Fields(s ...googleapi.Field) *TargetHttpProxiesAggregatedListCall { + 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 *TargetHttpProxiesAggregatedListCall) IfNoneMatch(entityTag string) *TargetHttpProxiesAggregatedListCall { + 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 *TargetHttpProxiesAggregatedListCall) Context(ctx context.Context) *TargetHttpProxiesAggregatedListCall { + 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 *TargetHttpProxiesAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *TargetHttpProxiesAggregatedListCall) 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/targetHttpProxies") + 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.targetHttpProxies.aggregatedList" call. +// Exactly one of *TargetHttpProxyAggregatedList or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *TargetHttpProxyAggregatedList.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 *TargetHttpProxiesAggregatedListCall) Do(opts ...googleapi.CallOption) (*TargetHttpProxyAggregatedList, 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 := &TargetHttpProxyAggregatedList{ + 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 TargetHttpProxy resources, regional and global, available to the specified project.", + // "httpMethod": "GET", + // "id": "compute.targetHttpProxies.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/targetHttpProxies", + // "response": { + // "$ref": "TargetHttpProxyAggregatedList" + // }, + // "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 *TargetHttpProxiesAggregatedListCall) Pages(ctx context.Context, f func(*TargetHttpProxyAggregatedList) 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.targetHttpProxies.delete": type TargetHttpProxiesDeleteCall struct { @@ -106422,7 +118505,7 @@ type TargetHttpProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetHttpProxy resource. Get a list of +// Get: Returns the specified TargetHttpProxy resource. Gets a list of // available target HTTP proxies by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/targetHttpProxies/get func (r *TargetHttpProxiesService) Get(project string, targetHttpProxy string) *TargetHttpProxiesGetCall { @@ -106527,7 +118610,7 @@ func (c *TargetHttpProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetHttp } return ret, nil // { - // "description": "Returns the specified TargetHttpProxy resource. Get a list of available target HTTP proxies by making a list() request.", + // "description": "Returns the specified TargetHttpProxy resource. Gets a list of available target HTTP proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetHttpProxies.get", // "parameterOrder": [ @@ -106744,32 +118827,28 @@ func (r *TargetHttpProxiesService) List(project string) *TargetHttpProxiesListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetHttpProxiesListCall) Filter(filter string) *TargetHttpProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -106913,7 +118992,7 @@ func (c *TargetHttpProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetHtt // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -107468,7 +119547,7 @@ type TargetHttpsProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetHttpsProxy resource. Get a list of +// Get: Returns the specified TargetHttpsProxy resource. Gets a list of // available target HTTPS proxies by making a list() request. func (r *TargetHttpsProxiesService) Get(project string, targetHttpsProxy string) *TargetHttpsProxiesGetCall { c := &TargetHttpsProxiesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -107572,7 +119651,7 @@ func (c *TargetHttpsProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetHtt } return ret, nil // { - // "description": "Returns the specified TargetHttpsProxy resource. Get a list of available target HTTPS proxies by making a list() request.", + // "description": "Returns the specified TargetHttpsProxy resource. Gets a list of available target HTTPS proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetHttpsProxies.get", // "parameterOrder": [ @@ -107787,32 +119866,28 @@ func (r *TargetHttpsProxiesService) List(project string) *TargetHttpsProxiesList return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetHttpsProxiesListCall) Filter(filter string) *TargetHttpsProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -107956,7 +120031,7 @@ func (c *TargetHttpsProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetHt // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -108869,32 +120944,28 @@ func (r *TargetInstancesService) AggregatedList(project string) *TargetInstances return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetInstancesAggregatedListCall) Filter(filter string) *TargetInstancesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -109038,7 +121109,7 @@ func (c *TargetInstancesAggregatedListCall) Do(opts ...googleapi.CallOption) (*T // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -109287,7 +121358,7 @@ type TargetInstancesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetInstance resource. Get a list of +// Get: Returns the specified TargetInstance resource. Gets a list of // available target instances by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/targetInstances/get func (r *TargetInstancesService) Get(project string, zone string, targetInstance string) *TargetInstancesGetCall { @@ -109394,7 +121465,7 @@ func (c *TargetInstancesGetCall) Do(opts ...googleapi.CallOption) (*TargetInstan } return ret, nil // { - // "description": "Returns the specified TargetInstance resource. Get a list of available target instances by making a list() request.", + // "description": "Returns the specified TargetInstance resource. Gets a list of available target instances by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetInstances.get", // "parameterOrder": [ @@ -109632,32 +121703,28 @@ func (r *TargetInstancesService) List(project string, zone string) *TargetInstan return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetInstancesListCall) Filter(filter string) *TargetInstancesListCall { c.urlParams_.Set("filter", filter) return c @@ -109803,7 +121870,7 @@ func (c *TargetInstancesListCall) Do(opts ...googleapi.CallOption) (*TargetInsta // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -110416,32 +122483,28 @@ func (r *TargetPoolsService) AggregatedList(project string) *TargetPoolsAggregat return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetPoolsAggregatedListCall) Filter(filter string) *TargetPoolsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -110585,7 +122648,7 @@ func (c *TargetPoolsAggregatedListCall) Do(opts ...googleapi.CallOption) (*Targe // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -110834,7 +122897,7 @@ type TargetPoolsGetCall struct { header_ http.Header } -// Get: Returns the specified target pool. Get a list of available +// Get: Returns the specified target pool. Gets a list of available // target pools by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/targetPools/get func (r *TargetPoolsService) Get(project string, region string, targetPool string) *TargetPoolsGetCall { @@ -110941,7 +123004,7 @@ func (c *TargetPoolsGetCall) Do(opts ...googleapi.CallOption) (*TargetPool, erro } return ret, nil // { - // "description": "Returns the specified target pool. Get a list of available target pools by making a list() request.", + // "description": "Returns the specified target pool. Gets a list of available target pools by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetPools.get", // "parameterOrder": [ @@ -111339,32 +123402,28 @@ func (r *TargetPoolsService) List(project string, region string) *TargetPoolsLis return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetPoolsListCall) Filter(filter string) *TargetPoolsListCall { c.urlParams_.Set("filter", filter) return c @@ -111510,7 +123569,7 @@ func (c *TargetPoolsListCall) Do(opts ...googleapi.CallOption) (*TargetPoolList, // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -112471,7 +124530,7 @@ type TargetSslProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetSslProxy resource. Get a list of +// Get: Returns the specified TargetSslProxy resource. Gets a list of // available target SSL proxies by making a list() request. func (r *TargetSslProxiesService) Get(project string, targetSslProxy string) *TargetSslProxiesGetCall { c := &TargetSslProxiesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -112575,7 +124634,7 @@ func (c *TargetSslProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetSslPr } return ret, nil // { - // "description": "Returns the specified TargetSslProxy resource. Get a list of available target SSL proxies by making a list() request.", + // "description": "Returns the specified TargetSslProxy resource. Gets a list of available target SSL proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetSslProxies.get", // "parameterOrder": [ @@ -112790,32 +124849,28 @@ func (r *TargetSslProxiesService) List(project string) *TargetSslProxiesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetSslProxiesListCall) Filter(filter string) *TargetSslProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -112959,7 +125014,7 @@ func (c *TargetSslProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetSslP // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -114025,7 +126080,7 @@ type TargetTcpProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetTcpProxy resource. Get a list of +// Get: Returns the specified TargetTcpProxy resource. Gets a list of // available target TCP proxies by making a list() request. func (r *TargetTcpProxiesService) Get(project string, targetTcpProxy string) *TargetTcpProxiesGetCall { c := &TargetTcpProxiesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -114129,7 +126184,7 @@ func (c *TargetTcpProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetTcpPr } return ret, nil // { - // "description": "Returns the specified TargetTcpProxy resource. Get a list of available target TCP proxies by making a list() request.", + // "description": "Returns the specified TargetTcpProxy resource. Gets a list of available target TCP proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetTcpProxies.get", // "parameterOrder": [ @@ -114344,32 +126399,28 @@ func (r *TargetTcpProxiesService) List(project string) *TargetTcpProxiesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetTcpProxiesListCall) Filter(filter string) *TargetTcpProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -114513,7 +126564,7 @@ func (c *TargetTcpProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetTcpP // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -115083,32 +127134,28 @@ func (r *TargetVpnGatewaysService) AggregatedList(project string) *TargetVpnGate return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetVpnGatewaysAggregatedListCall) Filter(filter string) *TargetVpnGatewaysAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -115252,7 +127299,7 @@ func (c *TargetVpnGatewaysAggregatedListCall) Do(opts ...googleapi.CallOption) ( // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -115500,7 +127547,7 @@ type TargetVpnGatewaysGetCall struct { header_ http.Header } -// Get: Returns the specified target VPN gateway. Get a list of +// Get: Returns the specified target VPN gateway. Gets a list of // available target VPN gateways by making a list() request. func (r *TargetVpnGatewaysService) Get(project string, region string, targetVpnGateway string) *TargetVpnGatewaysGetCall { c := &TargetVpnGatewaysGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -115606,7 +127653,7 @@ func (c *TargetVpnGatewaysGetCall) Do(opts ...googleapi.CallOption) (*TargetVpnG } return ret, nil // { - // "description": "Returns the specified target VPN gateway. Get a list of available target VPN gateways by making a list() request.", + // "description": "Returns the specified target VPN gateway. Gets a list of available target VPN gateways by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetVpnGateways.get", // "parameterOrder": [ @@ -115842,32 +127889,28 @@ func (r *TargetVpnGatewaysService) List(project string, region string) *TargetVp return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetVpnGatewaysListCall) Filter(filter string) *TargetVpnGatewaysListCall { c.urlParams_.Set("filter", filter) return c @@ -116013,7 +128056,7 @@ func (c *TargetVpnGatewaysListCall) Do(opts ...googleapi.CallOption) (*TargetVpn // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -116598,7 +128641,7 @@ type UrlMapsGetCall struct { header_ http.Header } -// Get: Returns the specified UrlMap resource. Get a list of available +// Get: Returns the specified UrlMap resource. Gets a list of available // URL maps by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/urlMaps/get func (r *UrlMapsService) Get(project string, urlMap string) *UrlMapsGetCall { @@ -116703,7 +128746,7 @@ func (c *UrlMapsGetCall) Do(opts ...googleapi.CallOption) (*UrlMap, error) { } return ret, nil // { - // "description": "Returns the specified UrlMap resource. Get a list of available URL maps by making a list() request.", + // "description": "Returns the specified UrlMap resource. Gets a list of available URL maps by making a list() request.", // "httpMethod": "GET", // "id": "compute.urlMaps.get", // "parameterOrder": [ @@ -117091,32 +129134,28 @@ func (r *UrlMapsService) List(project string) *UrlMapsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *UrlMapsListCall) Filter(filter string) *UrlMapsListCall { c.urlParams_.Set("filter", filter) return c @@ -117260,7 +129299,7 @@ func (c *UrlMapsListCall) Do(opts ...googleapi.CallOption) (*UrlMapList, error) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -117966,6 +130005,1358 @@ func (c *UrlMapsValidateCall) Do(opts ...googleapi.CallOption) (*UrlMapsValidate } +// method id "compute.vpnGateways.aggregatedList": + +type VpnGatewaysAggregatedListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves an aggregated list of VPN gateways. +func (r *VpnGatewaysService) AggregatedList(project string) *VpnGatewaysAggregatedListCall { + c := &VpnGatewaysAggregatedListCall{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 *VpnGatewaysAggregatedListCall) Filter(filter string) *VpnGatewaysAggregatedListCall { + 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 *VpnGatewaysAggregatedListCall) MaxResults(maxResults int64) *VpnGatewaysAggregatedListCall { + 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 *VpnGatewaysAggregatedListCall) OrderBy(orderBy string) *VpnGatewaysAggregatedListCall { + 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 *VpnGatewaysAggregatedListCall) PageToken(pageToken string) *VpnGatewaysAggregatedListCall { + 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 *VpnGatewaysAggregatedListCall) Fields(s ...googleapi.Field) *VpnGatewaysAggregatedListCall { + 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 *VpnGatewaysAggregatedListCall) IfNoneMatch(entityTag string) *VpnGatewaysAggregatedListCall { + 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 *VpnGatewaysAggregatedListCall) Context(ctx context.Context) *VpnGatewaysAggregatedListCall { + 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 *VpnGatewaysAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *VpnGatewaysAggregatedListCall) 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/vpnGateways") + 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.vpnGateways.aggregatedList" call. +// Exactly one of *VpnGatewayAggregatedList or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *VpnGatewayAggregatedList.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 *VpnGatewaysAggregatedListCall) Do(opts ...googleapi.CallOption) (*VpnGatewayAggregatedList, 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 := &VpnGatewayAggregatedList{ + 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 VPN gateways.", + // "httpMethod": "GET", + // "id": "compute.vpnGateways.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/vpnGateways", + // "response": { + // "$ref": "VpnGatewayAggregatedList" + // }, + // "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 *VpnGatewaysAggregatedListCall) Pages(ctx context.Context, f func(*VpnGatewayAggregatedList) 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.vpnGateways.delete": + +type VpnGatewaysDeleteCall struct { + s *Service + project string + region string + vpnGateway string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified VPN gateway. +func (r *VpnGatewaysService) Delete(project string, region string, vpnGateway string) *VpnGatewaysDeleteCall { + c := &VpnGatewaysDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.vpnGateway = vpnGateway + 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 *VpnGatewaysDeleteCall) RequestId(requestId string) *VpnGatewaysDeleteCall { + 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 *VpnGatewaysDeleteCall) Fields(s ...googleapi.Field) *VpnGatewaysDeleteCall { + 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 *VpnGatewaysDeleteCall) Context(ctx context.Context) *VpnGatewaysDeleteCall { + 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 *VpnGatewaysDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *VpnGatewaysDeleteCall) 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}/regions/{region}/vpnGateways/{vpnGateway}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "vpnGateway": c.vpnGateway, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.vpnGateways.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 *VpnGatewaysDeleteCall) 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 VPN gateway.", + // "httpMethod": "DELETE", + // "id": "compute.vpnGateways.delete", + // "parameterOrder": [ + // "project", + // "region", + // "vpnGateway" + // ], + // "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" + // }, + // "vpnGateway": { + // "description": "Name of the VPN gateway to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/vpnGateways/{vpnGateway}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.vpnGateways.get": + +type VpnGatewaysGetCall struct { + s *Service + project string + region string + vpnGateway string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns the specified VPN gateway. Gets a list of available VPN +// gateways by making a list() request. +func (r *VpnGatewaysService) Get(project string, region string, vpnGateway string) *VpnGatewaysGetCall { + c := &VpnGatewaysGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.vpnGateway = vpnGateway + 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 *VpnGatewaysGetCall) Fields(s ...googleapi.Field) *VpnGatewaysGetCall { + 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 *VpnGatewaysGetCall) IfNoneMatch(entityTag string) *VpnGatewaysGetCall { + 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 *VpnGatewaysGetCall) Context(ctx context.Context) *VpnGatewaysGetCall { + 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 *VpnGatewaysGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *VpnGatewaysGetCall) 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}/regions/{region}/vpnGateways/{vpnGateway}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "vpnGateway": c.vpnGateway, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.vpnGateways.get" call. +// Exactly one of *VpnGateway or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *VpnGateway.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 *VpnGatewaysGetCall) Do(opts ...googleapi.CallOption) (*VpnGateway, 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 := &VpnGateway{ + 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 VPN gateway. Gets a list of available VPN gateways by making a list() request.", + // "httpMethod": "GET", + // "id": "compute.vpnGateways.get", + // "parameterOrder": [ + // "project", + // "region", + // "vpnGateway" + // ], + // "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" + // }, + // "vpnGateway": { + // "description": "Name of the VPN gateway to return.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/vpnGateways/{vpnGateway}", + // "response": { + // "$ref": "VpnGateway" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.vpnGateways.insert": + +type VpnGatewaysInsertCall struct { + s *Service + project string + region string + vpngateway *VpnGateway + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a VPN gateway in the specified project and region +// using the data included in the request. +func (r *VpnGatewaysService) Insert(project string, region string, vpngateway *VpnGateway) *VpnGatewaysInsertCall { + c := &VpnGatewaysInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.vpngateway = vpngateway + 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 *VpnGatewaysInsertCall) RequestId(requestId string) *VpnGatewaysInsertCall { + 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 *VpnGatewaysInsertCall) Fields(s ...googleapi.Field) *VpnGatewaysInsertCall { + 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 *VpnGatewaysInsertCall) Context(ctx context.Context) *VpnGatewaysInsertCall { + 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 *VpnGatewaysInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *VpnGatewaysInsertCall) 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.vpngateway) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnGateways") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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.vpnGateways.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 *VpnGatewaysInsertCall) 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 VPN gateway in the specified project and region using the data included in the request.", + // "httpMethod": "POST", + // "id": "compute.vpnGateways.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}/vpnGateways", + // "request": { + // "$ref": "VpnGateway" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.vpnGateways.list": + +type VpnGatewaysListCall struct { + s *Service + project string + region string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves a list of VPN gateways available to the specified +// project and region. +func (r *VpnGatewaysService) List(project string, region string) *VpnGatewaysListCall { + c := &VpnGatewaysListCall{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 *VpnGatewaysListCall) Filter(filter string) *VpnGatewaysListCall { + 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 *VpnGatewaysListCall) MaxResults(maxResults int64) *VpnGatewaysListCall { + 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 *VpnGatewaysListCall) OrderBy(orderBy string) *VpnGatewaysListCall { + 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 *VpnGatewaysListCall) PageToken(pageToken string) *VpnGatewaysListCall { + 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 *VpnGatewaysListCall) Fields(s ...googleapi.Field) *VpnGatewaysListCall { + 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 *VpnGatewaysListCall) IfNoneMatch(entityTag string) *VpnGatewaysListCall { + 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 *VpnGatewaysListCall) Context(ctx context.Context) *VpnGatewaysListCall { + 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 *VpnGatewaysListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *VpnGatewaysListCall) 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}/regions/{region}/vpnGateways") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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.vpnGateways.list" call. +// Exactly one of *VpnGatewayList or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *VpnGatewayList.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 *VpnGatewaysListCall) Do(opts ...googleapi.CallOption) (*VpnGatewayList, 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 := &VpnGatewayList{ + 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 VPN gateways available to the specified project and region.", + // "httpMethod": "GET", + // "id": "compute.vpnGateways.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}/vpnGateways", + // "response": { + // "$ref": "VpnGatewayList" + // }, + // "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 *VpnGatewaysListCall) Pages(ctx context.Context, f func(*VpnGatewayList) 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.vpnGateways.setLabels": + +type VpnGatewaysSetLabelsCall struct { + s *Service + project string + region string + resource string + regionsetlabelsrequest *RegionSetLabelsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetLabels: Sets the labels on a VpnGateway. To learn more about +// labels, read the Labeling Resources documentation. +func (r *VpnGatewaysService) SetLabels(project string, region string, resource string, regionsetlabelsrequest *RegionSetLabelsRequest) *VpnGatewaysSetLabelsCall { + c := &VpnGatewaysSetLabelsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resource = resource + c.regionsetlabelsrequest = regionsetlabelsrequest + 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 *VpnGatewaysSetLabelsCall) RequestId(requestId string) *VpnGatewaysSetLabelsCall { + 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 *VpnGatewaysSetLabelsCall) Fields(s ...googleapi.Field) *VpnGatewaysSetLabelsCall { + 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 *VpnGatewaysSetLabelsCall) Context(ctx context.Context) *VpnGatewaysSetLabelsCall { + 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 *VpnGatewaysSetLabelsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *VpnGatewaysSetLabelsCall) 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.regionsetlabelsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnGateways/{resource}/setLabels") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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.vpnGateways.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 *VpnGatewaysSetLabelsCall) 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 VpnGateway. To learn more about labels, read the Labeling Resources documentation.", + // "httpMethod": "POST", + // "id": "compute.vpnGateways.setLabels", + // "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 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" + // }, + // "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" + // } + // }, + // "path": "{project}/regions/{region}/vpnGateways/{resource}/setLabels", + // "request": { + // "$ref": "RegionSetLabelsRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.vpnGateways.testIamPermissions": + +type VpnGatewaysTestIamPermissionsCall 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 *VpnGatewaysService) TestIamPermissions(project string, region string, resource string, testpermissionsrequest *TestPermissionsRequest) *VpnGatewaysTestIamPermissionsCall { + c := &VpnGatewaysTestIamPermissionsCall{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 *VpnGatewaysTestIamPermissionsCall) Fields(s ...googleapi.Field) *VpnGatewaysTestIamPermissionsCall { + 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 *VpnGatewaysTestIamPermissionsCall) Context(ctx context.Context) *VpnGatewaysTestIamPermissionsCall { + 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 *VpnGatewaysTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *VpnGatewaysTestIamPermissionsCall) 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}/regions/{region}/vpnGateways/{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, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.vpnGateways.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 *VpnGatewaysTestIamPermissionsCall) 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.vpnGateways.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 of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/vpnGateways/{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.vpnTunnels.aggregatedList": type VpnTunnelsAggregatedListCall struct { @@ -117984,32 +131375,28 @@ func (r *VpnTunnelsService) AggregatedList(project string) *VpnTunnelsAggregated return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *VpnTunnelsAggregatedListCall) Filter(filter string) *VpnTunnelsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -118153,7 +131540,7 @@ func (c *VpnTunnelsAggregatedListCall) Do(opts ...googleapi.CallOption) (*VpnTun // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -118401,7 +131788,7 @@ type VpnTunnelsGetCall struct { header_ http.Header } -// Get: Returns the specified VpnTunnel resource. Get a list of +// Get: Returns the specified VpnTunnel resource. Gets a list of // available VPN tunnels by making a list() request. func (r *VpnTunnelsService) Get(project string, region string, vpnTunnel string) *VpnTunnelsGetCall { c := &VpnTunnelsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -118507,7 +131894,7 @@ func (c *VpnTunnelsGetCall) Do(opts ...googleapi.CallOption) (*VpnTunnel, error) } return ret, nil // { - // "description": "Returns the specified VpnTunnel resource. Get a list of available VPN tunnels by making a list() request.", + // "description": "Returns the specified VpnTunnel resource. Gets a list of available VPN tunnels by making a list() request.", // "httpMethod": "GET", // "id": "compute.vpnTunnels.get", // "parameterOrder": [ @@ -118743,32 +132130,28 @@ func (r *VpnTunnelsService) List(project string, region string) *VpnTunnelsListC return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *VpnTunnelsListCall) Filter(filter string) *VpnTunnelsListCall { c.urlParams_.Set("filter", filter) return c @@ -118914,7 +132297,7 @@ func (c *VpnTunnelsListCall) Do(opts ...googleapi.CallOption) (*VpnTunnelList, e // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -119631,32 +133014,28 @@ func (r *ZoneOperationsService) List(project string, zone string) *ZoneOperation return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ZoneOperationsListCall) Filter(filter string) *ZoneOperationsListCall { c.urlParams_.Set("filter", filter) return c @@ -119802,7 +133181,7 @@ func (c *ZoneOperationsListCall) Do(opts ...googleapi.CallOption) (*OperationLis // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -119873,6 +133252,163 @@ func (c *ZoneOperationsListCall) Pages(ctx context.Context, f func(*OperationLis } } +// method id "compute.zoneOperations.wait": + +type ZoneOperationsWaitCall struct { + s *Service + project string + zone string + operation string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Wait: Waits for the specified zone-specific 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 *ZoneOperationsService) Wait(project string, zone string, operation string) *ZoneOperationsWaitCall { + c := &ZoneOperationsWaitCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.operation = operation + 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 *ZoneOperationsWaitCall) Fields(s ...googleapi.Field) *ZoneOperationsWaitCall { + 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 *ZoneOperationsWaitCall) Context(ctx context.Context) *ZoneOperationsWaitCall { + 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 *ZoneOperationsWaitCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ZoneOperationsWaitCall) 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}/operations/{operation}/wait") + 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, + "operation": c.operation, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.zoneOperations.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 *ZoneOperationsWaitCall) 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 zone-specific 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.zoneOperations.wait", + // "parameterOrder": [ + // "project", + // "zone", + // "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" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{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}/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.zones.get": type ZonesGetCall struct { @@ -119885,7 +133421,7 @@ type ZonesGetCall struct { header_ http.Header } -// Get: Returns the specified Zone resource. Get a list of available +// Get: Returns the specified Zone resource. Gets a list of available // zones by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/zones/get func (r *ZonesService) Get(project string, zone string) *ZonesGetCall { @@ -119990,7 +133526,7 @@ func (c *ZonesGetCall) Do(opts ...googleapi.CallOption) (*Zone, error) { } return ret, nil // { - // "description": "Returns the specified Zone resource. Get a list of available zones by making a list() request.", + // "description": "Returns the specified Zone resource. Gets a list of available zones by making a list() request.", // "httpMethod": "GET", // "id": "compute.zones.get", // "parameterOrder": [ @@ -120046,32 +133582,28 @@ func (r *ZonesService) List(project string) *ZonesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ZonesListCall) Filter(filter string) *ZonesListCall { c.urlParams_.Set("filter", filter) return c @@ -120215,7 +133747,7 @@ func (c *ZonesListCall) Do(opts ...googleapi.CallOption) (*ZoneList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, 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 690984a1541..ca392282063 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": "\"-iA1DTNe4s-I6JZXPt1t1Ypy8IU/JrYQUQoo567cA8hFPPaVrcEEzOY\"", + "etag": "\"Zkyw9ACJZUvcYmlFaKGChzhmtnE/gQPyaiSDCaC01bTsNohkwKrRGFY\"", "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" @@ -74,12 +74,12 @@ "type": "boolean" }, "quotaUser": { - "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.", + "description": "An opaque string that represents a user for quota purposes. Must not exceed 40 characters.", "location": "query", "type": "string" }, "userIp": { - "description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.", + "description": "Deprecated. Please use quotaUser instead.", "location": "query", "type": "string" } @@ -97,7 +97,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -138,7 +138,7 @@ ] }, "get": { - "description": "Returns the specified accelerator type. Get a list of available accelerator types by making a list() request.", + "description": "Returns the specified accelerator type.", "httpMethod": "GET", "id": "compute.acceleratorTypes.get", "parameterOrder": [ @@ -189,7 +189,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -249,7 +249,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -428,7 +428,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -582,7 +582,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -669,7 +669,7 @@ ] }, "get": { - "description": "Returns the specified autoscaler resource. Get a list of available autoscalers by making a list() request.", + "description": "Returns the specified autoscaler resource. Gets a list of available autoscalers by making a list() request.", "httpMethod": "GET", "id": "compute.autoscalers.get", "parameterOrder": [ @@ -761,7 +761,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1074,7 +1074,7 @@ ] }, "get": { - "description": "Returns the specified BackendBucket resource. Get a list of available backend buckets by making a list() request.", + "description": "Returns the specified BackendBucket resource. Gets a list of available backend buckets by making a list() request.", "httpMethod": "GET", "id": "compute.backendBuckets.get", "parameterOrder": [ @@ -1149,7 +1149,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1324,7 +1324,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1447,7 +1447,7 @@ ] }, "get": { - "description": "Returns the specified BackendService resource. Get a list of available backend services by making a list() request.", + "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", "httpMethod": "GET", "id": "compute.backendServices.get", "parameterOrder": [ @@ -1558,7 +1558,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1770,7 +1770,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1811,7 +1811,7 @@ ] }, "get": { - "description": "Returns the specified disk type. Get a list of available disk types by making a list() request.", + "description": "Returns the specified disk type. Gets a list of available disk types by making a list() request.", "httpMethod": "GET", "id": "compute.diskTypes.get", "parameterOrder": [ @@ -1862,7 +1862,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1922,7 +1922,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2061,7 +2061,7 @@ ] }, "get": { - "description": "Returns a specified persistent disk. Get a list of available persistent disks by making a list() request.", + "description": "Returns a specified persistent disk. Gets a list of available persistent disks by making a list() request.", "httpMethod": "GET", "id": "compute.disks.get", "parameterOrder": [ @@ -2158,7 +2158,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2466,7 +2466,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2638,7 +2638,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2817,7 +2817,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3050,7 +3050,7 @@ ] }, "get": { - "description": "Returns the specified address resource. Get a list of available addresses by making a list() request.", + "description": "Returns the specified address resource. Gets a list of available addresses by making a list() request.", "httpMethod": "GET", "id": "compute.globalAddresses.get", "parameterOrder": [ @@ -3125,7 +3125,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3281,7 +3281,7 @@ ] }, "get": { - "description": "Returns the specified GlobalForwardingRule resource. Get a list of available forwarding rules by making a list() request.", + "description": "Returns the specified GlobalForwardingRule resource. Gets a list of available forwarding rules by making a list() request.", "httpMethod": "GET", "id": "compute.globalForwardingRules.get", "parameterOrder": [ @@ -3356,7 +3356,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3523,7 +3523,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3594,7 +3594,7 @@ ] }, "get": { - "description": "Retrieves the specified Operations resource. Get a list of operations by making a list() request.", + "description": "Retrieves the specified Operations resource. Gets a list of operations by making a list() request.", "httpMethod": "GET", "id": "compute.globalOperations.get", "parameterOrder": [ @@ -3636,7 +3636,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3719,7 +3719,7 @@ ] }, "get": { - "description": "Returns the specified HealthCheck resource. Get a list of available health checks by making a list() request.", + "description": "Returns the specified HealthCheck resource. Gets a list of available health checks by making a list() request.", "httpMethod": "GET", "id": "compute.healthChecks.get", "parameterOrder": [ @@ -3794,7 +3794,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3996,7 +3996,7 @@ ] }, "get": { - "description": "Returns the specified HttpHealthCheck resource. Get a list of available HTTP health checks by making a list() request.", + "description": "Returns the specified HttpHealthCheck resource. Gets a list of available HTTP health checks by making a list() request.", "httpMethod": "GET", "id": "compute.httpHealthChecks.get", "parameterOrder": [ @@ -4071,7 +4071,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4273,7 +4273,7 @@ ] }, "get": { - "description": "Returns the specified HttpsHealthCheck resource. Get a list of available HTTPS health checks by making a list() request.", + "description": "Returns the specified HttpsHealthCheck resource. Gets a list of available HTTPS health checks by making a list() request.", "httpMethod": "GET", "id": "compute.httpsHealthChecks.get", "parameterOrder": [ @@ -4348,7 +4348,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4591,7 +4591,7 @@ ] }, "get": { - "description": "Returns the specified image. Get a list of available images by making a list() request.", + "description": "Returns the specified image. Gets a list of available images by making a list() request.", "httpMethod": "GET", "id": "compute.images.get", "parameterOrder": [ @@ -4708,7 +4708,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4881,7 +4881,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5013,7 +5013,7 @@ ] }, "get": { - "description": "Returns all of the details about the specified managed instance group. Get a list of available managed instance groups by making a list() request.", + "description": "Returns all of the details about the specified managed instance group. Gets a list of available managed instance groups by making a list() request.", "httpMethod": "GET", "id": "compute.instanceGroupManagers.get", "parameterOrder": [ @@ -5102,7 +5102,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5693,7 +5693,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5778,7 +5778,7 @@ ] }, "get": { - "description": "Returns the specified instance group. Get a list of available instance groups by making a list() request.", + "description": "Returns the specified instance group. Gets a list of available instance groups by making a list() request.", "httpMethod": "GET", "id": "compute.instanceGroups.get", "parameterOrder": [ @@ -5867,7 +5867,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5924,7 +5924,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -6161,7 +6161,7 @@ ] }, "get": { - "description": "Returns the specified instance template. Get a list of available instance templates by making a list() request.", + "description": "Returns the specified instance template. Gets a list of available instance templates by making a list() request.", "httpMethod": "GET", "id": "compute.instanceTemplates.get", "parameterOrder": [ @@ -6236,7 +6236,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -6382,7 +6382,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -6636,7 +6636,7 @@ ] }, "get": { - "description": "Returns the specified Instance resource. Get a list of available instances by making a list() request.", + "description": "Returns the specified Instance resource. Gets a list of available instances by making a list() request.", "httpMethod": "GET", "id": "compute.instances.get", "parameterOrder": [ @@ -6790,7 +6790,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -6848,7 +6848,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -7404,6 +7404,55 @@ "https://www.googleapis.com/auth/compute" ] }, + "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.", + "httpMethod": "PATCH", + "id": "compute.instances.setShieldedVmIntegrityPolicy", + "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}/setShieldedVmIntegrityPolicy", + "request": { + "$ref": "ShieldedVmIntegrityPolicy" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setTags": { "description": "Sets tags for the specified instance to the data included in the request.", "httpMethod": "POST", @@ -7453,8 +7502,49 @@ "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])?", + "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 using the instances().stop method. For more information, see Restart an instance.", + "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", "httpMethod": "POST", "id": "compute.instances.start", "parameterOrder": [ @@ -7500,7 +7590,7 @@ ] }, "startWithEncryptionKey": { - "description": "Starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance.", + "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", "httpMethod": "POST", "id": "compute.instances.startWithEncryptionKey", "parameterOrder": [ @@ -7750,6 +7840,55 @@ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/compute" ] + }, + "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.", + "httpMethod": "PATCH", + "id": "compute.instances.updateShieldedVmConfig", + "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}/updateShieldedVmConfig", + "request": { + "$ref": "ShieldedVmConfig" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] } } }, @@ -7764,7 +7903,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -7943,7 +8082,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8138,7 +8277,7 @@ "interconnectLocations": { "methods": { "get": { - "description": "Returns the details for the specified interconnect location. Get a list of available interconnect locations by making a list() request.", + "description": "Returns the details for the specified interconnect location. Gets a list of available interconnect locations by making a list() request.", "httpMethod": "GET", "id": "compute.interconnectLocations.get", "parameterOrder": [ @@ -8180,7 +8319,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8338,7 +8477,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8643,7 +8782,7 @@ ] }, "list": { - "description": "Retrieves the list of licenses available in the specified project. This method does not get any licenses that belong to other projects, including licenses attached to publicly-available images, like Debian 8. If you want to get a list of publicly-available licenses, use this method to make a request to the respective image project, such as debian-cloud or windows-cloud.", + "description": "Retrieves the list of licenses available in the specified project. This method does not get any licenses that belong to other projects, including licenses attached to publicly-available images, like Debian 9. If you want to get a list of publicly-available licenses, use this method to make a request to the respective image project, such as debian-cloud or windows-cloud.", "httpMethod": "GET", "id": "compute.licenses.list", "parameterOrder": [ @@ -8651,7 +8790,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8704,7 +8843,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8745,7 +8884,7 @@ ] }, "get": { - "description": "Returns the specified machine type. Get a list of available machine types by making a list() request.", + "description": "Returns the specified machine type. Gets a list of available machine types by making a list() request.", "httpMethod": "GET", "id": "compute.machineTypes.get", "parameterOrder": [ @@ -8796,7 +8935,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8927,7 +9066,7 @@ ] }, "get": { - "description": "Returns the specified network. Get a list of available networks by making a list() request.", + "description": "Returns the specified network. Gets a list of available networks by making a list() request.", "httpMethod": "GET", "id": "compute.networks.get", "parameterOrder": [ @@ -9002,7 +9141,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -9201,6 +9340,1053 @@ } } }, + "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 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}/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.", + "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.", + "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 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}/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.", + "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" + ] + }, + "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 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}/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 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}/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 of the resource 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/{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 of the resource 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/{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 of the resource 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/{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": { @@ -9356,7 +10542,7 @@ ] }, "getXpnHost": { - "description": "Get the shared VPC host project that this project links to. May be empty if no link exists.", + "description": "Gets the shared VPC host project that this project links to. May be empty if no link exists.", "httpMethod": "GET", "id": "compute.projects.getXpnHost", "parameterOrder": [ @@ -9381,7 +10567,7 @@ ] }, "getXpnResources": { - "description": "Get service resources (a.k.a service project) associated with this host project.", + "description": "Gets service resources (a.k.a service project) associated with this host project.", "httpMethod": "GET", "id": "compute.projects.getXpnResources", "parameterOrder": [ @@ -9425,7 +10611,7 @@ ] }, "listXpnHosts": { - "description": "List all shared VPC host projects visible to the user in an organization.", + "description": "Lists all shared VPC host projects visible to the user in an organization.", "httpMethod": "POST", "id": "compute.projects.listXpnHosts", "parameterOrder": [ @@ -9782,7 +10968,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10155,7 +11341,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10358,7 +11544,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10399,7 +11585,7 @@ ] }, "get": { - "description": "Returns the specified commitment resource. Get a list of available commitments by making a list() request.", + "description": "Returns the specified commitment resource. Gets a list of available commitments by making a list() request.", "httpMethod": "GET", "id": "compute.regionCommitments.get", "parameterOrder": [ @@ -10491,7 +11677,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10543,7 +11729,7 @@ "regionDiskTypes": { "methods": { "get": { - "description": "Returns the specified regional disk type. Get a list of available disk types by making a list() request.", + "description": "Returns the specified regional disk type. Gets a list of available disk types by making a list() request.", "httpMethod": "GET", "id": "compute.regionDiskTypes.get", "parameterOrder": [ @@ -10594,7 +11780,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10837,7 +12023,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11259,7 +12445,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11798,7 +12984,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11855,7 +13041,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -12096,7 +13282,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -12148,7 +13334,7 @@ "regions": { "methods": { "get": { - "description": "Returns the specified Region resource. Get a list of available regions by making a list() request.", + "description": "Returns the specified Region resource. Gets a list of available regions by making a list() request.", "httpMethod": "GET", "id": "compute.regions.get", "parameterOrder": [ @@ -12190,7 +13376,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -12243,7 +13429,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -12330,7 +13516,7 @@ ] }, "get": { - "description": "Returns the specified Router resource. Get a list of available routers by making a list() request.", + "description": "Returns the specified Router resource. Gets a list of available routers by making a list() request.", "httpMethod": "GET", "id": "compute.routers.get", "parameterOrder": [ @@ -12464,7 +13650,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -12742,7 +13928,7 @@ ] }, "get": { - "description": "Returns the specified Route resource. Get a list of available routes by making a list() request.", + "description": "Returns the specified Route resource. Gets a list of available routes by making a list() request.", "httpMethod": "GET", "id": "compute.routes.get", "parameterOrder": [ @@ -12817,7 +14003,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13088,7 +14274,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13330,7 +14516,7 @@ ] }, "get": { - "description": "Returns the specified Snapshot resource. Get a list of available snapshots by making a list() request.", + "description": "Returns the specified Snapshot resource. Gets a list of available snapshots by making a list() request.", "httpMethod": "GET", "id": "compute.snapshots.get", "parameterOrder": [ @@ -13372,7 +14558,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13528,7 +14714,7 @@ ] }, "get": { - "description": "Returns the specified SslCertificate resource. Get a list of available SSL certificates by making a list() request.", + "description": "Returns the specified SslCertificate resource. Gets a list of available SSL certificates by making a list() request.", "httpMethod": "GET", "id": "compute.sslCertificates.get", "parameterOrder": [ @@ -13603,7 +14789,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13722,7 +14908,7 @@ ] }, "get": { - "description": "List all of the ordered rules present in a single specified policy.", + "description": "Lists all of the ordered rules present in a single specified policy.", "httpMethod": "GET", "id": "compute.sslPolicies.get", "parameterOrder": [ @@ -13755,7 +14941,7 @@ ] }, "insert": { - "description": "Returns the specified SSL policy resource. Get a list of available SSL policies by making a list() request.", + "description": "Returns the specified SSL policy resource. Gets a list of available SSL policies by making a list() request.", "httpMethod": "POST", "id": "compute.sslPolicies.insert", "parameterOrder": [ @@ -13788,7 +14974,7 @@ ] }, "list": { - "description": "List all the SSL policies that have been configured for the specified project.", + "description": "Lists all the SSL policies that have been configured for the specified project.", "httpMethod": "GET", "id": "compute.sslPolicies.list", "parameterOrder": [ @@ -13796,7 +14982,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13845,7 +15031,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13975,7 +15161,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -14111,7 +15297,7 @@ ] }, "get": { - "description": "Returns the specified subnetwork. Get a list of available subnetworks list() request.", + "description": "Returns the specified subnetwork. Gets a list of available subnetworks list() request.", "httpMethod": "GET", "id": "compute.subnetworks.get", "parameterOrder": [ @@ -14245,7 +15431,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -14301,7 +15487,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -14342,7 +15528,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 and allow_subnet_cidr_routes_overlap. 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 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.", "httpMethod": "PATCH", "id": "compute.subnetworks.patch", "parameterOrder": [ @@ -14424,7 +15610,7 @@ }, "path": "{project}/regions/{region}/subnetworks/{resource}/setIamPolicy", "request": { - "$ref": "Policy" + "$ref": "RegionSetPolicyRequest" }, "response": { "$ref": "Policy" @@ -14571,7 +15757,7 @@ ] }, "get": { - "description": "Returns the specified TargetHttpProxy resource. Get a list of available target HTTP proxies by making a list() request.", + "description": "Returns the specified TargetHttpProxy resource. Gets a list of available target HTTP proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetHttpProxies.get", "parameterOrder": [ @@ -14646,7 +15832,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -14807,7 +15993,7 @@ ] }, "get": { - "description": "Returns the specified TargetHttpsProxy resource. Get a list of available target HTTPS proxies by making a list() request.", + "description": "Returns the specified TargetHttpsProxy resource. Gets a list of available target HTTPS proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetHttpsProxies.get", "parameterOrder": [ @@ -14882,7 +16068,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -15134,7 +16320,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -15221,7 +16407,7 @@ ] }, "get": { - "description": "Returns the specified TargetInstance resource. Get a list of available target instances by making a list() request.", + "description": "Returns the specified TargetInstance resource. Gets a list of available target instances by making a list() request.", "httpMethod": "GET", "id": "compute.targetInstances.get", "parameterOrder": [ @@ -15313,7 +16499,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -15516,7 +16702,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -15603,7 +16789,7 @@ ] }, "get": { - "description": "Returns the specified target pool. Get a list of available target pools by making a list() request.", + "description": "Returns the specified target pool. Gets a list of available target pools by making a list() request.", "httpMethod": "GET", "id": "compute.targetPools.get", "parameterOrder": [ @@ -15740,7 +16926,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -16028,7 +17214,7 @@ ] }, "get": { - "description": "Returns the specified TargetSslProxy resource. Get a list of available target SSL proxies by making a list() request.", + "description": "Returns the specified TargetSslProxy resource. Gets a list of available target SSL proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetSslProxies.get", "parameterOrder": [ @@ -16103,7 +17289,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -16386,7 +17572,7 @@ ] }, "get": { - "description": "Returns the specified TargetTcpProxy resource. Get a list of available target TCP proxies by making a list() request.", + "description": "Returns the specified TargetTcpProxy resource. Gets a list of available target TCP proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetTcpProxies.get", "parameterOrder": [ @@ -16461,7 +17647,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -16596,7 +17782,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -16683,7 +17869,7 @@ ] }, "get": { - "description": "Returns the specified target VPN gateway. Get a list of available target VPN gateways by making a list() request.", + "description": "Returns the specified target VPN gateway. Gets a list of available target VPN gateways by making a list() request.", "httpMethod": "GET", "id": "compute.targetVpnGateways.get", "parameterOrder": [ @@ -16775,7 +17961,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -16959,7 +18145,7 @@ ] }, "get": { - "description": "Returns the specified UrlMap resource. Get a list of available URL maps by making a list() request.", + "description": "Returns the specified UrlMap resource. Gets a list of available URL maps by making a list() request.", "httpMethod": "GET", "id": "compute.urlMaps.get", "parameterOrder": [ @@ -17075,7 +18261,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -17283,7 +18469,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -17370,7 +18556,7 @@ ] }, "get": { - "description": "Returns the specified VpnTunnel resource. Get a list of available VPN tunnels by making a list() request.", + "description": "Returns the specified VpnTunnel resource. Gets a list of available VPN tunnels by making a list() request.", "httpMethod": "GET", "id": "compute.vpnTunnels.get", "parameterOrder": [ @@ -17462,7 +18648,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -17697,7 +18883,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -17749,7 +18935,7 @@ "zones": { "methods": { "get": { - "description": "Returns the specified Zone resource. Get a list of available zones by making a list() request.", + "description": "Returns the specified Zone resource. Gets a list of available zones by making a list() request.", "httpMethod": "GET", "id": "compute.zones.get", "parameterOrder": [ @@ -17791,7 +18977,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -17834,7 +19020,7 @@ } } }, - "revision": "20180220", + "revision": "20180518", "rootUrl": "https://www.googleapis.com/", "schemas": { "AcceleratorConfig": { @@ -18128,7 +19314,7 @@ "id": "AcceleratorTypesScopedList", "properties": { "acceleratorTypes": { - "description": "[Output Only] List of accelerator types contained in this scope.", + "description": "[Output Only] A list of accelerator types contained in this scope.", "items": { "$ref": "AcceleratorType" }, @@ -18619,7 +19805,7 @@ "id": "AddressesScopedList", "properties": { "addresses": { - "description": "[Output Only] List of addresses contained in this scope.", + "description": "[Output Only] A list of addresses contained in this scope.", "items": { "$ref": "Address" }, @@ -19296,7 +20482,7 @@ "id": "AutoscalersScopedList", "properties": { "autoscalers": { - "description": "[Output Only] List of autoscalers contained in this scope.", + "description": "[Output Only] A list of autoscalers contained in this scope.", "items": { "$ref": "Autoscaler" }, @@ -19749,6 +20935,13 @@ "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" }, + "customRequestHeaders": { + "description": "Headers that the HTTP/S load balancer should add to proxied requests.", + "items": { + "type": "string" + }, + "type": "array" + }, "description": { "description": "An optional description of this resource. Provide this property when you create the resource.", "type": "string" @@ -19814,6 +21007,7 @@ "description": "The protocol this BackendService uses to communicate with backends.\n\nPossible values are HTTP, HTTPS, TCP, and SSL. The default is HTTP.\n\nFor internal load balancing, the possible values are TCP and UDP, and the default is TCP.", "enum": [ "HTTP", + "HTTP2", "HTTPS", "SSL", "TCP", @@ -19824,6 +21018,7 @@ "", "", "", + "", "" ], "type": "string" @@ -20155,7 +21350,7 @@ "id": "BackendServicesScopedList", "properties": { "backendServices": { - "description": "List of BackendServices contained in this scope.", + "description": "A list of BackendServices contained in this scope.", "items": { "$ref": "BackendService" }, @@ -20254,7 +21449,7 @@ "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." }, "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` or `joe@example.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`.", + "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" }, @@ -20363,7 +21558,7 @@ "type": "string" }, "resources": { - "description": "List of commitment amounts for particular resources. Note that VCPU and MEMORY resource commitments must occur together.", + "description": "A list of commitment amounts for particular resources. Note that VCPU and MEMORY resource commitments must occur together.", "items": { "$ref": "ResourceCommitment" }, @@ -20628,7 +21823,7 @@ "id": "CommitmentsScopedList", "properties": { "commitments": { - "description": "[Output Only] List of commitments contained in this scope.", + "description": "[Output Only] A list of commitments contained in this scope.", "items": { "$ref": "Commitment" }, @@ -20816,12 +22011,16 @@ "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" }, "rsaEncryptedKey": { - "description": "Specifies an RFC 4648 base64 encoded, RSA-wrapped 2048-bit customer-supplied encryption key to either encrypt or decrypt this resource.\n\nThe key must meet the following requirements before you can provide it to Compute Engine: \n- The key is wrapped using a RSA public key certificate provided by Google. \n- After being wrapped, the key must be encoded in RFC 4648 base64 encoding. Get the RSA public key certificate provided by Google at:\nhttps://cloud-certs.storage.googleapis.com/google-cloud-csek-ingress.pem", + "description": "Specifies an RFC 4648 base64 encoded, RSA-wrapped 2048-bit customer-supplied encryption key to either encrypt or decrypt this resource.\n\nThe key must meet the following requirements before you can provide it to Compute Engine: \n- The key is wrapped using a RSA public key certificate provided by Google. \n- After being wrapped, the key must be encoded in RFC 4648 base64 encoding. Gets the RSA public key certificate provided by Google at:\nhttps://cloud-certs.storage.googleapis.com/google-cloud-csek-ingress.pem", "type": "string" }, "sha256": { @@ -21369,6 +22568,10 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, + "region": { + "description": "[Output Only] URL of the region where the disk type 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" + }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" @@ -21612,7 +22815,7 @@ "id": "DiskTypesScopedList", "properties": { "diskTypes": { - "description": "[Output Only] List of disk types contained in this scope.", + "description": "[Output Only] A list of disk types contained in this scope.", "items": { "$ref": "DiskType" }, @@ -21717,7 +22920,7 @@ "id": "DisksScopedList", "properties": { "disks": { - "description": "[Output Only] List of disks contained in this scope.", + "description": "[Output Only] A list of disks contained in this scope.", "items": { "$ref": "Disk" }, @@ -21929,6 +23132,14 @@ ], "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" + }, + "enableLogging": { + "description": "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": { "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", "format": "uint64", @@ -22513,7 +23724,7 @@ "id": "ForwardingRulesScopedList", "properties": { "forwardingRules": { - "description": "List of forwarding rules contained in this scope.", + "description": "A list of forwarding rules contained in this scope.", "items": { "$ref": "ForwardingRule" }, @@ -22648,6 +23859,45 @@ }, "type": "object" }, + "HTTP2HealthCheck": { + "id": "HTTP2HealthCheck", + "properties": { + "host": { + "description": "The value of the host header in the HTTP/2 health check request. If left empty (default value), the IP on behalf of which this health check is performed will be used.", + "type": "string" + }, + "port": { + "description": "The TCP port number for the health check request. The default value is 443. 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" + }, + "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": [ + "NONE", + "PROXY_V1" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, + "requestPath": { + "description": "The request path of the HTTP/2 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" + }, "HTTPHealthCheck": { "id": "HTTPHealthCheck", "properties": { @@ -22748,6 +23998,9 @@ "format": "int32", "type": "integer" }, + "http2HealthCheck": { + "$ref": "HTTP2HealthCheck" + }, "httpHealthCheck": { "$ref": "HTTPHealthCheck" }, @@ -22788,6 +24041,7 @@ "description": "Specifies the type of the healthCheck, either TCP, SSL, HTTP or HTTPS. If not specified, the default is TCP. Exactly one of the protocol-specific health check field must be specified, which must match type field.", "enum": [ "HTTP", + "HTTP2", "HTTPS", "INVALID", "SSL", @@ -22800,6 +24054,7 @@ "", "", "", + "", "" ], "type": "string" @@ -23678,7 +24933,7 @@ "type": "array" }, "guestAccelerators": { - "description": "List of the type and count of accelerator cards attached to the instance.", + "description": "A list of the type and count of accelerator cards attached to the instance.", "items": { "$ref": "AcceleratorConfig" }, @@ -23695,7 +24950,7 @@ "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 instance.", + "description": "A fingerprint for this request, which is essentially a hash of the label's contents and 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 instance.", "format": "byte", "type": "string" }, @@ -23755,6 +25010,12 @@ }, "type": "array" }, + "shieldedVmConfig": { + "$ref": "ShieldedVmConfig" + }, + "shieldedVmIntegrityPolicy": { + "$ref": "ShieldedVmIntegrityPolicy" + }, "startRestricted": { "description": "[Output Only] Whether a VM has been restricted for start because Compute Engine has detected suspicious activity.", "type": "boolean" @@ -23959,7 +25220,7 @@ "type": "string" }, "region": { - "description": "The URL of the region where the instance group is located (for regional resources).", + "description": "[Output Only] The URL of the region where the instance group is located (for regional resources).", "type": "string" }, "selfLink": { @@ -23972,7 +25233,7 @@ "type": "integer" }, "subnetwork": { - "description": "The URL of the subnetwork to which all instances in the instance group belong.", + "description": "[Output Only] The URL of the subnetwork to which all instances in the instance group belong.", "type": "string" }, "zone": { @@ -24256,7 +25517,7 @@ "type": "string" }, "fingerprint": { - "description": "[Output Only] The fingerprint of the resource data. You can use this optional field for optimistic locking when you update the resource.", + "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.", "format": "byte", "type": "string" }, @@ -24309,7 +25570,7 @@ "type": "string" }, "serviceAccount": { - "description": "[Output Only] 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.", + "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" }, "targetPools": { @@ -25501,6 +26762,10 @@ }, "type": "array" }, + "shieldedVmConfig": { + "$ref": "ShieldedVmConfig", + "description": "Specifies the Shielded VM options for the instances that are created from this template." + }, "tags": { "$ref": "Tags", "description": "A list of tags to apply to the instances that are created from this template. 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." @@ -25726,7 +26991,7 @@ "id": "InstancesScopedList", "properties": { "instances": { - "description": "[Output Only] List of instances contained in this scope.", + "description": "[Output Only] A list of instances contained in this scope.", "items": { "$ref": "Instance" }, @@ -25837,7 +27102,7 @@ "id": "InstancesSetMachineResourcesRequest", "properties": { "guestAccelerators": { - "description": "List of the type and count of accelerator cards attached to the instance.", + "description": "A list of the type and count of accelerator cards attached to the instance.", "items": { "$ref": "AcceleratorConfig" }, @@ -25905,7 +27170,7 @@ "type": "boolean" }, "circuitInfos": { - "description": "[Output Only] List of CircuitInfo objects, that describe the individual circuits in this LAG.", + "description": "[Output Only] A list of CircuitInfo objects, that describe the individual circuits in this LAG.", "items": { "$ref": "InterconnectCircuitInfo" }, @@ -25924,7 +27189,7 @@ "type": "string" }, "expectedOutages": { - "description": "[Output Only] List of outages expected for this Interconnect.", + "description": "[Output Only] A list of outages expected for this Interconnect.", "items": { "$ref": "InterconnectOutageNotification" }, @@ -25954,9 +27219,11 @@ "description": "Type of interconnect. Note that \"IT_PRIVATE\" has been deprecated in favor of \"DEDICATED\"", "enum": [ "DEDICATED", - "IT_PRIVATE" + "IT_PRIVATE", + "PARTNER" ], "enumDescriptions": [ + "", "", "" ], @@ -26036,6 +27303,18 @@ "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" + }, + "state": { + "description": "[Output Only] The current state of whether or not this Interconnect is functional.", + "enum": [ + "ACTIVE", + "UNPROVISIONED" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" } }, "type": "object" @@ -26048,6 +27327,34 @@ "description": "Determines whether this Attachment will carry packets. Not present for PARTNER_PROVIDER.", "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.", + "enum": [ + "BPS_100M", + "BPS_10G", + "BPS_1G", + "BPS_200M", + "BPS_2G", + "BPS_300M", + "BPS_400M", + "BPS_500M", + "BPS_50M", + "BPS_5G" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, "candidateSubnets": { "description": "Up to 16 candidate prefixes that can be used to restrict the allocation of cloudRouterIpAddress and customerRouterIpAddress for this attachment. All prefixes must be within link-local address space (169.254.0.0/16) and must be /29 or shorter (/28, /27, etc). Google will attempt to select an unused /29 from the supplied candidate prefix(es). The request will fail if all possible /29s are in use on Google?s edge. If not supplied, Google will randomly select an unused /29 from all of link-local space.", "items": { @@ -26071,6 +27378,20 @@ "description": "An optional description of this resource.", "type": "string" }, + "edgeAvailabilityDomain": { + "description": "Desired availability domain for the attachment. Only available for type PARTNER, at creation time. For improved reliability, customers should configure a pair of attachments with one per availability domain. The selected availability domain will be provided to the Partner via the pairing key so that the provisioned circuit will lie in the specified domain. If not specified, the value will default to AVAILABILITY_DOMAIN_ANY.", + "enum": [ + "AVAILABILITY_DOMAIN_1", + "AVAILABILITY_DOMAIN_2", + "AVAILABILITY_DOMAIN_ANY" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, "googleReferenceId": { "description": "[Output Only] Google reference ID, to be used when raising support tickets with Google or otherwise to debug backend connectivity issues.", "type": "string" @@ -26118,6 +27439,19 @@ ], "type": "string" }, + "pairingKey": { + "description": "[Output only for type PARTNER. Input only for PARTNER_PROVIDER. Not present for DEDICATED]. The opaque identifier of an PARTNER attachment used to initiate provisioning with a selected partner. Of the form \"XXXXX/region/domain\"", + "type": "string" + }, + "partnerAsn": { + "description": "Optional BGP ASN for the router that should be supplied by a layer 3 Partner if they configured BGP on behalf of the customer. Output only for PARTNER type, input only for PARTNER_PROVIDER, not available for DEDICATED.", + "format": "int64", + "type": "string" + }, + "partnerMetadata": { + "$ref": "InterconnectAttachmentPartnerMetadata", + "description": "Informational metadata about Partner attachments from Partners to display to customers. Output only for for PARTNER type, mutable for PARTNER_PROVIDER, not available for DEDICATED." + }, "privateInterconnectInfo": { "$ref": "InterconnectAttachmentPrivateInfo", "description": "[Output Only] Information specific to an InterconnectAttachment. This property is populated if the interconnect that this is attached to is of type DEDICATED." @@ -26134,11 +27468,37 @@ "description": "[Output Only] Server-defined URL for the resource.", "type": "string" }, - "type": { + "state": { + "description": "[Output Only] The current state of this attachment's functionality.", "enum": [ - "DEDICATED" + "ACTIVE", + "DEFUNCT", + "PARTNER_REQUEST_RECEIVED", + "PENDING_CUSTOMER", + "PENDING_PARTNER", + "STATE_UNSPECIFIED", + "UNPROVISIONED" ], "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "type": { + "enum": [ + "DEDICATED", + "PARTNER", + "PARTNER_PROVIDER" + ], + "enumDescriptions": [ + "", + "", "" ], "type": "string" @@ -26375,6 +27735,25 @@ }, "type": "object" }, + "InterconnectAttachmentPartnerMetadata": { + "description": "Informational metadata about Partner attachments from Partners to display to customers. These fields are propagated from PARTNER_PROVIDER attachments to their corresponding PARTNER attachments.", + "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.", + "type": "string" + }, + "partnerName": { + "description": "Plain text name of the Partner providing this attachment. This value may be validated to match approved Partner values.", + "type": "string" + }, + "portalUrl": { + "description": "URL of the Partner?s portal for this Attachment. Partners may customise this to be a deep-link to the specific resource on the Partner portal. This value may be validated to match approved Partner values.", + "type": "string" + } + }, + "type": "object" + }, "InterconnectAttachmentPrivateInfo": { "description": "Information for an interconnect attachment when this belongs to an interconnect of type DEDICATED.", "id": "InterconnectAttachmentPrivateInfo", @@ -26391,7 +27770,7 @@ "id": "InterconnectAttachmentsScopedList", "properties": { "interconnectAttachments": { - "description": "List of interconnect attachments contained in this scope.", + "description": "A list of interconnect attachments contained in this scope.", "items": { "$ref": "InterconnectAttachment" }, @@ -26853,7 +28232,7 @@ "id": "InterconnectOutageNotification", "properties": { "affectedCircuits": { - "description": "Iff issue_type is IT_PARTIAL_OUTAGE, a list of the Google-side circuit IDs that will be affected.", + "description": "If issue_type is IT_PARTIAL_OUTAGE, a list of the Google-side circuit IDs that will be affected.", "items": { "type": "string" }, @@ -27554,7 +28933,7 @@ "id": "MachineTypesScopedList", "properties": { "machineTypes": { - "description": "[Output Only] List of machine types contained in this scope.", + "description": "[Output Only] A list of machine types contained in this scope.", "items": { "$ref": "MachineType" }, @@ -27875,7 +29254,7 @@ "type": "string" }, "peerings": { - "description": "[Output Only] List of network peerings for the resource.", + "description": "[Output Only] A list of network peerings for the resource.", "items": { "$ref": "NetworkPeering" }, @@ -28145,12 +29524,1231 @@ }, "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" + }, + "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" + }, + "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" + } + }, + "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" + }, + "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 charaicter, 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", "properties": { "clientOperationId": { - "description": "[Output Only] Reserved for future use.", + "description": "[Output Only] The value of `requestId` if you provided it in the request. Not present otherwise.", "type": "string" }, "creationTimestamp": { @@ -28590,7 +31188,7 @@ "id": "OperationsScopedList", "properties": { "operations": { - "description": "[Output Only] List of operations contained in this scope.", + "description": "[Output Only] A list of operations contained in this scope.", "items": { "$ref": "Operation" }, @@ -28725,7 +31323,7 @@ "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**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\nFor a description of IAM and its features, see the [IAM developer's guide](https://cloud.google.com/iam/docs).", + "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": { @@ -28947,16 +31545,20 @@ "INSTANCE_GROUP_MANAGERS", "INSTANCE_TEMPLATES", "INTERCONNECTS", + "INTERCONNECT_ATTACHMENTS_PER_REGION", + "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS", "INTERNAL_ADDRESSES", "IN_USE_ADDRESSES", "LOCAL_SSD_TOTAL_GB", "NETWORKS", "NVIDIA_K80_GPUS", "NVIDIA_P100_GPUS", + "NVIDIA_V100_GPUS", "PREEMPTIBLE_CPUS", "PREEMPTIBLE_LOCAL_SSD_GB", "PREEMPTIBLE_NVIDIA_K80_GPUS", "PREEMPTIBLE_NVIDIA_P100_GPUS", + "PREEMPTIBLE_NVIDIA_V100_GPUS", "REGIONAL_AUTOSCALERS", "REGIONAL_INSTANCE_GROUP_MANAGERS", "ROUTERS", @@ -29024,6 +31626,10 @@ "", "", "", + "", + "", + "", + "", "" ], "type": "string" @@ -29611,7 +32217,7 @@ "id": "RegionInstanceGroupManagersListInstancesResponse", "properties": { "managedInstances": { - "description": "List of managed instances.", + "description": "A list of managed instances.", "items": { "$ref": "ManagedInstance" }, @@ -29959,6 +32565,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", @@ -30583,6 +33211,18 @@ "description": "IP address of the interface inside Google Cloud Platform. Only IPv4 is supported.", "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.", + "enum": [ + "MANAGED_BY_ATTACHMENT", + "MANAGED_BY_USER" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, "name": { "description": "Name of this BGP peer. The name must be 1-63 characters long and comply with RFC1035.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", @@ -30615,6 +33255,18 @@ "description": "URI of the linked VPN tunnel. It must be in the same region as the router. Each interface can have at most one linked resource and it could either be a VPN Tunnel or an interconnect attachment.", "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.", + "enum": [ + "MANAGED_BY_ATTACHMENT", + "MANAGED_BY_USER" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, "name": { "description": "Name of this interface entry. The name must be 1-63 characters long and comply with RFC1035.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", @@ -30853,7 +33505,7 @@ "id": "RoutersScopedList", "properties": { "routers": { - "description": "List of routers contained in this scope.", + "description": "A list of routers contained in this scope.", "items": { "$ref": "Router" }, @@ -31052,6 +33704,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": [ @@ -31071,8 +33730,40 @@ }, "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'.", + "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", "id": "SecurityPolicy", "properties": { "creationTimestamp": { @@ -31104,7 +33795,7 @@ "type": "string" }, "rules": { - "description": "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.", + "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" }, @@ -31274,6 +33965,10 @@ "$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." }, + "expr": { + "$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": { @@ -31357,6 +34052,36 @@ }, "type": "object" }, + "ShieldedVmConfig": { + "description": "A set of Shielded VM options.", + "id": "ShieldedVmConfig", + "properties": { + "enableIntegrityMonitoring": { + "description": "Defines whether the instance should have integrity monitoring enabled.", + "type": "boolean" + }, + "enableSecureBoot": { + "description": "Defines whether the instance should have secure boot enabled.", + "type": "boolean" + }, + "enableVtpm": { + "description": "Defines whether the instance should have the TPM enabled.", + "type": "boolean" + } + }, + "type": "object" + }, + "ShieldedVmIntegrityPolicy": { + "description": "The policy describes how boot integrity measurements are evaluated.", + "id": "ShieldedVmIntegrityPolicy", + "properties": { + "updateAutoLearnPolicy": { + "description": "Triggers an auto relearn event: the integrity monitoring module copies existing guest measurements to the baseline.", + "type": "boolean" + } + }, + "type": "object" + }, "SignedUrlKey": { "description": "Represents a customer-supplied Signing Key used by Cloud CDN Signed URLs", "id": "SignedUrlKey", @@ -31413,7 +34138,7 @@ "type": "object" }, "licenseCodes": { - "description": "Integer license codes indicating which licenses are attached to this snapshot.", + "description": "[Output Only] Integer license codes indicating which licenses are attached to this snapshot.", "items": { "format": "int64", "type": "string" @@ -31902,7 +34627,7 @@ "type": "string" }, "customFeatures": { - "description": "List of features enabled when the selected profile is CUSTOM. The\n- method returns the set of features that can be specified in this list. This field must be empty if the profile is not CUSTOM.", + "description": "A list of features enabled when the selected profile is CUSTOM. The\n- method returns the set of features that can be specified in this list. This field must be empty if the profile is not CUSTOM.", "items": { "type": "string" }, @@ -31935,15 +34660,13 @@ "type": "string" }, "minTlsVersion": { - "description": "The minimum version of SSL protocol that can be used by the clients to establish a connection with the load balancer. This can be one of TLS_1_0, TLS_1_1, TLS_1_2, TLS_1_3.", + "description": "The minimum version of SSL protocol that can be used by the clients to establish a connection with the load balancer. This can be one of TLS_1_0, TLS_1_1, TLS_1_2.", "enum": [ "TLS_1_0", "TLS_1_1", - "TLS_1_2", - "TLS_1_3" + "TLS_1_2" ], "enumDescriptions": [ - "", "", "", "" @@ -32088,6 +34811,10 @@ "description": "An optional description of this resource. Provide this property when you create the resource. This field can be set only at resource creation time.", "type": "string" }, + "enableFlowLogs": { + "description": "Whether to enable flow logging for this subnetwork.", + "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.", "format": "byte", @@ -32395,7 +35122,7 @@ "id": "SubnetworksScopedList", "properties": { "subnetworks": { - "description": "List of subnetworks contained in this scope.", + "description": "A list of subnetworks contained in this scope.", "items": { "$ref": "Subnetwork" }, @@ -32534,7 +35261,7 @@ "id": "Tags", "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.\n\nTo see the latest fingerprint, make get() request to the instance.", + "description": "Specifies a fingerprint for this request, which is essentially a hash of the tags' contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update tags. You must always provide an up-to-date fingerprint hash in order to update or change tags.\n\nTo see the latest fingerprint, make get() request to the instance.", "format": "byte", "type": "string" }, @@ -33186,7 +35913,7 @@ "id": "TargetInstancesScopedList", "properties": { "targetInstances": { - "description": "List of target instances contained in this scope.", + "description": "A list of target instances contained in this scope.", "items": { "$ref": "TargetInstance" }, @@ -33652,7 +36379,7 @@ "id": "TargetPoolsScopedList", "properties": { "targetPools": { - "description": "List of target pools contained in this scope.", + "description": "A list of target pools contained in this scope.", "items": { "$ref": "TargetPool" }, @@ -34477,7 +37204,7 @@ "id": "TargetVpnGatewaysScopedList", "properties": { "targetVpnGateways": { - "description": "[Output Only] List of target vpn gateways contained in this scope.", + "description": "[Output Only] A list of target vpn gateways contained in this scope.", "items": { "$ref": "TargetVpnGateway" }, @@ -34900,6 +37627,13 @@ "description": "Network URL.", "type": "string" }, + "secondaryIpRanges": { + "description": "Secondary IP ranges.", + "items": { + "$ref": "UsableSubnetworkSecondaryRange" + }, + "type": "array" + }, "subnetwork": { "description": "Subnetwork URL.", "type": "string" @@ -34907,6 +37641,21 @@ }, "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": { @@ -35391,7 +38140,7 @@ "id": "VpnTunnelsScopedList", "properties": { "vpnTunnels": { - "description": "List of vpn tunnels contained in this scope.", + "description": "A list of vpn tunnels contained in this scope.", "items": { "$ref": "VpnTunnel" }, @@ -35804,6 +38553,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/beta/projects/", 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 1332bf10f07..897cc504f6c 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 @@ -98,6 +98,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) @@ -188,6 +191,12 @@ type Service struct { Networks *NetworksService + NodeGroups *NodeGroupsService + + NodeTemplates *NodeTemplatesService + + NodeTypes *NodeTypesService + Projects *ProjectsService RegionAutoscalers *RegionAutoscalersService @@ -495,6 +504,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 @@ -1164,7 +1200,7 @@ func (s *AcceleratorTypeListWarningData) MarshalJSON() ([]byte, error) { } type AcceleratorTypesScopedList struct { - // AcceleratorTypes: [Output Only] List of accelerator types contained + // AcceleratorTypes: [Output Only] A list of accelerator types contained // in this scope. AcceleratorTypes []*AcceleratorType `json:"acceleratorTypes,omitempty"` @@ -1818,7 +1854,7 @@ func (s *AddressListWarningData) MarshalJSON() ([]byte, error) { } type AddressesScopedList struct { - // Addresses: [Output Only] List of addresses contained in this scope. + // Addresses: [Output Only] A list of addresses contained in this scope. Addresses []*Address `json:"addresses,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -2838,7 +2874,7 @@ func (s *AutoscalerStatusDetails) MarshalJSON() ([]byte, error) { } type AutoscalersScopedList struct { - // Autoscalers: [Output Only] List of autoscalers contained in this + // Autoscalers: [Output Only] A list of autoscalers contained in this // scope. Autoscalers []*Autoscaler `json:"autoscalers,omitempty"` @@ -3671,6 +3707,10 @@ type BackendService struct { // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` + // CustomRequestHeaders: Headers that the HTTP/S load balancer should + // add to proxied requests. + CustomRequestHeaders []string `json:"customRequestHeaders,omitempty"` + // Description: An optional description of this resource. Provide this // property when you create the resource. Description string `json:"description,omitempty"` @@ -3751,6 +3791,7 @@ type BackendService struct { // // Possible values: // "HTTP" + // "HTTP2" // "HTTPS" // "SSL" // "TCP" @@ -4248,7 +4289,7 @@ func (s *BackendServiceListWarningData) MarshalJSON() ([]byte, error) { } type BackendServicesScopedList struct { - // BackendServices: List of BackendServices contained in this scope. + // BackendServices: A list of BackendServices contained in this scope. BackendServices []*BackendService `json:"backendServices,omitempty"` // Warning: Informational warning which replaces the list of backend @@ -4401,8 +4442,7 @@ type Binding struct { // account. // // * `user:{emailid}`: An email address that represents a specific - // Google account. For example, `alice@gmail.com` or - // `joe@example.com`. + // Google account. For example, `alice@gmail.com` . // // // @@ -4584,8 +4624,8 @@ type Commitment struct { // used. Region string `json:"region,omitempty"` - // Resources: List of commitment amounts for particular resources. Note - // that VCPU and MEMORY resource commitments must occur together. + // Resources: A list of commitment amounts for particular resources. + // Note that VCPU and MEMORY resource commitments must occur together. Resources []*ResourceCommitment `json:"resources,omitempty"` // SelfLink: [Output Only] Server-defined URL for the resource. @@ -4949,7 +4989,7 @@ func (s *CommitmentListWarningData) MarshalJSON() ([]byte, error) { } type CommitmentsScopedList struct { - // Commitments: [Output Only] List of commitments contained in this + // Commitments: [Output Only] A list of commitments contained in this // scope. Commitments []*Commitment `json:"commitments,omitempty"` @@ -5184,6 +5224,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"` @@ -5197,7 +5241,7 @@ type CustomerEncryptionKey struct { // - The key is wrapped using a RSA public key certificate provided by // Google. // - After being wrapped, the key must be encoded in RFC 4648 base64 - // encoding. Get the RSA public key certificate provided by Google + // encoding. Gets the RSA public key certificate provided by Google // at: // https://cloud-certs.storage.googleapis.com/google-cloud-csek-ingre // ss.pem @@ -5207,7 +5251,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 @@ -5215,8 +5259,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. @@ -6002,6 +6046,12 @@ type DiskType struct { // Name: [Output Only] Name of the resource. Name string `json:"name,omitempty"` + // Region: [Output Only] URL of the region where the disk type 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. + Region string `json:"region,omitempty"` + // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` @@ -6353,7 +6403,8 @@ func (s *DiskTypeListWarningData) MarshalJSON() ([]byte, error) { } type DiskTypesScopedList struct { - // DiskTypes: [Output Only] List of disk types contained in this scope. + // DiskTypes: [Output Only] A list of disk types contained in this + // scope. DiskTypes []*DiskType `json:"diskTypes,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -6514,7 +6565,7 @@ func (s *DisksResizeRequest) MarshalJSON() ([]byte, error) { } type DisksScopedList struct { - // Disks: [Output Only] List of disks contained in this scope. + // Disks: [Output Only] A list of disks contained in this scope. Disks []*Disk `json:"disks,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -6787,6 +6838,17 @@ 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"` + + // EnableLogging: 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 // identifier is defined by the server. Id uint64 `json:"id,omitempty,string"` @@ -7752,7 +7814,7 @@ func (s *ForwardingRuleListWarningData) MarshalJSON() ([]byte, error) { } type ForwardingRulesScopedList struct { - // ForwardingRules: List of forwarding rules contained in this scope. + // ForwardingRules: A list of forwarding rules contained in this scope. ForwardingRules []*ForwardingRule `json:"forwardingRules,omitempty"` // Warning: Informational warning which replaces the list of forwarding @@ -7965,6 +8027,61 @@ func (s *GuestOsFeature) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type HTTP2HealthCheck struct { + // Host: The value of the host header in the HTTP/2 health check + // request. If left empty (default value), the IP on behalf of which + // this health check is performed will be used. + Host string `json:"host,omitempty"` + + // Port: The TCP port number for the health check request. The default + // value is 443. 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"` + + // ProxyHeader: Specifies the type of proxy header to append before + // sending data to the backend, either NONE or PROXY_V1. The default is + // NONE. + // + // Possible values: + // "NONE" + // "PROXY_V1" + ProxyHeader string `json:"proxyHeader,omitempty"` + + // RequestPath: The request path of the HTTP/2 health check request. The + // 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, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Host") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *HTTP2HealthCheck) MarshalJSON() ([]byte, error) { + type NoMethod HTTP2HealthCheck + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type HTTPHealthCheck struct { // Host: The value of the host header in the HTTP health check request. // If left empty (default value), the IP on behalf of which this health @@ -8095,6 +8212,8 @@ type HealthCheck struct { // after this many consecutive successes. The default value is 2. HealthyThreshold int64 `json:"healthyThreshold,omitempty"` + Http2HealthCheck *HTTP2HealthCheck `json:"http2HealthCheck,omitempty"` + HttpHealthCheck *HTTPHealthCheck `json:"httpHealthCheck,omitempty"` HttpsHealthCheck *HTTPSHealthCheck `json:"httpsHealthCheck,omitempty"` @@ -8134,6 +8253,7 @@ type HealthCheck struct { // // Possible values: // "HTTP" + // "HTTP2" // "HTTPS" // "INVALID" // "SSL" @@ -9356,7 +9476,7 @@ type Instance struct { // must be created before you can assign them. Disks []*AttachedDisk `json:"disks,omitempty"` - // GuestAccelerators: List of the type and count of accelerator cards + // GuestAccelerators: A list of the type and count of accelerator cards // attached to the instance. GuestAccelerators []*AcceleratorConfig `json:"guestAccelerators,omitempty"` @@ -9369,11 +9489,11 @@ type Instance struct { 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 + // essentially a hash of the label'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 + // 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 metadata. + // change labels. // // To see the latest fingerprint, make get() request to the instance. LabelFingerprint string `json:"labelFingerprint,omitempty"` @@ -9447,6 +9567,10 @@ type Instance struct { // instance. See Service Accounts for more information. ServiceAccounts []*ServiceAccount `json:"serviceAccounts,omitempty"` + ShieldedVmConfig *ShieldedVmConfig `json:"shieldedVmConfig,omitempty"` + + ShieldedVmIntegrityPolicy *ShieldedVmIntegrityPolicy `json:"shieldedVmIntegrityPolicy,omitempty"` + // StartRestricted: [Output Only] Whether a VM has been restricted for // start because Compute Engine has detected suspicious activity. StartRestricted bool `json:"startRestricted,omitempty"` @@ -9710,8 +9834,8 @@ type InstanceGroup struct { // instance group belong. Network string `json:"network,omitempty"` - // Region: The URL of the region where the instance group is located - // (for regional resources). + // Region: [Output Only] The URL of the region where the instance group + // is located (for regional resources). Region string `json:"region,omitempty"` // SelfLink: [Output Only] The URL for this instance group. The server @@ -9722,8 +9846,8 @@ type InstanceGroup struct { // group. Size int64 `json:"size,omitempty"` - // Subnetwork: The URL of the subnetwork to which all instances in the - // instance group belong. + // Subnetwork: [Output Only] The URL of the subnetwork to which all + // instances in the instance group belong. Subnetwork string `json:"subnetwork,omitempty"` // Zone: [Output Only] The URL of the zone where the instance group is @@ -10111,9 +10235,10 @@ type InstanceGroupManager struct { // "UNKNOWN" FailoverAction string `json:"failoverAction,omitempty"` - // Fingerprint: [Output Only] The fingerprint of the resource data. You - // can use this optional field for optimistic locking when you update - // the resource. + // 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. Fingerprint string `json:"fingerprint,omitempty"` // Id: [Output Only] A unique identifier for this resource type. The @@ -10153,11 +10278,11 @@ type InstanceGroupManager struct { // server defines this URL. SelfLink string `json:"selfLink,omitempty"` - // ServiceAccount: [Output Only] 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. + // ServiceAccount: 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. ServiceAccount string `json:"serviceAccount,omitempty"` // TargetPools: The URLs for all TargetPool resources to which instances @@ -12048,6 +12173,10 @@ type InstanceProperties struct { // to obtain the access tokens for these instances. ServiceAccounts []*ServiceAccount `json:"serviceAccounts,omitempty"` + // ShieldedVmConfig: Specifies the Shielded VM options for the instances + // that are created from this template. + ShieldedVmConfig *ShieldedVmConfig `json:"shieldedVmConfig,omitempty"` + // Tags: A list of tags to apply to the instances that are created from // this template. The tags identify valid sources or targets for network // firewalls. The setTags method can modify this list of tags. Each tag @@ -12380,7 +12509,7 @@ func (s *InstanceWithNamedPorts) MarshalJSON() ([]byte, error) { } type InstancesScopedList struct { - // Instances: [Output Only] List of instances contained in this scope. + // Instances: [Output Only] A list of instances contained in this scope. Instances []*Instance `json:"instances,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -12545,7 +12674,7 @@ func (s *InstancesSetLabelsRequest) MarshalJSON() ([]byte, error) { } type InstancesSetMachineResourcesRequest struct { - // GuestAccelerators: List of the type and count of accelerator cards + // GuestAccelerators: A list of the type and count of accelerator cards // attached to the instance. GuestAccelerators []*AcceleratorConfig `json:"guestAccelerators,omitempty"` @@ -12709,7 +12838,7 @@ type Interconnect struct { // set to true. AdminEnabled bool `json:"adminEnabled,omitempty"` - // CircuitInfos: [Output Only] List of CircuitInfo objects, that + // CircuitInfos: [Output Only] A list of CircuitInfo objects, that // describe the individual circuits in this LAG. CircuitInfos []*InterconnectCircuitInfo `json:"circuitInfos,omitempty"` @@ -12725,7 +12854,7 @@ type Interconnect struct { // property when you create the resource. Description string `json:"description,omitempty"` - // ExpectedOutages: [Output Only] List of outages expected for this + // ExpectedOutages: [Output Only] A list of outages expected for this // Interconnect. ExpectedOutages []*InterconnectOutageNotification `json:"expectedOutages,omitempty"` @@ -12752,6 +12881,7 @@ type Interconnect struct { // Possible values: // "DEDICATED" // "IT_PRIVATE" + // "PARTNER" InterconnectType string `json:"interconnectType,omitempty"` // Kind: [Output Only] Type of the resource. Always compute#interconnect @@ -12827,6 +12957,14 @@ type Interconnect struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // State: [Output Only] The current state of whether or not this + // Interconnect is functional. + // + // Possible values: + // "ACTIVE" + // "UNPROVISIONED" + State string `json:"state,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -12863,6 +13001,24 @@ type InterconnectAttachment struct { // Not present for PARTNER_PROVIDER. AdminEnabled bool `json:"adminEnabled,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. + // + // Possible values: + // "BPS_100M" + // "BPS_10G" + // "BPS_1G" + // "BPS_200M" + // "BPS_2G" + // "BPS_300M" + // "BPS_400M" + // "BPS_500M" + // "BPS_50M" + // "BPS_5G" + Bandwidth string `json:"bandwidth,omitempty"` + // CandidateSubnets: Up to 16 candidate prefixes that can be used to // restrict the allocation of cloudRouterIpAddress and // customerRouterIpAddress for this attachment. All prefixes must be @@ -12890,6 +13046,20 @@ type InterconnectAttachment struct { // Description: An optional description of this resource. Description string `json:"description,omitempty"` + // EdgeAvailabilityDomain: Desired availability domain for the + // attachment. Only available for type PARTNER, at creation time. For + // improved reliability, customers should configure a pair of + // attachments with one per availability domain. The selected + // availability domain will be provided to the Partner via the pairing + // key so that the provisioned circuit will lie in the specified domain. + // If not specified, the value will default to AVAILABILITY_DOMAIN_ANY. + // + // Possible values: + // "AVAILABILITY_DOMAIN_1" + // "AVAILABILITY_DOMAIN_2" + // "AVAILABILITY_DOMAIN_ANY" + EdgeAvailabilityDomain string `json:"edgeAvailabilityDomain,omitempty"` + // GoogleReferenceId: [Output Only] Google reference ID, to be used when // raising support tickets with Google or otherwise to debug backend // connectivity issues. @@ -12940,6 +13110,23 @@ type InterconnectAttachment struct { // "OS_UNPROVISIONED" OperationalStatus string `json:"operationalStatus,omitempty"` + // PairingKey: [Output only for type PARTNER. Input only for + // PARTNER_PROVIDER. Not present for DEDICATED]. The opaque identifier + // of an PARTNER attachment used to initiate provisioning with a + // selected partner. Of the form "XXXXX/region/domain" + PairingKey string `json:"pairingKey,omitempty"` + + // PartnerAsn: Optional BGP ASN for the router that should be supplied + // by a layer 3 Partner if they configured BGP on behalf of the + // customer. Output only for PARTNER type, input only for + // PARTNER_PROVIDER, not available for DEDICATED. + PartnerAsn int64 `json:"partnerAsn,omitempty,string"` + + // PartnerMetadata: Informational metadata about Partner attachments + // from Partners to display to customers. Output only for for PARTNER + // type, mutable for PARTNER_PROVIDER, not available for DEDICATED. + PartnerMetadata *InterconnectAttachmentPartnerMetadata `json:"partnerMetadata,omitempty"` + // PrivateInterconnectInfo: [Output Only] Information specific to an // InterconnectAttachment. This property is populated if the // interconnect that this is attached to is of type DEDICATED. @@ -12960,8 +13147,23 @@ type InterconnectAttachment struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // State: [Output Only] The current state of this attachment's + // functionality. + // + // Possible values: + // "ACTIVE" + // "DEFUNCT" + // "PARTNER_REQUEST_RECEIVED" + // "PENDING_CUSTOMER" + // "PENDING_PARTNER" + // "STATE_UNSPECIFIED" + // "UNPROVISIONED" + State string `json:"state,omitempty"` + // Possible values: // "DEDICATED" + // "PARTNER" + // "PARTNER_PROVIDER" Type string `json:"type,omitempty"` // VlanTag8021q: Available only for DEDICATED and PARTNER_PROVIDER. @@ -13311,6 +13513,52 @@ func (s *InterconnectAttachmentListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// InterconnectAttachmentPartnerMetadata: Informational metadata about +// Partner attachments from Partners to display to customers. These +// fields are propagated from PARTNER_PROVIDER attachments to their +// corresponding PARTNER attachments. +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 + // values. + InterconnectName string `json:"interconnectName,omitempty"` + + // PartnerName: Plain text name of the Partner providing this + // attachment. This value may be validated to match approved Partner + // values. + PartnerName string `json:"partnerName,omitempty"` + + // PortalUrl: URL of the Partner?s portal for this Attachment. Partners + // may customise this to be a deep-link to the specific resource on the + // Partner portal. This value may be validated to match approved Partner + // values. + PortalUrl string `json:"portalUrl,omitempty"` + + // ForceSendFields is a list of field names (e.g. "InterconnectName") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "InterconnectName") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectAttachmentPartnerMetadata) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectAttachmentPartnerMetadata + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // InterconnectAttachmentPrivateInfo: Information for an interconnect // attachment when this belongs to an interconnect of type DEDICATED. type InterconnectAttachmentPrivateInfo struct { @@ -13343,7 +13591,7 @@ func (s *InterconnectAttachmentPrivateInfo) MarshalJSON() ([]byte, error) { } type InterconnectAttachmentsScopedList struct { - // InterconnectAttachments: List of interconnect attachments contained + // InterconnectAttachments: A list of interconnect attachments contained // in this scope. InterconnectAttachments []*InterconnectAttachment `json:"interconnectAttachments,omitempty"` @@ -13976,7 +14224,7 @@ func (s *InterconnectLocationRegionInfo) MarshalJSON() ([]byte, error) { // InterconnectOutageNotification: Description of a planned outage on // this Interconnect. Next id: 9 type InterconnectOutageNotification struct { - // AffectedCircuits: Iff issue_type is IT_PARTIAL_OUTAGE, a list of the + // AffectedCircuits: If issue_type is IT_PARTIAL_OUTAGE, a list of the // Google-side circuit IDs that will be affected. AffectedCircuits []string `json:"affectedCircuits,omitempty"` @@ -14952,7 +15200,7 @@ func (s *MachineTypeListWarningData) MarshalJSON() ([]byte, error) { } type MachineTypesScopedList struct { - // MachineTypes: [Output Only] List of machine types contained in this + // MachineTypes: [Output Only] A list of machine types contained in this // scope. MachineTypes []*MachineType `json:"machineTypes,omitempty"` @@ -15461,7 +15709,7 @@ type Network struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` - // Peerings: [Output Only] List of network peerings for the resource. + // Peerings: [Output Only] A list of network peerings for the resource. Peerings []*NetworkPeering `json:"peerings,omitempty"` // RoutingConfig: The network-level routing configuration for this @@ -15910,13 +16158,1737 @@ 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"` + + // 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"` + + // 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"` + + // 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 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 charaicter, 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 ==) // (== resource_for beta.regionOperations ==) (== resource_for // v1.zoneOperations ==) (== resource_for beta.zoneOperations ==) type Operation struct { - // ClientOperationId: [Output Only] Reserved for future use. + // ClientOperationId: [Output Only] The value of `requestId` if you + // provided it in the request. Not present otherwise. ClientOperationId string `json:"clientOperationId,omitempty"` // CreationTimestamp: [Deprecated] This field is deprecated. @@ -16521,7 +18493,8 @@ func (s *OperationListWarningData) MarshalJSON() ([]byte, error) { } type OperationsScopedList struct { - // Operations: [Output Only] List of operations contained in this scope. + // Operations: [Output Only] A list of operations contained in this + // scope. Operations []*Operation `json:"operations,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -16744,20 +18717,30 @@ func (s *PathRule) MarshalJSON() ([]byte, error) { // // // -// A `Policy` consists of a list of `bindings`. A `Binding` binds a list +// 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. // -// **Example** +// **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", ] }, { +// "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 { @@ -17100,16 +19083,20 @@ type Quota struct { // "INSTANCE_GROUP_MANAGERS" // "INSTANCE_TEMPLATES" // "INTERCONNECTS" + // "INTERCONNECT_ATTACHMENTS_PER_REGION" + // "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS" // "INTERNAL_ADDRESSES" // "IN_USE_ADDRESSES" // "LOCAL_SSD_TOTAL_GB" // "NETWORKS" // "NVIDIA_K80_GPUS" // "NVIDIA_P100_GPUS" + // "NVIDIA_V100_GPUS" // "PREEMPTIBLE_CPUS" // "PREEMPTIBLE_LOCAL_SSD_GB" // "PREEMPTIBLE_NVIDIA_K80_GPUS" // "PREEMPTIBLE_NVIDIA_P100_GPUS" + // "PREEMPTIBLE_NVIDIA_V100_GPUS" // "REGIONAL_AUTOSCALERS" // "REGIONAL_INSTANCE_GROUP_MANAGERS" // "ROUTERS" @@ -17994,7 +19981,7 @@ func (s *RegionInstanceGroupManagersDeleteInstancesRequest) MarshalJSON() ([]byt } type RegionInstanceGroupManagersListInstancesResponse struct { - // ManagedInstances: List of managed instances. + // ManagedInstances: A list of managed instances. ManagedInstances []*ManagedInstance `json:"managedInstances,omitempty"` // NextPageToken: [Output Only] This token allows you to get the next @@ -18570,6 +20557,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 { @@ -19383,6 +21408,18 @@ 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. + // + // Possible values: + // "MANAGED_BY_ATTACHMENT" + // "MANAGED_BY_USER" + ManagementType string `json:"managementType,omitempty"` + // Name: Name of this BGP peer. The name must be 1-63 characters long // and comply with RFC1035. Name string `json:"name,omitempty"` @@ -19438,6 +21475,18 @@ 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. + // + // Possible values: + // "MANAGED_BY_ATTACHMENT" + // "MANAGED_BY_USER" + ManagementType string `json:"managementType,omitempty"` + // Name: Name of this interface entry. The name must be 1-63 characters // long and comply with RFC1035. Name string `json:"name,omitempty"` @@ -19781,7 +21830,7 @@ func (s *RoutersPreviewResponse) MarshalJSON() ([]byte, error) { } type RoutersScopedList struct { - // Routers: List of routers contained in this scope. + // Routers: A list of routers contained in this scope. Routers []*Router `json:"routers,omitempty"` // Warning: Informational warning which replaces the list of routers @@ -20038,6 +22087,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 @@ -20078,8 +22130,49 @@ 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'. +// It can also be associated with one or more 'targets'. Next available +// tag: 11 type SecurityPolicy struct { // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text // format. @@ -20117,9 +22210,9 @@ type SecurityPolicy struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` - // Rules: 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 + // 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"` @@ -20397,6 +22490,11 @@ type SecurityPolicyRuleMatcher struct { // specified and cannot be specified if versioned_expr is not specified. Config *SecurityPolicyRuleMatcherConfig `json:"config,omitempty"` + // Expr: 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. + Expr *Expr `json:"expr,omitempty"` + // SrcIpRanges: CIDR IP address range. SrcIpRanges []string `json:"srcIpRanges,omitempty"` @@ -20543,6 +22641,76 @@ func (s *ServiceAccount) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// ShieldedVmConfig: A set of Shielded VM options. +type ShieldedVmConfig struct { + // EnableIntegrityMonitoring: Defines whether the instance should have + // integrity monitoring enabled. + EnableIntegrityMonitoring bool `json:"enableIntegrityMonitoring,omitempty"` + + // EnableSecureBoot: Defines whether the instance should have secure + // boot enabled. + EnableSecureBoot bool `json:"enableSecureBoot,omitempty"` + + // EnableVtpm: Defines whether the instance should have the TPM enabled. + EnableVtpm bool `json:"enableVtpm,omitempty"` + + // ForceSendFields is a list of field names (e.g. + // "EnableIntegrityMonitoring") to unconditionally include in API + // requests. By default, fields with empty values are omitted from API + // requests. However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. + // "EnableIntegrityMonitoring") to include in API requests with the JSON + // null value. By default, fields with empty values are omitted from API + // requests. However, any field with an empty value appearing in + // NullFields will be sent to the server as null. It is an error if a + // field in this list has a non-empty value. This may be used to include + // null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ShieldedVmConfig) MarshalJSON() ([]byte, error) { + type NoMethod ShieldedVmConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ShieldedVmIntegrityPolicy: The policy describes how boot integrity +// measurements are evaluated. +type ShieldedVmIntegrityPolicy struct { + // UpdateAutoLearnPolicy: Triggers an auto relearn event: the integrity + // monitoring module copies existing guest measurements to the baseline. + UpdateAutoLearnPolicy bool `json:"updateAutoLearnPolicy,omitempty"` + + // ForceSendFields is a list of field names (e.g. + // "UpdateAutoLearnPolicy") to unconditionally include in API requests. + // By default, fields with empty values are omitted from API requests. + // However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "UpdateAutoLearnPolicy") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *ShieldedVmIntegrityPolicy) MarshalJSON() ([]byte, error) { + type NoMethod ShieldedVmIntegrityPolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // SignedUrlKey: Represents a customer-supplied Signing Key used by // Cloud CDN Signed URLs type SignedUrlKey struct { @@ -20618,8 +22786,8 @@ type Snapshot struct { // by the setLabels method. Label values may be empty. Labels map[string]string `json:"labels,omitempty"` - // LicenseCodes: Integer license codes indicating which licenses are - // attached to this snapshot. + // LicenseCodes: [Output Only] Integer license codes indicating which + // licenses are attached to this snapshot. LicenseCodes googleapi.Int64s `json:"licenseCodes,omitempty"` // Licenses: [Output Only] A list of public visible licenses that apply @@ -21330,8 +23498,8 @@ type SslPolicy struct { // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` - // CustomFeatures: List of features enabled when the selected profile is - // CUSTOM. The + // CustomFeatures: A list of features enabled when the selected profile + // is CUSTOM. The // - method returns the set of features that can be specified in this // list. This field must be empty if the profile is not CUSTOM. CustomFeatures []string `json:"customFeatures,omitempty"` @@ -21360,13 +23528,12 @@ type SslPolicy struct { // MinTlsVersion: The minimum version of SSL protocol that can be used // by the clients to establish a connection with the load balancer. This - // can be one of TLS_1_0, TLS_1_1, TLS_1_2, TLS_1_3. + // can be one of TLS_1_0, TLS_1_1, TLS_1_2. // // Possible values: // "TLS_1_0" // "TLS_1_1" // "TLS_1_2" - // "TLS_1_3" MinTlsVersion string `json:"minTlsVersion,omitempty"` // Name: Name of the resource. The name must be 1-63 characters long, @@ -21585,6 +23752,9 @@ type Subnetwork struct { // resource creation time. Description string `json:"description,omitempty"` + // EnableFlowLogs: Whether to enable flow logging for this subnetwork. + 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 @@ -22054,7 +24224,7 @@ func (s *SubnetworksExpandIpCidrRangeRequest) MarshalJSON() ([]byte, error) { } type SubnetworksScopedList struct { - // Subnetworks: List of subnetworks contained in this scope. + // Subnetworks: A list of subnetworks contained in this scope. Subnetworks []*Subnetwork `json:"subnetworks,omitempty"` // Warning: An informational warning that appears when the list of @@ -22269,11 +24439,11 @@ func (s *TCPHealthCheck) MarshalJSON() ([]byte, error) { // Tags: A set of instance tags. type Tags struct { // Fingerprint: Specifies a fingerprint for this request, which is - // essentially a hash of the metadata's contents and used for optimistic + // essentially a hash of the tags' 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. + // changes after every request to modify or update tags. You must always + // provide an up-to-date fingerprint hash in order to update or change + // tags. // // To see the latest fingerprint, make get() request to the instance. Fingerprint string `json:"fingerprint,omitempty"` @@ -23230,7 +25400,7 @@ func (s *TargetInstanceListWarningData) MarshalJSON() ([]byte, error) { } type TargetInstancesScopedList struct { - // TargetInstances: List of target instances contained in this scope. + // TargetInstances: A list of target instances contained in this scope. TargetInstances []*TargetInstance `json:"targetInstances,omitempty"` // Warning: Informational warning which replaces the list of addresses @@ -23973,7 +26143,7 @@ func (s *TargetPoolsRemoveInstanceRequest) MarshalJSON() ([]byte, error) { } type TargetPoolsScopedList struct { - // TargetPools: List of target pools contained in this scope. + // TargetPools: A list of target pools contained in this scope. TargetPools []*TargetPool `json:"targetPools,omitempty"` // Warning: Informational warning which replaces the list of addresses @@ -25161,7 +27331,7 @@ func (s *TargetVpnGatewayListWarningData) MarshalJSON() ([]byte, error) { } type TargetVpnGatewaysScopedList struct { - // TargetVpnGateways: [Output Only] List of target vpn gateways + // TargetVpnGateways: [Output Only] A list of target vpn gateways // contained in this scope. TargetVpnGateways []*TargetVpnGateway `json:"targetVpnGateways,omitempty"` @@ -25834,6 +28004,9 @@ type UsableSubnetwork struct { // 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"` @@ -25860,6 +28033,42 @@ func (s *UsableSubnetwork) MarshalJSON() ([]byte, error) { 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. @@ -26506,7 +28715,7 @@ func (s *VpnTunnelListWarningData) MarshalJSON() ([]byte, error) { } type VpnTunnelsScopedList struct { - // VpnTunnels: List of vpn tunnels contained in this scope. + // VpnTunnels: A list of vpn tunnels contained in this scope. VpnTunnels []*VpnTunnel `json:"vpnTunnels,omitempty"` // Warning: Informational warning which replaces the list of addresses @@ -27091,6 +29300,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 { @@ -27109,32 +29356,28 @@ func (r *AcceleratorTypesService) AggregatedList(project string) *AcceleratorTyp return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AcceleratorTypesAggregatedListCall) Filter(filter string) *AcceleratorTypesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -27278,7 +29521,7 @@ func (c *AcceleratorTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (* // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -27355,8 +29598,7 @@ type AcceleratorTypesGetCall struct { header_ http.Header } -// Get: Returns the specified accelerator type. Get a list of available -// accelerator types by making a list() request. +// Get: Returns the specified accelerator type. func (r *AcceleratorTypesService) Get(project string, zone string, acceleratorType string) *AcceleratorTypesGetCall { c := &AcceleratorTypesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -27461,7 +29703,7 @@ func (c *AcceleratorTypesGetCall) Do(opts ...googleapi.CallOption) (*Accelerator } return ret, nil // { - // "description": "Returns the specified accelerator type. Get a list of available accelerator types by making a list() request.", + // "description": "Returns the specified accelerator type.", // "httpMethod": "GET", // "id": "compute.acceleratorTypes.get", // "parameterOrder": [ @@ -27526,32 +29768,28 @@ func (r *AcceleratorTypesService) List(project string, zone string) *Accelerator return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AcceleratorTypesListCall) Filter(filter string) *AcceleratorTypesListCall { c.urlParams_.Set("filter", filter) return c @@ -27697,7 +29935,7 @@ func (c *AcceleratorTypesListCall) Do(opts ...googleapi.CallOption) (*Accelerato // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -27787,32 +30025,28 @@ func (r *AddressesService) AggregatedList(project string) *AddressesAggregatedLi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AddressesAggregatedListCall) Filter(filter string) *AddressesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -27956,7 +30190,7 @@ func (c *AddressesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Address // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -28549,32 +30783,28 @@ func (r *AddressesService) List(project string, region string) *AddressesListCal return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AddressesListCall) Filter(filter string) *AddressesListCall { c.urlParams_.Set("filter", filter) return c @@ -28720,7 +30950,7 @@ func (c *AddressesListCall) Do(opts ...googleapi.CallOption) (*AddressList, erro // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -29150,32 +31380,28 @@ func (r *AutoscalersService) AggregatedList(project string) *AutoscalersAggregat return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AutoscalersAggregatedListCall) Filter(filter string) *AutoscalersAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -29319,7 +31545,7 @@ func (c *AutoscalersAggregatedListCall) Do(opts ...googleapi.CallOption) (*Autos // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -29567,7 +31793,7 @@ type AutoscalersGetCall struct { header_ http.Header } -// Get: Returns the specified autoscaler resource. Get a list of +// Get: Returns the specified autoscaler resource. Gets a list of // available autoscalers by making a list() request. func (r *AutoscalersService) Get(project string, zone string, autoscaler string) *AutoscalersGetCall { c := &AutoscalersGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -29673,7 +31899,7 @@ func (c *AutoscalersGetCall) Do(opts ...googleapi.CallOption) (*Autoscaler, erro } return ret, nil // { - // "description": "Returns the specified autoscaler resource. Get a list of available autoscalers by making a list() request.", + // "description": "Returns the specified autoscaler resource. Gets a list of available autoscalers by making a list() request.", // "httpMethod": "GET", // "id": "compute.autoscalers.get", // "parameterOrder": [ @@ -29909,32 +32135,28 @@ func (r *AutoscalersService) List(project string, zone string) *AutoscalersListC return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AutoscalersListCall) Filter(filter string) *AutoscalersListCall { c.urlParams_.Set("filter", filter) return c @@ -30080,7 +32302,7 @@ func (c *AutoscalersListCall) Do(opts ...googleapi.CallOption) (*AutoscalerList, // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -31188,7 +33410,7 @@ type BackendBucketsGetCall struct { header_ http.Header } -// Get: Returns the specified BackendBucket resource. Get a list of +// Get: Returns the specified BackendBucket resource. Gets a list of // available backend buckets by making a list() request. func (r *BackendBucketsService) Get(project string, backendBucket string) *BackendBucketsGetCall { c := &BackendBucketsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -31292,7 +33514,7 @@ func (c *BackendBucketsGetCall) Do(opts ...googleapi.CallOption) (*BackendBucket } return ret, nil // { - // "description": "Returns the specified BackendBucket resource. Get a list of available backend buckets by making a list() request.", + // "description": "Returns the specified BackendBucket resource. Gets a list of available backend buckets by making a list() request.", // "httpMethod": "GET", // "id": "compute.backendBuckets.get", // "parameterOrder": [ @@ -31507,32 +33729,28 @@ func (r *BackendBucketsService) List(project string) *BackendBucketsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *BackendBucketsListCall) Filter(filter string) *BackendBucketsListCall { c.urlParams_.Set("filter", filter) return c @@ -31676,7 +33894,7 @@ func (c *BackendBucketsListCall) Do(opts ...googleapi.CallOption) (*BackendBucke // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -32272,32 +34490,28 @@ func (r *BackendServicesService) AggregatedList(project string) *BackendServices return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *BackendServicesAggregatedListCall) Filter(filter string) *BackendServicesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -32441,7 +34655,7 @@ func (c *BackendServicesAggregatedListCall) Do(opts ...googleapi.CallOption) (*B // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -32846,7 +35060,7 @@ type BackendServicesGetCall struct { header_ http.Header } -// Get: Returns the specified BackendService resource. Get a list of +// Get: Returns the specified BackendService resource. Gets a list of // available backend services by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/backendServices/get func (r *BackendServicesService) Get(project string, backendService string) *BackendServicesGetCall { @@ -32951,7 +35165,7 @@ func (c *BackendServicesGetCall) Do(opts ...googleapi.CallOption) (*BackendServi } return ret, nil // { - // "description": "Returns the specified BackendService resource. Get a list of available backend services by making a list() request.", + // "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", // "httpMethod": "GET", // "id": "compute.backendServices.get", // "parameterOrder": [ @@ -33318,32 +35532,28 @@ func (r *BackendServicesService) List(project string) *BackendServicesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *BackendServicesListCall) Filter(filter string) *BackendServicesListCall { c.urlParams_.Set("filter", filter) return c @@ -33487,7 +35697,7 @@ func (c *BackendServicesListCall) Do(opts ...googleapi.CallOption) (*BackendServ // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -34238,32 +36448,28 @@ func (r *DiskTypesService) AggregatedList(project string) *DiskTypesAggregatedLi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DiskTypesAggregatedListCall) Filter(filter string) *DiskTypesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -34407,7 +36613,7 @@ func (c *DiskTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (*DiskTyp // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -34484,7 +36690,7 @@ type DiskTypesGetCall struct { header_ http.Header } -// Get: Returns the specified disk type. Get a list of available disk +// Get: Returns the specified disk type. Gets a list of available disk // types by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/diskTypes/get func (r *DiskTypesService) Get(project string, zone string, diskType string) *DiskTypesGetCall { @@ -34591,7 +36797,7 @@ func (c *DiskTypesGetCall) Do(opts ...googleapi.CallOption) (*DiskType, error) { } return ret, nil // { - // "description": "Returns the specified disk type. Get a list of available disk types by making a list() request.", + // "description": "Returns the specified disk type. Gets a list of available disk types by making a list() request.", // "httpMethod": "GET", // "id": "compute.diskTypes.get", // "parameterOrder": [ @@ -34657,32 +36863,28 @@ func (r *DiskTypesService) List(project string, zone string) *DiskTypesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DiskTypesListCall) Filter(filter string) *DiskTypesListCall { c.urlParams_.Set("filter", filter) return c @@ -34828,7 +37030,7 @@ func (c *DiskTypesListCall) Do(opts ...googleapi.CallOption) (*DiskTypeList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -34918,32 +37120,28 @@ func (r *DisksService) AggregatedList(project string) *DisksAggregatedListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DisksAggregatedListCall) Filter(filter string) *DisksAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -35087,7 +37285,7 @@ func (c *DisksAggregatedListCall) Do(opts ...googleapi.CallOption) (*DiskAggrega // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -35530,7 +37728,7 @@ type DisksGetCall struct { header_ http.Header } -// Get: Returns a specified persistent disk. Get a list of available +// Get: Returns a specified persistent disk. Gets a list of available // persistent disks by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/disks/get func (r *DisksService) Get(project string, zone string, disk string) *DisksGetCall { @@ -35637,7 +37835,7 @@ func (c *DisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, error) { } return ret, nil // { - // "description": "Returns a specified persistent disk. Get a list of available persistent disks by making a list() request.", + // "description": "Returns a specified persistent disk. Gets a list of available persistent disks by making a list() request.", // "httpMethod": "GET", // "id": "compute.disks.get", // "parameterOrder": [ @@ -35890,32 +38088,28 @@ func (r *DisksService) List(project string, zone string) *DisksListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DisksListCall) Filter(filter string) *DisksListCall { c.urlParams_.Set("filter", filter) return c @@ -36061,7 +38255,7 @@ func (c *DisksListCall) Do(opts ...googleapi.CallOption) (*DiskList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -37149,32 +39343,28 @@ func (r *FirewallsService) List(project string) *FirewallsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *FirewallsListCall) Filter(filter string) *FirewallsListCall { c.urlParams_.Set("filter", filter) return c @@ -37318,7 +39508,7 @@ func (c *FirewallsListCall) Do(opts ...googleapi.CallOption) (*FirewallList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -37896,32 +40086,28 @@ func (r *ForwardingRulesService) AggregatedList(project string) *ForwardingRules return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ForwardingRulesAggregatedListCall) Filter(filter string) *ForwardingRulesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -38065,7 +40251,7 @@ func (c *ForwardingRulesAggregatedListCall) Do(opts ...googleapi.CallOption) (*F // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -38658,32 +40844,28 @@ func (r *ForwardingRulesService) List(project string, region string) *Forwarding return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ForwardingRulesListCall) Filter(filter string) *ForwardingRulesListCall { c.urlParams_.Set("filter", filter) return c @@ -38829,7 +41011,7 @@ func (c *ForwardingRulesListCall) Do(opts ...googleapi.CallOption) (*ForwardingR // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -39597,7 +41779,7 @@ type GlobalAddressesGetCall struct { header_ http.Header } -// Get: Returns the specified address resource. Get a list of available +// Get: Returns the specified address resource. Gets a list of available // addresses by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/globalAddresses/get func (r *GlobalAddressesService) Get(project string, address string) *GlobalAddressesGetCall { @@ -39702,7 +41884,7 @@ func (c *GlobalAddressesGetCall) Do(opts ...googleapi.CallOption) (*Address, err } return ret, nil // { - // "description": "Returns the specified address resource. Get a list of available addresses by making a list() request.", + // "description": "Returns the specified address resource. Gets a list of available addresses by making a list() request.", // "httpMethod": "GET", // "id": "compute.globalAddresses.get", // "parameterOrder": [ @@ -39918,32 +42100,28 @@ func (r *GlobalAddressesService) List(project string) *GlobalAddressesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalAddressesListCall) Filter(filter string) *GlobalAddressesListCall { c.urlParams_.Set("filter", filter) return c @@ -40087,7 +42265,7 @@ func (c *GlobalAddressesListCall) Do(opts ...googleapi.CallOption) (*AddressList // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -40619,7 +42797,7 @@ type GlobalForwardingRulesGetCall struct { header_ http.Header } -// Get: Returns the specified GlobalForwardingRule resource. Get a list +// Get: Returns the specified GlobalForwardingRule resource. Gets a list // of available forwarding rules by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/globalForwardingRules/get func (r *GlobalForwardingRulesService) Get(project string, forwardingRule string) *GlobalForwardingRulesGetCall { @@ -40724,7 +42902,7 @@ func (c *GlobalForwardingRulesGetCall) Do(opts ...googleapi.CallOption) (*Forwar } return ret, nil // { - // "description": "Returns the specified GlobalForwardingRule resource. Get a list of available forwarding rules by making a list() request.", + // "description": "Returns the specified GlobalForwardingRule resource. Gets a list of available forwarding rules by making a list() request.", // "httpMethod": "GET", // "id": "compute.globalForwardingRules.get", // "parameterOrder": [ @@ -40941,32 +43119,28 @@ func (r *GlobalForwardingRulesService) List(project string) *GlobalForwardingRul return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalForwardingRulesListCall) Filter(filter string) *GlobalForwardingRulesListCall { c.urlParams_.Set("filter", filter) return c @@ -41110,7 +43284,7 @@ func (c *GlobalForwardingRulesListCall) Do(opts ...googleapi.CallOption) (*Forwa // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -41660,32 +43834,28 @@ func (r *GlobalOperationsService) AggregatedList(project string) *GlobalOperatio return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalOperationsAggregatedListCall) Filter(filter string) *GlobalOperationsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -41829,7 +43999,7 @@ func (c *GlobalOperationsAggregatedListCall) Do(opts ...googleapi.CallOption) (* // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -42014,7 +44184,7 @@ type GlobalOperationsGetCall struct { header_ http.Header } -// Get: Retrieves the specified Operations resource. Get a list of +// Get: Retrieves the specified Operations resource. Gets a list of // operations by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/globalOperations/get func (r *GlobalOperationsService) Get(project string, operation string) *GlobalOperationsGetCall { @@ -42119,7 +44289,7 @@ func (c *GlobalOperationsGetCall) Do(opts ...googleapi.CallOption) (*Operation, } return ret, nil // { - // "description": "Retrieves the specified Operations resource. Get a list of operations by making a list() request.", + // "description": "Retrieves the specified Operations resource. Gets a list of operations by making a list() request.", // "httpMethod": "GET", // "id": "compute.globalOperations.get", // "parameterOrder": [ @@ -42175,32 +44345,28 @@ func (r *GlobalOperationsService) List(project string) *GlobalOperationsListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalOperationsListCall) Filter(filter string) *GlobalOperationsListCall { c.urlParams_.Set("filter", filter) return c @@ -42344,7 +44510,7 @@ func (c *GlobalOperationsListCall) Do(opts ...googleapi.CallOption) (*OperationL // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -42580,7 +44746,7 @@ type HealthChecksGetCall struct { header_ http.Header } -// Get: Returns the specified HealthCheck resource. Get a list of +// Get: Returns the specified HealthCheck resource. Gets a list of // available health checks by making a list() request. func (r *HealthChecksService) Get(project string, healthCheck string) *HealthChecksGetCall { c := &HealthChecksGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -42684,7 +44850,7 @@ func (c *HealthChecksGetCall) Do(opts ...googleapi.CallOption) (*HealthCheck, er } return ret, nil // { - // "description": "Returns the specified HealthCheck resource. Get a list of available health checks by making a list() request.", + // "description": "Returns the specified HealthCheck resource. Gets a list of available health checks by making a list() request.", // "httpMethod": "GET", // "id": "compute.healthChecks.get", // "parameterOrder": [ @@ -42899,32 +45065,28 @@ func (r *HealthChecksService) List(project string) *HealthChecksListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *HealthChecksListCall) Filter(filter string) *HealthChecksListCall { c.urlParams_.Set("filter", filter) return c @@ -43068,7 +45230,7 @@ func (c *HealthChecksListCall) Do(opts ...googleapi.CallOption) (*HealthCheckLis // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -43796,7 +45958,7 @@ type HttpHealthChecksGetCall struct { header_ http.Header } -// Get: Returns the specified HttpHealthCheck resource. Get a list of +// Get: Returns the specified HttpHealthCheck resource. Gets a list of // available HTTP health checks by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/httpHealthChecks/get func (r *HttpHealthChecksService) Get(project string, httpHealthCheck string) *HttpHealthChecksGetCall { @@ -43901,7 +46063,7 @@ func (c *HttpHealthChecksGetCall) Do(opts ...googleapi.CallOption) (*HttpHealthC } return ret, nil // { - // "description": "Returns the specified HttpHealthCheck resource. Get a list of available HTTP health checks by making a list() request.", + // "description": "Returns the specified HttpHealthCheck resource. Gets a list of available HTTP health checks by making a list() request.", // "httpMethod": "GET", // "id": "compute.httpHealthChecks.get", // "parameterOrder": [ @@ -44118,32 +46280,28 @@ func (r *HttpHealthChecksService) List(project string) *HttpHealthChecksListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *HttpHealthChecksListCall) Filter(filter string) *HttpHealthChecksListCall { c.urlParams_.Set("filter", filter) return c @@ -44287,7 +46445,7 @@ func (c *HttpHealthChecksListCall) Do(opts ...googleapi.CallOption) (*HttpHealth // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -45016,7 +47174,7 @@ type HttpsHealthChecksGetCall struct { header_ http.Header } -// Get: Returns the specified HttpsHealthCheck resource. Get a list of +// Get: Returns the specified HttpsHealthCheck resource. Gets a list of // available HTTPS health checks by making a list() request. func (r *HttpsHealthChecksService) Get(project string, httpsHealthCheck string) *HttpsHealthChecksGetCall { c := &HttpsHealthChecksGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -45120,7 +47278,7 @@ func (c *HttpsHealthChecksGetCall) Do(opts ...googleapi.CallOption) (*HttpsHealt } return ret, nil // { - // "description": "Returns the specified HttpsHealthCheck resource. Get a list of available HTTPS health checks by making a list() request.", + // "description": "Returns the specified HttpsHealthCheck resource. Gets a list of available HTTPS health checks by making a list() request.", // "httpMethod": "GET", // "id": "compute.httpsHealthChecks.get", // "parameterOrder": [ @@ -45335,32 +47493,28 @@ func (r *HttpsHealthChecksService) List(project string) *HttpsHealthChecksListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *HttpsHealthChecksListCall) Filter(filter string) *HttpsHealthChecksListCall { c.urlParams_.Set("filter", filter) return c @@ -45504,7 +47658,7 @@ func (c *HttpsHealthChecksListCall) Do(opts ...googleapi.CallOption) (*HttpsHeal // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -46406,7 +48560,7 @@ type ImagesGetCall struct { header_ http.Header } -// Get: Returns the specified image. Get a list of available images by +// Get: Returns the specified image. Gets a list of available images by // making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/images/get func (r *ImagesService) Get(project string, image string) *ImagesGetCall { @@ -46511,7 +48665,7 @@ func (c *ImagesGetCall) Do(opts ...googleapi.CallOption) (*Image, error) { } return ret, nil // { - // "description": "Returns the specified image. Get a list of available images by making a list() request.", + // "description": "Returns the specified image. Gets a list of available images by making a list() request.", // "httpMethod": "GET", // "id": "compute.images.get", // "parameterOrder": [ @@ -46900,32 +49054,28 @@ func (r *ImagesService) List(project string) *ImagesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ImagesListCall) Filter(filter string) *ImagesListCall { c.urlParams_.Set("filter", filter) return c @@ -47069,7 +49219,7 @@ func (c *ImagesListCall) Do(opts ...googleapi.CallOption) (*ImageList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -47642,32 +49792,28 @@ func (r *InstanceGroupManagersService) AggregatedList(project string) *InstanceG return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupManagersAggregatedListCall) Filter(filter string) *InstanceGroupManagersAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -47812,7 +49958,7 @@ func (c *InstanceGroupManagersAggregatedListCall) Do(opts ...googleapi.CallOptio // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -48256,7 +50402,7 @@ type InstanceGroupManagersGetCall struct { } // Get: Returns all of the details about the specified managed instance -// group. Get a list of available managed instance groups by making a +// group. Gets a list of available managed instance groups by making a // list() request. func (r *InstanceGroupManagersService) Get(project string, zone string, instanceGroupManager string) *InstanceGroupManagersGetCall { c := &InstanceGroupManagersGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -48362,7 +50508,7 @@ func (c *InstanceGroupManagersGetCall) Do(opts ...googleapi.CallOption) (*Instan } return ret, nil // { - // "description": "Returns all of the details about the specified managed instance group. Get a list of available managed instance groups by making a list() request.", + // "description": "Returns all of the details about the specified managed instance group. Gets a list of available managed instance groups by making a list() request.", // "httpMethod": "GET", // "id": "compute.instanceGroupManagers.get", // "parameterOrder": [ @@ -48603,32 +50749,28 @@ func (r *InstanceGroupManagersService) List(project string, zone string) *Instan return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupManagersListCall) Filter(filter string) *InstanceGroupManagersListCall { c.urlParams_.Set("filter", filter) return c @@ -48774,7 +50916,7 @@ func (c *InstanceGroupManagersListCall) Do(opts ...googleapi.CallOption) (*Insta // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -50907,32 +53049,28 @@ func (r *InstanceGroupsService) AggregatedList(project string) *InstanceGroupsAg return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupsAggregatedListCall) Filter(filter string) *InstanceGroupsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -51076,7 +53214,7 @@ func (c *InstanceGroupsAggregatedListCall) Do(opts ...googleapi.CallOption) (*In // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -51325,7 +53463,7 @@ type InstanceGroupsGetCall struct { header_ http.Header } -// Get: Returns the specified instance group. Get a list of available +// Get: Returns the specified instance group. Gets a list of available // instance groups by making a list() request. func (r *InstanceGroupsService) Get(project string, zone string, instanceGroup string) *InstanceGroupsGetCall { c := &InstanceGroupsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -51431,7 +53569,7 @@ func (c *InstanceGroupsGetCall) Do(opts ...googleapi.CallOption) (*InstanceGroup } return ret, nil // { - // "description": "Returns the specified instance group. Get a list of available instance groups by making a list() request.", + // "description": "Returns the specified instance group. Gets a list of available instance groups by making a list() request.", // "httpMethod": "GET", // "id": "compute.instanceGroups.get", // "parameterOrder": [ @@ -51664,32 +53802,28 @@ func (r *InstanceGroupsService) List(project string, zone string) *InstanceGroup return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupsListCall) Filter(filter string) *InstanceGroupsListCall { c.urlParams_.Set("filter", filter) return c @@ -51835,7 +53969,7 @@ func (c *InstanceGroupsListCall) Do(opts ...googleapi.CallOption) (*InstanceGrou // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -51928,32 +54062,28 @@ func (r *InstanceGroupsService) ListInstances(project string, zone string, insta return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupsListInstancesCall) Filter(filter string) *InstanceGroupsListInstancesCall { c.urlParams_.Set("filter", filter) return c @@ -52093,7 +54223,7 @@ func (c *InstanceGroupsListInstancesCall) Do(opts ...googleapi.CallOption) (*Ins // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -52869,8 +54999,8 @@ type InstanceTemplatesGetCall struct { header_ http.Header } -// Get: Returns the specified instance template. Get a list of available -// instance templates by making a list() request. +// Get: Returns the specified instance template. Gets a list of +// available instance templates by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/instanceTemplates/get func (r *InstanceTemplatesService) Get(project string, instanceTemplate string) *InstanceTemplatesGetCall { c := &InstanceTemplatesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -52974,7 +55104,7 @@ func (c *InstanceTemplatesGetCall) Do(opts ...googleapi.CallOption) (*InstanceTe } return ret, nil // { - // "description": "Returns the specified instance template. Get a list of available instance templates by making a list() request.", + // "description": "Returns the specified instance template. Gets a list of available instance templates by making a list() request.", // "httpMethod": "GET", // "id": "compute.instanceTemplates.get", // "parameterOrder": [ @@ -53194,32 +55324,28 @@ func (r *InstanceTemplatesService) List(project string) *InstanceTemplatesListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceTemplatesListCall) Filter(filter string) *InstanceTemplatesListCall { c.urlParams_.Set("filter", filter) return c @@ -53363,7 +55489,7 @@ func (c *InstanceTemplatesListCall) Do(opts ...googleapi.CallOption) (*InstanceT // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -53785,32 +55911,28 @@ func (r *InstancesService) AggregatedList(project string) *InstancesAggregatedLi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstancesAggregatedListCall) Filter(filter string) *InstancesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -53954,7 +56076,7 @@ func (c *InstancesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Instanc // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -54771,8 +56893,8 @@ type InstancesGetCall struct { header_ http.Header } -// Get: Returns the specified Instance resource. Get a list of available -// instances by making a list() request. +// Get: Returns the specified Instance resource. Gets a list of +// available instances by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/get func (r *InstancesService) Get(project string, zone string, instance string) *InstancesGetCall { c := &InstancesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -54878,7 +57000,7 @@ func (c *InstancesGetCall) Do(opts ...googleapi.CallOption) (*Instance, error) { } return ret, nil // { - // "description": "Returns the specified Instance resource. Get a list of available instances by making a list() request.", + // "description": "Returns the specified Instance resource. Gets a list of available instances by making a list() request.", // "httpMethod": "GET", // "id": "compute.instances.get", // "parameterOrder": [ @@ -55334,32 +57456,28 @@ func (r *InstancesService) List(project string, zone string) *InstancesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstancesListCall) Filter(filter string) *InstancesListCall { c.urlParams_.Set("filter", filter) return c @@ -55505,7 +57623,7 @@ func (c *InstancesListCall) Do(opts ...googleapi.CallOption) (*InstanceList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -55599,32 +57717,28 @@ func (r *InstancesService) ListReferrers(project string, zone string, instance s return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstancesListReferrersCall) Filter(filter string) *InstancesListReferrersCall { c.urlParams_.Set("filter", filter) return c @@ -55772,7 +57886,7 @@ func (c *InstancesListReferrersCall) Do(opts ...googleapi.CallOption) (*Instance // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -57675,6 +59789,189 @@ func (c *InstancesSetServiceAccountCall) Do(opts ...googleapi.CallOption) (*Oper } +// method id "compute.instances.setShieldedVmIntegrityPolicy": + +type InstancesSetShieldedVmIntegrityPolicyCall struct { + s *Service + project string + zone string + instance string + shieldedvmintegritypolicy *ShieldedVmIntegrityPolicy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// 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. +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 + c.zone = zone + c.instance = instance + c.shieldedvmintegritypolicy = shieldedvmintegritypolicy + 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 *InstancesSetShieldedVmIntegrityPolicyCall) RequestId(requestId string) *InstancesSetShieldedVmIntegrityPolicyCall { + 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 *InstancesSetShieldedVmIntegrityPolicyCall) Fields(s ...googleapi.Field) *InstancesSetShieldedVmIntegrityPolicyCall { + 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 *InstancesSetShieldedVmIntegrityPolicyCall) Context(ctx context.Context) *InstancesSetShieldedVmIntegrityPolicyCall { + 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 *InstancesSetShieldedVmIntegrityPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesSetShieldedVmIntegrityPolicyCall) 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.shieldedvmintegritypolicy) + 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}/instances/{instance}/setShieldedVmIntegrityPolicy") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PATCH", urls, body) + 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.setShieldedVmIntegrityPolicy" 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 *InstancesSetShieldedVmIntegrityPolicyCall) 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 Shielded VM integrity policy for an instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "httpMethod": "PATCH", + // "id": "compute.instances.setShieldedVmIntegrityPolicy", + // "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}/setShieldedVmIntegrityPolicy", + // "request": { + // "$ref": "ShieldedVmIntegrityPolicy" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instances.setTags": type InstancesSetTagsCall struct { @@ -57858,6 +60155,154 @@ 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/simulateMaintenanceEvent") + 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, + "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])?", + // "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 { @@ -57870,9 +60315,8 @@ type InstancesStartCall struct { header_ http.Header } -// Start: Starts an instance that was stopped using the using the -// instances().stop method. For more information, see Restart an -// instance. +// Start: Starts an instance that was stopped using the instances().stop +// method. For more information, see Restart an instance. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/start func (r *InstancesService) Start(project string, zone string, instance string) *InstancesStartCall { c := &InstancesStartCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -57984,7 +60428,7 @@ func (c *InstancesStartCall) Do(opts ...googleapi.CallOption) (*Operation, error } return ret, nil // { - // "description": "Starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance.", + // "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", // "httpMethod": "POST", // "id": "compute.instances.start", // "parameterOrder": [ @@ -58046,8 +60490,8 @@ type InstancesStartWithEncryptionKeyCall struct { } // StartWithEncryptionKey: Starts an instance that was stopped using the -// using the instances().stop method. For more information, see Restart -// an instance. +// instances().stop method. For more information, see Restart an +// instance. func (r *InstancesService) StartWithEncryptionKey(project string, zone string, instance string, instancesstartwithencryptionkeyrequest *InstancesStartWithEncryptionKeyRequest) *InstancesStartWithEncryptionKeyCall { c := &InstancesStartWithEncryptionKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -58164,7 +60608,7 @@ func (c *InstancesStartWithEncryptionKeyCall) Do(opts ...googleapi.CallOption) ( } return ret, nil // { - // "description": "Starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance.", + // "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", // "httpMethod": "POST", // "id": "compute.instances.startWithEncryptionKey", // "parameterOrder": [ @@ -58933,6 +61377,189 @@ func (c *InstancesUpdateNetworkInterfaceCall) Do(opts ...googleapi.CallOption) ( } +// method id "compute.instances.updateShieldedVmConfig": + +type InstancesUpdateShieldedVmConfigCall struct { + s *Service + project string + zone string + instance string + shieldedvmconfig *ShieldedVmConfig + urlParams_ gensupport.URLParams + ctx_ context.Context + 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. +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 + c.zone = zone + c.instance = instance + c.shieldedvmconfig = shieldedvmconfig + 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 *InstancesUpdateShieldedVmConfigCall) RequestId(requestId string) *InstancesUpdateShieldedVmConfigCall { + 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 *InstancesUpdateShieldedVmConfigCall) Fields(s ...googleapi.Field) *InstancesUpdateShieldedVmConfigCall { + 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 *InstancesUpdateShieldedVmConfigCall) Context(ctx context.Context) *InstancesUpdateShieldedVmConfigCall { + 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 *InstancesUpdateShieldedVmConfigCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesUpdateShieldedVmConfigCall) 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.shieldedvmconfig) + 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}/instances/{instance}/updateShieldedVmConfig") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PATCH", urls, body) + 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.updateShieldedVmConfig" 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 *InstancesUpdateShieldedVmConfigCall) 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 Shielded VM config for an instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "httpMethod": "PATCH", + // "id": "compute.instances.updateShieldedVmConfig", + // "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}/updateShieldedVmConfig", + // "request": { + // "$ref": "ShieldedVmConfig" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.interconnectAttachments.aggregatedList": type InterconnectAttachmentsAggregatedListCall struct { @@ -58952,32 +61579,28 @@ func (r *InterconnectAttachmentsService) AggregatedList(project string) *Interco return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectAttachmentsAggregatedListCall) Filter(filter string) *InterconnectAttachmentsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -59122,7 +61745,7 @@ func (c *InterconnectAttachmentsAggregatedListCall) Do(opts ...googleapi.CallOpt // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -59711,32 +62334,28 @@ func (r *InterconnectAttachmentsService) List(project string, region string) *In return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectAttachmentsListCall) Filter(filter string) *InterconnectAttachmentsListCall { c.urlParams_.Set("filter", filter) return c @@ -59882,7 +62501,7 @@ func (c *InterconnectAttachmentsListCall) Do(opts ...googleapi.CallOption) (*Int // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -60489,8 +63108,8 @@ type InterconnectLocationsGetCall struct { header_ http.Header } -// Get: Returns the details for the specified interconnect location. Get -// a list of available interconnect locations by making a list() +// Get: Returns the details for the specified interconnect location. +// Gets a list of available interconnect locations by making a list() // request. func (r *InterconnectLocationsService) Get(project string, interconnectLocation string) *InterconnectLocationsGetCall { c := &InterconnectLocationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -60594,7 +63213,7 @@ func (c *InterconnectLocationsGetCall) Do(opts ...googleapi.CallOption) (*Interc } return ret, nil // { - // "description": "Returns the details for the specified interconnect location. Get a list of available interconnect locations by making a list() request.", + // "description": "Returns the details for the specified interconnect location. Gets a list of available interconnect locations by making a list() request.", // "httpMethod": "GET", // "id": "compute.interconnectLocations.get", // "parameterOrder": [ @@ -60649,32 +63268,28 @@ func (r *InterconnectLocationsService) List(project string) *InterconnectLocatio return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectLocationsListCall) Filter(filter string) *InterconnectLocationsListCall { c.urlParams_.Set("filter", filter) return c @@ -60818,7 +63433,7 @@ func (c *InterconnectLocationsListCall) Do(opts ...googleapi.CallOption) (*Inter // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -61373,32 +63988,28 @@ func (r *InterconnectsService) List(project string) *InterconnectsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectsListCall) Filter(filter string) *InterconnectsListCall { c.urlParams_.Set("filter", filter) return c @@ -61542,7 +64153,7 @@ func (c *InterconnectsListCall) Do(opts ...googleapi.CallOption) (*InterconnectL // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -62713,7 +65324,7 @@ type LicensesListCall struct { // List: Retrieves the list of licenses available in the specified // project. This method does not get any licenses that belong to other // projects, including licenses attached to publicly-available images, -// like Debian 8. If you want to get a list of publicly-available +// like Debian 9. If you want to get a list of publicly-available // licenses, use this method to make a request to the respective image // project, such as debian-cloud or windows-cloud. func (r *LicensesService) List(project string) *LicensesListCall { @@ -62722,32 +65333,28 @@ func (r *LicensesService) List(project string) *LicensesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *LicensesListCall) Filter(filter string) *LicensesListCall { c.urlParams_.Set("filter", filter) return c @@ -62883,7 +65490,7 @@ func (c *LicensesListCall) Do(opts ...googleapi.CallOption) (*LicensesListRespon } return ret, nil // { - // "description": "Retrieves the list of licenses available in the specified project. This method does not get any licenses that belong to other projects, including licenses attached to publicly-available images, like Debian 8. If you want to get a list of publicly-available licenses, use this method to make a request to the respective image project, such as debian-cloud or windows-cloud.", + // "description": "Retrieves the list of licenses available in the specified project. This method does not get any licenses that belong to other projects, including licenses attached to publicly-available images, like Debian 9. If you want to get a list of publicly-available licenses, use this method to make a request to the respective image project, such as debian-cloud or windows-cloud.", // "httpMethod": "GET", // "id": "compute.licenses.list", // "parameterOrder": [ @@ -62891,7 +65498,7 @@ func (c *LicensesListCall) Do(opts ...googleapi.CallOption) (*LicensesListRespon // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -62974,32 +65581,28 @@ func (r *MachineTypesService) AggregatedList(project string) *MachineTypesAggreg return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *MachineTypesAggregatedListCall) Filter(filter string) *MachineTypesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -63143,7 +65746,7 @@ func (c *MachineTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Mach // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -63220,7 +65823,7 @@ type MachineTypesGetCall struct { header_ http.Header } -// Get: Returns the specified machine type. Get a list of available +// Get: Returns the specified machine type. Gets a list of available // machine types by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/machineTypes/get func (r *MachineTypesService) Get(project string, zone string, machineType string) *MachineTypesGetCall { @@ -63327,7 +65930,7 @@ func (c *MachineTypesGetCall) Do(opts ...googleapi.CallOption) (*MachineType, er } return ret, nil // { - // "description": "Returns the specified machine type. Get a list of available machine types by making a list() request.", + // "description": "Returns the specified machine type. Gets a list of available machine types by making a list() request.", // "httpMethod": "GET", // "id": "compute.machineTypes.get", // "parameterOrder": [ @@ -63393,32 +65996,28 @@ func (r *MachineTypesService) List(project string, zone string) *MachineTypesLis return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *MachineTypesListCall) Filter(filter string) *MachineTypesListCall { c.urlParams_.Set("filter", filter) return c @@ -63564,7 +66163,7 @@ func (c *MachineTypesListCall) Do(opts ...googleapi.CallOption) (*MachineTypeLis // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -63978,7 +66577,7 @@ type NetworksGetCall struct { header_ http.Header } -// Get: Returns the specified network. Get a list of available networks +// Get: Returns the specified network. Gets a list of available networks // by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/networks/get func (r *NetworksService) Get(project string, network string) *NetworksGetCall { @@ -64083,7 +66682,7 @@ func (c *NetworksGetCall) Do(opts ...googleapi.CallOption) (*Network, error) { } return ret, nil // { - // "description": "Returns the specified network. Get a list of available networks by making a list() request.", + // "description": "Returns the specified network. Gets a list of available networks by making a list() request.", // "httpMethod": "GET", // "id": "compute.networks.get", // "parameterOrder": [ @@ -64300,32 +66899,28 @@ func (r *NetworksService) List(project string) *NetworksListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *NetworksListCall) Filter(filter string) *NetworksListCall { c.urlParams_.Set("filter", filter) return c @@ -64469,7 +67064,7 @@ func (c *NetworksListCall) Do(opts ...googleapi.CallOption) (*NetworkList, error // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -65184,6 +67779,4209 @@ func (c *NetworksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Test } +// 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/addNodes") + 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, + "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 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}/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. +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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeGroups") + 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.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.", + // "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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}") + 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, + "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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/deleteNodes") + 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, + "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. +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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}") + 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, + "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.", + // "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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{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.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 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}/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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups") + 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.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. +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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups") + 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.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.", + // "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.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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{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.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 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}/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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/setNodeTemplate") + 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, + "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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{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.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 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}/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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeTemplates") + 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.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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{nodeTemplate}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", urls, body) + 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{nodeTemplate}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{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, + "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 of the resource 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/{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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{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, + "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 of the resource 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/{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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{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, + "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 of the resource 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/{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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeTypes") + 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.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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeTypes/{nodeType}") + 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, + "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) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeTypes") + 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.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 { @@ -65955,7 +72753,7 @@ type ProjectsGetXpnHostCall struct { header_ http.Header } -// GetXpnHost: Get the shared VPC host project that this project links +// GetXpnHost: Gets the shared VPC host project that this project links // to. May be empty if no link exists. func (r *ProjectsService) GetXpnHost(project string) *ProjectsGetXpnHostCall { c := &ProjectsGetXpnHostCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -66057,7 +72855,7 @@ func (c *ProjectsGetXpnHostCall) Do(opts ...googleapi.CallOption) (*Project, err } return ret, nil // { - // "description": "Get the shared VPC host project that this project links to. May be empty if no link exists.", + // "description": "Gets the shared VPC host project that this project links to. May be empty if no link exists.", // "httpMethod": "GET", // "id": "compute.projects.getXpnHost", // "parameterOrder": [ @@ -66095,7 +72893,7 @@ type ProjectsGetXpnResourcesCall struct { header_ http.Header } -// GetXpnResources: Get service resources (a.k.a service project) +// GetXpnResources: Gets service resources (a.k.a service project) // associated with this host project. func (r *ProjectsService) GetXpnResources(project string) *ProjectsGetXpnResourcesCall { c := &ProjectsGetXpnResourcesCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -66221,7 +73019,7 @@ func (c *ProjectsGetXpnResourcesCall) Do(opts ...googleapi.CallOption) (*Project } return ret, nil // { - // "description": "Get service resources (a.k.a service project) associated with this host project.", + // "description": "Gets service resources (a.k.a service project) associated with this host project.", // "httpMethod": "GET", // "id": "compute.projects.getXpnResources", // "parameterOrder": [ @@ -66299,7 +73097,7 @@ type ProjectsListXpnHostsCall struct { header_ http.Header } -// ListXpnHosts: List all shared VPC host projects visible to the user +// ListXpnHosts: Lists all shared VPC host projects visible to the user // in an organization. func (r *ProjectsService) ListXpnHosts(project string, projectslistxpnhostsrequest *ProjectsListXpnHostsRequest) *ProjectsListXpnHostsCall { c := &ProjectsListXpnHostsCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -66418,7 +73216,7 @@ func (c *ProjectsListXpnHostsCall) Do(opts ...googleapi.CallOption) (*XpnHostLis } return ret, nil // { - // "description": "List all shared VPC host projects visible to the user in an organization.", + // "description": "Lists all shared VPC host projects visible to the user in an organization.", // "httpMethod": "POST", // "id": "compute.projects.listXpnHosts", // "parameterOrder": [ @@ -67821,32 +74619,28 @@ func (r *RegionAutoscalersService) List(project string, region string) *RegionAu return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionAutoscalersListCall) Filter(filter string) *RegionAutoscalersListCall { c.urlParams_.Set("filter", filter) return c @@ -67992,7 +74786,7 @@ func (c *RegionAutoscalersListCall) Do(opts ...googleapi.CallOption) (*RegionAut // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -69277,32 +76071,28 @@ func (r *RegionBackendServicesService) List(project string, region string) *Regi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionBackendServicesListCall) Filter(filter string) *RegionBackendServicesListCall { c.urlParams_.Set("filter", filter) return c @@ -69448,7 +76238,7 @@ func (c *RegionBackendServicesListCall) Do(opts ...googleapi.CallOption) (*Backe // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -70066,32 +76856,28 @@ func (r *RegionCommitmentsService) AggregatedList(project string) *RegionCommitm return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionCommitmentsAggregatedListCall) Filter(filter string) *RegionCommitmentsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -70235,7 +77021,7 @@ func (c *RegionCommitmentsAggregatedListCall) Do(opts ...googleapi.CallOption) ( // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -70312,7 +77098,7 @@ type RegionCommitmentsGetCall struct { header_ http.Header } -// Get: Returns the specified commitment resource. Get a list of +// Get: Returns the specified commitment resource. Gets a list of // available commitments by making a list() request. func (r *RegionCommitmentsService) Get(project string, region string, commitment string) *RegionCommitmentsGetCall { c := &RegionCommitmentsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -70418,7 +77204,7 @@ func (c *RegionCommitmentsGetCall) Do(opts ...googleapi.CallOption) (*Commitment } return ret, nil // { - // "description": "Returns the specified commitment resource. Get a list of available commitments by making a list() request.", + // "description": "Returns the specified commitment resource. Gets a list of available commitments by making a list() request.", // "httpMethod": "GET", // "id": "compute.regionCommitments.get", // "parameterOrder": [ @@ -70654,32 +77440,28 @@ func (r *RegionCommitmentsService) List(project string, region string) *RegionCo return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionCommitmentsListCall) Filter(filter string) *RegionCommitmentsListCall { c.urlParams_.Set("filter", filter) return c @@ -70825,7 +77607,7 @@ func (c *RegionCommitmentsListCall) Do(opts ...googleapi.CallOption) (*Commitmen // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -70909,7 +77691,7 @@ type RegionDiskTypesGetCall struct { header_ http.Header } -// Get: Returns the specified regional disk type. Get a list of +// Get: Returns the specified regional disk type. Gets a list of // available disk types by making a list() request. func (r *RegionDiskTypesService) Get(project string, region string, diskType string) *RegionDiskTypesGetCall { c := &RegionDiskTypesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -71015,7 +77797,7 @@ func (c *RegionDiskTypesGetCall) Do(opts ...googleapi.CallOption) (*DiskType, er } return ret, nil // { - // "description": "Returns the specified regional disk type. Get a list of available disk types by making a list() request.", + // "description": "Returns the specified regional disk type. Gets a list of available disk types by making a list() request.", // "httpMethod": "GET", // "id": "compute.regionDiskTypes.get", // "parameterOrder": [ @@ -71080,32 +77862,28 @@ func (r *RegionDiskTypesService) List(project string, region string) *RegionDisk return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionDiskTypesListCall) Filter(filter string) *RegionDiskTypesListCall { c.urlParams_.Set("filter", filter) return c @@ -71251,7 +78029,7 @@ func (c *RegionDiskTypesListCall) Do(opts ...googleapi.CallOption) (*RegionDiskT // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -72042,32 +78820,28 @@ func (r *RegionDisksService) List(project string, region string) *RegionDisksLis return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionDisksListCall) Filter(filter string) *RegionDisksListCall { c.urlParams_.Set("filter", filter) return c @@ -72213,7 +78987,7 @@ func (c *RegionDisksListCall) Do(opts ...googleapi.CallOption) (*DiskList, error // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -73723,32 +80497,28 @@ func (r *RegionInstanceGroupManagersService) List(project string, region string) return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionInstanceGroupManagersListCall) Filter(filter string) *RegionInstanceGroupManagersListCall { c.urlParams_.Set("filter", filter) return c @@ -73894,7 +80664,7 @@ func (c *RegionInstanceGroupManagersListCall) Do(opts ...googleapi.CallOption) ( // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -75812,32 +82582,28 @@ func (r *RegionInstanceGroupsService) List(project string, region string) *Regio return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionInstanceGroupsListCall) Filter(filter string) *RegionInstanceGroupsListCall { c.urlParams_.Set("filter", filter) return c @@ -75983,7 +82749,7 @@ func (c *RegionInstanceGroupsListCall) Do(opts ...googleapi.CallOption) (*Region // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -76079,32 +82845,28 @@ func (r *RegionInstanceGroupsService) ListInstances(project string, region strin return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionInstanceGroupsListInstancesCall) Filter(filter string) *RegionInstanceGroupsListInstancesCall { c.urlParams_.Set("filter", filter) return c @@ -76245,7 +83007,7 @@ func (c *RegionInstanceGroupsListInstancesCall) Do(opts ...googleapi.CallOption) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -76968,32 +83730,28 @@ func (r *RegionOperationsService) List(project string, region string) *RegionOpe return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionOperationsListCall) Filter(filter string) *RegionOperationsListCall { c.urlParams_.Set("filter", filter) return c @@ -77139,7 +83897,7 @@ func (c *RegionOperationsListCall) Do(opts ...googleapi.CallOption) (*OperationL // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -77222,7 +83980,7 @@ type RegionsGetCall struct { header_ http.Header } -// Get: Returns the specified Region resource. Get a list of available +// Get: Returns the specified Region resource. Gets a list of available // regions by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/regions/get func (r *RegionsService) Get(project string, region string) *RegionsGetCall { @@ -77327,7 +84085,7 @@ func (c *RegionsGetCall) Do(opts ...googleapi.CallOption) (*Region, error) { } return ret, nil // { - // "description": "Returns the specified Region resource. Get a list of available regions by making a list() request.", + // "description": "Returns the specified Region resource. Gets a list of available regions by making a list() request.", // "httpMethod": "GET", // "id": "compute.regions.get", // "parameterOrder": [ @@ -77383,32 +84141,28 @@ func (r *RegionsService) List(project string) *RegionsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionsListCall) Filter(filter string) *RegionsListCall { c.urlParams_.Set("filter", filter) return c @@ -77552,7 +84306,7 @@ func (c *RegionsListCall) Do(opts ...googleapi.CallOption) (*RegionList, error) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -77634,32 +84388,28 @@ func (r *RoutersService) AggregatedList(project string) *RoutersAggregatedListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RoutersAggregatedListCall) Filter(filter string) *RoutersAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -77803,7 +84553,7 @@ func (c *RoutersAggregatedListCall) Do(opts ...googleapi.CallOption) (*RouterAgg // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -78051,7 +84801,7 @@ type RoutersGetCall struct { header_ http.Header } -// Get: Returns the specified Router resource. Get a list of available +// Get: Returns the specified Router resource. Gets a list of available // routers by making a list() request. func (r *RoutersService) Get(project string, region string, router string) *RoutersGetCall { c := &RoutersGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -78157,7 +84907,7 @@ func (c *RoutersGetCall) Do(opts ...googleapi.CallOption) (*Router, error) { } return ret, nil // { - // "description": "Returns the specified Router resource. Get a list of available routers by making a list() request.", + // "description": "Returns the specified Router resource. Gets a list of available routers by making a list() request.", // "httpMethod": "GET", // "id": "compute.routers.get", // "parameterOrder": [ @@ -78556,32 +85306,28 @@ func (r *RoutersService) List(project string, region string) *RoutersListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RoutersListCall) Filter(filter string) *RoutersListCall { c.urlParams_.Set("filter", filter) return c @@ -78727,7 +85473,7 @@ func (c *RoutersListCall) Do(opts ...googleapi.CallOption) (*RouterList, error) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -79655,7 +86401,7 @@ type RoutesGetCall struct { header_ http.Header } -// Get: Returns the specified Route resource. Get a list of available +// Get: Returns the specified Route resource. Gets a list of available // routes by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/routes/get func (r *RoutesService) Get(project string, route string) *RoutesGetCall { @@ -79760,7 +86506,7 @@ func (c *RoutesGetCall) Do(opts ...googleapi.CallOption) (*Route, error) { } return ret, nil // { - // "description": "Returns the specified Route resource. Get a list of available routes by making a list() request.", + // "description": "Returns the specified Route resource. Gets a list of available routes by making a list() request.", // "httpMethod": "GET", // "id": "compute.routes.get", // "parameterOrder": [ @@ -79977,32 +86723,28 @@ func (r *RoutesService) List(project string) *RoutesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RoutesListCall) Filter(filter string) *RoutesListCall { c.urlParams_.Set("filter", filter) return c @@ -80146,7 +86888,7 @@ func (c *RoutesListCall) Do(opts ...googleapi.CallOption) (*RouteList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -81159,32 +87901,28 @@ func (r *SecurityPoliciesService) List(project string) *SecurityPoliciesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 @@ -81328,7 +88066,7 @@ func (c *SecurityPoliciesListCall) Do(opts ...googleapi.CallOption) (*SecurityPo // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -82198,8 +88936,8 @@ type SnapshotsGetCall struct { header_ http.Header } -// Get: Returns the specified Snapshot resource. Get a list of available -// snapshots by making a list() request. +// Get: Returns the specified Snapshot resource. Gets a list of +// available snapshots by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/snapshots/get func (r *SnapshotsService) Get(project string, snapshot string) *SnapshotsGetCall { c := &SnapshotsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -82303,7 +89041,7 @@ func (c *SnapshotsGetCall) Do(opts ...googleapi.CallOption) (*Snapshot, error) { } return ret, nil // { - // "description": "Returns the specified Snapshot resource. Get a list of available snapshots by making a list() request.", + // "description": "Returns the specified Snapshot resource. Gets a list of available snapshots by making a list() request.", // "httpMethod": "GET", // "id": "compute.snapshots.get", // "parameterOrder": [ @@ -82359,32 +89097,28 @@ func (r *SnapshotsService) List(project string) *SnapshotsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SnapshotsListCall) Filter(filter string) *SnapshotsListCall { c.urlParams_.Set("filter", filter) return c @@ -82528,7 +89262,7 @@ func (c *SnapshotsListCall) Do(opts ...googleapi.CallOption) (*SnapshotList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -83059,7 +89793,7 @@ type SslCertificatesGetCall struct { header_ http.Header } -// Get: Returns the specified SslCertificate resource. Get a list of +// Get: Returns the specified SslCertificate resource. Gets a list of // available SSL certificates by making a list() request. func (r *SslCertificatesService) Get(project string, sslCertificate string) *SslCertificatesGetCall { c := &SslCertificatesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -83163,7 +89897,7 @@ func (c *SslCertificatesGetCall) Do(opts ...googleapi.CallOption) (*SslCertifica } return ret, nil // { - // "description": "Returns the specified SslCertificate resource. Get a list of available SSL certificates by making a list() request.", + // "description": "Returns the specified SslCertificate resource. Gets a list of available SSL certificates by making a list() request.", // "httpMethod": "GET", // "id": "compute.sslCertificates.get", // "parameterOrder": [ @@ -83378,32 +90112,28 @@ func (r *SslCertificatesService) List(project string) *SslCertificatesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SslCertificatesListCall) Filter(filter string) *SslCertificatesListCall { c.urlParams_.Set("filter", filter) return c @@ -83547,7 +90277,7 @@ func (c *SslCertificatesListCall) Do(opts ...googleapi.CallOption) (*SslCertific // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -83932,7 +90662,7 @@ type SslPoliciesGetCall struct { header_ http.Header } -// Get: List all of the ordered rules present in a single specified +// Get: Lists all of the ordered rules present in a single specified // policy. func (r *SslPoliciesService) Get(project string, sslPolicy string) *SslPoliciesGetCall { c := &SslPoliciesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -84036,7 +90766,7 @@ func (c *SslPoliciesGetCall) Do(opts ...googleapi.CallOption) (*SslPolicy, error } return ret, nil // { - // "description": "List all of the ordered rules present in a single specified policy.", + // "description": "Lists all of the ordered rules present in a single specified policy.", // "httpMethod": "GET", // "id": "compute.sslPolicies.get", // "parameterOrder": [ @@ -84082,7 +90812,7 @@ type SslPoliciesInsertCall struct { header_ http.Header } -// Insert: Returns the specified SSL policy resource. Get a list of +// Insert: Returns the specified SSL policy resource. Gets a list of // available SSL policies by making a list() request. func (r *SslPoliciesService) Insert(project string, sslpolicy *SslPolicy) *SslPoliciesInsertCall { c := &SslPoliciesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -84196,7 +90926,7 @@ func (c *SslPoliciesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, er } return ret, nil // { - // "description": "Returns the specified SSL policy resource. Get a list of available SSL policies by making a list() request.", + // "description": "Returns the specified SSL policy resource. Gets a list of available SSL policies by making a list() request.", // "httpMethod": "POST", // "id": "compute.sslPolicies.insert", // "parameterOrder": [ @@ -84242,7 +90972,7 @@ type SslPoliciesListCall struct { header_ http.Header } -// List: List all the SSL policies that have been configured for the +// List: Lists all the SSL policies that have been configured for the // specified project. func (r *SslPoliciesService) List(project string) *SslPoliciesListCall { c := &SslPoliciesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -84250,32 +90980,28 @@ func (r *SslPoliciesService) List(project string) *SslPoliciesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SslPoliciesListCall) Filter(filter string) *SslPoliciesListCall { c.urlParams_.Set("filter", filter) return c @@ -84411,7 +91137,7 @@ func (c *SslPoliciesListCall) Do(opts ...googleapi.CallOption) (*SslPoliciesList } return ret, nil // { - // "description": "List all the SSL policies that have been configured for the specified project.", + // "description": "Lists all the SSL policies that have been configured for the specified project.", // "httpMethod": "GET", // "id": "compute.sslPolicies.list", // "parameterOrder": [ @@ -84419,7 +91145,7 @@ func (c *SslPoliciesListCall) Do(opts ...googleapi.CallOption) (*SslPoliciesList // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -84502,32 +91228,28 @@ func (r *SslPoliciesService) ListAvailableFeatures(project string) *SslPoliciesL return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SslPoliciesListAvailableFeaturesCall) Filter(filter string) *SslPoliciesListAvailableFeaturesCall { c.urlParams_.Set("filter", filter) return c @@ -84673,7 +91395,7 @@ func (c *SslPoliciesListAvailableFeaturesCall) Do(opts ...googleapi.CallOption) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -85052,32 +91774,28 @@ func (r *SubnetworksService) AggregatedList(project string) *SubnetworksAggregat return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SubnetworksAggregatedListCall) Filter(filter string) *SubnetworksAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -85221,7 +91939,7 @@ func (c *SubnetworksAggregatedListCall) Do(opts ...googleapi.CallOption) (*Subne // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -85651,7 +92369,7 @@ type SubnetworksGetCall struct { header_ http.Header } -// Get: Returns the specified subnetwork. Get a list of available +// Get: Returns the specified subnetwork. Gets a list of available // subnetworks list() request. func (r *SubnetworksService) Get(project string, region string, subnetwork string) *SubnetworksGetCall { c := &SubnetworksGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -85757,7 +92475,7 @@ func (c *SubnetworksGetCall) Do(opts ...googleapi.CallOption) (*Subnetwork, erro } return ret, nil // { - // "description": "Returns the specified subnetwork. Get a list of available subnetworks list() request.", + // "description": "Returns the specified subnetwork. Gets a list of available subnetworks list() request.", // "httpMethod": "GET", // "id": "compute.subnetworks.get", // "parameterOrder": [ @@ -86156,32 +92874,28 @@ func (r *SubnetworksService) List(project string, region string) *SubnetworksLis return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SubnetworksListCall) Filter(filter string) *SubnetworksListCall { c.urlParams_.Set("filter", filter) return c @@ -86327,7 +93041,7 @@ func (c *SubnetworksListCall) Do(opts ...googleapi.CallOption) (*SubnetworkList, // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -86416,32 +93130,28 @@ func (r *SubnetworksService) ListUsable(project string) *SubnetworksListUsableCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 @@ -86585,7 +93295,7 @@ func (c *SubnetworksListUsableCall) Do(opts ...googleapi.CallOption) (*UsableSub // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -86664,9 +93374,10 @@ 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 and -// allow_subnet_cidr_routes_overlap. It is also mandatory to specify the -// current fingeprint of the subnetwork resource being patched. +// 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. 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 @@ -86783,7 +93494,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 and allow_subnet_cidr_routes_overlap. 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 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.", // "httpMethod": "PATCH", // "id": "compute.subnetworks.patch", // "parameterOrder": [ @@ -86837,24 +93548,24 @@ 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 - policy *Policy - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header + 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, policy *Policy) *SubnetworksSetIamPolicyCall { +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.policy = policy + c.regionsetpolicyrequest = regionsetpolicyrequest return c } @@ -86890,7 +93601,7 @@ func (c *SubnetworksSetIamPolicyCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.regionsetpolicyrequest) if err != nil { return nil, err } @@ -86979,7 +93690,7 @@ func (c *SubnetworksSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, // }, // "path": "{project}/regions/{region}/subnetworks/{resource}/setIamPolicy", // "request": { - // "$ref": "Policy" + // "$ref": "RegionSetPolicyRequest" // }, // "response": { // "$ref": "Policy" @@ -87507,7 +94218,7 @@ type TargetHttpProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetHttpProxy resource. Get a list of +// Get: Returns the specified TargetHttpProxy resource. Gets a list of // available target HTTP proxies by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/targetHttpProxies/get func (r *TargetHttpProxiesService) Get(project string, targetHttpProxy string) *TargetHttpProxiesGetCall { @@ -87612,7 +94323,7 @@ func (c *TargetHttpProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetHttp } return ret, nil // { - // "description": "Returns the specified TargetHttpProxy resource. Get a list of available target HTTP proxies by making a list() request.", + // "description": "Returns the specified TargetHttpProxy resource. Gets a list of available target HTTP proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetHttpProxies.get", // "parameterOrder": [ @@ -87829,32 +94540,28 @@ func (r *TargetHttpProxiesService) List(project string) *TargetHttpProxiesListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetHttpProxiesListCall) Filter(filter string) *TargetHttpProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -87998,7 +94705,7 @@ func (c *TargetHttpProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetHtt // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -88553,7 +95260,7 @@ type TargetHttpsProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetHttpsProxy resource. Get a list of +// Get: Returns the specified TargetHttpsProxy resource. Gets a list of // available target HTTPS proxies by making a list() request. func (r *TargetHttpsProxiesService) Get(project string, targetHttpsProxy string) *TargetHttpsProxiesGetCall { c := &TargetHttpsProxiesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -88657,7 +95364,7 @@ func (c *TargetHttpsProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetHtt } return ret, nil // { - // "description": "Returns the specified TargetHttpsProxy resource. Get a list of available target HTTPS proxies by making a list() request.", + // "description": "Returns the specified TargetHttpsProxy resource. Gets a list of available target HTTPS proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetHttpsProxies.get", // "parameterOrder": [ @@ -88872,32 +95579,28 @@ func (r *TargetHttpsProxiesService) List(project string) *TargetHttpsProxiesList return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetHttpsProxiesListCall) Filter(filter string) *TargetHttpsProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -89041,7 +95744,7 @@ func (c *TargetHttpsProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetHt // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -89954,32 +96657,28 @@ func (r *TargetInstancesService) AggregatedList(project string) *TargetInstances return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetInstancesAggregatedListCall) Filter(filter string) *TargetInstancesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -90123,7 +96822,7 @@ func (c *TargetInstancesAggregatedListCall) Do(opts ...googleapi.CallOption) (*T // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -90372,7 +97071,7 @@ type TargetInstancesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetInstance resource. Get a list of +// Get: Returns the specified TargetInstance resource. Gets a list of // available target instances by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/targetInstances/get func (r *TargetInstancesService) Get(project string, zone string, targetInstance string) *TargetInstancesGetCall { @@ -90479,7 +97178,7 @@ func (c *TargetInstancesGetCall) Do(opts ...googleapi.CallOption) (*TargetInstan } return ret, nil // { - // "description": "Returns the specified TargetInstance resource. Get a list of available target instances by making a list() request.", + // "description": "Returns the specified TargetInstance resource. Gets a list of available target instances by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetInstances.get", // "parameterOrder": [ @@ -90717,32 +97416,28 @@ func (r *TargetInstancesService) List(project string, zone string) *TargetInstan return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetInstancesListCall) Filter(filter string) *TargetInstancesListCall { c.urlParams_.Set("filter", filter) return c @@ -90888,7 +97583,7 @@ func (c *TargetInstancesListCall) Do(opts ...googleapi.CallOption) (*TargetInsta // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -91501,32 +98196,28 @@ func (r *TargetPoolsService) AggregatedList(project string) *TargetPoolsAggregat return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetPoolsAggregatedListCall) Filter(filter string) *TargetPoolsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -91670,7 +98361,7 @@ func (c *TargetPoolsAggregatedListCall) Do(opts ...googleapi.CallOption) (*Targe // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -91919,7 +98610,7 @@ type TargetPoolsGetCall struct { header_ http.Header } -// Get: Returns the specified target pool. Get a list of available +// Get: Returns the specified target pool. Gets a list of available // target pools by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/targetPools/get func (r *TargetPoolsService) Get(project string, region string, targetPool string) *TargetPoolsGetCall { @@ -92026,7 +98717,7 @@ func (c *TargetPoolsGetCall) Do(opts ...googleapi.CallOption) (*TargetPool, erro } return ret, nil // { - // "description": "Returns the specified target pool. Get a list of available target pools by making a list() request.", + // "description": "Returns the specified target pool. Gets a list of available target pools by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetPools.get", // "parameterOrder": [ @@ -92424,32 +99115,28 @@ func (r *TargetPoolsService) List(project string, region string) *TargetPoolsLis return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetPoolsListCall) Filter(filter string) *TargetPoolsListCall { c.urlParams_.Set("filter", filter) return c @@ -92595,7 +99282,7 @@ func (c *TargetPoolsListCall) Do(opts ...googleapi.CallOption) (*TargetPoolList, // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -93556,7 +100243,7 @@ type TargetSslProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetSslProxy resource. Get a list of +// Get: Returns the specified TargetSslProxy resource. Gets a list of // available target SSL proxies by making a list() request. func (r *TargetSslProxiesService) Get(project string, targetSslProxy string) *TargetSslProxiesGetCall { c := &TargetSslProxiesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -93660,7 +100347,7 @@ func (c *TargetSslProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetSslPr } return ret, nil // { - // "description": "Returns the specified TargetSslProxy resource. Get a list of available target SSL proxies by making a list() request.", + // "description": "Returns the specified TargetSslProxy resource. Gets a list of available target SSL proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetSslProxies.get", // "parameterOrder": [ @@ -93875,32 +100562,28 @@ func (r *TargetSslProxiesService) List(project string) *TargetSslProxiesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetSslProxiesListCall) Filter(filter string) *TargetSslProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -94044,7 +100727,7 @@ func (c *TargetSslProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetSslP // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -95110,7 +101793,7 @@ type TargetTcpProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetTcpProxy resource. Get a list of +// Get: Returns the specified TargetTcpProxy resource. Gets a list of // available target TCP proxies by making a list() request. func (r *TargetTcpProxiesService) Get(project string, targetTcpProxy string) *TargetTcpProxiesGetCall { c := &TargetTcpProxiesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -95214,7 +101897,7 @@ func (c *TargetTcpProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetTcpPr } return ret, nil // { - // "description": "Returns the specified TargetTcpProxy resource. Get a list of available target TCP proxies by making a list() request.", + // "description": "Returns the specified TargetTcpProxy resource. Gets a list of available target TCP proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetTcpProxies.get", // "parameterOrder": [ @@ -95429,32 +102112,28 @@ func (r *TargetTcpProxiesService) List(project string) *TargetTcpProxiesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetTcpProxiesListCall) Filter(filter string) *TargetTcpProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -95598,7 +102277,7 @@ func (c *TargetTcpProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetTcpP // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -96020,32 +102699,28 @@ func (r *TargetVpnGatewaysService) AggregatedList(project string) *TargetVpnGate return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetVpnGatewaysAggregatedListCall) Filter(filter string) *TargetVpnGatewaysAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -96189,7 +102864,7 @@ func (c *TargetVpnGatewaysAggregatedListCall) Do(opts ...googleapi.CallOption) ( // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -96437,7 +103112,7 @@ type TargetVpnGatewaysGetCall struct { header_ http.Header } -// Get: Returns the specified target VPN gateway. Get a list of +// Get: Returns the specified target VPN gateway. Gets a list of // available target VPN gateways by making a list() request. func (r *TargetVpnGatewaysService) Get(project string, region string, targetVpnGateway string) *TargetVpnGatewaysGetCall { c := &TargetVpnGatewaysGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -96543,7 +103218,7 @@ func (c *TargetVpnGatewaysGetCall) Do(opts ...googleapi.CallOption) (*TargetVpnG } return ret, nil // { - // "description": "Returns the specified target VPN gateway. Get a list of available target VPN gateways by making a list() request.", + // "description": "Returns the specified target VPN gateway. Gets a list of available target VPN gateways by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetVpnGateways.get", // "parameterOrder": [ @@ -96779,32 +103454,28 @@ func (r *TargetVpnGatewaysService) List(project string, region string) *TargetVp return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetVpnGatewaysListCall) Filter(filter string) *TargetVpnGatewaysListCall { c.urlParams_.Set("filter", filter) return c @@ -96950,7 +103621,7 @@ func (c *TargetVpnGatewaysListCall) Do(opts ...googleapi.CallOption) (*TargetVpn // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -97535,7 +104206,7 @@ type UrlMapsGetCall struct { header_ http.Header } -// Get: Returns the specified UrlMap resource. Get a list of available +// Get: Returns the specified UrlMap resource. Gets a list of available // URL maps by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/urlMaps/get func (r *UrlMapsService) Get(project string, urlMap string) *UrlMapsGetCall { @@ -97640,7 +104311,7 @@ func (c *UrlMapsGetCall) Do(opts ...googleapi.CallOption) (*UrlMap, error) { } return ret, nil // { - // "description": "Returns the specified UrlMap resource. Get a list of available URL maps by making a list() request.", + // "description": "Returns the specified UrlMap resource. Gets a list of available URL maps by making a list() request.", // "httpMethod": "GET", // "id": "compute.urlMaps.get", // "parameterOrder": [ @@ -98028,32 +104699,28 @@ func (r *UrlMapsService) List(project string) *UrlMapsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *UrlMapsListCall) Filter(filter string) *UrlMapsListCall { c.urlParams_.Set("filter", filter) return c @@ -98197,7 +104864,7 @@ func (c *UrlMapsListCall) Do(opts ...googleapi.CallOption) (*UrlMapList, error) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -98921,32 +105588,28 @@ func (r *VpnTunnelsService) AggregatedList(project string) *VpnTunnelsAggregated return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *VpnTunnelsAggregatedListCall) Filter(filter string) *VpnTunnelsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -99090,7 +105753,7 @@ func (c *VpnTunnelsAggregatedListCall) Do(opts ...googleapi.CallOption) (*VpnTun // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -99338,7 +106001,7 @@ type VpnTunnelsGetCall struct { header_ http.Header } -// Get: Returns the specified VpnTunnel resource. Get a list of +// Get: Returns the specified VpnTunnel resource. Gets a list of // available VPN tunnels by making a list() request. func (r *VpnTunnelsService) Get(project string, region string, vpnTunnel string) *VpnTunnelsGetCall { c := &VpnTunnelsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -99444,7 +106107,7 @@ func (c *VpnTunnelsGetCall) Do(opts ...googleapi.CallOption) (*VpnTunnel, error) } return ret, nil // { - // "description": "Returns the specified VpnTunnel resource. Get a list of available VPN tunnels by making a list() request.", + // "description": "Returns the specified VpnTunnel resource. Gets a list of available VPN tunnels by making a list() request.", // "httpMethod": "GET", // "id": "compute.vpnTunnels.get", // "parameterOrder": [ @@ -99680,32 +106343,28 @@ func (r *VpnTunnelsService) List(project string, region string) *VpnTunnelsListC return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *VpnTunnelsListCall) Filter(filter string) *VpnTunnelsListCall { c.urlParams_.Set("filter", filter) return c @@ -99851,7 +106510,7 @@ func (c *VpnTunnelsListCall) Do(opts ...googleapi.CallOption) (*VpnTunnelList, e // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -100568,32 +107227,28 @@ func (r *ZoneOperationsService) List(project string, zone string) *ZoneOperation return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ZoneOperationsListCall) Filter(filter string) *ZoneOperationsListCall { c.urlParams_.Set("filter", filter) return c @@ -100739,7 +107394,7 @@ func (c *ZoneOperationsListCall) Do(opts ...googleapi.CallOption) (*OperationLis // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -100822,7 +107477,7 @@ type ZonesGetCall struct { header_ http.Header } -// Get: Returns the specified Zone resource. Get a list of available +// Get: Returns the specified Zone resource. Gets a list of available // zones by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/zones/get func (r *ZonesService) Get(project string, zone string) *ZonesGetCall { @@ -100927,7 +107582,7 @@ func (c *ZonesGetCall) Do(opts ...googleapi.CallOption) (*Zone, error) { } return ret, nil // { - // "description": "Returns the specified Zone resource. Get a list of available zones by making a list() request.", + // "description": "Returns the specified Zone resource. Gets a list of available zones by making a list() request.", // "httpMethod": "GET", // "id": "compute.zones.get", // "parameterOrder": [ @@ -100983,32 +107638,28 @@ func (r *ZonesService) List(project string) *ZonesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ZonesListCall) Filter(filter string) *ZonesListCall { c.urlParams_.Set("filter", filter) return c @@ -101152,7 +107803,7 @@ func (c *ZonesListCall) Do(opts ...googleapi.CallOption) (*ZoneList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, 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 a188c6df4cf..8fb9acc9868 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": "\"-iA1DTNe4s-I6JZXPt1t1Ypy8IU/-YzN1b0_oAWbrk9rmdu60A0nf94\"", + "etag": "\"Zkyw9ACJZUvcYmlFaKGChzhmtnE/rcMTQpIOHgWYetp22aQ7_LoqIH4\"", "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" @@ -74,12 +74,12 @@ "type": "boolean" }, "quotaUser": { - "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.", + "description": "An opaque string that represents a user for quota purposes. Must not exceed 40 characters.", "location": "query", "type": "string" }, "userIp": { - "description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.", + "description": "Deprecated. Please use quotaUser instead.", "location": "query", "type": "string" } @@ -97,7 +97,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -138,7 +138,7 @@ ] }, "get": { - "description": "Returns the specified accelerator type. Get a list of available accelerator types by making a list() request.", + "description": "Returns the specified accelerator type.", "httpMethod": "GET", "id": "compute.acceleratorTypes.get", "parameterOrder": [ @@ -189,7 +189,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -249,7 +249,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -428,7 +428,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -488,7 +488,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -575,7 +575,7 @@ ] }, "get": { - "description": "Returns the specified autoscaler resource. Get a list of available autoscalers by making a list() request.", + "description": "Returns the specified autoscaler resource. Gets a list of available autoscalers by making a list() request.", "httpMethod": "GET", "id": "compute.autoscalers.get", "parameterOrder": [ @@ -667,7 +667,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -851,7 +851,7 @@ ] }, "get": { - "description": "Returns the specified BackendBucket resource. Get a list of available backend buckets by making a list() request.", + "description": "Returns the specified BackendBucket resource. Gets a list of available backend buckets by making a list() request.", "httpMethod": "GET", "id": "compute.backendBuckets.get", "parameterOrder": [ @@ -926,7 +926,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1061,7 +1061,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1140,7 +1140,7 @@ ] }, "get": { - "description": "Returns the specified BackendService resource. Get a list of available backend services by making a list() request.", + "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", "httpMethod": "GET", "id": "compute.backendServices.get", "parameterOrder": [ @@ -1251,7 +1251,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1386,7 +1386,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1427,7 +1427,7 @@ ] }, "get": { - "description": "Returns the specified disk type. Get a list of available disk types by making a list() request.", + "description": "Returns the specified disk type. Gets a list of available disk types by making a list() request.", "httpMethod": "GET", "id": "compute.diskTypes.get", "parameterOrder": [ @@ -1478,7 +1478,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1538,7 +1538,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -1677,7 +1677,7 @@ ] }, "get": { - "description": "Returns a specified persistent disk. Get a list of available persistent disks by making a list() request.", + "description": "Returns a specified persistent disk. Gets a list of available persistent disks by making a list() request.", "httpMethod": "GET", "id": "compute.disks.get", "parameterOrder": [ @@ -1774,7 +1774,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2037,7 +2037,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2172,7 +2172,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2351,7 +2351,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2490,7 +2490,7 @@ ] }, "get": { - "description": "Returns the specified address resource. Get a list of available addresses by making a list() request.", + "description": "Returns the specified address resource. Gets a list of available addresses by making a list() request.", "httpMethod": "GET", "id": "compute.globalAddresses.get", "parameterOrder": [ @@ -2565,7 +2565,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2648,7 +2648,7 @@ ] }, "get": { - "description": "Returns the specified GlobalForwardingRule resource. Get a list of available forwarding rules by making a list() request.", + "description": "Returns the specified GlobalForwardingRule resource. Gets a list of available forwarding rules by making a list() request.", "httpMethod": "GET", "id": "compute.globalForwardingRules.get", "parameterOrder": [ @@ -2723,7 +2723,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2817,7 +2817,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -2888,7 +2888,7 @@ ] }, "get": { - "description": "Retrieves the specified Operations resource. Get a list of operations by making a list() request.", + "description": "Retrieves the specified Operations resource. Gets a list of operations by making a list() request.", "httpMethod": "GET", "id": "compute.globalOperations.get", "parameterOrder": [ @@ -2930,7 +2930,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3013,7 +3013,7 @@ ] }, "get": { - "description": "Returns the specified HealthCheck resource. Get a list of available health checks by making a list() request.", + "description": "Returns the specified HealthCheck resource. Gets a list of available health checks by making a list() request.", "httpMethod": "GET", "id": "compute.healthChecks.get", "parameterOrder": [ @@ -3088,7 +3088,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3253,7 +3253,7 @@ ] }, "get": { - "description": "Returns the specified HttpHealthCheck resource. Get a list of available HTTP health checks by making a list() request.", + "description": "Returns the specified HttpHealthCheck resource. Gets a list of available HTTP health checks by making a list() request.", "httpMethod": "GET", "id": "compute.httpHealthChecks.get", "parameterOrder": [ @@ -3328,7 +3328,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3493,7 +3493,7 @@ ] }, "get": { - "description": "Returns the specified HttpsHealthCheck resource. Get a list of available HTTPS health checks by making a list() request.", + "description": "Returns the specified HttpsHealthCheck resource. Gets a list of available HTTPS health checks by making a list() request.", "httpMethod": "GET", "id": "compute.httpsHealthChecks.get", "parameterOrder": [ @@ -3568,7 +3568,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -3774,7 +3774,7 @@ ] }, "get": { - "description": "Returns the specified image. Get a list of available images by making a list() request.", + "description": "Returns the specified image. Gets a list of available images by making a list() request.", "httpMethod": "GET", "id": "compute.images.get", "parameterOrder": [ @@ -3891,7 +3891,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4027,7 +4027,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4159,7 +4159,7 @@ ] }, "get": { - "description": "Returns all of the details about the specified managed instance group. Get a list of available managed instance groups by making a list() request.", + "description": "Returns all of the details about the specified managed instance group. Gets a list of available managed instance groups by making a list() request.", "httpMethod": "GET", "id": "compute.instanceGroupManagers.get", "parameterOrder": [ @@ -4248,7 +4248,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4606,7 +4606,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4691,7 +4691,7 @@ ] }, "get": { - "description": "Returns the specified instance group. Get a list of available instance groups by making a list() request.", + "description": "Returns the specified instance group. Gets a list of available instance groups by making a list() request.", "httpMethod": "GET", "id": "compute.instanceGroups.get", "parameterOrder": [ @@ -4780,7 +4780,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -4837,7 +4837,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5029,7 +5029,7 @@ ] }, "get": { - "description": "Returns the specified instance template. Get a list of available instance templates by making a list() request.", + "description": "Returns the specified instance template. Gets a list of available instance templates by making a list() request.", "httpMethod": "GET", "id": "compute.instanceTemplates.get", "parameterOrder": [ @@ -5104,7 +5104,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5213,7 +5213,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5263,6 +5263,11 @@ "instance" ], "parameters": { + "forceAttach": { + "description": "Whether to force attach the disk even if it's currently attached to another instance. This is only available for regional disks.", + "location": "query", + "type": "boolean" + }, "instance": { "description": "The instance name for this request.", "location": "path", @@ -5462,7 +5467,7 @@ ] }, "get": { - "description": "Returns the specified Instance resource. Get a list of available instances by making a list() request.", + "description": "Returns the specified Instance resource. Gets a list of available instances by making a list() request.", "httpMethod": "GET", "id": "compute.instances.get", "parameterOrder": [ @@ -5581,6 +5586,11 @@ "location": "query", "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", + "location": "query", + "type": "string" + }, "zone": { "description": "The name of the zone for this request.", "location": "path", @@ -5611,7 +5621,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -5669,7 +5679,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -6275,7 +6285,7 @@ ] }, "start": { - "description": "Starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance.", + "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", "httpMethod": "POST", "id": "compute.instances.start", "parameterOrder": [ @@ -6321,7 +6331,7 @@ ] }, "startWithEncryptionKey": { - "description": "Starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance.", + "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", "httpMethod": "POST", "id": "compute.instances.startWithEncryptionKey", "parameterOrder": [ @@ -6540,7 +6550,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -6719,7 +6729,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -6765,13 +6775,62 @@ "https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/compute.readonly" ] + }, + "patch": { + "description": "Updates the specified interconnect attachment with the data included in the request. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + "httpMethod": "PATCH", + "id": "compute.interconnectAttachments.patch", + "parameterOrder": [ + "project", + "region", + "interconnectAttachment" + ], + "parameters": { + "interconnectAttachment": { + "description": "Name of the interconnect attachment to patch.", + "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": "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}/interconnectAttachments/{interconnectAttachment}", + "request": { + "$ref": "InterconnectAttachment" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] } } }, "interconnectLocations": { "methods": { "get": { - "description": "Returns the details for the specified interconnect location. Get a list of available interconnect locations by making a list() request.", + "description": "Returns the details for the specified interconnect location. Gets a list of available interconnect locations by making a list() request.", "httpMethod": "GET", "id": "compute.interconnectLocations.get", "parameterOrder": [ @@ -6813,7 +6872,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -6971,7 +7030,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -7054,8 +7113,121 @@ } } }, + "licenseCodes": { + "methods": { + "get": { + "description": "Return a specified license code. License codes are mirrored across all projects that have permissions to read the License Code.", + "httpMethod": "GET", + "id": "compute.licenseCodes.get", + "parameterOrder": [ + "project", + "licenseCode" + ], + "parameters": { + "licenseCode": { + "description": "Number corresponding to the License code resource to return.", + "location": "path", + "pattern": "[0-9]{0,61}?", + "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/licenseCodes/{licenseCode}", + "response": { + "$ref": "LicenseCode" + }, + "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.licenseCodes.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 of the resource for this request.", + "location": "path", + "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/licenseCodes/{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" + ] + } + } + }, "licenses": { "methods": { + "delete": { + "description": "Deletes the specified license.", + "httpMethod": "DELETE", + "id": "compute.licenses.delete", + "parameterOrder": [ + "project", + "license" + ], + "parameters": { + "license": { + "description": "Name of the license 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" + } + }, + "path": "{project}/global/licenses/{license}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "get": { "description": "Returns the specified License resource.", "httpMethod": "GET", @@ -7089,6 +7261,128 @@ "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", + "id": "compute.licenses.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/licenses", + "request": { + "$ref": "License" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/devstorage.full_control", + "https://www.googleapis.com/auth/devstorage.read_only", + "https://www.googleapis.com/auth/devstorage.read_write" + ] + }, + "list": { + "description": "Retrieves the list of licenses available in the specified project. This method does not get any licenses that belong to other projects, including licenses attached to publicly-available images, like Debian 9. If you want to get a list of publicly-available licenses, use this method to make a request to the respective image project, such as debian-cloud or windows-cloud.", + "httpMethod": "GET", + "id": "compute.licenses.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/licenses", + "response": { + "$ref": "LicensesListResponse" + }, + "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.licenses.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 of the resource for this request.", + "location": "path", + "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/licenses/{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" + ] } } }, @@ -7103,7 +7397,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -7144,7 +7438,7 @@ ] }, "get": { - "description": "Returns the specified machine type. Get a list of available machine types by making a list() request.", + "description": "Returns the specified machine type. Gets a list of available machine types by making a list() request.", "httpMethod": "GET", "id": "compute.machineTypes.get", "parameterOrder": [ @@ -7195,7 +7489,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -7326,7 +7620,7 @@ ] }, "get": { - "description": "Returns the specified network. Get a list of available networks by making a list() request.", + "description": "Returns the specified network. Gets a list of available networks by making a list() request.", "httpMethod": "GET", "id": "compute.networks.get", "parameterOrder": [ @@ -7401,7 +7695,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -7718,7 +8012,7 @@ ] }, "getXpnHost": { - "description": "Get the shared VPC host project that this project links to. May be empty if no link exists.", + "description": "Gets the shared VPC host project that this project links to. May be empty if no link exists.", "httpMethod": "GET", "id": "compute.projects.getXpnHost", "parameterOrder": [ @@ -7743,7 +8037,7 @@ ] }, "getXpnResources": { - "description": "Get service resources (a.k.a service project) associated with this host project.", + "description": "Gets service resources (a.k.a service project) associated with this host project.", "httpMethod": "GET", "id": "compute.projects.getXpnResources", "parameterOrder": [ @@ -7787,7 +8081,7 @@ ] }, "listXpnHosts": { - "description": "List all shared VPC host projects visible to the user in an organization.", + "description": "Lists all shared VPC host projects visible to the user in an organization.", "httpMethod": "POST", "id": "compute.projects.listXpnHosts", "parameterOrder": [ @@ -8111,7 +8405,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8439,7 +8733,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8597,7 +8891,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8638,7 +8932,7 @@ ] }, "get": { - "description": "Returns the specified commitment resource. Get a list of available commitments by making a list() request.", + "description": "Returns the specified commitment resource. Gets a list of available commitments by making a list() request.", "httpMethod": "GET", "id": "compute.regionCommitments.get", "parameterOrder": [ @@ -8730,7 +9024,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -8779,6 +9073,495 @@ } } }, + "regionDiskTypes": { + "methods": { + "get": { + "description": "Returns the specified regional disk type. Gets a list of available disk types by making a list() request.", + "httpMethod": "GET", + "id": "compute.regionDiskTypes.get", + "parameterOrder": [ + "project", + "region", + "diskType" + ], + "parameters": { + "diskType": { + "description": "Name of the disk 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" + }, + "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}/diskTypes/{diskType}", + "response": { + "$ref": "DiskType" + }, + "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 regional disk types available to the specified project.", + "httpMethod": "GET", + "id": "compute.regionDiskTypes.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}/diskTypes", + "response": { + "$ref": "RegionDiskTypeList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + } + } + }, + "regionDisks": { + "methods": { + "createSnapshot": { + "description": "Creates a snapshot of this regional disk.", + "httpMethod": "POST", + "id": "compute.regionDisks.createSnapshot", + "parameterOrder": [ + "project", + "region", + "disk" + ], + "parameters": { + "disk": { + "description": "Name of the regional persistent disk to snapshot.", + "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": "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}/createSnapshot", + "request": { + "$ref": "Snapshot" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "delete": { + "description": "Deletes the specified regional persistent disk. Deleting a regional disk removes all the replicas of its data permanently and is irreversible. However, deleting a disk does not delete any snapshots previously made from the disk. You must separately delete snapshots.", + "httpMethod": "DELETE", + "id": "compute.regionDisks.delete", + "parameterOrder": [ + "project", + "region", + "disk" + ], + "parameters": { + "disk": { + "description": "Name of the regional persistent disk to delete.", + "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 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}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Returns a specified regional persistent disk.", + "httpMethod": "GET", + "id": "compute.regionDisks.get", + "parameterOrder": [ + "project", + "region", + "disk" + ], + "parameters": { + "disk": { + "description": "Name of the regional persistent disk 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": "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}/disks/{disk}", + "response": { + "$ref": "Disk" + }, + "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 regional disk in the specified project using the data included in the request.", + "httpMethod": "POST", + "id": "compute.regionDisks.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" + }, + "sourceImage": { + "description": "Optional. Source image to restore onto a disk.", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/disks", + "request": { + "$ref": "Disk" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "Retrieves the list of persistent disks contained within the specified region.", + "httpMethod": "GET", + "id": "compute.regionDisks.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}/disks", + "response": { + "$ref": "DiskList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "resize": { + "description": "Resizes the specified regional persistent disk.", + "httpMethod": "POST", + "id": "compute.regionDisks.resize", + "parameterOrder": [ + "project", + "region", + "disk" + ], + "parameters": { + "disk": { + "description": "Name of the regional persistent disk.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "The project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{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}/disks/{disk}/resize", + "request": { + "$ref": "RegionDisksResizeRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "setLabels": { + "description": "Sets the labels on the target regional disk.", + "httpMethod": "POST", + "id": "compute.regionDisks.setLabels", + "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 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" + }, + "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" + } + }, + "path": "{project}/regions/{region}/disks/{resource}/setLabels", + "request": { + "$ref": "RegionSetLabelsRequest" + }, + "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.regionDisks.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 of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/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" + ] + } + } + }, "regionInstanceGroupManagers": { "methods": { "abandonInstances": { @@ -9009,7 +9792,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -9362,7 +10145,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -9419,7 +10202,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -9615,7 +10398,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -9667,7 +10450,7 @@ "regions": { "methods": { "get": { - "description": "Returns the specified Region resource. Get a list of available regions by making a list() request.", + "description": "Returns the specified Region resource. Gets a list of available regions by making a list() request.", "httpMethod": "GET", "id": "compute.regions.get", "parameterOrder": [ @@ -9709,7 +10492,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -9762,7 +10545,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -9849,7 +10632,7 @@ ] }, "get": { - "description": "Returns the specified Router resource. Get a list of available routers by making a list() request.", + "description": "Returns the specified Router resource. Gets a list of available routers by making a list() request.", "httpMethod": "GET", "id": "compute.routers.get", "parameterOrder": [ @@ -9983,7 +10766,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10216,7 +10999,7 @@ ] }, "get": { - "description": "Returns the specified Route resource. Get a list of available routes by making a list() request.", + "description": "Returns the specified Route resource. Gets a list of available routes by making a list() request.", "httpMethod": "GET", "id": "compute.routes.get", "parameterOrder": [ @@ -10291,7 +11074,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10374,7 +11157,7 @@ ] }, "get": { - "description": "Returns the specified Snapshot resource. Get a list of available snapshots by making a list() request.", + "description": "Returns the specified Snapshot resource. Gets a list of available snapshots by making a list() request.", "httpMethod": "GET", "id": "compute.snapshots.get", "parameterOrder": [ @@ -10416,7 +11199,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10535,7 +11318,7 @@ ] }, "get": { - "description": "Returns the specified SslCertificate resource. Get a list of available SSL certificates by making a list() request.", + "description": "Returns the specified SslCertificate resource. Gets a list of available SSL certificates by making a list() request.", "httpMethod": "GET", "id": "compute.sslCertificates.get", "parameterOrder": [ @@ -10610,7 +11393,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10652,6 +11435,251 @@ } } }, + "sslPolicies": { + "methods": { + "delete": { + "description": "Deletes the specified SSL policy. The SSL policy resource can be deleted only if it is not in use by any TargetHttpsProxy or TargetSslProxy resources.", + "httpMethod": "DELETE", + "id": "compute.sslPolicies.delete", + "parameterOrder": [ + "project", + "sslPolicy" + ], + "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" + }, + "sslPolicy": { + "description": "Name of the SSL policy to delete. The name must be 1-63 characters long, and comply with RFC1035.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/sslPolicies/{sslPolicy}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Lists all of the ordered rules present in a single specified policy.", + "httpMethod": "GET", + "id": "compute.sslPolicies.get", + "parameterOrder": [ + "project", + "sslPolicy" + ], + "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" + }, + "sslPolicy": { + "description": "Name of the SSL policy to update. The name must be 1-63 characters long, and comply with RFC1035.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/sslPolicies/{sslPolicy}", + "response": { + "$ref": "SslPolicy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "insert": { + "description": "Returns the specified SSL policy resource. Gets a list of available SSL policies by making a list() request.", + "httpMethod": "POST", + "id": "compute.sslPolicies.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/sslPolicies", + "request": { + "$ref": "SslPolicy" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "Lists all the SSL policies that have been configured for the specified project.", + "httpMethod": "GET", + "id": "compute.sslPolicies.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/sslPolicies", + "response": { + "$ref": "SslPoliciesList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "listAvailableFeatures": { + "description": "Lists all features that can be specified in the SSL policy when using custom profile.", + "httpMethod": "GET", + "id": "compute.sslPolicies.listAvailableFeatures", + "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/sslPolicies/listAvailableFeatures", + "response": { + "$ref": "SslPoliciesListAvailableFeaturesResponse" + }, + "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 SSL policy with the data included in the request.", + "httpMethod": "PATCH", + "id": "compute.sslPolicies.patch", + "parameterOrder": [ + "project", + "sslPolicy" + ], + "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" + }, + "sslPolicy": { + "description": "Name of the SSL policy to update. The name must be 1-63 characters long, and comply with RFC1035.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/sslPolicies/{sslPolicy}", + "request": { + "$ref": "SslPolicy" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + } + } + }, "subnetworks": { "methods": { "aggregatedList": { @@ -10663,7 +11691,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10799,7 +11827,7 @@ ] }, "get": { - "description": "Returns the specified subnetwork. Get a list of available subnetworks list() request.", + "description": "Returns the specified subnetwork. Gets a list of available subnetworks list() request.", "httpMethod": "GET", "id": "compute.subnetworks.get", "parameterOrder": [ @@ -10891,7 +11919,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -10939,7 +11967,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 and allow_subnet_cidr_routes_overlap. 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 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.", "httpMethod": "PATCH", "id": "compute.subnetworks.patch", "parameterOrder": [ @@ -11079,7 +12107,7 @@ ] }, "get": { - "description": "Returns the specified TargetHttpProxy resource. Get a list of available target HTTP proxies by making a list() request.", + "description": "Returns the specified TargetHttpProxy resource. Gets a list of available target HTTP proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetHttpProxies.get", "parameterOrder": [ @@ -11154,7 +12182,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11278,7 +12306,7 @@ ] }, "get": { - "description": "Returns the specified TargetHttpsProxy resource. Get a list of available target HTTPS proxies by making a list() request.", + "description": "Returns the specified TargetHttpsProxy resource. Gets a list of available target HTTPS proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetHttpsProxies.get", "parameterOrder": [ @@ -11353,7 +12381,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11393,6 +12421,46 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "setQuicOverride": { + "description": "Sets the QUIC override policy for TargetHttpsProxy.", + "httpMethod": "POST", + "id": "compute.targetHttpsProxies.setQuicOverride", + "parameterOrder": [ + "project", + "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" + }, + "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 the QUIC override policy for. The name should conform to RFC1035.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setQuicOverride", + "request": { + "$ref": "TargetHttpsProxiesSetQuicOverrideRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setSslCertificates": { "description": "Replaces SslCertificates for TargetHttpsProxy.", "httpMethod": "POST", @@ -11434,6 +12502,46 @@ "https://www.googleapis.com/auth/compute" ] }, + "setSslPolicy": { + "description": "Sets the SSL policy for TargetHttpsProxy. The SSL policy specifies the server-side support for SSL features. This affects connections between clients and the HTTPS proxy load balancer. They do not affect the connection between the load balancer and the backends.", + "httpMethod": "POST", + "id": "compute.targetHttpsProxies.setSslPolicy", + "parameterOrder": [ + "project", + "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" + }, + "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 whose SSL policy is to be set. The name must be 1-63 characters long, and comply with RFC1035.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setSslPolicy", + "request": { + "$ref": "SslPolicyReference" + }, + "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", @@ -11488,7 +12596,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11575,7 +12683,7 @@ ] }, "get": { - "description": "Returns the specified TargetInstance resource. Get a list of available target instances by making a list() request.", + "description": "Returns the specified TargetInstance resource. Gets a list of available target instances by making a list() request.", "httpMethod": "GET", "id": "compute.targetInstances.get", "parameterOrder": [ @@ -11667,7 +12775,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11825,7 +12933,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -11912,7 +13020,7 @@ ] }, "get": { - "description": "Returns the specified target pool. Get a list of available target pools by making a list() request.", + "description": "Returns the specified target pool. Gets a list of available target pools by making a list() request.", "httpMethod": "GET", "id": "compute.targetPools.get", "parameterOrder": [ @@ -12049,7 +13157,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -12292,7 +13400,7 @@ ] }, "get": { - "description": "Returns the specified TargetSslProxy resource. Get a list of available target SSL proxies by making a list() request.", + "description": "Returns the specified TargetSslProxy resource. Gets a list of available target SSL proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetSslProxies.get", "parameterOrder": [ @@ -12367,7 +13475,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -12529,6 +13637,46 @@ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/compute" ] + }, + "setSslPolicy": { + "description": "Sets the SSL policy for TargetSslProxy. The SSL policy specifies the server-side support for SSL features. This affects connections between clients and the SSL proxy load balancer. They do not affect the connection between the load balancer and the backends.", + "httpMethod": "POST", + "id": "compute.targetSslProxies.setSslPolicy", + "parameterOrder": [ + "project", + "targetSslProxy" + ], + "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" + }, + "targetSslProxy": { + "description": "Name of the TargetSslProxy resource whose SSL policy is to be set. The name must be 1-63 characters long, and comply with RFC1035.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/targetSslProxies/{targetSslProxy}/setSslPolicy", + "request": { + "$ref": "SslPolicyReference" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] } } }, @@ -12573,7 +13721,7 @@ ] }, "get": { - "description": "Returns the specified TargetTcpProxy resource. Get a list of available target TCP proxies by making a list() request.", + "description": "Returns the specified TargetTcpProxy resource. Gets a list of available target TCP proxies by making a list() request.", "httpMethod": "GET", "id": "compute.targetTcpProxies.get", "parameterOrder": [ @@ -12648,7 +13796,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -12783,7 +13931,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -12870,7 +14018,7 @@ ] }, "get": { - "description": "Returns the specified target VPN gateway. Get a list of available target VPN gateways by making a list() request.", + "description": "Returns the specified target VPN gateway. Gets a list of available target VPN gateways by making a list() request.", "httpMethod": "GET", "id": "compute.targetVpnGateways.get", "parameterOrder": [ @@ -12962,7 +14110,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13052,7 +14200,7 @@ ] }, "get": { - "description": "Returns the specified UrlMap resource. Get a list of available URL maps by making a list() request.", + "description": "Returns the specified UrlMap resource. Gets a list of available URL maps by making a list() request.", "httpMethod": "GET", "id": "compute.urlMaps.get", "parameterOrder": [ @@ -13168,7 +14316,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13339,7 +14487,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13426,7 +14574,7 @@ ] }, "get": { - "description": "Returns the specified VpnTunnel resource. Get a list of available VPN tunnels by making a list() request.", + "description": "Returns the specified VpnTunnel resource. Gets a list of available VPN tunnels by making a list() request.", "httpMethod": "GET", "id": "compute.vpnTunnels.get", "parameterOrder": [ @@ -13518,7 +14666,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13659,7 +14807,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13711,7 +14859,7 @@ "zones": { "methods": { "get": { - "description": "Returns the specified Zone resource. Get a list of available zones by making a list() request.", + "description": "Returns the specified Zone resource. Gets a list of available zones by making a list() request.", "httpMethod": "GET", "id": "compute.zones.get", "parameterOrder": [ @@ -13753,7 +14901,7 @@ ], "parameters": { "filter": { - "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + "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" }, @@ -13796,7 +14944,7 @@ } } }, - "revision": "20180220", + "revision": "20180518", "rootUrl": "https://www.googleapis.com/", "schemas": { "AcceleratorConfig": { @@ -14090,7 +15238,7 @@ "id": "AcceleratorTypesScopedList", "properties": { "acceleratorTypes": { - "description": "[Output Only] List of accelerator types contained in this scope.", + "description": "[Output Only] A list of accelerator types contained in this scope.", "items": { "$ref": "AcceleratorType" }, @@ -14545,7 +15693,7 @@ "id": "AddressesScopedList", "properties": { "addresses": { - "description": "[Output Only] List of addresses contained in this scope.", + "description": "[Output Only] A list of addresses contained in this scope.", "items": { "$ref": "Address" }, @@ -15130,7 +16278,7 @@ "id": "AutoscalersScopedList", "properties": { "autoscalers": { - "description": "[Output Only] List of autoscalers contained in this scope.", + "description": "[Output Only] A list of autoscalers contained in this scope.", "items": { "$ref": "Autoscaler" }, @@ -15941,7 +17089,7 @@ "id": "BackendServicesScopedList", "properties": { "backendServices": { - "description": "List of BackendServices contained in this scope.", + "description": "A list of BackendServices contained in this scope.", "items": { "$ref": "BackendService" }, @@ -16127,7 +17275,7 @@ "type": "string" }, "resources": { - "description": "List of commitment amounts for particular resources. Note that VCPU and MEMORY resource commitments must occur together.", + "description": "A list of commitment amounts for particular resources. Note that VCPU and MEMORY resource commitments must occur together.", "items": { "$ref": "ResourceCommitment" }, @@ -16392,7 +17540,7 @@ "id": "CommitmentsScopedList", "properties": { "commitments": { - "description": "[Output Only] List of commitments contained in this scope.", + "description": "[Output Only] A list of commitments contained in this scope.", "items": { "$ref": "Commitment" }, @@ -16613,6 +17761,14 @@ "description": "[Output Only] Last detach timestamp in RFC3339 text format.", "type": "string" }, + "licenseCodes": { + "description": "Integer license codes indicating which licenses are attached to this disk.", + "items": { + "format": "int64", + "type": "string" + }, + "type": "array" + }, "licenses": { "description": "Any applicable publicly visible licenses.", "items": { @@ -16634,6 +17790,17 @@ "description": "Internal use only.", "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" + }, + "replicaZones": { + "description": "URLs of the zones where the disk should be replicated to. Only applicable for regional resources.", + "items": { + "type": "string" + }, + "type": "array" + }, "selfLink": { "description": "[Output Only] Server-defined fully-qualified URL for this resource.", "type": "string" @@ -16975,6 +18142,10 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, + "region": { + "description": "[Output Only] URL of the region where the disk type 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" + }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" @@ -17218,7 +18389,7 @@ "id": "DiskTypesScopedList", "properties": { "diskTypes": { - "description": "[Output Only] List of disk types contained in this scope.", + "description": "[Output Only] A list of disk types contained in this scope.", "items": { "$ref": "DiskType" }, @@ -17323,7 +18494,7 @@ "id": "DisksScopedList", "properties": { "disks": { - "description": "[Output Only] List of disks contained in this scope.", + "description": "[Output Only] A list of disks contained in this scope.", "items": { "$ref": "Disk" }, @@ -18013,7 +19184,7 @@ "id": "ForwardingRulesScopedList", "properties": { "forwardingRules": { - "description": "List of forwarding rules contained in this scope.", + "description": "A list of forwarding rules contained in this scope.", "items": { "$ref": "ForwardingRule" }, @@ -18898,6 +20069,14 @@ "description": "Labels to apply to this image. These can be later modified by the setLabels method.", "type": "object" }, + "licenseCodes": { + "description": "Integer license codes indicating which licenses are attached to this image.", + "items": { + "format": "int64", + "type": "string" + }, + "type": "array" + }, "licenses": { "description": "Any applicable license URI.", "items": { @@ -19157,7 +20336,7 @@ "type": "array" }, "guestAccelerators": { - "description": "List of the type and count of accelerator cards attached to the instance.", + "description": "A list of the type and count of accelerator cards attached to the instance.", "items": { "$ref": "AcceleratorConfig" }, @@ -19174,7 +20353,7 @@ "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 instance.", + "description": "A fingerprint for this request, which is essentially a hash of the label's contents and 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 instance.", "format": "byte", "type": "string" }, @@ -19438,7 +20617,7 @@ "type": "string" }, "region": { - "description": "The URL of the region where the instance group is located (for regional resources).", + "description": "[Output Only] The URL of the region where the instance group is located (for regional resources).", "type": "string" }, "selfLink": { @@ -19451,7 +20630,7 @@ "type": "integer" }, "subnetwork": { - "description": "The URL of the subnetwork to which all instances in the instance group belong.", + "description": "[Output Only] The URL of the subnetwork to which all instances in the instance group belong.", "type": "string" }, "zone": { @@ -19712,7 +20891,7 @@ "type": "string" }, "fingerprint": { - "description": "[Output Only] The fingerprint of the resource data. You can use this optional field for optimistic locking when you update the resource.", + "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.", "format": "byte", "type": "string" }, @@ -21019,7 +22198,7 @@ "id": "InstancesScopedList", "properties": { "instances": { - "description": "[Output Only] List of instances contained in this scope.", + "description": "[Output Only] A list of instances contained in this scope.", "items": { "$ref": "Instance" }, @@ -21130,7 +22309,7 @@ "id": "InstancesSetMachineResourcesRequest", "properties": { "guestAccelerators": { - "description": "List of the type and count of accelerator cards attached to the instance.", + "description": "A list of the type and count of accelerator cards attached to the instance.", "items": { "$ref": "AcceleratorConfig" }, @@ -21198,7 +22377,7 @@ "type": "boolean" }, "circuitInfos": { - "description": "[Output Only] List of CircuitInfo objects, that describe the individual circuits in this LAG.", + "description": "[Output Only] A list of CircuitInfo objects, that describe the individual circuits in this LAG.", "items": { "$ref": "InterconnectCircuitInfo" }, @@ -21217,7 +22396,7 @@ "type": "string" }, "expectedOutages": { - "description": "[Output Only] List of outages expected for this Interconnect.", + "description": "[Output Only] A list of outages expected for this Interconnect.", "items": { "$ref": "InterconnectOutageNotification" }, @@ -21247,9 +22426,11 @@ "description": "Type of interconnect. Note that \"IT_PRIVATE\" has been deprecated in favor of \"DEDICATED\"", "enum": [ "DEDICATED", - "IT_PRIVATE" + "IT_PRIVATE", + "PARTNER" ], "enumDescriptions": [ + "", "", "" ], @@ -21317,6 +22498,18 @@ "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" + }, + "state": { + "description": "[Output Only] The current state of whether or not this Interconnect is functional.", + "enum": [ + "ACTIVE", + "UNPROVISIONED" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" } }, "type": "object" @@ -21325,6 +22518,45 @@ "description": "Represents an InterconnectAttachment (VLAN attachment) resource. For more information, see Creating VLAN Attachments. (== resource_for beta.interconnectAttachments ==) (== resource_for v1.interconnectAttachments ==)", "id": "InterconnectAttachment", "properties": { + "adminEnabled": { + "description": "Determines whether this Attachment will carry packets. Not present for PARTNER_PROVIDER.", + "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.", + "enum": [ + "BPS_100M", + "BPS_10G", + "BPS_1G", + "BPS_200M", + "BPS_2G", + "BPS_300M", + "BPS_400M", + "BPS_500M", + "BPS_50M", + "BPS_5G" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "candidateSubnets": { + "description": "Up to 16 candidate prefixes that can be used to restrict the allocation of cloudRouterIpAddress and customerRouterIpAddress for this attachment. All prefixes must be within link-local address space (169.254.0.0/16) and must be /29 or shorter (/28, /27, etc). Google will attempt to select an unused /29 from the supplied candidate prefix(es). The request will fail if all possible /29s are in use on Google?s edge. If not supplied, Google will randomly select an unused /29 from all of link-local space.", + "items": { + "type": "string" + }, + "type": "array" + }, "cloudRouterIpAddress": { "description": "[Output Only] IPv4 address + prefix length to be configured on Cloud Router Interface for this interconnect attachment.", "type": "string" @@ -21341,6 +22573,20 @@ "description": "An optional description of this resource.", "type": "string" }, + "edgeAvailabilityDomain": { + "description": "Desired availability domain for the attachment. Only available for type PARTNER, at creation time. For improved reliability, customers should configure a pair of attachments with one per availability domain. The selected availability domain will be provided to the Partner via the pairing key so that the provisioned circuit will lie in the specified domain. If not specified, the value will default to AVAILABILITY_DOMAIN_ANY.", + "enum": [ + "AVAILABILITY_DOMAIN_1", + "AVAILABILITY_DOMAIN_2", + "AVAILABILITY_DOMAIN_ANY" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, "googleReferenceId": { "description": "[Output Only] Google reference ID, to be used when raising support tickets with Google or otherwise to debug backend connectivity issues.", "type": "string" @@ -21376,6 +22622,19 @@ ], "type": "string" }, + "pairingKey": { + "description": "[Output only for type PARTNER. Input only for PARTNER_PROVIDER. Not present for DEDICATED]. The opaque identifier of an PARTNER attachment used to initiate provisioning with a selected partner. Of the form \"XXXXX/region/domain\"", + "type": "string" + }, + "partnerAsn": { + "description": "Optional BGP ASN for the router that should be supplied by a layer 3 Partner if they configured BGP on behalf of the customer. Output only for PARTNER type, input only for PARTNER_PROVIDER, not available for DEDICATED.", + "format": "int64", + "type": "string" + }, + "partnerMetadata": { + "$ref": "InterconnectAttachmentPartnerMetadata", + "description": "Informational metadata about Partner attachments from Partners to display to customers. Output only for for PARTNER type, mutable for PARTNER_PROVIDER, not available for DEDICATED." + }, "privateInterconnectInfo": { "$ref": "InterconnectAttachmentPrivateInfo", "description": "[Output Only] Information specific to an InterconnectAttachment. This property is populated if the interconnect that this is attached to is of type DEDICATED." @@ -21391,6 +22650,46 @@ "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" + }, + "state": { + "description": "[Output Only] The current state of this attachment's functionality.", + "enum": [ + "ACTIVE", + "DEFUNCT", + "PARTNER_REQUEST_RECEIVED", + "PENDING_CUSTOMER", + "PENDING_PARTNER", + "STATE_UNSPECIFIED", + "UNPROVISIONED" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "type": { + "enum": [ + "DEDICATED", + "PARTNER", + "PARTNER_PROVIDER" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "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.", + "format": "int32", + "type": "integer" } }, "type": "object" @@ -21619,6 +22918,25 @@ }, "type": "object" }, + "InterconnectAttachmentPartnerMetadata": { + "description": "Informational metadata about Partner attachments from Partners to display to customers. These fields are propagated from PARTNER_PROVIDER attachments to their corresponding PARTNER attachments.", + "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.", + "type": "string" + }, + "partnerName": { + "description": "Plain text name of the Partner providing this attachment. This value may be validated to match approved Partner values.", + "type": "string" + }, + "portalUrl": { + "description": "URL of the Partner?s portal for this Attachment. Partners may customise this to be a deep-link to the specific resource on the Partner portal. This value may be validated to match approved Partner values.", + "type": "string" + } + }, + "type": "object" + }, "InterconnectAttachmentPrivateInfo": { "description": "Information for an interconnect attachment when this belongs to an interconnect of type DEDICATED.", "id": "InterconnectAttachmentPrivateInfo", @@ -21635,7 +22953,7 @@ "id": "InterconnectAttachmentsScopedList", "properties": { "interconnectAttachments": { - "description": "List of interconnect attachments contained in this scope.", + "description": "A list of interconnect attachments contained in this scope.", "items": { "$ref": "InterconnectAttachment" }, @@ -22097,7 +23415,7 @@ "id": "InterconnectOutageNotification", "properties": { "affectedCircuits": { - "description": "Iff issue_type is IT_PARTIAL_OUTAGE, a list of the Google-side circuit IDs that will be affected.", + "description": "If issue_type is IT_PARTIAL_OUTAGE, a list of the Google-side circuit IDs that will be affected.", "items": { "type": "string" }, @@ -22176,11 +23494,29 @@ "description": "[Output Only] Deprecated. This field no longer reflects whether a license charges a usage fee.", "type": "boolean" }, + "creationTimestamp": { + "description": "[Output Only] Creation timestamp in RFC3339 text format.", + "type": "string" + }, + "description": { + "description": "An optional textual description of the resource; provided by the client when the resource is created.", + "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#license", "description": "[Output Only] Type of resource. Always compute#license for licenses.", "type": "string" }, + "licenseCode": { + "description": "[Output Only] The unique code used to attach this license to images, snapshots, and disks.", + "format": "uint64", + "type": "string" + }, "name": { "annotations": { "required": [ @@ -22191,9 +23527,219 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, + "resourceRequirements": { + "$ref": "LicenseResourceRequirements" + }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" + }, + "transferable": { + "description": "If false, licenses will not be copied from the source resource when creating an image from a disk, disk from snapshot, or snapshot from disk.", + "type": "boolean" + } + }, + "type": "object" + }, + "LicenseCode": { + "id": "LicenseCode", + "properties": { + "creationTimestamp": { + "description": "[Output Only] Creation timestamp in RFC3339 text format.", + "type": "string" + }, + "description": { + "description": "[Output Only] Description of this License Code.", + "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#licenseCode", + "description": "[Output Only] Type of resource. Always compute#licenseCode for licenses.", + "type": "string" + }, + "licenseAlias": { + "description": "[Output Only] URL and description aliases of Licenses with the same License Code.", + "items": { + "$ref": "LicenseCodeLicenseAlias" + }, + "type": "array" + }, + "name": { + "annotations": { + "required": [ + "compute.licenses.insert" + ] + }, + "description": "[Output Only] Name of the resource. The name is 1-20 characters long and must be a valid 64 bit integer.", + "pattern": "[0-9]{0,20}?", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for the resource.", + "type": "string" + }, + "state": { + "description": "[Output Only] Current state of this License Code.", + "enum": [ + "DISABLED", + "ENABLED", + "RESTRICTED", + "STATE_UNSPECIFIED", + "TERMINATED" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "transferable": { + "description": "[Output Only] If true, the license will remain attached when creating images or snapshots from disks. Otherwise, the license is not transferred.", + "type": "boolean" + } + }, + "type": "object" + }, + "LicenseCodeLicenseAlias": { + "id": "LicenseCodeLicenseAlias", + "properties": { + "description": { + "description": "[Output Only] Description of this License Code.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] URL of license corresponding to this License Code.", + "type": "string" + } + }, + "type": "object" + }, + "LicenseResourceRequirements": { + "id": "LicenseResourceRequirements", + "properties": { + "minGuestCpuCount": { + "description": "Minimum number of guest cpus required to use the Instance. Enforced at Instance creation and Instance start.", + "format": "int32", + "type": "integer" + }, + "minMemoryMb": { + "description": "Minimum memory required to use the Instance. Enforced at Instance creation and Instance start.", + "format": "int32", + "type": "integer" + } + }, + "type": "object" + }, + "LicensesListResponse": { + "id": "LicensesListResponse", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of License resources.", + "items": { + "$ref": "License" + }, + "type": "array" + }, + "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" @@ -22259,7 +23805,7 @@ "type": "string" }, "scratchDisks": { - "description": "[Output Only] List of extended scratch disks assigned to the instance.", + "description": "[Output Only] A list of extended scratch disks assigned to the instance.", "items": { "properties": { "diskGb": { @@ -22511,7 +24057,7 @@ "id": "MachineTypesScopedList", "properties": { "machineTypes": { - "description": "[Output Only] List of machine types contained in this scope.", + "description": "[Output Only] A list of machine types contained in this scope.", "items": { "$ref": "MachineType" }, @@ -22812,7 +24358,7 @@ "type": "string" }, "peerings": { - "description": "[Output Only] List of network peerings for the resource.", + "description": "[Output Only] A list of network peerings for the resource.", "items": { "$ref": "NetworkPeering" }, @@ -23087,7 +24633,7 @@ "id": "Operation", "properties": { "clientOperationId": { - "description": "[Output Only] Reserved for future use.", + "description": "[Output Only] The value of `requestId` if you provided it in the request. Not present otherwise.", "type": "string" }, "creationTimestamp": { @@ -23527,7 +25073,7 @@ "id": "OperationsScopedList", "properties": { "operations": { - "description": "[Output Only] List of operations contained in this scope.", + "description": "[Output Only] A list of operations contained in this scope.", "items": { "$ref": "Operation" }, @@ -23812,16 +25358,20 @@ "INSTANCE_GROUP_MANAGERS", "INSTANCE_TEMPLATES", "INTERCONNECTS", + "INTERCONNECT_ATTACHMENTS_PER_REGION", + "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS", "INTERNAL_ADDRESSES", "IN_USE_ADDRESSES", "LOCAL_SSD_TOTAL_GB", "NETWORKS", "NVIDIA_K80_GPUS", "NVIDIA_P100_GPUS", + "NVIDIA_V100_GPUS", "PREEMPTIBLE_CPUS", "PREEMPTIBLE_LOCAL_SSD_GB", "PREEMPTIBLE_NVIDIA_K80_GPUS", "PREEMPTIBLE_NVIDIA_P100_GPUS", + "PREEMPTIBLE_NVIDIA_V100_GPUS", "REGIONAL_AUTOSCALERS", "REGIONAL_INSTANCE_GROUP_MANAGERS", "ROUTERS", @@ -23889,6 +25439,10 @@ "", "", "", + "", + "", + "", + "", "" ], "type": "string" @@ -24100,6 +25654,128 @@ }, "type": "object" }, + "RegionDiskTypeList": { + "id": "RegionDiskTypeList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of DiskType resources.", + "items": { + "$ref": "DiskType" + }, + "type": "array" + }, + "kind": { + "default": "compute#regionDiskTypeList", + "description": "[Output Only] Type of resource. Always compute#regionDiskTypeList for region disk 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" + }, + "RegionDisksResizeRequest": { + "id": "RegionDisksResizeRequest", + "properties": { + "sizeGb": { + "description": "The new size of the regional persistent disk, which is specified in GB.", + "format": "int64", + "type": "string" + } + }, + "type": "object" + }, "RegionInstanceGroupList": { "description": "Contains a list of InstanceGroup resources.", "id": "RegionInstanceGroupList", @@ -24354,7 +26030,7 @@ "id": "RegionInstanceGroupManagersListInstancesResponse", "properties": { "managedInstances": { - "description": "List of managed instances.", + "description": "A list of managed instances.", "items": { "$ref": "ManagedInstance" }, @@ -24668,6 +26344,24 @@ }, "type": "object" }, + "RegionSetLabelsRequest": { + "id": "RegionSetLabelsRequest", + "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 in order to update or change labels. Make a get() request to the resource to get the latest fingerprint.", + "format": "byte", + "type": "string" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "The labels to set for this resource.", + "type": "object" + } + }, + "type": "object" + }, "ResourceCommitment": { "description": "Commitment for a particular resource (a Commitment is composed of one or more of these).", "id": "ResourceCommitment", @@ -25292,6 +26986,18 @@ "description": "IP address of the interface inside Google Cloud Platform. Only IPv4 is supported.", "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.", + "enum": [ + "MANAGED_BY_ATTACHMENT", + "MANAGED_BY_USER" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, "name": { "description": "Name of this BGP peer. The name must be 1-63 characters long and comply with RFC1035.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", @@ -25324,6 +27030,18 @@ "description": "URI of the linked VPN tunnel. It must be in the same region as the router. Each interface can have at most one linked resource and it could either be a VPN Tunnel or an interconnect attachment.", "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.", + "enum": [ + "MANAGED_BY_ATTACHMENT", + "MANAGED_BY_USER" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, "name": { "description": "Name of this interface entry. The name must be 1-63 characters long and comply with RFC1035.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", @@ -25562,7 +27280,7 @@ "id": "RoutersScopedList", "properties": { "routers": { - "description": "List of routers contained in this scope.", + "description": "A list of routers contained in this scope.", "items": { "$ref": "Router" }, @@ -25801,6 +27519,14 @@ "description": "Labels to apply to this snapshot. These can be later modified by the setLabels method. Label values may be empty.", "type": "object" }, + "licenseCodes": { + "description": "[Output Only] Integer license codes indicating which licenses are attached to this snapshot.", + "items": { + "format": "int64", + "type": "string" + }, + "type": "array" + }, "licenses": { "description": "[Output Only] A list of public visible licenses that apply to this snapshot. This can be because the original image had licenses attached (such as a Windows image).", "items": { @@ -26137,6 +27863,306 @@ }, "type": "object" }, + "SslPoliciesList": { + "id": "SslPoliciesList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of SslPolicy resources.", + "items": { + "$ref": "SslPolicy" + }, + "type": "array" + }, + "kind": { + "default": "compute#sslPoliciesList", + "description": "[Output Only] Type of the resource. Always compute#sslPoliciesList for lists of sslPolicies.", + "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" + }, + "SslPoliciesListAvailableFeaturesResponse": { + "id": "SslPoliciesListAvailableFeaturesResponse", + "properties": { + "features": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "SslPolicy": { + "description": "A SSL policy specifies the server-side support for SSL features. This can be attached to a TargetHttpsProxy or a TargetSslProxy. This affects connections between clients and the HTTPS or SSL proxy load balancer. They do not affect the connection between the load balancers and the backends.", + "id": "SslPolicy", + "properties": { + "creationTimestamp": { + "description": "[Output Only] Creation timestamp in RFC3339 text format.", + "type": "string" + }, + "customFeatures": { + "description": "A list of features enabled when the selected profile is CUSTOM. The\n- method returns the set of features that can be specified in this list. This field must be empty if the profile is not CUSTOM.", + "items": { + "type": "string" + }, + "type": "array" + }, + "description": { + "description": "An optional description of this resource. Provide this property when you create the resource.", + "type": "string" + }, + "enabledFeatures": { + "description": "[Output Only] The list of features enabled in the SSL policy.", + "items": { + "type": "string" + }, + "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.", + "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#sslPolicy", + "description": "[Output only] Type of the resource. Always compute#sslPolicyfor SSL policies.", + "type": "string" + }, + "minTlsVersion": { + "description": "The minimum version of SSL protocol that can be used by the clients to establish a connection with the load balancer. This can be one of TLS_1_0, TLS_1_1, TLS_1_2.", + "enum": [ + "TLS_1_0", + "TLS_1_1", + "TLS_1_2" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, + "name": { + "description": "Name of 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])?", + "type": "string" + }, + "profile": { + "description": "Profile specifies the set of SSL features that can be used by the load balancer when negotiating SSL with clients. This can be one of COMPATIBLE, MODERN, RESTRICTED, or CUSTOM. If using CUSTOM, the set of SSL features to enable must be specified in the customFeatures field.", + "enum": [ + "COMPATIBLE", + "CUSTOM", + "MODERN", + "RESTRICTED" + ], + "enumDescriptions": [ + "", + "", + "", + "" + ], + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for the resource.", + "type": "string" + }, + "warnings": { + "description": "[Output Only] If potential misconfigurations are detected for this SSL policy, this field will be populated with warning messages.", + "items": { + "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": "array" + } + }, + "type": "object" + }, + "SslPolicyReference": { + "id": "SslPolicyReference", + "properties": { + "sslPolicy": { + "description": "URL of the SSL policy resource. Set this to empty string to clear any existing SSL policy associated with the target proxy resource.", + "type": "string" + } + }, + "type": "object" + }, "Subnetwork": { "description": "A Subnetwork resource. (== resource_for beta.subnetworks ==) (== resource_for v1.subnetworks ==)", "id": "Subnetwork", @@ -26149,6 +28175,10 @@ "description": "An optional description of this resource. Provide this property when you create the resource. This field can be set only at resource creation time.", "type": "string" }, + "enableFlowLogs": { + "description": "Whether to enable flow logging for this subnetwork.", + "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.", "format": "byte", @@ -26456,7 +28486,7 @@ "id": "SubnetworksScopedList", "properties": { "subnetworks": { - "description": "List of subnetworks contained in this scope.", + "description": "A list of subnetworks contained in this scope.", "items": { "$ref": "Subnetwork" }, @@ -26595,7 +28625,7 @@ "id": "Tags", "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.\n\nTo see the latest fingerprint, make get() request to the instance.", + "description": "Specifies a fingerprint for this request, which is essentially a hash of the tags' contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update tags. You must always provide an up-to-date fingerprint hash in order to update or change tags.\n\nTo see the latest fingerprint, make get() request to the instance.", "format": "byte", "type": "string" }, @@ -26759,6 +28789,26 @@ }, "type": "object" }, + "TargetHttpsProxiesSetQuicOverrideRequest": { + "id": "TargetHttpsProxiesSetQuicOverrideRequest", + "properties": { + "quicOverride": { + "description": "QUIC policy for the TargetHttpsProxy resource.", + "enum": [ + "DISABLE", + "ENABLE", + "NONE" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, "TargetHttpsProxiesSetSslCertificatesRequest": { "id": "TargetHttpsProxiesSetSslCertificatesRequest", "properties": { @@ -26799,6 +28849,20 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, + "quicOverride": { + "description": "Specifies the QUIC override policy for this TargetHttpsProxy resource. This determines whether the load balancer will attempt to negotiate QUIC with clients or not. Can specify one of NONE, ENABLE, or DISABLE. Specify ENABLE to always enable QUIC, Enables QUIC when set to ENABLE, and disables QUIC when set to DISABLE. If NONE is specified, uses the QUIC policy with no user overrides, which is equivalent to DISABLE. Not specifying this field is equivalent to specifying NONE.", + "enum": [ + "DISABLE", + "ENABLE", + "NONE" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" @@ -26810,6 +28874,10 @@ }, "type": "array" }, + "sslPolicy": { + "description": "URL of SslPolicy resource that will be associated with the TargetHttpsProxy resource. If not set, the TargetHttpsProxy resource will not have any SSL policy configured.", + "type": "string" + }, "urlMap": { "description": "A fully-qualified or valid partial URL to the UrlMap resource that defines the mapping from URL to the BackendService. For example, the following are all valid URLs for specifying a URL map: \n- https://www.googleapis.compute/v1/projects/project/global/urlMaps/url-map \n- projects/project/global/urlMaps/url-map \n- global/urlMaps/url-map", "type": "string" @@ -27209,7 +29277,7 @@ "id": "TargetInstancesScopedList", "properties": { "targetInstances": { - "description": "List of target instances contained in this scope.", + "description": "A list of target instances contained in this scope.", "items": { "$ref": "TargetInstance" }, @@ -27675,7 +29743,7 @@ "id": "TargetPoolsScopedList", "properties": { "targetPools": { - "description": "List of target pools contained in this scope.", + "description": "A list of target pools contained in this scope.", "items": { "$ref": "TargetPool" }, @@ -27868,6 +29936,10 @@ "type": "string" }, "type": "array" + }, + "sslPolicy": { + "description": "URL of SslPolicy resource that will be associated with the TargetSslProxy resource. If not set, the TargetSslProxy resource will not have any SSL policy configured.", + "type": "string" } }, "type": "object" @@ -28484,7 +30556,7 @@ "id": "TargetVpnGatewaysScopedList", "properties": { "targetVpnGateways": { - "description": "[Output Only] List of target vpn gateways contained in this scope.", + "description": "[Output Only] A list of target vpn gateways contained in this scope.", "items": { "$ref": "TargetVpnGateway" }, @@ -28592,6 +30664,32 @@ }, "type": "object" }, + "TestPermissionsRequest": { + "id": "TestPermissionsRequest", + "properties": { + "permissions": { + "description": "The set of permissions to check for the 'resource'. Permissions with wildcards (such as '*' or 'storage.*') are not allowed.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "TestPermissionsResponse": { + "id": "TestPermissionsResponse", + "properties": { + "permissions": { + "description": "A subset of `TestPermissionsRequest.permissions` that the caller is allowed.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "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", @@ -29207,7 +31305,7 @@ "id": "VpnTunnelsScopedList", "properties": { "vpnTunnels": { - "description": "List of vpn tunnels contained in this scope.", + "description": "A list of vpn tunnels contained in this scope.", "items": { "$ref": "VpnTunnel" }, 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 ec6bd538549..2a4ab9d74d6 100644 --- a/vendor/google.golang.org/api/compute/v1/compute-gen.go +++ b/vendor/google.golang.org/api/compute/v1/compute-gen.go @@ -94,6 +94,7 @@ func New(client *http.Client) (*Service, error) { s.InterconnectAttachments = NewInterconnectAttachmentsService(s) s.InterconnectLocations = NewInterconnectLocationsService(s) s.Interconnects = NewInterconnectsService(s) + s.LicenseCodes = NewLicenseCodesService(s) s.Licenses = NewLicensesService(s) s.MachineTypes = NewMachineTypesService(s) s.Networks = NewNetworksService(s) @@ -101,6 +102,8 @@ func New(client *http.Client) (*Service, error) { s.RegionAutoscalers = NewRegionAutoscalersService(s) s.RegionBackendServices = NewRegionBackendServicesService(s) s.RegionCommitments = NewRegionCommitmentsService(s) + s.RegionDiskTypes = NewRegionDiskTypesService(s) + s.RegionDisks = NewRegionDisksService(s) s.RegionInstanceGroupManagers = NewRegionInstanceGroupManagersService(s) s.RegionInstanceGroups = NewRegionInstanceGroupsService(s) s.RegionOperations = NewRegionOperationsService(s) @@ -109,6 +112,7 @@ func New(client *http.Client) (*Service, error) { s.Routes = NewRoutesService(s) s.Snapshots = NewSnapshotsService(s) s.SslCertificates = NewSslCertificatesService(s) + s.SslPolicies = NewSslPoliciesService(s) s.Subnetworks = NewSubnetworksService(s) s.TargetHttpProxies = NewTargetHttpProxiesService(s) s.TargetHttpsProxies = NewTargetHttpsProxiesService(s) @@ -175,6 +179,8 @@ type Service struct { Interconnects *InterconnectsService + LicenseCodes *LicenseCodesService + Licenses *LicensesService MachineTypes *MachineTypesService @@ -189,6 +195,10 @@ type Service struct { RegionCommitments *RegionCommitmentsService + RegionDiskTypes *RegionDiskTypesService + + RegionDisks *RegionDisksService + RegionInstanceGroupManagers *RegionInstanceGroupManagersService RegionInstanceGroups *RegionInstanceGroupsService @@ -205,6 +215,8 @@ type Service struct { SslCertificates *SslCertificatesService + SslPolicies *SslPoliciesService + Subnetworks *SubnetworksService TargetHttpProxies *TargetHttpProxiesService @@ -444,6 +456,15 @@ type InterconnectsService struct { s *Service } +func NewLicenseCodesService(s *Service) *LicenseCodesService { + rs := &LicenseCodesService{s: s} + return rs +} + +type LicenseCodesService struct { + s *Service +} + func NewLicensesService(s *Service) *LicensesService { rs := &LicensesService{s: s} return rs @@ -507,6 +528,24 @@ type RegionCommitmentsService struct { s *Service } +func NewRegionDiskTypesService(s *Service) *RegionDiskTypesService { + rs := &RegionDiskTypesService{s: s} + return rs +} + +type RegionDiskTypesService struct { + s *Service +} + +func NewRegionDisksService(s *Service) *RegionDisksService { + rs := &RegionDisksService{s: s} + return rs +} + +type RegionDisksService struct { + s *Service +} + func NewRegionInstanceGroupManagersService(s *Service) *RegionInstanceGroupManagersService { rs := &RegionInstanceGroupManagersService{s: s} return rs @@ -579,6 +618,15 @@ type SslCertificatesService struct { s *Service } +func NewSslPoliciesService(s *Service) *SslPoliciesService { + rs := &SslPoliciesService{s: s} + return rs +} + +type SslPoliciesService struct { + s *Service +} + func NewSubnetworksService(s *Service) *SubnetworksService { rs := &SubnetworksService{s: s} return rs @@ -1104,7 +1152,7 @@ func (s *AcceleratorTypeListWarningData) MarshalJSON() ([]byte, error) { } type AcceleratorTypesScopedList struct { - // AcceleratorTypes: [Output Only] List of accelerator types contained + // AcceleratorTypes: [Output Only] A list of accelerator types contained // in this scope. AcceleratorTypes []*AcceleratorType `json:"acceleratorTypes,omitempty"` @@ -1715,7 +1763,7 @@ func (s *AddressListWarningData) MarshalJSON() ([]byte, error) { } type AddressesScopedList struct { - // Addresses: [Output Only] List of addresses contained in this scope. + // Addresses: [Output Only] A list of addresses contained in this scope. Addresses []*Address `json:"addresses,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -2584,7 +2632,7 @@ func (s *AutoscalerStatusDetails) MarshalJSON() ([]byte, error) { } type AutoscalersScopedList struct { - // Autoscalers: [Output Only] List of autoscalers contained in this + // Autoscalers: [Output Only] A list of autoscalers contained in this // scope. Autoscalers []*Autoscaler `json:"autoscalers,omitempty"` @@ -3878,7 +3926,7 @@ func (s *BackendServiceListWarningData) MarshalJSON() ([]byte, error) { } type BackendServicesScopedList struct { - // BackendServices: List of BackendServices contained in this scope. + // BackendServices: A list of BackendServices contained in this scope. BackendServices []*BackendService `json:"backendServices,omitempty"` // Warning: Informational warning which replaces the list of backend @@ -4149,8 +4197,8 @@ type Commitment struct { // used. Region string `json:"region,omitempty"` - // Resources: List of commitment amounts for particular resources. Note - // that VCPU and MEMORY resource commitments must occur together. + // Resources: A list of commitment amounts for particular resources. + // Note that VCPU and MEMORY resource commitments must occur together. Resources []*ResourceCommitment `json:"resources,omitempty"` // SelfLink: [Output Only] Server-defined URL for the resource. @@ -4514,7 +4562,7 @@ func (s *CommitmentListWarningData) MarshalJSON() ([]byte, error) { } type CommitmentsScopedList struct { - // Commitments: [Output Only] List of commitments contained in this + // Commitments: [Output Only] A list of commitments contained in this // scope. Commitments []*Commitment `json:"commitments,omitempty"` @@ -4869,6 +4917,10 @@ type Disk struct { // text format. LastDetachTimestamp string `json:"lastDetachTimestamp,omitempty"` + // LicenseCodes: Integer license codes indicating which licenses are + // attached to this disk. + LicenseCodes googleapi.Int64s `json:"licenseCodes,omitempty"` + // Licenses: Any applicable publicly visible licenses. Licenses []string `json:"licenses,omitempty"` @@ -4884,6 +4936,16 @@ type Disk struct { // Options: Internal use only. Options string `json:"options,omitempty"` + // 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 + // request body. + Region string `json:"region,omitempty"` + + // ReplicaZones: URLs of the zones where the disk should be replicated + // to. Only applicable for regional resources. + ReplicaZones []string `json:"replicaZones,omitempty"` + // SelfLink: [Output Only] Server-defined fully-qualified URL for this // resource. SelfLink string `json:"selfLink,omitempty"` @@ -5397,6 +5459,12 @@ type DiskType struct { // Name: [Output Only] Name of the resource. Name string `json:"name,omitempty"` + // Region: [Output Only] URL of the region where the disk type 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. + Region string `json:"region,omitempty"` + // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` @@ -5748,7 +5816,8 @@ func (s *DiskTypeListWarningData) MarshalJSON() ([]byte, error) { } type DiskTypesScopedList struct { - // DiskTypes: [Output Only] List of disk types contained in this scope. + // DiskTypes: [Output Only] A list of disk types contained in this + // scope. DiskTypes []*DiskType `json:"diskTypes,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -5909,7 +5978,7 @@ func (s *DisksResizeRequest) MarshalJSON() ([]byte, error) { } type DisksScopedList struct { - // Disks: [Output Only] List of disks contained in this scope. + // Disks: [Output Only] A list of disks contained in this scope. Disks []*Disk `json:"disks,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -6944,7 +7013,7 @@ func (s *ForwardingRuleListWarningData) MarshalJSON() ([]byte, error) { } type ForwardingRulesScopedList struct { - // ForwardingRules: List of forwarding rules contained in this scope. + // ForwardingRules: A list of forwarding rules contained in this scope. ForwardingRules []*ForwardingRule `json:"forwardingRules,omitempty"` // Warning: Informational warning which replaces the list of forwarding @@ -8184,6 +8253,10 @@ type Image struct { // the setLabels method. Labels map[string]string `json:"labels,omitempty"` + // LicenseCodes: Integer license codes indicating which licenses are + // attached to this image. + LicenseCodes googleapi.Int64s `json:"licenseCodes,omitempty"` + // Licenses: Any applicable license URI. Licenses []string `json:"licenses,omitempty"` @@ -8531,7 +8604,7 @@ type Instance struct { // must be created before you can assign them. Disks []*AttachedDisk `json:"disks,omitempty"` - // GuestAccelerators: List of the type and count of accelerator cards + // GuestAccelerators: A list of the type and count of accelerator cards // attached to the instance. GuestAccelerators []*AcceleratorConfig `json:"guestAccelerators,omitempty"` @@ -8544,11 +8617,11 @@ type Instance struct { 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 + // essentially a hash of the label'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 + // 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 metadata. + // change labels. // // To see the latest fingerprint, make get() request to the instance. LabelFingerprint string `json:"labelFingerprint,omitempty"` @@ -8885,8 +8958,8 @@ type InstanceGroup struct { // instance group belong. Network string `json:"network,omitempty"` - // Region: The URL of the region where the instance group is located - // (for regional resources). + // Region: [Output Only] The URL of the region where the instance group + // is located (for regional resources). Region string `json:"region,omitempty"` // SelfLink: [Output Only] The URL for this instance group. The server @@ -8897,8 +8970,8 @@ type InstanceGroup struct { // group. Size int64 `json:"size,omitempty"` - // Subnetwork: The URL of the subnetwork to which all instances in the - // instance group belong. + // Subnetwork: [Output Only] The URL of the subnetwork to which all + // instances in the instance group belong. Subnetwork string `json:"subnetwork,omitempty"` // Zone: [Output Only] The URL of the zone where the instance group is @@ -9270,9 +9343,10 @@ type InstanceGroupManager struct { // property when you create the resource. Description string `json:"description,omitempty"` - // Fingerprint: [Output Only] The fingerprint of the resource data. You - // can use this optional field for optimistic locking when you update - // the resource. + // 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. Fingerprint string `json:"fingerprint,omitempty"` // Id: [Output Only] A unique identifier for this resource type. The @@ -11210,7 +11284,7 @@ func (s *InstanceWithNamedPorts) MarshalJSON() ([]byte, error) { } type InstancesScopedList struct { - // Instances: [Output Only] List of instances contained in this scope. + // Instances: [Output Only] A list of instances contained in this scope. Instances []*Instance `json:"instances,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -11375,7 +11449,7 @@ func (s *InstancesSetLabelsRequest) MarshalJSON() ([]byte, error) { } type InstancesSetMachineResourcesRequest struct { - // GuestAccelerators: List of the type and count of accelerator cards + // GuestAccelerators: A list of the type and count of accelerator cards // attached to the instance. GuestAccelerators []*AcceleratorConfig `json:"guestAccelerators,omitempty"` @@ -11539,7 +11613,7 @@ type Interconnect struct { // set to true. AdminEnabled bool `json:"adminEnabled,omitempty"` - // CircuitInfos: [Output Only] List of CircuitInfo objects, that + // CircuitInfos: [Output Only] A list of CircuitInfo objects, that // describe the individual circuits in this LAG. CircuitInfos []*InterconnectCircuitInfo `json:"circuitInfos,omitempty"` @@ -11555,7 +11629,7 @@ type Interconnect struct { // property when you create the resource. Description string `json:"description,omitempty"` - // ExpectedOutages: [Output Only] List of outages expected for this + // ExpectedOutages: [Output Only] A list of outages expected for this // Interconnect. ExpectedOutages []*InterconnectOutageNotification `json:"expectedOutages,omitempty"` @@ -11582,6 +11656,7 @@ type Interconnect struct { // Possible values: // "DEDICATED" // "IT_PRIVATE" + // "PARTNER" InterconnectType string `json:"interconnectType,omitempty"` // Kind: [Output Only] Type of the resource. Always compute#interconnect @@ -11641,6 +11716,14 @@ type Interconnect struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // State: [Output Only] The current state of whether or not this + // Interconnect is functional. + // + // Possible values: + // "ACTIVE" + // "UNPROVISIONED" + State string `json:"state,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -11673,6 +11756,38 @@ func (s *Interconnect) MarshalJSON() ([]byte, error) { // Attachments. (== resource_for beta.interconnectAttachments ==) (== // resource_for v1.interconnectAttachments ==) type InterconnectAttachment struct { + // AdminEnabled: Determines whether this Attachment will carry packets. + // Not present for PARTNER_PROVIDER. + AdminEnabled bool `json:"adminEnabled,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. + // + // Possible values: + // "BPS_100M" + // "BPS_10G" + // "BPS_1G" + // "BPS_200M" + // "BPS_2G" + // "BPS_300M" + // "BPS_400M" + // "BPS_500M" + // "BPS_50M" + // "BPS_5G" + Bandwidth string `json:"bandwidth,omitempty"` + + // CandidateSubnets: Up to 16 candidate prefixes that can be used to + // restrict the allocation of cloudRouterIpAddress and + // customerRouterIpAddress for this attachment. All prefixes must be + // within link-local address space (169.254.0.0/16) and must be /29 or + // shorter (/28, /27, etc). Google will attempt to select an unused /29 + // from the supplied candidate prefix(es). The request will fail if all + // possible /29s are in use on Google?s edge. If not supplied, Google + // will randomly select an unused /29 from all of link-local space. + CandidateSubnets []string `json:"candidateSubnets,omitempty"` + // CloudRouterIpAddress: [Output Only] IPv4 address + prefix length to // be configured on Cloud Router Interface for this interconnect // attachment. @@ -11690,6 +11805,20 @@ type InterconnectAttachment struct { // Description: An optional description of this resource. Description string `json:"description,omitempty"` + // EdgeAvailabilityDomain: Desired availability domain for the + // attachment. Only available for type PARTNER, at creation time. For + // improved reliability, customers should configure a pair of + // attachments with one per availability domain. The selected + // availability domain will be provided to the Partner via the pairing + // key so that the provisioned circuit will lie in the specified domain. + // If not specified, the value will default to AVAILABILITY_DOMAIN_ANY. + // + // Possible values: + // "AVAILABILITY_DOMAIN_1" + // "AVAILABILITY_DOMAIN_2" + // "AVAILABILITY_DOMAIN_ANY" + EdgeAvailabilityDomain string `json:"edgeAvailabilityDomain,omitempty"` + // GoogleReferenceId: [Output Only] Google reference ID, to be used when // raising support tickets with Google or otherwise to debug backend // connectivity issues. @@ -11724,6 +11853,23 @@ type InterconnectAttachment struct { // "OS_UNPROVISIONED" OperationalStatus string `json:"operationalStatus,omitempty"` + // PairingKey: [Output only for type PARTNER. Input only for + // PARTNER_PROVIDER. Not present for DEDICATED]. The opaque identifier + // of an PARTNER attachment used to initiate provisioning with a + // selected partner. Of the form "XXXXX/region/domain" + PairingKey string `json:"pairingKey,omitempty"` + + // PartnerAsn: Optional BGP ASN for the router that should be supplied + // by a layer 3 Partner if they configured BGP on behalf of the + // customer. Output only for PARTNER type, input only for + // PARTNER_PROVIDER, not available for DEDICATED. + PartnerAsn int64 `json:"partnerAsn,omitempty,string"` + + // PartnerMetadata: Informational metadata about Partner attachments + // from Partners to display to customers. Output only for for PARTNER + // type, mutable for PARTNER_PROVIDER, not available for DEDICATED. + PartnerMetadata *InterconnectAttachmentPartnerMetadata `json:"partnerMetadata,omitempty"` + // PrivateInterconnectInfo: [Output Only] Information specific to an // InterconnectAttachment. This property is populated if the // interconnect that this is attached to is of type DEDICATED. @@ -11744,26 +11890,49 @@ type InterconnectAttachment struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // State: [Output Only] The current state of this attachment's + // functionality. + // + // Possible values: + // "ACTIVE" + // "DEFUNCT" + // "PARTNER_REQUEST_RECEIVED" + // "PENDING_CUSTOMER" + // "PENDING_PARTNER" + // "STATE_UNSPECIFIED" + // "UNPROVISIONED" + State string `json:"state,omitempty"` + + // Possible values: + // "DEDICATED" + // "PARTNER" + // "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 int64 `json:"vlanTag8021q,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. - // "CloudRouterIpAddress") to unconditionally include in API requests. - // By default, fields with empty values are omitted from API requests. - // However, any non-pointer, non-interface field appearing in - // ForceSendFields will be sent 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. "AdminEnabled") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CloudRouterIpAddress") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an 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. "AdminEnabled") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` } @@ -12087,6 +12256,52 @@ func (s *InterconnectAttachmentListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// InterconnectAttachmentPartnerMetadata: Informational metadata about +// Partner attachments from Partners to display to customers. These +// fields are propagated from PARTNER_PROVIDER attachments to their +// corresponding PARTNER attachments. +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 + // values. + InterconnectName string `json:"interconnectName,omitempty"` + + // PartnerName: Plain text name of the Partner providing this + // attachment. This value may be validated to match approved Partner + // values. + PartnerName string `json:"partnerName,omitempty"` + + // PortalUrl: URL of the Partner?s portal for this Attachment. Partners + // may customise this to be a deep-link to the specific resource on the + // Partner portal. This value may be validated to match approved Partner + // values. + PortalUrl string `json:"portalUrl,omitempty"` + + // ForceSendFields is a list of field names (e.g. "InterconnectName") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "InterconnectName") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectAttachmentPartnerMetadata) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectAttachmentPartnerMetadata + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // InterconnectAttachmentPrivateInfo: Information for an interconnect // attachment when this belongs to an interconnect of type DEDICATED. type InterconnectAttachmentPrivateInfo struct { @@ -12119,7 +12334,7 @@ func (s *InterconnectAttachmentPrivateInfo) MarshalJSON() ([]byte, error) { } type InterconnectAttachmentsScopedList struct { - // InterconnectAttachments: List of interconnect attachments contained + // InterconnectAttachments: A list of interconnect attachments contained // in this scope. InterconnectAttachments []*InterconnectAttachment `json:"interconnectAttachments,omitempty"` @@ -12752,7 +12967,7 @@ func (s *InterconnectLocationRegionInfo) MarshalJSON() ([]byte, error) { // InterconnectOutageNotification: Description of a planned outage on // this Interconnect. Next id: 9 type InterconnectOutageNotification struct { - // AffectedCircuits: Iff issue_type is IT_PARTIAL_OUTAGE, a list of the + // AffectedCircuits: If issue_type is IT_PARTIAL_OUTAGE, a list of the // Google-side circuit IDs that will be affected. AffectedCircuits []string `json:"affectedCircuits,omitempty"` @@ -12829,17 +13044,40 @@ type License struct { // reflects whether a license charges a usage fee. ChargesUseFee bool `json:"chargesUseFee,omitempty"` + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text + // format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + + // Description: An optional textual description of the resource; + // provided by the client when the resource is created. + 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 resource. Always compute#license for // licenses. Kind string `json:"kind,omitempty"` + // LicenseCode: [Output Only] The unique code used to attach this + // 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 string `json:"name,omitempty"` + ResourceRequirements *LicenseResourceRequirements `json:"resourceRequirements,omitempty"` + // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // Transferable: If false, licenses will not be copied from the source + // resource when creating an image from a disk, disk from snapshot, or + // snapshot from disk. + Transferable bool `json:"transferable,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -12867,6 +13105,291 @@ func (s *License) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type LicenseCode struct { + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text + // format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + + // Description: [Output Only] Description of this License Code. + 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 resource. Always compute#licenseCode for + // licenses. + Kind string `json:"kind,omitempty"` + + // LicenseAlias: [Output Only] URL and description aliases of Licenses + // with the same License Code. + LicenseAlias []*LicenseCodeLicenseAlias `json:"licenseAlias,omitempty"` + + // Name: [Output Only] Name of the resource. The name is 1-20 characters + // long and must be a valid 64 bit integer. + Name string `json:"name,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for the resource. + SelfLink string `json:"selfLink,omitempty"` + + // State: [Output Only] Current state of this License Code. + // + // Possible values: + // "DISABLED" + // "ENABLED" + // "RESTRICTED" + // "STATE_UNSPECIFIED" + // "TERMINATED" + State string `json:"state,omitempty"` + + // Transferable: [Output Only] If true, the license will remain attached + // when creating images or snapshots from disks. Otherwise, the license + // is not transferred. + Transferable bool `json:"transferable,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 *LicenseCode) MarshalJSON() ([]byte, error) { + type NoMethod LicenseCode + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type LicenseCodeLicenseAlias struct { + // Description: [Output Only] Description of this License Code. + Description string `json:"description,omitempty"` + + // SelfLink: [Output Only] URL of license corresponding to this License + // Code. + SelfLink string `json:"selfLink,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 *LicenseCodeLicenseAlias) MarshalJSON() ([]byte, error) { + type NoMethod LicenseCodeLicenseAlias + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type LicenseResourceRequirements struct { + // MinGuestCpuCount: Minimum number of guest cpus required to use the + // Instance. Enforced at Instance creation and Instance start. + MinGuestCpuCount int64 `json:"minGuestCpuCount,omitempty"` + + // MinMemoryMb: Minimum memory required to use the Instance. Enforced at + // Instance creation and Instance start. + MinMemoryMb int64 `json:"minMemoryMb,omitempty"` + + // ForceSendFields is a list of field names (e.g. "MinGuestCpuCount") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "MinGuestCpuCount") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *LicenseResourceRequirements) MarshalJSON() ([]byte, error) { + type NoMethod LicenseResourceRequirements + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type LicensesListResponse struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of License resources. + Items []*License `json:"items,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 *LicensesListResponseWarning `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 *LicensesListResponse) MarshalJSON() ([]byte, error) { + type NoMethod LicensesListResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// LicensesListResponseWarning: [Output Only] Informational warning +// message. +type LicensesListResponseWarning 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 []*LicensesListResponseWarningData `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 *LicensesListResponseWarning) MarshalJSON() ([]byte, error) { + type NoMethod LicensesListResponseWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type LicensesListResponseWarningData 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 *LicensesListResponseWarningData) MarshalJSON() ([]byte, error) { + type NoMethod LicensesListResponseWarningData + 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 { @@ -12917,7 +13440,7 @@ type MachineType struct { // Name: [Output Only] Name of the resource. Name string `json:"name,omitempty"` - // ScratchDisks: [Output Only] List of extended scratch disks assigned + // ScratchDisks: [Output Only] A list of extended scratch disks assigned // to the instance. ScratchDisks []*MachineTypeScratchDisks `json:"scratchDisks,omitempty"` @@ -13295,7 +13818,7 @@ func (s *MachineTypeListWarningData) MarshalJSON() ([]byte, error) { } type MachineTypesScopedList struct { - // MachineTypes: [Output Only] List of machine types contained in this + // MachineTypes: [Output Only] A list of machine types contained in this // scope. MachineTypes []*MachineType `json:"machineTypes,omitempty"` @@ -13767,7 +14290,7 @@ type Network struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` - // Peerings: [Output Only] List of network peerings for the resource. + // Peerings: [Output Only] A list of network peerings for the resource. Peerings []*NetworkPeering `json:"peerings,omitempty"` // RoutingConfig: The network-level routing configuration for this @@ -14222,7 +14745,8 @@ func (s *NetworksRemovePeeringRequest) MarshalJSON() ([]byte, error) { // (== resource_for beta.regionOperations ==) (== resource_for // v1.zoneOperations ==) (== resource_for beta.zoneOperations ==) type Operation struct { - // ClientOperationId: [Output Only] Reserved for future use. + // ClientOperationId: [Output Only] The value of `requestId` if you + // provided it in the request. Not present otherwise. ClientOperationId string `json:"clientOperationId,omitempty"` // CreationTimestamp: [Deprecated] This field is deprecated. @@ -14827,7 +15351,8 @@ func (s *OperationListWarningData) MarshalJSON() ([]byte, error) { } type OperationsScopedList struct { - // Operations: [Output Only] List of operations contained in this scope. + // Operations: [Output Only] A list of operations contained in this + // scope. Operations []*Operation `json:"operations,omitempty"` // Warning: [Output Only] Informational warning which replaces the list @@ -15279,16 +15804,20 @@ type Quota struct { // "INSTANCE_GROUP_MANAGERS" // "INSTANCE_TEMPLATES" // "INTERCONNECTS" + // "INTERCONNECT_ATTACHMENTS_PER_REGION" + // "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS" // "INTERNAL_ADDRESSES" // "IN_USE_ADDRESSES" // "LOCAL_SSD_TOTAL_GB" // "NETWORKS" // "NVIDIA_K80_GPUS" // "NVIDIA_P100_GPUS" + // "NVIDIA_V100_GPUS" // "PREEMPTIBLE_CPUS" // "PREEMPTIBLE_LOCAL_SSD_GB" // "PREEMPTIBLE_NVIDIA_K80_GPUS" // "PREEMPTIBLE_NVIDIA_P100_GPUS" + // "PREEMPTIBLE_NVIDIA_V100_GPUS" // "REGIONAL_AUTOSCALERS" // "REGIONAL_INSTANCE_GROUP_MANAGERS" // "ROUTERS" @@ -15618,6 +16147,189 @@ func (s *RegionAutoscalerListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type RegionDiskTypeList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of DiskType resources. + Items []*DiskType `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource. Always + // compute#regionDiskTypeList for region disk 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 *RegionDiskTypeListWarning `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 *RegionDiskTypeList) MarshalJSON() ([]byte, error) { + type NoMethod RegionDiskTypeList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// RegionDiskTypeListWarning: [Output Only] Informational warning +// message. +type RegionDiskTypeListWarning 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 []*RegionDiskTypeListWarningData `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 *RegionDiskTypeListWarning) MarshalJSON() ([]byte, error) { + type NoMethod RegionDiskTypeListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type RegionDiskTypeListWarningData 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 *RegionDiskTypeListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod RegionDiskTypeListWarningData + 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. + SizeGb int64 `json:"sizeGb,omitempty,string"` + + // ForceSendFields is a list of field names (e.g. "SizeGb") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "SizeGb") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *RegionDisksResizeRequest) MarshalJSON() ([]byte, error) { + type NoMethod RegionDisksResizeRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // RegionInstanceGroupList: Contains a list of InstanceGroup resources. type RegionInstanceGroupList struct { // Id: [Output Only] Unique identifier for the resource; defined by the @@ -15990,7 +16702,7 @@ func (s *RegionInstanceGroupManagersDeleteInstancesRequest) MarshalJSON() ([]byt } type RegionInstanceGroupManagersListInstancesResponse struct { - // ManagedInstances: List of managed instances. + // ManagedInstances: A list of managed instances. ManagedInstances []*ManagedInstance `json:"managedInstances,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -16495,6 +17207,42 @@ func (s *RegionListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type RegionSetLabelsRequest struct { + // LabelFingerprint: 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 in order to update or change labels. Make a get() request to the + // resource to get the latest fingerprint. + LabelFingerprint string `json:"labelFingerprint,omitempty"` + + // Labels: The labels to set for this resource. + Labels map[string]string `json:"labels,omitempty"` + + // ForceSendFields is a list of field names (e.g. "LabelFingerprint") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "LabelFingerprint") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *RegionSetLabelsRequest) MarshalJSON() ([]byte, error) { + type NoMethod RegionSetLabelsRequest + 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 { @@ -17308,6 +18056,18 @@ 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. + // + // Possible values: + // "MANAGED_BY_ATTACHMENT" + // "MANAGED_BY_USER" + ManagementType string `json:"managementType,omitempty"` + // Name: Name of this BGP peer. The name must be 1-63 characters long // and comply with RFC1035. Name string `json:"name,omitempty"` @@ -17363,6 +18123,18 @@ 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. + // + // Possible values: + // "MANAGED_BY_ATTACHMENT" + // "MANAGED_BY_USER" + ManagementType string `json:"managementType,omitempty"` + // Name: Name of this interface entry. The name must be 1-63 characters // long and comply with RFC1035. Name string `json:"name,omitempty"` @@ -17706,7 +18478,7 @@ func (s *RoutersPreviewResponse) MarshalJSON() ([]byte, error) { } type RoutersScopedList struct { - // Routers: List of routers contained in this scope. + // Routers: A list of routers contained in this scope. Routers []*Router `json:"routers,omitempty"` // Warning: Informational warning which replaces the list of routers @@ -18062,6 +18834,10 @@ type Snapshot struct { // by the setLabels method. Label values may be empty. Labels map[string]string `json:"labels,omitempty"` + // LicenseCodes: [Output Only] Integer license codes indicating which + // licenses are attached to this snapshot. + LicenseCodes googleapi.Int64s `json:"licenseCodes,omitempty"` + // Licenses: [Output Only] A list of public visible licenses that apply // to this snapshot. This can be because the original image had licenses // attached (such as a Windows image). @@ -18543,6 +19319,425 @@ func (s *SslCertificateListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type SslPoliciesList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of SslPolicy resources. + Items []*SslPolicy `json:"items,omitempty"` + + // Kind: [Output Only] Type of the resource. Always + // compute#sslPoliciesList for lists of sslPolicies. + 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 *SslPoliciesListWarning `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 *SslPoliciesList) MarshalJSON() ([]byte, error) { + type NoMethod SslPoliciesList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// SslPoliciesListWarning: [Output Only] Informational warning message. +type SslPoliciesListWarning 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 []*SslPoliciesListWarningData `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 *SslPoliciesListWarning) MarshalJSON() ([]byte, error) { + type NoMethod SslPoliciesListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SslPoliciesListWarningData 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 *SslPoliciesListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod SslPoliciesListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SslPoliciesListAvailableFeaturesResponse struct { + Features []string `json:"features,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Features") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Features") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SslPoliciesListAvailableFeaturesResponse) MarshalJSON() ([]byte, error) { + type NoMethod SslPoliciesListAvailableFeaturesResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// SslPolicy: A SSL policy specifies the server-side support for SSL +// features. This can be attached to a TargetHttpsProxy or a +// TargetSslProxy. This affects connections between clients and the +// HTTPS or SSL proxy load balancer. They do not affect the connection +// between the load balancers and the backends. +type SslPolicy struct { + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text + // format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + + // CustomFeatures: A list of features enabled when the selected profile + // is CUSTOM. The + // - method returns the set of features that can be specified in this + // list. This field must be empty if the profile is not CUSTOM. + CustomFeatures []string `json:"customFeatures,omitempty"` + + // Description: An optional description of this resource. Provide this + // property when you create the resource. + Description string `json:"description,omitempty"` + + // EnabledFeatures: [Output Only] The list of features enabled in the + // SSL policy. + EnabledFeatures []string `json:"enabledFeatures,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 SslPolicy. An up-to-date + // fingerprint must be provided in order to update the SslPolicy. + 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#sslPolicyfor + // SSL policies. + Kind string `json:"kind,omitempty"` + + // MinTlsVersion: The minimum version of SSL protocol that can be used + // by the clients to establish a connection with the load balancer. This + // can be one of TLS_1_0, TLS_1_1, TLS_1_2. + // + // Possible values: + // "TLS_1_0" + // "TLS_1_1" + // "TLS_1_2" + MinTlsVersion string `json:"minTlsVersion,omitempty"` + + // Name: Name of 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. + Name string `json:"name,omitempty"` + + // Profile: Profile specifies the set of SSL features that can be used + // by the load balancer when negotiating SSL with clients. This can be + // one of COMPATIBLE, MODERN, RESTRICTED, or CUSTOM. If using CUSTOM, + // the set of SSL features to enable must be specified in the + // customFeatures field. + // + // Possible values: + // "COMPATIBLE" + // "CUSTOM" + // "MODERN" + // "RESTRICTED" + Profile string `json:"profile,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for the resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warnings: [Output Only] If potential misconfigurations are detected + // for this SSL policy, this field will be populated with warning + // messages. + Warnings []*SslPolicyWarnings `json:"warnings,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 *SslPolicy) MarshalJSON() ([]byte, error) { + type NoMethod SslPolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SslPolicyWarnings 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 []*SslPolicyWarningsData `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 *SslPolicyWarnings) MarshalJSON() ([]byte, error) { + type NoMethod SslPolicyWarnings + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SslPolicyWarningsData 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 *SslPolicyWarningsData) MarshalJSON() ([]byte, error) { + type NoMethod SslPolicyWarningsData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SslPolicyReference struct { + // SslPolicy: URL of the SSL policy resource. Set this to empty string + // to clear any existing SSL policy associated with the target proxy + // resource. + SslPolicy string `json:"sslPolicy,omitempty"` + + // ForceSendFields is a list of field names (e.g. "SslPolicy") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "SslPolicy") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SslPolicyReference) MarshalJSON() ([]byte, error) { + type NoMethod SslPolicyReference + 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 { @@ -18555,6 +19750,9 @@ type Subnetwork struct { // resource creation time. Description string `json:"description,omitempty"` + // EnableFlowLogs: Whether to enable flow logging for this subnetwork. + 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 @@ -19023,7 +20221,7 @@ func (s *SubnetworksExpandIpCidrRangeRequest) MarshalJSON() ([]byte, error) { } type SubnetworksScopedList struct { - // Subnetworks: List of subnetworks contained in this scope. + // Subnetworks: A list of subnetworks contained in this scope. Subnetworks []*Subnetwork `json:"subnetworks,omitempty"` // Warning: An informational warning that appears when the list of @@ -19238,11 +20436,11 @@ func (s *TCPHealthCheck) MarshalJSON() ([]byte, error) { // Tags: A set of instance tags. type Tags struct { // Fingerprint: Specifies a fingerprint for this request, which is - // essentially a hash of the metadata's contents and used for optimistic + // essentially a hash of the tags' 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. + // changes after every request to modify or update tags. You must always + // provide an up-to-date fingerprint hash in order to update or change + // tags. // // To see the latest fingerprint, make get() request to the instance. Fingerprint string `json:"fingerprint,omitempty"` @@ -19494,6 +20692,38 @@ func (s *TargetHttpProxyListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type TargetHttpsProxiesSetQuicOverrideRequest struct { + // QuicOverride: QUIC policy for the TargetHttpsProxy resource. + // + // Possible values: + // "DISABLE" + // "ENABLE" + // "NONE" + QuicOverride string `json:"quicOverride,omitempty"` + + // ForceSendFields is a list of field names (e.g. "QuicOverride") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "QuicOverride") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *TargetHttpsProxiesSetQuicOverrideRequest) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpsProxiesSetQuicOverrideRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type TargetHttpsProxiesSetSslCertificatesRequest struct { // SslCertificates: New set of SslCertificate resources to associate // with this TargetHttpsProxy resource. Currently exactly one @@ -19553,6 +20783,21 @@ type TargetHttpsProxy struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` + // QuicOverride: Specifies the QUIC override policy for this + // TargetHttpsProxy resource. This determines whether the load balancer + // will attempt to negotiate QUIC with clients or not. Can specify one + // of NONE, ENABLE, or DISABLE. Specify ENABLE to always enable QUIC, + // Enables QUIC when set to ENABLE, and disables QUIC when set to + // DISABLE. If NONE is specified, uses the QUIC policy with no user + // overrides, which is equivalent to DISABLE. Not specifying this field + // is equivalent to specifying NONE. + // + // Possible values: + // "DISABLE" + // "ENABLE" + // "NONE" + QuicOverride string `json:"quicOverride,omitempty"` + // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` @@ -19561,6 +20806,11 @@ type TargetHttpsProxy struct { // Currently, exactly one SSL certificate must be specified. SslCertificates []string `json:"sslCertificates,omitempty"` + // SslPolicy: URL of SslPolicy resource that will be associated with the + // TargetHttpsProxy resource. If not set, the TargetHttpsProxy resource + // will not have any SSL policy configured. + SslPolicy string `json:"sslPolicy,omitempty"` + // UrlMap: A fully-qualified or valid partial URL to the UrlMap resource // that defines the mapping from URL to the BackendService. For example, // the following are all valid URLs for specifying a URL map: @@ -20147,7 +21397,7 @@ func (s *TargetInstanceListWarningData) MarshalJSON() ([]byte, error) { } type TargetInstancesScopedList struct { - // TargetInstances: List of target instances contained in this scope. + // TargetInstances: A list of target instances contained in this scope. TargetInstances []*TargetInstance `json:"targetInstances,omitempty"` // Warning: Informational warning which replaces the list of addresses @@ -20890,7 +22140,7 @@ func (s *TargetPoolsRemoveInstanceRequest) MarshalJSON() ([]byte, error) { } type TargetPoolsScopedList struct { - // TargetPools: List of target pools contained in this scope. + // TargetPools: A list of target pools contained in this scope. TargetPools []*TargetPool `json:"targetPools,omitempty"` // Warning: Informational warning which replaces the list of addresses @@ -21187,6 +22437,11 @@ type TargetSslProxy struct { // certificate must be specified. SslCertificates []string `json:"sslCertificates,omitempty"` + // SslPolicy: URL of SslPolicy resource that will be associated with the + // TargetSslProxy resource. If not set, the TargetSslProxy resource will + // not have any SSL policy configured. + SslPolicy string `json:"sslPolicy,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -22057,7 +23312,7 @@ func (s *TargetVpnGatewayListWarningData) MarshalJSON() ([]byte, error) { } type TargetVpnGatewaysScopedList struct { - // TargetVpnGateways: [Output Only] List of target vpn gateways + // TargetVpnGateways: [Output Only] A list of target vpn gateways // contained in this scope. TargetVpnGateways []*TargetVpnGateway `json:"targetVpnGateways,omitempty"` @@ -22223,6 +23478,67 @@ func (s *TestFailure) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type TestPermissionsRequest struct { + // Permissions: The set of permissions to check for the 'resource'. + // Permissions with wildcards (such as '*' or 'storage.*') are not + // allowed. + Permissions []string `json:"permissions,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Permissions") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Permissions") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *TestPermissionsRequest) MarshalJSON() ([]byte, error) { + type NoMethod TestPermissionsRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type TestPermissionsResponse struct { + // Permissions: A subset of `TestPermissionsRequest.permissions` that + // the caller is allowed. + Permissions []string `json:"permissions,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Permissions") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Permissions") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *TestPermissionsResponse) MarshalJSON() ([]byte, error) { + type NoMethod TestPermissionsResponse + 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. @@ -23092,7 +24408,7 @@ func (s *VpnTunnelListWarningData) MarshalJSON() ([]byte, error) { } type VpnTunnelsScopedList struct { - // VpnTunnels: List of vpn tunnels contained in this scope. + // VpnTunnels: A list of vpn tunnels contained in this scope. VpnTunnels []*VpnTunnel `json:"vpnTunnels,omitempty"` // Warning: Informational warning which replaces the list of addresses @@ -23695,32 +25011,28 @@ func (r *AcceleratorTypesService) AggregatedList(project string) *AcceleratorTyp return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AcceleratorTypesAggregatedListCall) Filter(filter string) *AcceleratorTypesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -23864,7 +25176,7 @@ func (c *AcceleratorTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (* // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -23941,8 +25253,7 @@ type AcceleratorTypesGetCall struct { header_ http.Header } -// Get: Returns the specified accelerator type. Get a list of available -// accelerator types by making a list() request. +// Get: Returns the specified accelerator type. func (r *AcceleratorTypesService) Get(project string, zone string, acceleratorType string) *AcceleratorTypesGetCall { c := &AcceleratorTypesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -24047,7 +25358,7 @@ func (c *AcceleratorTypesGetCall) Do(opts ...googleapi.CallOption) (*Accelerator } return ret, nil // { - // "description": "Returns the specified accelerator type. Get a list of available accelerator types by making a list() request.", + // "description": "Returns the specified accelerator type.", // "httpMethod": "GET", // "id": "compute.acceleratorTypes.get", // "parameterOrder": [ @@ -24112,32 +25423,28 @@ func (r *AcceleratorTypesService) List(project string, zone string) *Accelerator return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AcceleratorTypesListCall) Filter(filter string) *AcceleratorTypesListCall { c.urlParams_.Set("filter", filter) return c @@ -24283,7 +25590,7 @@ func (c *AcceleratorTypesListCall) Do(opts ...googleapi.CallOption) (*Accelerato // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -24373,32 +25680,28 @@ func (r *AddressesService) AggregatedList(project string) *AddressesAggregatedLi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AddressesAggregatedListCall) Filter(filter string) *AddressesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -24542,7 +25845,7 @@ func (c *AddressesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Address // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -25135,32 +26438,28 @@ func (r *AddressesService) List(project string, region string) *AddressesListCal return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AddressesListCall) Filter(filter string) *AddressesListCall { c.urlParams_.Set("filter", filter) return c @@ -25306,7 +26605,7 @@ func (c *AddressesListCall) Do(opts ...googleapi.CallOption) (*AddressList, erro // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -25395,32 +26694,28 @@ func (r *AutoscalersService) AggregatedList(project string) *AutoscalersAggregat return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AutoscalersAggregatedListCall) Filter(filter string) *AutoscalersAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -25564,7 +26859,7 @@ func (c *AutoscalersAggregatedListCall) Do(opts ...googleapi.CallOption) (*Autos // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -25812,7 +27107,7 @@ type AutoscalersGetCall struct { header_ http.Header } -// Get: Returns the specified autoscaler resource. Get a list of +// Get: Returns the specified autoscaler resource. Gets a list of // available autoscalers by making a list() request. func (r *AutoscalersService) Get(project string, zone string, autoscaler string) *AutoscalersGetCall { c := &AutoscalersGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -25918,7 +27213,7 @@ func (c *AutoscalersGetCall) Do(opts ...googleapi.CallOption) (*Autoscaler, erro } return ret, nil // { - // "description": "Returns the specified autoscaler resource. Get a list of available autoscalers by making a list() request.", + // "description": "Returns the specified autoscaler resource. Gets a list of available autoscalers by making a list() request.", // "httpMethod": "GET", // "id": "compute.autoscalers.get", // "parameterOrder": [ @@ -26154,32 +27449,28 @@ func (r *AutoscalersService) List(project string, zone string) *AutoscalersListC return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *AutoscalersListCall) Filter(filter string) *AutoscalersListCall { c.urlParams_.Set("filter", filter) return c @@ -26325,7 +27616,7 @@ func (c *AutoscalersListCall) Do(opts ...googleapi.CallOption) (*AutoscalerList, // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -26937,7 +28228,7 @@ type BackendBucketsGetCall struct { header_ http.Header } -// Get: Returns the specified BackendBucket resource. Get a list of +// Get: Returns the specified BackendBucket resource. Gets a list of // available backend buckets by making a list() request. func (r *BackendBucketsService) Get(project string, backendBucket string) *BackendBucketsGetCall { c := &BackendBucketsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -27041,7 +28332,7 @@ func (c *BackendBucketsGetCall) Do(opts ...googleapi.CallOption) (*BackendBucket } return ret, nil // { - // "description": "Returns the specified BackendBucket resource. Get a list of available backend buckets by making a list() request.", + // "description": "Returns the specified BackendBucket resource. Gets a list of available backend buckets by making a list() request.", // "httpMethod": "GET", // "id": "compute.backendBuckets.get", // "parameterOrder": [ @@ -27256,32 +28547,28 @@ func (r *BackendBucketsService) List(project string) *BackendBucketsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *BackendBucketsListCall) Filter(filter string) *BackendBucketsListCall { c.urlParams_.Set("filter", filter) return c @@ -27425,7 +28712,7 @@ func (c *BackendBucketsListCall) Do(opts ...googleapi.CallOption) (*BackendBucke // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -27851,32 +29138,28 @@ func (r *BackendServicesService) AggregatedList(project string) *BackendServices return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *BackendServicesAggregatedListCall) Filter(filter string) *BackendServicesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -28020,7 +29303,7 @@ func (c *BackendServicesAggregatedListCall) Do(opts ...googleapi.CallOption) (*B // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -28257,7 +29540,7 @@ type BackendServicesGetCall struct { header_ http.Header } -// Get: Returns the specified BackendService resource. Get a list of +// Get: Returns the specified BackendService resource. Gets a list of // available backend services by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/backendServices/get func (r *BackendServicesService) Get(project string, backendService string) *BackendServicesGetCall { @@ -28362,7 +29645,7 @@ func (c *BackendServicesGetCall) Do(opts ...googleapi.CallOption) (*BackendServi } return ret, nil // { - // "description": "Returns the specified BackendService resource. Get a list of available backend services by making a list() request.", + // "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", // "httpMethod": "GET", // "id": "compute.backendServices.get", // "parameterOrder": [ @@ -28729,32 +30012,28 @@ func (r *BackendServicesService) List(project string) *BackendServicesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *BackendServicesListCall) Filter(filter string) *BackendServicesListCall { c.urlParams_.Set("filter", filter) return c @@ -28898,7 +30177,7 @@ func (c *BackendServicesListCall) Do(opts ...googleapi.CallOption) (*BackendServ // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -29331,32 +30610,28 @@ func (r *DiskTypesService) AggregatedList(project string) *DiskTypesAggregatedLi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DiskTypesAggregatedListCall) Filter(filter string) *DiskTypesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -29500,7 +30775,7 @@ func (c *DiskTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (*DiskTyp // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -29577,7 +30852,7 @@ type DiskTypesGetCall struct { header_ http.Header } -// Get: Returns the specified disk type. Get a list of available disk +// Get: Returns the specified disk type. Gets a list of available disk // types by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/diskTypes/get func (r *DiskTypesService) Get(project string, zone string, diskType string) *DiskTypesGetCall { @@ -29684,7 +30959,7 @@ func (c *DiskTypesGetCall) Do(opts ...googleapi.CallOption) (*DiskType, error) { } return ret, nil // { - // "description": "Returns the specified disk type. Get a list of available disk types by making a list() request.", + // "description": "Returns the specified disk type. Gets a list of available disk types by making a list() request.", // "httpMethod": "GET", // "id": "compute.diskTypes.get", // "parameterOrder": [ @@ -29750,32 +31025,28 @@ func (r *DiskTypesService) List(project string, zone string) *DiskTypesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DiskTypesListCall) Filter(filter string) *DiskTypesListCall { c.urlParams_.Set("filter", filter) return c @@ -29921,7 +31192,7 @@ func (c *DiskTypesListCall) Do(opts ...googleapi.CallOption) (*DiskTypeList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -30011,32 +31282,28 @@ func (r *DisksService) AggregatedList(project string) *DisksAggregatedListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DisksAggregatedListCall) Filter(filter string) *DisksAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -30180,7 +31447,7 @@ func (c *DisksAggregatedListCall) Do(opts ...googleapi.CallOption) (*DiskAggrega // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -30623,7 +31890,7 @@ type DisksGetCall struct { header_ http.Header } -// Get: Returns a specified persistent disk. Get a list of available +// Get: Returns a specified persistent disk. Gets a list of available // persistent disks by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/disks/get func (r *DisksService) Get(project string, zone string, disk string) *DisksGetCall { @@ -30730,7 +31997,7 @@ func (c *DisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, error) { } return ret, nil // { - // "description": "Returns a specified persistent disk. Get a list of available persistent disks by making a list() request.", + // "description": "Returns a specified persistent disk. Gets a list of available persistent disks by making a list() request.", // "httpMethod": "GET", // "id": "compute.disks.get", // "parameterOrder": [ @@ -30983,32 +32250,28 @@ func (r *DisksService) List(project string, zone string) *DisksListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *DisksListCall) Filter(filter string) *DisksListCall { c.urlParams_.Set("filter", filter) return c @@ -31154,7 +32417,7 @@ func (c *DisksListCall) Do(opts ...googleapi.CallOption) (*DiskList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -32083,32 +33346,28 @@ func (r *FirewallsService) List(project string) *FirewallsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *FirewallsListCall) Filter(filter string) *FirewallsListCall { c.urlParams_.Set("filter", filter) return c @@ -32252,7 +33511,7 @@ func (c *FirewallsListCall) Do(opts ...googleapi.CallOption) (*FirewallList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -32682,32 +33941,28 @@ func (r *ForwardingRulesService) AggregatedList(project string) *ForwardingRules return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ForwardingRulesAggregatedListCall) Filter(filter string) *ForwardingRulesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -32851,7 +34106,7 @@ func (c *ForwardingRulesAggregatedListCall) Do(opts ...googleapi.CallOption) (*F // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -33444,32 +34699,28 @@ func (r *ForwardingRulesService) List(project string, region string) *Forwarding return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ForwardingRulesListCall) Filter(filter string) *ForwardingRulesListCall { c.urlParams_.Set("filter", filter) return c @@ -33615,7 +34866,7 @@ func (c *ForwardingRulesListCall) Do(opts ...googleapi.CallOption) (*ForwardingR // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -34042,7 +35293,7 @@ type GlobalAddressesGetCall struct { header_ http.Header } -// Get: Returns the specified address resource. Get a list of available +// Get: Returns the specified address resource. Gets a list of available // addresses by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/globalAddresses/get func (r *GlobalAddressesService) Get(project string, address string) *GlobalAddressesGetCall { @@ -34147,7 +35398,7 @@ func (c *GlobalAddressesGetCall) Do(opts ...googleapi.CallOption) (*Address, err } return ret, nil // { - // "description": "Returns the specified address resource. Get a list of available addresses by making a list() request.", + // "description": "Returns the specified address resource. Gets a list of available addresses by making a list() request.", // "httpMethod": "GET", // "id": "compute.globalAddresses.get", // "parameterOrder": [ @@ -34363,32 +35614,28 @@ func (r *GlobalAddressesService) List(project string) *GlobalAddressesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalAddressesListCall) Filter(filter string) *GlobalAddressesListCall { c.urlParams_.Set("filter", filter) return c @@ -34532,7 +35779,7 @@ func (c *GlobalAddressesListCall) Do(opts ...googleapi.CallOption) (*AddressList // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -34769,7 +36016,7 @@ type GlobalForwardingRulesGetCall struct { header_ http.Header } -// Get: Returns the specified GlobalForwardingRule resource. Get a list +// Get: Returns the specified GlobalForwardingRule resource. Gets a list // of available forwarding rules by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/globalForwardingRules/get func (r *GlobalForwardingRulesService) Get(project string, forwardingRule string) *GlobalForwardingRulesGetCall { @@ -34874,7 +36121,7 @@ func (c *GlobalForwardingRulesGetCall) Do(opts ...googleapi.CallOption) (*Forwar } return ret, nil // { - // "description": "Returns the specified GlobalForwardingRule resource. Get a list of available forwarding rules by making a list() request.", + // "description": "Returns the specified GlobalForwardingRule resource. Gets a list of available forwarding rules by making a list() request.", // "httpMethod": "GET", // "id": "compute.globalForwardingRules.get", // "parameterOrder": [ @@ -35091,32 +36338,28 @@ func (r *GlobalForwardingRulesService) List(project string) *GlobalForwardingRul return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalForwardingRulesListCall) Filter(filter string) *GlobalForwardingRulesListCall { c.urlParams_.Set("filter", filter) return c @@ -35260,7 +36503,7 @@ func (c *GlobalForwardingRulesListCall) Do(opts ...googleapi.CallOption) (*Forwa // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -35515,32 +36758,28 @@ func (r *GlobalOperationsService) AggregatedList(project string) *GlobalOperatio return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalOperationsAggregatedListCall) Filter(filter string) *GlobalOperationsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -35684,7 +36923,7 @@ func (c *GlobalOperationsAggregatedListCall) Do(opts ...googleapi.CallOption) (* // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -35869,7 +37108,7 @@ type GlobalOperationsGetCall struct { header_ http.Header } -// Get: Retrieves the specified Operations resource. Get a list of +// Get: Retrieves the specified Operations resource. Gets a list of // operations by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/globalOperations/get func (r *GlobalOperationsService) Get(project string, operation string) *GlobalOperationsGetCall { @@ -35974,7 +37213,7 @@ func (c *GlobalOperationsGetCall) Do(opts ...googleapi.CallOption) (*Operation, } return ret, nil // { - // "description": "Retrieves the specified Operations resource. Get a list of operations by making a list() request.", + // "description": "Retrieves the specified Operations resource. Gets a list of operations by making a list() request.", // "httpMethod": "GET", // "id": "compute.globalOperations.get", // "parameterOrder": [ @@ -36030,32 +37269,28 @@ func (r *GlobalOperationsService) List(project string) *GlobalOperationsListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *GlobalOperationsListCall) Filter(filter string) *GlobalOperationsListCall { c.urlParams_.Set("filter", filter) return c @@ -36199,7 +37434,7 @@ func (c *GlobalOperationsListCall) Do(opts ...googleapi.CallOption) (*OperationL // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -36435,7 +37670,7 @@ type HealthChecksGetCall struct { header_ http.Header } -// Get: Returns the specified HealthCheck resource. Get a list of +// Get: Returns the specified HealthCheck resource. Gets a list of // available health checks by making a list() request. func (r *HealthChecksService) Get(project string, healthCheck string) *HealthChecksGetCall { c := &HealthChecksGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -36539,7 +37774,7 @@ func (c *HealthChecksGetCall) Do(opts ...googleapi.CallOption) (*HealthCheck, er } return ret, nil // { - // "description": "Returns the specified HealthCheck resource. Get a list of available health checks by making a list() request.", + // "description": "Returns the specified HealthCheck resource. Gets a list of available health checks by making a list() request.", // "httpMethod": "GET", // "id": "compute.healthChecks.get", // "parameterOrder": [ @@ -36754,32 +37989,28 @@ func (r *HealthChecksService) List(project string) *HealthChecksListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *HealthChecksListCall) Filter(filter string) *HealthChecksListCall { c.urlParams_.Set("filter", filter) return c @@ -36923,7 +38154,7 @@ func (c *HealthChecksListCall) Do(opts ...googleapi.CallOption) (*HealthCheckLis // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -37503,7 +38734,7 @@ type HttpHealthChecksGetCall struct { header_ http.Header } -// Get: Returns the specified HttpHealthCheck resource. Get a list of +// Get: Returns the specified HttpHealthCheck resource. Gets a list of // available HTTP health checks by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/httpHealthChecks/get func (r *HttpHealthChecksService) Get(project string, httpHealthCheck string) *HttpHealthChecksGetCall { @@ -37608,7 +38839,7 @@ func (c *HttpHealthChecksGetCall) Do(opts ...googleapi.CallOption) (*HttpHealthC } return ret, nil // { - // "description": "Returns the specified HttpHealthCheck resource. Get a list of available HTTP health checks by making a list() request.", + // "description": "Returns the specified HttpHealthCheck resource. Gets a list of available HTTP health checks by making a list() request.", // "httpMethod": "GET", // "id": "compute.httpHealthChecks.get", // "parameterOrder": [ @@ -37825,32 +39056,28 @@ func (r *HttpHealthChecksService) List(project string) *HttpHealthChecksListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *HttpHealthChecksListCall) Filter(filter string) *HttpHealthChecksListCall { c.urlParams_.Set("filter", filter) return c @@ -37994,7 +39221,7 @@ func (c *HttpHealthChecksListCall) Do(opts ...googleapi.CallOption) (*HttpHealth // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -38575,7 +39802,7 @@ type HttpsHealthChecksGetCall struct { header_ http.Header } -// Get: Returns the specified HttpsHealthCheck resource. Get a list of +// Get: Returns the specified HttpsHealthCheck resource. Gets a list of // available HTTPS health checks by making a list() request. func (r *HttpsHealthChecksService) Get(project string, httpsHealthCheck string) *HttpsHealthChecksGetCall { c := &HttpsHealthChecksGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -38679,7 +39906,7 @@ func (c *HttpsHealthChecksGetCall) Do(opts ...googleapi.CallOption) (*HttpsHealt } return ret, nil // { - // "description": "Returns the specified HttpsHealthCheck resource. Get a list of available HTTPS health checks by making a list() request.", + // "description": "Returns the specified HttpsHealthCheck resource. Gets a list of available HTTPS health checks by making a list() request.", // "httpMethod": "GET", // "id": "compute.httpsHealthChecks.get", // "parameterOrder": [ @@ -38894,32 +40121,28 @@ func (r *HttpsHealthChecksService) List(project string) *HttpsHealthChecksListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *HttpsHealthChecksListCall) Filter(filter string) *HttpsHealthChecksListCall { c.urlParams_.Set("filter", filter) return c @@ -39063,7 +40286,7 @@ func (c *HttpsHealthChecksListCall) Do(opts ...googleapi.CallOption) (*HttpsHeal // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -39817,7 +41040,7 @@ type ImagesGetCall struct { header_ http.Header } -// Get: Returns the specified image. Get a list of available images by +// Get: Returns the specified image. Gets a list of available images by // making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/images/get func (r *ImagesService) Get(project string, image string) *ImagesGetCall { @@ -39922,7 +41145,7 @@ func (c *ImagesGetCall) Do(opts ...googleapi.CallOption) (*Image, error) { } return ret, nil // { - // "description": "Returns the specified image. Get a list of available images by making a list() request.", + // "description": "Returns the specified image. Gets a list of available images by making a list() request.", // "httpMethod": "GET", // "id": "compute.images.get", // "parameterOrder": [ @@ -40311,32 +41534,28 @@ func (r *ImagesService) List(project string) *ImagesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ImagesListCall) Filter(filter string) *ImagesListCall { c.urlParams_.Set("filter", filter) return c @@ -40480,7 +41699,7 @@ func (c *ImagesListCall) Do(opts ...googleapi.CallOption) (*ImageList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -40905,32 +42124,28 @@ func (r *InstanceGroupManagersService) AggregatedList(project string) *InstanceG return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupManagersAggregatedListCall) Filter(filter string) *InstanceGroupManagersAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -41075,7 +42290,7 @@ func (c *InstanceGroupManagersAggregatedListCall) Do(opts ...googleapi.CallOptio // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -41519,7 +42734,7 @@ type InstanceGroupManagersGetCall struct { } // Get: Returns all of the details about the specified managed instance -// group. Get a list of available managed instance groups by making a +// group. Gets a list of available managed instance groups by making a // list() request. func (r *InstanceGroupManagersService) Get(project string, zone string, instanceGroupManager string) *InstanceGroupManagersGetCall { c := &InstanceGroupManagersGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -41625,7 +42840,7 @@ func (c *InstanceGroupManagersGetCall) Do(opts ...googleapi.CallOption) (*Instan } return ret, nil // { - // "description": "Returns all of the details about the specified managed instance group. Get a list of available managed instance groups by making a list() request.", + // "description": "Returns all of the details about the specified managed instance group. Gets a list of available managed instance groups by making a list() request.", // "httpMethod": "GET", // "id": "compute.instanceGroupManagers.get", // "parameterOrder": [ @@ -41866,32 +43081,28 @@ func (r *InstanceGroupManagersService) List(project string, zone string) *Instan return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupManagersListCall) Filter(filter string) *InstanceGroupManagersListCall { c.urlParams_.Set("filter", filter) return c @@ -42037,7 +43248,7 @@ func (c *InstanceGroupManagersListCall) Do(opts ...googleapi.CallOption) (*Insta // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -43250,32 +44461,28 @@ func (r *InstanceGroupsService) AggregatedList(project string) *InstanceGroupsAg return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupsAggregatedListCall) Filter(filter string) *InstanceGroupsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -43419,7 +44626,7 @@ func (c *InstanceGroupsAggregatedListCall) Do(opts ...googleapi.CallOption) (*In // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -43668,7 +44875,7 @@ type InstanceGroupsGetCall struct { header_ http.Header } -// Get: Returns the specified instance group. Get a list of available +// Get: Returns the specified instance group. Gets a list of available // instance groups by making a list() request. func (r *InstanceGroupsService) Get(project string, zone string, instanceGroup string) *InstanceGroupsGetCall { c := &InstanceGroupsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -43774,7 +44981,7 @@ func (c *InstanceGroupsGetCall) Do(opts ...googleapi.CallOption) (*InstanceGroup } return ret, nil // { - // "description": "Returns the specified instance group. Get a list of available instance groups by making a list() request.", + // "description": "Returns the specified instance group. Gets a list of available instance groups by making a list() request.", // "httpMethod": "GET", // "id": "compute.instanceGroups.get", // "parameterOrder": [ @@ -44007,32 +45214,28 @@ func (r *InstanceGroupsService) List(project string, zone string) *InstanceGroup return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupsListCall) Filter(filter string) *InstanceGroupsListCall { c.urlParams_.Set("filter", filter) return c @@ -44178,7 +45381,7 @@ func (c *InstanceGroupsListCall) Do(opts ...googleapi.CallOption) (*InstanceGrou // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -44271,32 +45474,28 @@ func (r *InstanceGroupsService) ListInstances(project string, zone string, insta return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceGroupsListInstancesCall) Filter(filter string) *InstanceGroupsListInstancesCall { c.urlParams_.Set("filter", filter) return c @@ -44436,7 +45635,7 @@ func (c *InstanceGroupsListInstancesCall) Do(opts ...googleapi.CallOption) (*Ins // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -45053,8 +46252,8 @@ type InstanceTemplatesGetCall struct { header_ http.Header } -// Get: Returns the specified instance template. Get a list of available -// instance templates by making a list() request. +// Get: Returns the specified instance template. Gets a list of +// available instance templates by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/instanceTemplates/get func (r *InstanceTemplatesService) Get(project string, instanceTemplate string) *InstanceTemplatesGetCall { c := &InstanceTemplatesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -45158,7 +46357,7 @@ func (c *InstanceTemplatesGetCall) Do(opts ...googleapi.CallOption) (*InstanceTe } return ret, nil // { - // "description": "Returns the specified instance template. Get a list of available instance templates by making a list() request.", + // "description": "Returns the specified instance template. Gets a list of available instance templates by making a list() request.", // "httpMethod": "GET", // "id": "compute.instanceTemplates.get", // "parameterOrder": [ @@ -45378,32 +46577,28 @@ func (r *InstanceTemplatesService) List(project string) *InstanceTemplatesListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstanceTemplatesListCall) Filter(filter string) *InstanceTemplatesListCall { c.urlParams_.Set("filter", filter) return c @@ -45547,7 +46742,7 @@ func (c *InstanceTemplatesListCall) Do(opts ...googleapi.CallOption) (*InstanceT // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -45821,32 +47016,28 @@ func (r *InstancesService) AggregatedList(project string) *InstancesAggregatedLi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstancesAggregatedListCall) Filter(filter string) *InstancesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -45990,7 +47181,7 @@ func (c *InstancesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Instanc // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -46081,6 +47272,14 @@ func (r *InstancesService) AttachDisk(project string, zone string, instance stri return c } +// ForceAttach sets the optional parameter "forceAttach": Whether to +// force attach the disk even if it's currently attached to another +// instance. This is only available for regional disks. +func (c *InstancesAttachDiskCall) ForceAttach(forceAttach bool) *InstancesAttachDiskCall { + c.urlParams_.Set("forceAttach", fmt.Sprint(forceAttach)) + 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 @@ -46197,6 +47396,11 @@ func (c *InstancesAttachDiskCall) Do(opts ...googleapi.CallOption) (*Operation, // "instance" // ], // "parameters": { + // "forceAttach": { + // "description": "Whether to force attach the disk even if it's currently attached to another instance. This is only available for regional disks.", + // "location": "query", + // "type": "boolean" + // }, // "instance": { // "description": "The instance name for this request.", // "location": "path", @@ -46794,8 +47998,8 @@ type InstancesGetCall struct { header_ http.Header } -// Get: Returns the specified Instance resource. Get a list of available -// instances by making a list() request. +// Get: Returns the specified Instance resource. Gets a list of +// available instances by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/get func (r *InstancesService) Get(project string, zone string, instance string) *InstancesGetCall { c := &InstancesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -46901,7 +48105,7 @@ func (c *InstancesGetCall) Do(opts ...googleapi.CallOption) (*Instance, error) { } return ret, nil // { - // "description": "Returns the specified Instance resource. Get a list of available instances by making a list() request.", + // "description": "Returns the specified Instance resource. Gets a list of available instances by making a list() request.", // "httpMethod": "GET", // "id": "compute.instances.get", // "parameterOrder": [ @@ -47184,6 +48388,22 @@ func (c *InstancesInsertCall) RequestId(requestId string) *InstancesInsertCall { return c } +// SourceInstanceTemplate sets the optional parameter +// "sourceInstanceTemplate": Specifies instance template 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/instanceTemplates/instanceTemplate +// - projects/project/global/global/instanceTemplates/instanceTemplate +// +// - global/instancesTemplates/instanceTemplate +func (c *InstancesInsertCall) SourceInstanceTemplate(sourceInstanceTemplate string) *InstancesInsertCall { + c.urlParams_.Set("sourceInstanceTemplate", sourceInstanceTemplate) + return c +} + // Fields allows partial responses to be retrieved. See // https://developers.google.com/gdata/docs/2.0/basics#PartialResponse // for more information. @@ -47291,6 +48511,11 @@ func (c *InstancesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "location": "query", // "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", + // "location": "query", + // "type": "string" + // }, // "zone": { // "description": "The name of the zone for this request.", // "location": "path", @@ -47336,32 +48561,28 @@ func (r *InstancesService) List(project string, zone string) *InstancesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstancesListCall) Filter(filter string) *InstancesListCall { c.urlParams_.Set("filter", filter) return c @@ -47507,7 +48728,7 @@ func (c *InstancesListCall) Do(opts ...googleapi.CallOption) (*InstanceList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -47601,32 +48822,28 @@ func (r *InstancesService) ListReferrers(project string, zone string, instance s return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InstancesListReferrersCall) Filter(filter string) *InstancesListReferrersCall { c.urlParams_.Set("filter", filter) return c @@ -47774,7 +48991,7 @@ func (c *InstancesListReferrersCall) Do(opts ...googleapi.CallOption) (*Instance // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -49872,9 +51089,8 @@ type InstancesStartCall struct { header_ http.Header } -// Start: Starts an instance that was stopped using the using the -// instances().stop method. For more information, see Restart an -// instance. +// Start: Starts an instance that was stopped using the instances().stop +// method. For more information, see Restart an instance. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/start func (r *InstancesService) Start(project string, zone string, instance string) *InstancesStartCall { c := &InstancesStartCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -49986,7 +51202,7 @@ func (c *InstancesStartCall) Do(opts ...googleapi.CallOption) (*Operation, error } return ret, nil // { - // "description": "Starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance.", + // "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", // "httpMethod": "POST", // "id": "compute.instances.start", // "parameterOrder": [ @@ -50048,8 +51264,8 @@ type InstancesStartWithEncryptionKeyCall struct { } // StartWithEncryptionKey: Starts an instance that was stopped using the -// using the instances().stop method. For more information, see Restart -// an instance. +// instances().stop method. For more information, see Restart an +// instance. func (r *InstancesService) StartWithEncryptionKey(project string, zone string, instance string, instancesstartwithencryptionkeyrequest *InstancesStartWithEncryptionKeyRequest) *InstancesStartWithEncryptionKeyCall { c := &InstancesStartWithEncryptionKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -50166,7 +51382,7 @@ func (c *InstancesStartWithEncryptionKeyCall) Do(opts ...googleapi.CallOption) ( } return ret, nil // { - // "description": "Starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance.", + // "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", // "httpMethod": "POST", // "id": "compute.instances.startWithEncryptionKey", // "parameterOrder": [ @@ -50795,32 +52011,28 @@ func (r *InterconnectAttachmentsService) AggregatedList(project string) *Interco return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectAttachmentsAggregatedListCall) Filter(filter string) *InterconnectAttachmentsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -50965,7 +52177,7 @@ func (c *InterconnectAttachmentsAggregatedListCall) Do(opts ...googleapi.CallOpt // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -51554,32 +52766,28 @@ func (r *InterconnectAttachmentsService) List(project string, region string) *In return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectAttachmentsListCall) Filter(filter string) *InterconnectAttachmentsListCall { c.urlParams_.Set("filter", filter) return c @@ -51725,7 +52933,7 @@ func (c *InterconnectAttachmentsListCall) Do(opts ...googleapi.CallOption) (*Int // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -51796,6 +53004,189 @@ func (c *InterconnectAttachmentsListCall) Pages(ctx context.Context, f func(*Int } } +// method id "compute.interconnectAttachments.patch": + +type InterconnectAttachmentsPatchCall struct { + s *Service + project string + region string + interconnectAttachment string + interconnectattachment *InterconnectAttachment + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Updates the specified interconnect attachment with the data +// included in the request. This method supports PATCH semantics and +// uses the JSON merge patch format and processing rules. +func (r *InterconnectAttachmentsService) Patch(project string, region string, interconnectAttachment string, interconnectattachment *InterconnectAttachment) *InterconnectAttachmentsPatchCall { + c := &InterconnectAttachmentsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.interconnectAttachment = interconnectAttachment + c.interconnectattachment = interconnectattachment + 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 *InterconnectAttachmentsPatchCall) RequestId(requestId string) *InterconnectAttachmentsPatchCall { + 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 *InterconnectAttachmentsPatchCall) Fields(s ...googleapi.Field) *InterconnectAttachmentsPatchCall { + 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 *InterconnectAttachmentsPatchCall) Context(ctx context.Context) *InterconnectAttachmentsPatchCall { + 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 *InterconnectAttachmentsPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InterconnectAttachmentsPatchCall) 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.interconnectattachment) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{interconnectAttachment}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PATCH", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "interconnectAttachment": c.interconnectAttachment, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.interconnectAttachments.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 *InterconnectAttachmentsPatchCall) 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 interconnect attachment with the data included in the request. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "httpMethod": "PATCH", + // "id": "compute.interconnectAttachments.patch", + // "parameterOrder": [ + // "project", + // "region", + // "interconnectAttachment" + // ], + // "parameters": { + // "interconnectAttachment": { + // "description": "Name of the interconnect attachment to patch.", + // "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": "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}/interconnectAttachments/{interconnectAttachment}", + // "request": { + // "$ref": "InterconnectAttachment" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.interconnectLocations.get": type InterconnectLocationsGetCall struct { @@ -51808,8 +53199,8 @@ type InterconnectLocationsGetCall struct { header_ http.Header } -// Get: Returns the details for the specified interconnect location. Get -// a list of available interconnect locations by making a list() +// Get: Returns the details for the specified interconnect location. +// Gets a list of available interconnect locations by making a list() // request. func (r *InterconnectLocationsService) Get(project string, interconnectLocation string) *InterconnectLocationsGetCall { c := &InterconnectLocationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -51913,7 +53304,7 @@ func (c *InterconnectLocationsGetCall) Do(opts ...googleapi.CallOption) (*Interc } return ret, nil // { - // "description": "Returns the details for the specified interconnect location. Get a list of available interconnect locations by making a list() request.", + // "description": "Returns the details for the specified interconnect location. Gets a list of available interconnect locations by making a list() request.", // "httpMethod": "GET", // "id": "compute.interconnectLocations.get", // "parameterOrder": [ @@ -51968,32 +53359,28 @@ func (r *InterconnectLocationsService) List(project string) *InterconnectLocatio return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectLocationsListCall) Filter(filter string) *InterconnectLocationsListCall { c.urlParams_.Set("filter", filter) return c @@ -52137,7 +53524,7 @@ func (c *InterconnectLocationsListCall) Do(opts ...googleapi.CallOption) (*Inter // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -52692,32 +54079,28 @@ func (r *InterconnectsService) List(project string) *InterconnectsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *InterconnectsListCall) Filter(filter string) *InterconnectsListCall { c.urlParams_.Set("filter", filter) return c @@ -52861,7 +54244,7 @@ func (c *InterconnectsListCall) Do(opts ...googleapi.CallOption) (*InterconnectL // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -53097,6 +54480,466 @@ func (c *InterconnectsPatchCall) Do(opts ...googleapi.CallOption) (*Operation, e } +// method id "compute.licenseCodes.get": + +type LicenseCodesGetCall struct { + s *Service + project string + licenseCode string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Return a specified license code. License codes are mirrored +// across all projects that have permissions to read the License Code. +func (r *LicenseCodesService) Get(project string, licenseCode string) *LicenseCodesGetCall { + c := &LicenseCodesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.licenseCode = licenseCode + 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 *LicenseCodesGetCall) Fields(s ...googleapi.Field) *LicenseCodesGetCall { + 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 *LicenseCodesGetCall) IfNoneMatch(entityTag string) *LicenseCodesGetCall { + 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 *LicenseCodesGetCall) Context(ctx context.Context) *LicenseCodesGetCall { + 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 *LicenseCodesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *LicenseCodesGetCall) 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}/global/licenseCodes/{licenseCode}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "licenseCode": c.licenseCode, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.licenseCodes.get" call. +// Exactly one of *LicenseCode or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *LicenseCode.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 *LicenseCodesGetCall) Do(opts ...googleapi.CallOption) (*LicenseCode, 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 := &LicenseCode{ + 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": "Return a specified license code. License codes are mirrored across all projects that have permissions to read the License Code.", + // "httpMethod": "GET", + // "id": "compute.licenseCodes.get", + // "parameterOrder": [ + // "project", + // "licenseCode" + // ], + // "parameters": { + // "licenseCode": { + // "description": "Number corresponding to the License code resource to return.", + // "location": "path", + // "pattern": "[0-9]{0,61}?", + // "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/licenseCodes/{licenseCode}", + // "response": { + // "$ref": "LicenseCode" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.licenseCodes.testIamPermissions": + +type LicenseCodesTestIamPermissionsCall 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 *LicenseCodesService) TestIamPermissions(project string, resource string, testpermissionsrequest *TestPermissionsRequest) *LicenseCodesTestIamPermissionsCall { + c := &LicenseCodesTestIamPermissionsCall{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 *LicenseCodesTestIamPermissionsCall) Fields(s ...googleapi.Field) *LicenseCodesTestIamPermissionsCall { + 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 *LicenseCodesTestIamPermissionsCall) Context(ctx context.Context) *LicenseCodesTestIamPermissionsCall { + 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 *LicenseCodesTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *LicenseCodesTestIamPermissionsCall) 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}/global/licenseCodes/{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, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.licenseCodes.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 *LicenseCodesTestIamPermissionsCall) 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.licenseCodes.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 of the resource for this request.", + // "location": "path", + // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/licenseCodes/{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.licenses.delete": + +type LicensesDeleteCall struct { + s *Service + project string + license string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified license. +func (r *LicensesService) Delete(project string, license string) *LicensesDeleteCall { + c := &LicensesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.license = license + 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 *LicensesDeleteCall) RequestId(requestId string) *LicensesDeleteCall { + 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 *LicensesDeleteCall) Fields(s ...googleapi.Field) *LicensesDeleteCall { + 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 *LicensesDeleteCall) Context(ctx context.Context) *LicensesDeleteCall { + 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 *LicensesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *LicensesDeleteCall) 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}/global/licenses/{license}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "license": c.license, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.licenses.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 *LicensesDeleteCall) 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 license.", + // "httpMethod": "DELETE", + // "id": "compute.licenses.delete", + // "parameterOrder": [ + // "project", + // "license" + // ], + // "parameters": { + // "license": { + // "description": "Name of the license 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" + // } + // }, + // "path": "{project}/global/licenses/{license}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.licenses.get": type LicensesGetCall struct { @@ -53249,6 +55092,568 @@ func (c *LicensesGetCall) Do(opts ...googleapi.CallOption) (*License, error) { } +// method id "compute.licenses.insert": + +type LicensesInsertCall struct { + s *Service + project string + license *License + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Create a License resource in the specified project. +func (r *LicensesService) Insert(project string, license *License) *LicensesInsertCall { + c := &LicensesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.license = license + 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 *LicensesInsertCall) RequestId(requestId string) *LicensesInsertCall { + 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 *LicensesInsertCall) Fields(s ...googleapi.Field) *LicensesInsertCall { + 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 *LicensesInsertCall) Context(ctx context.Context) *LicensesInsertCall { + 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 *LicensesInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *LicensesInsertCall) 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.license) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", 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.licenses.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 *LicensesInsertCall) 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": "Create a License resource in the specified project.", + // "httpMethod": "POST", + // "id": "compute.licenses.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/licenses", + // "request": { + // "$ref": "License" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/devstorage.full_control", + // "https://www.googleapis.com/auth/devstorage.read_only", + // "https://www.googleapis.com/auth/devstorage.read_write" + // ] + // } + +} + +// method id "compute.licenses.list": + +type LicensesListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves the list of licenses available in the specified +// project. This method does not get any licenses that belong to other +// projects, including licenses attached to publicly-available images, +// like Debian 9. If you want to get a list of publicly-available +// licenses, use this method to make a request to the respective image +// project, such as debian-cloud or windows-cloud. +func (r *LicensesService) List(project string) *LicensesListCall { + c := &LicensesListCall{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 *LicensesListCall) Filter(filter string) *LicensesListCall { + 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 *LicensesListCall) MaxResults(maxResults int64) *LicensesListCall { + 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 *LicensesListCall) OrderBy(orderBy string) *LicensesListCall { + 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 *LicensesListCall) PageToken(pageToken string) *LicensesListCall { + 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 *LicensesListCall) Fields(s ...googleapi.Field) *LicensesListCall { + 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 *LicensesListCall) IfNoneMatch(entityTag string) *LicensesListCall { + 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 *LicensesListCall) Context(ctx context.Context) *LicensesListCall { + 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 *LicensesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *LicensesListCall) 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}/global/licenses") + 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.licenses.list" call. +// Exactly one of *LicensesListResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *LicensesListResponse.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 *LicensesListCall) Do(opts ...googleapi.CallOption) (*LicensesListResponse, 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 := &LicensesListResponse{ + 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 licenses available in the specified project. This method does not get any licenses that belong to other projects, including licenses attached to publicly-available images, like Debian 9. If you want to get a list of publicly-available licenses, use this method to make a request to the respective image project, such as debian-cloud or windows-cloud.", + // "httpMethod": "GET", + // "id": "compute.licenses.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/licenses", + // "response": { + // "$ref": "LicensesListResponse" + // }, + // "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 *LicensesListCall) Pages(ctx context.Context, f func(*LicensesListResponse) 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.licenses.testIamPermissions": + +type LicensesTestIamPermissionsCall 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 *LicensesService) TestIamPermissions(project string, resource string, testpermissionsrequest *TestPermissionsRequest) *LicensesTestIamPermissionsCall { + c := &LicensesTestIamPermissionsCall{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 *LicensesTestIamPermissionsCall) Fields(s ...googleapi.Field) *LicensesTestIamPermissionsCall { + 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 *LicensesTestIamPermissionsCall) Context(ctx context.Context) *LicensesTestIamPermissionsCall { + 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 *LicensesTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *LicensesTestIamPermissionsCall) 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}/global/licenses/{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, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.licenses.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 *LicensesTestIamPermissionsCall) 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.licenses.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 of the resource for this request.", + // "location": "path", + // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/licenses/{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 { @@ -53268,32 +55673,28 @@ func (r *MachineTypesService) AggregatedList(project string) *MachineTypesAggreg return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *MachineTypesAggregatedListCall) Filter(filter string) *MachineTypesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -53437,7 +55838,7 @@ func (c *MachineTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Mach // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -53514,7 +55915,7 @@ type MachineTypesGetCall struct { header_ http.Header } -// Get: Returns the specified machine type. Get a list of available +// Get: Returns the specified machine type. Gets a list of available // machine types by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/machineTypes/get func (r *MachineTypesService) Get(project string, zone string, machineType string) *MachineTypesGetCall { @@ -53621,7 +56022,7 @@ func (c *MachineTypesGetCall) Do(opts ...googleapi.CallOption) (*MachineType, er } return ret, nil // { - // "description": "Returns the specified machine type. Get a list of available machine types by making a list() request.", + // "description": "Returns the specified machine type. Gets a list of available machine types by making a list() request.", // "httpMethod": "GET", // "id": "compute.machineTypes.get", // "parameterOrder": [ @@ -53687,32 +56088,28 @@ func (r *MachineTypesService) List(project string, zone string) *MachineTypesLis return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *MachineTypesListCall) Filter(filter string) *MachineTypesListCall { c.urlParams_.Set("filter", filter) return c @@ -53858,7 +56255,7 @@ func (c *MachineTypesListCall) Do(opts ...googleapi.CallOption) (*MachineTypeLis // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -54272,7 +56669,7 @@ type NetworksGetCall struct { header_ http.Header } -// Get: Returns the specified network. Get a list of available networks +// Get: Returns the specified network. Gets a list of available networks // by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/networks/get func (r *NetworksService) Get(project string, network string) *NetworksGetCall { @@ -54377,7 +56774,7 @@ func (c *NetworksGetCall) Do(opts ...googleapi.CallOption) (*Network, error) { } return ret, nil // { - // "description": "Returns the specified network. Get a list of available networks by making a list() request.", + // "description": "Returns the specified network. Gets a list of available networks by making a list() request.", // "httpMethod": "GET", // "id": "compute.networks.get", // "parameterOrder": [ @@ -54594,32 +56991,28 @@ func (r *NetworksService) List(project string) *NetworksListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *NetworksListCall) Filter(filter string) *NetworksListCall { c.urlParams_.Set("filter", filter) return c @@ -54763,7 +57156,7 @@ func (c *NetworksListCall) Do(opts ...googleapi.CallOption) (*NetworkList, error // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -56101,7 +58494,7 @@ type ProjectsGetXpnHostCall struct { header_ http.Header } -// GetXpnHost: Get the shared VPC host project that this project links +// GetXpnHost: Gets the shared VPC host project that this project links // to. May be empty if no link exists. func (r *ProjectsService) GetXpnHost(project string) *ProjectsGetXpnHostCall { c := &ProjectsGetXpnHostCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -56203,7 +58596,7 @@ func (c *ProjectsGetXpnHostCall) Do(opts ...googleapi.CallOption) (*Project, err } return ret, nil // { - // "description": "Get the shared VPC host project that this project links to. May be empty if no link exists.", + // "description": "Gets the shared VPC host project that this project links to. May be empty if no link exists.", // "httpMethod": "GET", // "id": "compute.projects.getXpnHost", // "parameterOrder": [ @@ -56241,7 +58634,7 @@ type ProjectsGetXpnResourcesCall struct { header_ http.Header } -// GetXpnResources: Get service resources (a.k.a service project) +// GetXpnResources: Gets service resources (a.k.a service project) // associated with this host project. func (r *ProjectsService) GetXpnResources(project string) *ProjectsGetXpnResourcesCall { c := &ProjectsGetXpnResourcesCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -56367,7 +58760,7 @@ func (c *ProjectsGetXpnResourcesCall) Do(opts ...googleapi.CallOption) (*Project } return ret, nil // { - // "description": "Get service resources (a.k.a service project) associated with this host project.", + // "description": "Gets service resources (a.k.a service project) associated with this host project.", // "httpMethod": "GET", // "id": "compute.projects.getXpnResources", // "parameterOrder": [ @@ -56445,7 +58838,7 @@ type ProjectsListXpnHostsCall struct { header_ http.Header } -// ListXpnHosts: List all shared VPC host projects visible to the user +// ListXpnHosts: Lists all shared VPC host projects visible to the user // in an organization. func (r *ProjectsService) ListXpnHosts(project string, projectslistxpnhostsrequest *ProjectsListXpnHostsRequest) *ProjectsListXpnHostsCall { c := &ProjectsListXpnHostsCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -56564,7 +58957,7 @@ func (c *ProjectsListXpnHostsCall) Do(opts ...googleapi.CallOption) (*XpnHostLis } return ret, nil // { - // "description": "List all shared VPC host projects visible to the user in an organization.", + // "description": "Lists all shared VPC host projects visible to the user in an organization.", // "httpMethod": "POST", // "id": "compute.projects.listXpnHosts", // "parameterOrder": [ @@ -57805,32 +60198,28 @@ func (r *RegionAutoscalersService) List(project string, region string) *RegionAu return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionAutoscalersListCall) Filter(filter string) *RegionAutoscalersListCall { c.urlParams_.Set("filter", filter) return c @@ -57976,7 +60365,7 @@ func (c *RegionAutoscalersListCall) Do(opts ...googleapi.CallOption) (*RegionAut // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -59102,32 +61491,28 @@ func (r *RegionBackendServicesService) List(project string, region string) *Regi return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionBackendServicesListCall) Filter(filter string) *RegionBackendServicesListCall { c.urlParams_.Set("filter", filter) return c @@ -59273,7 +61658,7 @@ func (c *RegionBackendServicesListCall) Do(opts ...googleapi.CallOption) (*Backe // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -59732,32 +62117,28 @@ func (r *RegionCommitmentsService) AggregatedList(project string) *RegionCommitm return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionCommitmentsAggregatedListCall) Filter(filter string) *RegionCommitmentsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -59901,7 +62282,7 @@ func (c *RegionCommitmentsAggregatedListCall) Do(opts ...googleapi.CallOption) ( // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -59978,7 +62359,7 @@ type RegionCommitmentsGetCall struct { header_ http.Header } -// Get: Returns the specified commitment resource. Get a list of +// Get: Returns the specified commitment resource. Gets a list of // available commitments by making a list() request. func (r *RegionCommitmentsService) Get(project string, region string, commitment string) *RegionCommitmentsGetCall { c := &RegionCommitmentsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -60084,7 +62465,7 @@ func (c *RegionCommitmentsGetCall) Do(opts ...googleapi.CallOption) (*Commitment } return ret, nil // { - // "description": "Returns the specified commitment resource. Get a list of available commitments by making a list() request.", + // "description": "Returns the specified commitment resource. Gets a list of available commitments by making a list() request.", // "httpMethod": "GET", // "id": "compute.regionCommitments.get", // "parameterOrder": [ @@ -60320,32 +62701,28 @@ func (r *RegionCommitmentsService) List(project string, region string) *RegionCo return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionCommitmentsListCall) Filter(filter string) *RegionCommitmentsListCall { c.urlParams_.Set("filter", filter) return c @@ -60491,7 +62868,7 @@ func (c *RegionCommitmentsListCall) Do(opts ...googleapi.CallOption) (*Commitmen // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -60562,6 +62939,1907 @@ func (c *RegionCommitmentsListCall) Pages(ctx context.Context, f func(*Commitmen } } +// method id "compute.regionDiskTypes.get": + +type RegionDiskTypesGetCall struct { + s *Service + project string + region string + diskType string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns the specified regional disk type. Gets a list of +// available disk types by making a list() request. +func (r *RegionDiskTypesService) Get(project string, region string, diskType string) *RegionDiskTypesGetCall { + c := &RegionDiskTypesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.diskType = diskType + 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 *RegionDiskTypesGetCall) Fields(s ...googleapi.Field) *RegionDiskTypesGetCall { + 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 *RegionDiskTypesGetCall) IfNoneMatch(entityTag string) *RegionDiskTypesGetCall { + 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 *RegionDiskTypesGetCall) Context(ctx context.Context) *RegionDiskTypesGetCall { + 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 *RegionDiskTypesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDiskTypesGetCall) 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}/regions/{region}/diskTypes/{diskType}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "diskType": c.diskType, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionDiskTypes.get" call. +// Exactly one of *DiskType or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *DiskType.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 *RegionDiskTypesGetCall) Do(opts ...googleapi.CallOption) (*DiskType, 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 := &DiskType{ + 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 regional disk type. Gets a list of available disk types by making a list() request.", + // "httpMethod": "GET", + // "id": "compute.regionDiskTypes.get", + // "parameterOrder": [ + // "project", + // "region", + // "diskType" + // ], + // "parameters": { + // "diskType": { + // "description": "Name of the disk 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" + // }, + // "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}/diskTypes/{diskType}", + // "response": { + // "$ref": "DiskType" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.regionDiskTypes.list": + +type RegionDiskTypesListCall struct { + s *Service + project string + region string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves a list of regional disk types available to the +// specified project. +func (r *RegionDiskTypesService) List(project string, region string) *RegionDiskTypesListCall { + c := &RegionDiskTypesListCall{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 *RegionDiskTypesListCall) Filter(filter string) *RegionDiskTypesListCall { + 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 *RegionDiskTypesListCall) MaxResults(maxResults int64) *RegionDiskTypesListCall { + 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 *RegionDiskTypesListCall) OrderBy(orderBy string) *RegionDiskTypesListCall { + 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 *RegionDiskTypesListCall) PageToken(pageToken string) *RegionDiskTypesListCall { + 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 *RegionDiskTypesListCall) Fields(s ...googleapi.Field) *RegionDiskTypesListCall { + 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 *RegionDiskTypesListCall) IfNoneMatch(entityTag string) *RegionDiskTypesListCall { + 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 *RegionDiskTypesListCall) Context(ctx context.Context) *RegionDiskTypesListCall { + 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 *RegionDiskTypesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDiskTypesListCall) 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}/regions/{region}/diskTypes") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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.regionDiskTypes.list" call. +// Exactly one of *RegionDiskTypeList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *RegionDiskTypeList.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 *RegionDiskTypesListCall) Do(opts ...googleapi.CallOption) (*RegionDiskTypeList, 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 := &RegionDiskTypeList{ + 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 regional disk types available to the specified project.", + // "httpMethod": "GET", + // "id": "compute.regionDiskTypes.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}/diskTypes", + // "response": { + // "$ref": "RegionDiskTypeList" + // }, + // "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 *RegionDiskTypesListCall) Pages(ctx context.Context, f func(*RegionDiskTypeList) 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.regionDisks.createSnapshot": + +type RegionDisksCreateSnapshotCall struct { + s *Service + project string + region string + disk string + snapshot *Snapshot + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// CreateSnapshot: Creates a snapshot of this regional disk. +func (r *RegionDisksService) CreateSnapshot(project string, region string, disk string, snapshot *Snapshot) *RegionDisksCreateSnapshotCall { + c := &RegionDisksCreateSnapshotCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.disk = disk + c.snapshot = snapshot + 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 *RegionDisksCreateSnapshotCall) RequestId(requestId string) *RegionDisksCreateSnapshotCall { + 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 *RegionDisksCreateSnapshotCall) Fields(s ...googleapi.Field) *RegionDisksCreateSnapshotCall { + 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 *RegionDisksCreateSnapshotCall) Context(ctx context.Context) *RegionDisksCreateSnapshotCall { + 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 *RegionDisksCreateSnapshotCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksCreateSnapshotCall) 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.snapshot) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/createSnapshot") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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.createSnapshot" 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 *RegionDisksCreateSnapshotCall) 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 snapshot of this regional disk.", + // "httpMethod": "POST", + // "id": "compute.regionDisks.createSnapshot", + // "parameterOrder": [ + // "project", + // "region", + // "disk" + // ], + // "parameters": { + // "disk": { + // "description": "Name of the regional persistent disk to snapshot.", + // "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": "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}/createSnapshot", + // "request": { + // "$ref": "Snapshot" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionDisks.delete": + +type RegionDisksDeleteCall struct { + s *Service + project string + region string + disk string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified regional persistent disk. Deleting a +// regional disk removes all the replicas of its data permanently and is +// irreversible. However, deleting a disk does not delete any snapshots +// previously made from the disk. You must separately delete snapshots. +func (r *RegionDisksService) Delete(project string, region string, disk string) *RegionDisksDeleteCall { + c := &RegionDisksDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.disk = disk + 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 *RegionDisksDeleteCall) RequestId(requestId string) *RegionDisksDeleteCall { + 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 *RegionDisksDeleteCall) Fields(s ...googleapi.Field) *RegionDisksDeleteCall { + 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 *RegionDisksDeleteCall) Context(ctx context.Context) *RegionDisksDeleteCall { + 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 *RegionDisksDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksDeleteCall) 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}/regions/{region}/disks/{disk}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", urls, body) + 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.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 *RegionDisksDeleteCall) 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 regional persistent disk. Deleting a regional disk removes all the replicas of its data permanently and is irreversible. However, deleting a disk does not delete any snapshots previously made from the disk. You must separately delete snapshots.", + // "httpMethod": "DELETE", + // "id": "compute.regionDisks.delete", + // "parameterOrder": [ + // "project", + // "region", + // "disk" + // ], + // "parameters": { + // "disk": { + // "description": "Name of the regional persistent disk to delete.", + // "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 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}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionDisks.get": + +type RegionDisksGetCall struct { + s *Service + project string + region string + disk string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns a specified regional persistent disk. +func (r *RegionDisksService) Get(project string, region string, disk string) *RegionDisksGetCall { + c := &RegionDisksGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.disk = disk + 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 *RegionDisksGetCall) Fields(s ...googleapi.Field) *RegionDisksGetCall { + 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 *RegionDisksGetCall) IfNoneMatch(entityTag string) *RegionDisksGetCall { + 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 *RegionDisksGetCall) Context(ctx context.Context) *RegionDisksGetCall { + 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 *RegionDisksGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksGetCall) 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}/regions/{region}/disks/{disk}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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.get" call. +// Exactly one of *Disk or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Disk.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 *RegionDisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, 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 := &Disk{ + 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 a specified regional persistent disk.", + // "httpMethod": "GET", + // "id": "compute.regionDisks.get", + // "parameterOrder": [ + // "project", + // "region", + // "disk" + // ], + // "parameters": { + // "disk": { + // "description": "Name of the regional persistent disk 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": "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}/disks/{disk}", + // "response": { + // "$ref": "Disk" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.regionDisks.insert": + +type RegionDisksInsertCall struct { + s *Service + project string + region string + disk *Disk + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a persistent regional disk in the specified project +// using the data included in the request. +func (r *RegionDisksService) Insert(project string, region string, disk *Disk) *RegionDisksInsertCall { + c := &RegionDisksInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.disk = disk + 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 *RegionDisksInsertCall) RequestId(requestId string) *RegionDisksInsertCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// SourceImage sets the optional parameter "sourceImage": Source image +// to restore onto a disk. +func (c *RegionDisksInsertCall) SourceImage(sourceImage string) *RegionDisksInsertCall { + c.urlParams_.Set("sourceImage", sourceImage) + 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 *RegionDisksInsertCall) Fields(s ...googleapi.Field) *RegionDisksInsertCall { + 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 *RegionDisksInsertCall) Context(ctx context.Context) *RegionDisksInsertCall { + 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 *RegionDisksInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksInsertCall) 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.disk) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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.regionDisks.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 *RegionDisksInsertCall) 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 persistent regional disk in the specified project using the data included in the request.", + // "httpMethod": "POST", + // "id": "compute.regionDisks.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" + // }, + // "sourceImage": { + // "description": "Optional. Source image to restore onto a disk.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/disks", + // "request": { + // "$ref": "Disk" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionDisks.list": + +type RegionDisksListCall struct { + s *Service + project string + region string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves the list of persistent disks contained within the +// specified region. +func (r *RegionDisksService) List(project string, region string) *RegionDisksListCall { + c := &RegionDisksListCall{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 *RegionDisksListCall) Filter(filter string) *RegionDisksListCall { + 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 *RegionDisksListCall) MaxResults(maxResults int64) *RegionDisksListCall { + 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 *RegionDisksListCall) OrderBy(orderBy string) *RegionDisksListCall { + 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 *RegionDisksListCall) PageToken(pageToken string) *RegionDisksListCall { + 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 *RegionDisksListCall) Fields(s ...googleapi.Field) *RegionDisksListCall { + 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 *RegionDisksListCall) IfNoneMatch(entityTag string) *RegionDisksListCall { + 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 *RegionDisksListCall) Context(ctx context.Context) *RegionDisksListCall { + 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 *RegionDisksListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksListCall) 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}/regions/{region}/disks") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + 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.regionDisks.list" call. +// Exactly one of *DiskList or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *DiskList.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 *RegionDisksListCall) Do(opts ...googleapi.CallOption) (*DiskList, 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 := &DiskList{ + 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 persistent disks contained within the specified region.", + // "httpMethod": "GET", + // "id": "compute.regionDisks.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}/disks", + // "response": { + // "$ref": "DiskList" + // }, + // "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 *RegionDisksListCall) Pages(ctx context.Context, f func(*DiskList) 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.regionDisks.resize": + +type RegionDisksResizeCall struct { + s *Service + project string + region string + disk string + regiondisksresizerequest *RegionDisksResizeRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Resize: Resizes the specified regional persistent disk. +func (r *RegionDisksService) Resize(project string, region string, disk string, regiondisksresizerequest *RegionDisksResizeRequest) *RegionDisksResizeCall { + c := &RegionDisksResizeCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.disk = disk + c.regiondisksresizerequest = regiondisksresizerequest + 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 *RegionDisksResizeCall) RequestId(requestId string) *RegionDisksResizeCall { + 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 *RegionDisksResizeCall) Fields(s ...googleapi.Field) *RegionDisksResizeCall { + 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 *RegionDisksResizeCall) Context(ctx context.Context) *RegionDisksResizeCall { + 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 *RegionDisksResizeCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksResizeCall) 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.regiondisksresizerequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/resize") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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.resize" 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 *RegionDisksResizeCall) 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": "Resizes the specified regional persistent disk.", + // "httpMethod": "POST", + // "id": "compute.regionDisks.resize", + // "parameterOrder": [ + // "project", + // "region", + // "disk" + // ], + // "parameters": { + // "disk": { + // "description": "Name of the regional persistent disk.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "The project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{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}/disks/{disk}/resize", + // "request": { + // "$ref": "RegionDisksResizeRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionDisks.setLabels": + +type RegionDisksSetLabelsCall struct { + s *Service + project string + region string + resource string + regionsetlabelsrequest *RegionSetLabelsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetLabels: Sets the labels on the target regional disk. +func (r *RegionDisksService) SetLabels(project string, region string, resource string, regionsetlabelsrequest *RegionSetLabelsRequest) *RegionDisksSetLabelsCall { + c := &RegionDisksSetLabelsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resource = resource + c.regionsetlabelsrequest = regionsetlabelsrequest + 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 *RegionDisksSetLabelsCall) RequestId(requestId string) *RegionDisksSetLabelsCall { + 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 *RegionDisksSetLabelsCall) Fields(s ...googleapi.Field) *RegionDisksSetLabelsCall { + 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 *RegionDisksSetLabelsCall) Context(ctx context.Context) *RegionDisksSetLabelsCall { + 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 *RegionDisksSetLabelsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksSetLabelsCall) 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.regionsetlabelsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{resource}/setLabels") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + 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.regionDisks.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 *RegionDisksSetLabelsCall) 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 the target regional disk.", + // "httpMethod": "POST", + // "id": "compute.regionDisks.setLabels", + // "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 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" + // }, + // "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" + // } + // }, + // "path": "{project}/regions/{region}/disks/{resource}/setLabels", + // "request": { + // "$ref": "RegionSetLabelsRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionDisks.testIamPermissions": + +type RegionDisksTestIamPermissionsCall 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 *RegionDisksService) TestIamPermissions(project string, region string, resource string, testpermissionsrequest *TestPermissionsRequest) *RegionDisksTestIamPermissionsCall { + c := &RegionDisksTestIamPermissionsCall{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 *RegionDisksTestIamPermissionsCall) Fields(s ...googleapi.Field) *RegionDisksTestIamPermissionsCall { + 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 *RegionDisksTestIamPermissionsCall) Context(ctx context.Context) *RegionDisksTestIamPermissionsCall { + 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 *RegionDisksTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksTestIamPermissionsCall) 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}/regions/{region}/disks/{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, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionDisks.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 *RegionDisksTestIamPermissionsCall) 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.regionDisks.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 of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/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.regionInstanceGroupManagers.abandonInstances": type RegionInstanceGroupManagersAbandonInstancesCall struct { @@ -61480,32 +65758,28 @@ func (r *RegionInstanceGroupManagersService) List(project string, region string) return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionInstanceGroupManagersListCall) Filter(filter string) *RegionInstanceGroupManagersListCall { c.urlParams_.Set("filter", filter) return c @@ -61651,7 +65925,7 @@ func (c *RegionInstanceGroupManagersListCall) Do(opts ...googleapi.CallOption) ( // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -62841,32 +67115,28 @@ func (r *RegionInstanceGroupsService) List(project string, region string) *Regio return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionInstanceGroupsListCall) Filter(filter string) *RegionInstanceGroupsListCall { c.urlParams_.Set("filter", filter) return c @@ -63012,7 +67282,7 @@ func (c *RegionInstanceGroupsListCall) Do(opts ...googleapi.CallOption) (*Region // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -63108,32 +67378,28 @@ func (r *RegionInstanceGroupsService) ListInstances(project string, region strin return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionInstanceGroupsListInstancesCall) Filter(filter string) *RegionInstanceGroupsListInstancesCall { c.urlParams_.Set("filter", filter) return c @@ -63274,7 +67540,7 @@ func (c *RegionInstanceGroupsListInstancesCall) Do(opts ...googleapi.CallOption) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -63838,32 +68104,28 @@ func (r *RegionOperationsService) List(project string, region string) *RegionOpe return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionOperationsListCall) Filter(filter string) *RegionOperationsListCall { c.urlParams_.Set("filter", filter) return c @@ -64009,7 +68271,7 @@ func (c *RegionOperationsListCall) Do(opts ...googleapi.CallOption) (*OperationL // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -64092,7 +68354,7 @@ type RegionsGetCall struct { header_ http.Header } -// Get: Returns the specified Region resource. Get a list of available +// Get: Returns the specified Region resource. Gets a list of available // regions by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/regions/get func (r *RegionsService) Get(project string, region string) *RegionsGetCall { @@ -64197,7 +68459,7 @@ func (c *RegionsGetCall) Do(opts ...googleapi.CallOption) (*Region, error) { } return ret, nil // { - // "description": "Returns the specified Region resource. Get a list of available regions by making a list() request.", + // "description": "Returns the specified Region resource. Gets a list of available regions by making a list() request.", // "httpMethod": "GET", // "id": "compute.regions.get", // "parameterOrder": [ @@ -64253,32 +68515,28 @@ func (r *RegionsService) List(project string) *RegionsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RegionsListCall) Filter(filter string) *RegionsListCall { c.urlParams_.Set("filter", filter) return c @@ -64422,7 +68680,7 @@ func (c *RegionsListCall) Do(opts ...googleapi.CallOption) (*RegionList, error) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -64504,32 +68762,28 @@ func (r *RoutersService) AggregatedList(project string) *RoutersAggregatedListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RoutersAggregatedListCall) Filter(filter string) *RoutersAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -64673,7 +68927,7 @@ func (c *RoutersAggregatedListCall) Do(opts ...googleapi.CallOption) (*RouterAgg // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -64921,7 +69175,7 @@ type RoutersGetCall struct { header_ http.Header } -// Get: Returns the specified Router resource. Get a list of available +// Get: Returns the specified Router resource. Gets a list of available // routers by making a list() request. func (r *RoutersService) Get(project string, region string, router string) *RoutersGetCall { c := &RoutersGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -65027,7 +69281,7 @@ func (c *RoutersGetCall) Do(opts ...googleapi.CallOption) (*Router, error) { } return ret, nil // { - // "description": "Returns the specified Router resource. Get a list of available routers by making a list() request.", + // "description": "Returns the specified Router resource. Gets a list of available routers by making a list() request.", // "httpMethod": "GET", // "id": "compute.routers.get", // "parameterOrder": [ @@ -65426,32 +69680,28 @@ func (r *RoutersService) List(project string, region string) *RoutersListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RoutersListCall) Filter(filter string) *RoutersListCall { c.urlParams_.Set("filter", filter) return c @@ -65597,7 +69847,7 @@ func (c *RoutersListCall) Do(opts ...googleapi.CallOption) (*RouterList, error) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -66366,7 +70616,7 @@ type RoutesGetCall struct { header_ http.Header } -// Get: Returns the specified Route resource. Get a list of available +// Get: Returns the specified Route resource. Gets a list of available // routes by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/routes/get func (r *RoutesService) Get(project string, route string) *RoutesGetCall { @@ -66471,7 +70721,7 @@ func (c *RoutesGetCall) Do(opts ...googleapi.CallOption) (*Route, error) { } return ret, nil // { - // "description": "Returns the specified Route resource. Get a list of available routes by making a list() request.", + // "description": "Returns the specified Route resource. Gets a list of available routes by making a list() request.", // "httpMethod": "GET", // "id": "compute.routes.get", // "parameterOrder": [ @@ -66688,32 +70938,28 @@ func (r *RoutesService) List(project string) *RoutesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *RoutesListCall) Filter(filter string) *RoutesListCall { c.urlParams_.Set("filter", filter) return c @@ -66857,7 +71103,7 @@ func (c *RoutesListCall) Do(opts ...googleapi.CallOption) (*RouteList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -67100,8 +71346,8 @@ type SnapshotsGetCall struct { header_ http.Header } -// Get: Returns the specified Snapshot resource. Get a list of available -// snapshots by making a list() request. +// Get: Returns the specified Snapshot resource. Gets a list of +// available snapshots by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/snapshots/get func (r *SnapshotsService) Get(project string, snapshot string) *SnapshotsGetCall { c := &SnapshotsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -67205,7 +71451,7 @@ func (c *SnapshotsGetCall) Do(opts ...googleapi.CallOption) (*Snapshot, error) { } return ret, nil // { - // "description": "Returns the specified Snapshot resource. Get a list of available snapshots by making a list() request.", + // "description": "Returns the specified Snapshot resource. Gets a list of available snapshots by making a list() request.", // "httpMethod": "GET", // "id": "compute.snapshots.get", // "parameterOrder": [ @@ -67261,32 +71507,28 @@ func (r *SnapshotsService) List(project string) *SnapshotsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SnapshotsListCall) Filter(filter string) *SnapshotsListCall { c.urlParams_.Set("filter", filter) return c @@ -67430,7 +71672,7 @@ func (c *SnapshotsListCall) Do(opts ...googleapi.CallOption) (*SnapshotList, err // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -67813,7 +72055,7 @@ type SslCertificatesGetCall struct { header_ http.Header } -// Get: Returns the specified SslCertificate resource. Get a list of +// Get: Returns the specified SslCertificate resource. Gets a list of // available SSL certificates by making a list() request. func (r *SslCertificatesService) Get(project string, sslCertificate string) *SslCertificatesGetCall { c := &SslCertificatesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -67917,7 +72159,7 @@ func (c *SslCertificatesGetCall) Do(opts ...googleapi.CallOption) (*SslCertifica } return ret, nil // { - // "description": "Returns the specified SslCertificate resource. Get a list of available SSL certificates by making a list() request.", + // "description": "Returns the specified SslCertificate resource. Gets a list of available SSL certificates by making a list() request.", // "httpMethod": "GET", // "id": "compute.sslCertificates.get", // "parameterOrder": [ @@ -68132,32 +72374,28 @@ func (r *SslCertificatesService) List(project string) *SslCertificatesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SslCertificatesListCall) Filter(filter string) *SslCertificatesListCall { c.urlParams_.Set("filter", filter) return c @@ -68301,7 +72539,7 @@ func (c *SslCertificatesListCall) Do(opts ...googleapi.CallOption) (*SslCertific // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -68365,6 +72603,1125 @@ func (c *SslCertificatesListCall) Pages(ctx context.Context, f func(*SslCertific } } +// method id "compute.sslPolicies.delete": + +type SslPoliciesDeleteCall struct { + s *Service + project string + sslPolicy string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified SSL policy. The SSL policy resource can +// be deleted only if it is not in use by any TargetHttpsProxy or +// TargetSslProxy resources. +func (r *SslPoliciesService) Delete(project string, sslPolicy string) *SslPoliciesDeleteCall { + c := &SslPoliciesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.sslPolicy = sslPolicy + 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 *SslPoliciesDeleteCall) RequestId(requestId string) *SslPoliciesDeleteCall { + 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 *SslPoliciesDeleteCall) Fields(s ...googleapi.Field) *SslPoliciesDeleteCall { + 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 *SslPoliciesDeleteCall) Context(ctx context.Context) *SslPoliciesDeleteCall { + 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 *SslPoliciesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SslPoliciesDeleteCall) 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}/global/sslPolicies/{sslPolicy}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "sslPolicy": c.sslPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.sslPolicies.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 *SslPoliciesDeleteCall) 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 SSL policy. The SSL policy resource can be deleted only if it is not in use by any TargetHttpsProxy or TargetSslProxy resources.", + // "httpMethod": "DELETE", + // "id": "compute.sslPolicies.delete", + // "parameterOrder": [ + // "project", + // "sslPolicy" + // ], + // "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" + // }, + // "sslPolicy": { + // "description": "Name of the SSL policy to delete. The name must be 1-63 characters long, and comply with RFC1035.", + // "location": "path", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/sslPolicies/{sslPolicy}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.sslPolicies.get": + +type SslPoliciesGetCall struct { + s *Service + project string + sslPolicy string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Lists all of the ordered rules present in a single specified +// policy. +func (r *SslPoliciesService) Get(project string, sslPolicy string) *SslPoliciesGetCall { + c := &SslPoliciesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.sslPolicy = sslPolicy + 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 *SslPoliciesGetCall) Fields(s ...googleapi.Field) *SslPoliciesGetCall { + 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 *SslPoliciesGetCall) IfNoneMatch(entityTag string) *SslPoliciesGetCall { + 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 *SslPoliciesGetCall) Context(ctx context.Context) *SslPoliciesGetCall { + 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 *SslPoliciesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SslPoliciesGetCall) 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}/global/sslPolicies/{sslPolicy}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "sslPolicy": c.sslPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.sslPolicies.get" call. +// Exactly one of *SslPolicy or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *SslPolicy.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 *SslPoliciesGetCall) Do(opts ...googleapi.CallOption) (*SslPolicy, 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 := &SslPolicy{ + 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 all of the ordered rules present in a single specified policy.", + // "httpMethod": "GET", + // "id": "compute.sslPolicies.get", + // "parameterOrder": [ + // "project", + // "sslPolicy" + // ], + // "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" + // }, + // "sslPolicy": { + // "description": "Name of the SSL policy to update. The name must be 1-63 characters long, and comply with RFC1035.", + // "location": "path", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/sslPolicies/{sslPolicy}", + // "response": { + // "$ref": "SslPolicy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.sslPolicies.insert": + +type SslPoliciesInsertCall struct { + s *Service + project string + sslpolicy *SslPolicy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Returns the specified SSL policy resource. Gets a list of +// available SSL policies by making a list() request. +func (r *SslPoliciesService) Insert(project string, sslpolicy *SslPolicy) *SslPoliciesInsertCall { + c := &SslPoliciesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.sslpolicy = sslpolicy + 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 *SslPoliciesInsertCall) RequestId(requestId string) *SslPoliciesInsertCall { + 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 *SslPoliciesInsertCall) Fields(s ...googleapi.Field) *SslPoliciesInsertCall { + 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 *SslPoliciesInsertCall) Context(ctx context.Context) *SslPoliciesInsertCall { + 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 *SslPoliciesInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SslPoliciesInsertCall) 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.sslpolicy) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", 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.sslPolicies.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 *SslPoliciesInsertCall) 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": "Returns the specified SSL policy resource. Gets a list of available SSL policies by making a list() request.", + // "httpMethod": "POST", + // "id": "compute.sslPolicies.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/sslPolicies", + // "request": { + // "$ref": "SslPolicy" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.sslPolicies.list": + +type SslPoliciesListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists all the SSL policies that have been configured for the +// specified project. +func (r *SslPoliciesService) List(project string) *SslPoliciesListCall { + c := &SslPoliciesListCall{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 *SslPoliciesListCall) Filter(filter string) *SslPoliciesListCall { + 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 *SslPoliciesListCall) MaxResults(maxResults int64) *SslPoliciesListCall { + 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 *SslPoliciesListCall) OrderBy(orderBy string) *SslPoliciesListCall { + 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 *SslPoliciesListCall) PageToken(pageToken string) *SslPoliciesListCall { + 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 *SslPoliciesListCall) Fields(s ...googleapi.Field) *SslPoliciesListCall { + 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 *SslPoliciesListCall) IfNoneMatch(entityTag string) *SslPoliciesListCall { + 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 *SslPoliciesListCall) Context(ctx context.Context) *SslPoliciesListCall { + 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 *SslPoliciesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SslPoliciesListCall) 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}/global/sslPolicies") + 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.sslPolicies.list" call. +// Exactly one of *SslPoliciesList or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *SslPoliciesList.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 *SslPoliciesListCall) Do(opts ...googleapi.CallOption) (*SslPoliciesList, 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 := &SslPoliciesList{ + 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 all the SSL policies that have been configured for the specified project.", + // "httpMethod": "GET", + // "id": "compute.sslPolicies.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/sslPolicies", + // "response": { + // "$ref": "SslPoliciesList" + // }, + // "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 *SslPoliciesListCall) Pages(ctx context.Context, f func(*SslPoliciesList) 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.sslPolicies.listAvailableFeatures": + +type SslPoliciesListAvailableFeaturesCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// ListAvailableFeatures: Lists all features that can be specified in +// the SSL policy when using custom profile. +func (r *SslPoliciesService) ListAvailableFeatures(project string) *SslPoliciesListAvailableFeaturesCall { + c := &SslPoliciesListAvailableFeaturesCall{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 *SslPoliciesListAvailableFeaturesCall) Filter(filter string) *SslPoliciesListAvailableFeaturesCall { + 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 *SslPoliciesListAvailableFeaturesCall) MaxResults(maxResults int64) *SslPoliciesListAvailableFeaturesCall { + 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 *SslPoliciesListAvailableFeaturesCall) OrderBy(orderBy string) *SslPoliciesListAvailableFeaturesCall { + 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 *SslPoliciesListAvailableFeaturesCall) PageToken(pageToken string) *SslPoliciesListAvailableFeaturesCall { + 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 *SslPoliciesListAvailableFeaturesCall) Fields(s ...googleapi.Field) *SslPoliciesListAvailableFeaturesCall { + 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 *SslPoliciesListAvailableFeaturesCall) IfNoneMatch(entityTag string) *SslPoliciesListAvailableFeaturesCall { + 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 *SslPoliciesListAvailableFeaturesCall) Context(ctx context.Context) *SslPoliciesListAvailableFeaturesCall { + 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 *SslPoliciesListAvailableFeaturesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SslPoliciesListAvailableFeaturesCall) 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}/global/sslPolicies/listAvailableFeatures") + 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.sslPolicies.listAvailableFeatures" call. +// Exactly one of *SslPoliciesListAvailableFeaturesResponse or error +// will be non-nil. Any non-2xx status code is an error. Response +// headers are in either +// *SslPoliciesListAvailableFeaturesResponse.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 *SslPoliciesListAvailableFeaturesCall) Do(opts ...googleapi.CallOption) (*SslPoliciesListAvailableFeaturesResponse, 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 := &SslPoliciesListAvailableFeaturesResponse{ + 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 all features that can be specified in the SSL policy when using custom profile.", + // "httpMethod": "GET", + // "id": "compute.sslPolicies.listAvailableFeatures", + // "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/sslPolicies/listAvailableFeatures", + // "response": { + // "$ref": "SslPoliciesListAvailableFeaturesResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.sslPolicies.patch": + +type SslPoliciesPatchCall struct { + s *Service + project string + sslPolicy string + sslpolicy *SslPolicy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Patches the specified SSL policy with the data included in the +// request. +func (r *SslPoliciesService) Patch(project string, sslPolicy string, sslpolicy *SslPolicy) *SslPoliciesPatchCall { + c := &SslPoliciesPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.sslPolicy = sslPolicy + c.sslpolicy = sslpolicy + 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 *SslPoliciesPatchCall) RequestId(requestId string) *SslPoliciesPatchCall { + 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 *SslPoliciesPatchCall) Fields(s ...googleapi.Field) *SslPoliciesPatchCall { + 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 *SslPoliciesPatchCall) Context(ctx context.Context) *SslPoliciesPatchCall { + 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 *SslPoliciesPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SslPoliciesPatchCall) 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.sslpolicy) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{sslPolicy}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PATCH", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "sslPolicy": c.sslPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.sslPolicies.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 *SslPoliciesPatchCall) 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 SSL policy with the data included in the request.", + // "httpMethod": "PATCH", + // "id": "compute.sslPolicies.patch", + // "parameterOrder": [ + // "project", + // "sslPolicy" + // ], + // "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" + // }, + // "sslPolicy": { + // "description": "Name of the SSL policy to update. The name must be 1-63 characters long, and comply with RFC1035.", + // "location": "path", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/sslPolicies/{sslPolicy}", + // "request": { + // "$ref": "SslPolicy" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.subnetworks.aggregatedList": type SubnetworksAggregatedListCall struct { @@ -68383,32 +73740,28 @@ func (r *SubnetworksService) AggregatedList(project string) *SubnetworksAggregat return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SubnetworksAggregatedListCall) Filter(filter string) *SubnetworksAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -68552,7 +73905,7 @@ func (c *SubnetworksAggregatedListCall) Do(opts ...googleapi.CallOption) (*Subne // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -68982,7 +74335,7 @@ type SubnetworksGetCall struct { header_ http.Header } -// Get: Returns the specified subnetwork. Get a list of available +// Get: Returns the specified subnetwork. Gets a list of available // subnetworks list() request. func (r *SubnetworksService) Get(project string, region string, subnetwork string) *SubnetworksGetCall { c := &SubnetworksGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -69088,7 +74441,7 @@ func (c *SubnetworksGetCall) Do(opts ...googleapi.CallOption) (*Subnetwork, erro } return ret, nil // { - // "description": "Returns the specified subnetwork. Get a list of available subnetworks list() request.", + // "description": "Returns the specified subnetwork. Gets a list of available subnetworks list() request.", // "httpMethod": "GET", // "id": "compute.subnetworks.get", // "parameterOrder": [ @@ -69324,32 +74677,28 @@ func (r *SubnetworksService) List(project string, region string) *SubnetworksLis return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *SubnetworksListCall) Filter(filter string) *SubnetworksListCall { c.urlParams_.Set("filter", filter) return c @@ -69495,7 +74844,7 @@ func (c *SubnetworksListCall) Do(opts ...googleapi.CallOption) (*SubnetworkList, // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -69581,9 +74930,10 @@ 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 and -// allow_subnet_cidr_routes_overlap. It is also mandatory to specify the -// current fingeprint of the subnetwork resource being patched. +// 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. 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 @@ -69700,7 +75050,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 and allow_subnet_cidr_routes_overlap. 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 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.", // "httpMethod": "PATCH", // "id": "compute.subnetworks.patch", // "parameterOrder": [ @@ -70107,7 +75457,7 @@ type TargetHttpProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetHttpProxy resource. Get a list of +// Get: Returns the specified TargetHttpProxy resource. Gets a list of // available target HTTP proxies by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/targetHttpProxies/get func (r *TargetHttpProxiesService) Get(project string, targetHttpProxy string) *TargetHttpProxiesGetCall { @@ -70212,7 +75562,7 @@ func (c *TargetHttpProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetHttp } return ret, nil // { - // "description": "Returns the specified TargetHttpProxy resource. Get a list of available target HTTP proxies by making a list() request.", + // "description": "Returns the specified TargetHttpProxy resource. Gets a list of available target HTTP proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetHttpProxies.get", // "parameterOrder": [ @@ -70429,32 +75779,28 @@ func (r *TargetHttpProxiesService) List(project string) *TargetHttpProxiesListCa return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetHttpProxiesListCall) Filter(filter string) *TargetHttpProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -70598,7 +75944,7 @@ func (c *TargetHttpProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetHtt // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -71005,7 +76351,7 @@ type TargetHttpsProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetHttpsProxy resource. Get a list of +// Get: Returns the specified TargetHttpsProxy resource. Gets a list of // available target HTTPS proxies by making a list() request. func (r *TargetHttpsProxiesService) Get(project string, targetHttpsProxy string) *TargetHttpsProxiesGetCall { c := &TargetHttpsProxiesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -71109,7 +76455,7 @@ func (c *TargetHttpsProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetHtt } return ret, nil // { - // "description": "Returns the specified TargetHttpsProxy resource. Get a list of available target HTTPS proxies by making a list() request.", + // "description": "Returns the specified TargetHttpsProxy resource. Gets a list of available target HTTPS proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetHttpsProxies.get", // "parameterOrder": [ @@ -71324,32 +76670,28 @@ func (r *TargetHttpsProxiesService) List(project string) *TargetHttpsProxiesList return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetHttpsProxiesListCall) Filter(filter string) *TargetHttpsProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -71493,7 +76835,7 @@ func (c *TargetHttpsProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetHt // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -71557,6 +76899,175 @@ func (c *TargetHttpsProxiesListCall) Pages(ctx context.Context, f func(*TargetHt } } +// method id "compute.targetHttpsProxies.setQuicOverride": + +type TargetHttpsProxiesSetQuicOverrideCall struct { + s *Service + project string + targetHttpsProxy string + targethttpsproxiessetquicoverriderequest *TargetHttpsProxiesSetQuicOverrideRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetQuicOverride: Sets the QUIC override policy for TargetHttpsProxy. +func (r *TargetHttpsProxiesService) SetQuicOverride(project string, targetHttpsProxy string, targethttpsproxiessetquicoverriderequest *TargetHttpsProxiesSetQuicOverrideRequest) *TargetHttpsProxiesSetQuicOverrideCall { + c := &TargetHttpsProxiesSetQuicOverrideCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.targetHttpsProxy = targetHttpsProxy + c.targethttpsproxiessetquicoverriderequest = targethttpsproxiessetquicoverriderequest + 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 *TargetHttpsProxiesSetQuicOverrideCall) RequestId(requestId string) *TargetHttpsProxiesSetQuicOverrideCall { + 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 *TargetHttpsProxiesSetQuicOverrideCall) Fields(s ...googleapi.Field) *TargetHttpsProxiesSetQuicOverrideCall { + 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 *TargetHttpsProxiesSetQuicOverrideCall) Context(ctx context.Context) *TargetHttpsProxiesSetQuicOverrideCall { + 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 *TargetHttpsProxiesSetQuicOverrideCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *TargetHttpsProxiesSetQuicOverrideCall) 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.targethttpsproxiessetquicoverriderequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setQuicOverride") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "targetHttpsProxy": c.targetHttpsProxy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.targetHttpsProxies.setQuicOverride" 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 *TargetHttpsProxiesSetQuicOverrideCall) 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 QUIC override policy for TargetHttpsProxy.", + // "httpMethod": "POST", + // "id": "compute.targetHttpsProxies.setQuicOverride", + // "parameterOrder": [ + // "project", + // "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" + // }, + // "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 the QUIC override policy for. The name should conform to RFC1035.", + // "location": "path", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setQuicOverride", + // "request": { + // "$ref": "TargetHttpsProxiesSetQuicOverrideRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.targetHttpsProxies.setSslCertificates": type TargetHttpsProxiesSetSslCertificatesCall struct { @@ -71727,6 +77238,179 @@ func (c *TargetHttpsProxiesSetSslCertificatesCall) Do(opts ...googleapi.CallOpti } +// method id "compute.targetHttpsProxies.setSslPolicy": + +type TargetHttpsProxiesSetSslPolicyCall struct { + s *Service + project string + targetHttpsProxy string + sslpolicyreference *SslPolicyReference + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetSslPolicy: Sets the SSL policy for TargetHttpsProxy. The SSL +// policy specifies the server-side support for SSL features. This +// affects connections between clients and the HTTPS proxy load +// balancer. They do not affect the connection between the load balancer +// and the backends. +func (r *TargetHttpsProxiesService) SetSslPolicy(project string, targetHttpsProxy string, sslpolicyreference *SslPolicyReference) *TargetHttpsProxiesSetSslPolicyCall { + c := &TargetHttpsProxiesSetSslPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.targetHttpsProxy = targetHttpsProxy + c.sslpolicyreference = sslpolicyreference + 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 *TargetHttpsProxiesSetSslPolicyCall) RequestId(requestId string) *TargetHttpsProxiesSetSslPolicyCall { + 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 *TargetHttpsProxiesSetSslPolicyCall) Fields(s ...googleapi.Field) *TargetHttpsProxiesSetSslPolicyCall { + 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 *TargetHttpsProxiesSetSslPolicyCall) Context(ctx context.Context) *TargetHttpsProxiesSetSslPolicyCall { + 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 *TargetHttpsProxiesSetSslPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *TargetHttpsProxiesSetSslPolicyCall) 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.sslpolicyreference) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setSslPolicy") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "targetHttpsProxy": c.targetHttpsProxy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.targetHttpsProxies.setSslPolicy" 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 *TargetHttpsProxiesSetSslPolicyCall) 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 SSL policy for TargetHttpsProxy. The SSL policy specifies the server-side support for SSL features. This affects connections between clients and the HTTPS proxy load balancer. They do not affect the connection between the load balancer and the backends.", + // "httpMethod": "POST", + // "id": "compute.targetHttpsProxies.setSslPolicy", + // "parameterOrder": [ + // "project", + // "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" + // }, + // "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 whose SSL policy is to be set. The name must be 1-63 characters long, and comply with RFC1035.", + // "location": "path", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setSslPolicy", + // "request": { + // "$ref": "SslPolicyReference" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.targetHttpsProxies.setUrlMap": type TargetHttpsProxiesSetUrlMapCall struct { @@ -71916,32 +77600,28 @@ func (r *TargetInstancesService) AggregatedList(project string) *TargetInstances return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetInstancesAggregatedListCall) Filter(filter string) *TargetInstancesAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -72085,7 +77765,7 @@ func (c *TargetInstancesAggregatedListCall) Do(opts ...googleapi.CallOption) (*T // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -72334,7 +78014,7 @@ type TargetInstancesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetInstance resource. Get a list of +// Get: Returns the specified TargetInstance resource. Gets a list of // available target instances by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/targetInstances/get func (r *TargetInstancesService) Get(project string, zone string, targetInstance string) *TargetInstancesGetCall { @@ -72441,7 +78121,7 @@ func (c *TargetInstancesGetCall) Do(opts ...googleapi.CallOption) (*TargetInstan } return ret, nil // { - // "description": "Returns the specified TargetInstance resource. Get a list of available target instances by making a list() request.", + // "description": "Returns the specified TargetInstance resource. Gets a list of available target instances by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetInstances.get", // "parameterOrder": [ @@ -72679,32 +78359,28 @@ func (r *TargetInstancesService) List(project string, zone string) *TargetInstan return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetInstancesListCall) Filter(filter string) *TargetInstancesListCall { c.urlParams_.Set("filter", filter) return c @@ -72850,7 +78526,7 @@ func (c *TargetInstancesListCall) Do(opts ...googleapi.CallOption) (*TargetInsta // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -73304,32 +78980,28 @@ func (r *TargetPoolsService) AggregatedList(project string) *TargetPoolsAggregat return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetPoolsAggregatedListCall) Filter(filter string) *TargetPoolsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -73473,7 +79145,7 @@ func (c *TargetPoolsAggregatedListCall) Do(opts ...googleapi.CallOption) (*Targe // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -73722,7 +79394,7 @@ type TargetPoolsGetCall struct { header_ http.Header } -// Get: Returns the specified target pool. Get a list of available +// Get: Returns the specified target pool. Gets a list of available // target pools by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/targetPools/get func (r *TargetPoolsService) Get(project string, region string, targetPool string) *TargetPoolsGetCall { @@ -73829,7 +79501,7 @@ func (c *TargetPoolsGetCall) Do(opts ...googleapi.CallOption) (*TargetPool, erro } return ret, nil // { - // "description": "Returns the specified target pool. Get a list of available target pools by making a list() request.", + // "description": "Returns the specified target pool. Gets a list of available target pools by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetPools.get", // "parameterOrder": [ @@ -74227,32 +79899,28 @@ func (r *TargetPoolsService) List(project string, region string) *TargetPoolsLis return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetPoolsListCall) Filter(filter string) *TargetPoolsListCall { c.urlParams_.Set("filter", filter) return c @@ -74398,7 +80066,7 @@ func (c *TargetPoolsListCall) Do(opts ...googleapi.CallOption) (*TargetPoolList, // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -75200,7 +80868,7 @@ type TargetSslProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetSslProxy resource. Get a list of +// Get: Returns the specified TargetSslProxy resource. Gets a list of // available target SSL proxies by making a list() request. func (r *TargetSslProxiesService) Get(project string, targetSslProxy string) *TargetSslProxiesGetCall { c := &TargetSslProxiesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -75304,7 +80972,7 @@ func (c *TargetSslProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetSslPr } return ret, nil // { - // "description": "Returns the specified TargetSslProxy resource. Get a list of available target SSL proxies by making a list() request.", + // "description": "Returns the specified TargetSslProxy resource. Gets a list of available target SSL proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetSslProxies.get", // "parameterOrder": [ @@ -75519,32 +81187,28 @@ func (r *TargetSslProxiesService) List(project string) *TargetSslProxiesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetSslProxiesListCall) Filter(filter string) *TargetSslProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -75688,7 +81352,7 @@ func (c *TargetSslProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetSslP // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -76262,6 +81926,178 @@ func (c *TargetSslProxiesSetSslCertificatesCall) Do(opts ...googleapi.CallOption } +// method id "compute.targetSslProxies.setSslPolicy": + +type TargetSslProxiesSetSslPolicyCall struct { + s *Service + project string + targetSslProxy string + sslpolicyreference *SslPolicyReference + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetSslPolicy: Sets the SSL policy for TargetSslProxy. The SSL policy +// specifies the server-side support for SSL features. This affects +// connections between clients and the SSL proxy load balancer. They do +// not affect the connection between the load balancer and the backends. +func (r *TargetSslProxiesService) SetSslPolicy(project string, targetSslProxy string, sslpolicyreference *SslPolicyReference) *TargetSslProxiesSetSslPolicyCall { + c := &TargetSslProxiesSetSslPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.targetSslProxy = targetSslProxy + c.sslpolicyreference = sslpolicyreference + 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 *TargetSslProxiesSetSslPolicyCall) RequestId(requestId string) *TargetSslProxiesSetSslPolicyCall { + 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 *TargetSslProxiesSetSslPolicyCall) Fields(s ...googleapi.Field) *TargetSslProxiesSetSslPolicyCall { + 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 *TargetSslProxiesSetSslPolicyCall) Context(ctx context.Context) *TargetSslProxiesSetSslPolicyCall { + 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 *TargetSslProxiesSetSslPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *TargetSslProxiesSetSslPolicyCall) 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.sslpolicyreference) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setSslPolicy") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "targetSslProxy": c.targetSslProxy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.targetSslProxies.setSslPolicy" 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 *TargetSslProxiesSetSslPolicyCall) 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 SSL policy for TargetSslProxy. The SSL policy specifies the server-side support for SSL features. This affects connections between clients and the SSL proxy load balancer. They do not affect the connection between the load balancer and the backends.", + // "httpMethod": "POST", + // "id": "compute.targetSslProxies.setSslPolicy", + // "parameterOrder": [ + // "project", + // "targetSslProxy" + // ], + // "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" + // }, + // "targetSslProxy": { + // "description": "Name of the TargetSslProxy resource whose SSL policy is to be set. The name must be 1-63 characters long, and comply with RFC1035.", + // "location": "path", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/targetSslProxies/{targetSslProxy}/setSslPolicy", + // "request": { + // "$ref": "SslPolicyReference" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.targetTcpProxies.delete": type TargetTcpProxiesDeleteCall struct { @@ -76434,7 +82270,7 @@ type TargetTcpProxiesGetCall struct { header_ http.Header } -// Get: Returns the specified TargetTcpProxy resource. Get a list of +// Get: Returns the specified TargetTcpProxy resource. Gets a list of // available target TCP proxies by making a list() request. func (r *TargetTcpProxiesService) Get(project string, targetTcpProxy string) *TargetTcpProxiesGetCall { c := &TargetTcpProxiesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -76538,7 +82374,7 @@ func (c *TargetTcpProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetTcpPr } return ret, nil // { - // "description": "Returns the specified TargetTcpProxy resource. Get a list of available target TCP proxies by making a list() request.", + // "description": "Returns the specified TargetTcpProxy resource. Gets a list of available target TCP proxies by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetTcpProxies.get", // "parameterOrder": [ @@ -76753,32 +82589,28 @@ func (r *TargetTcpProxiesService) List(project string) *TargetTcpProxiesListCall return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetTcpProxiesListCall) Filter(filter string) *TargetTcpProxiesListCall { c.urlParams_.Set("filter", filter) return c @@ -76922,7 +82754,7 @@ func (c *TargetTcpProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetTcpP // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -77344,32 +83176,28 @@ func (r *TargetVpnGatewaysService) AggregatedList(project string) *TargetVpnGate return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetVpnGatewaysAggregatedListCall) Filter(filter string) *TargetVpnGatewaysAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -77513,7 +83341,7 @@ func (c *TargetVpnGatewaysAggregatedListCall) Do(opts ...googleapi.CallOption) ( // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -77761,7 +83589,7 @@ type TargetVpnGatewaysGetCall struct { header_ http.Header } -// Get: Returns the specified target VPN gateway. Get a list of +// Get: Returns the specified target VPN gateway. Gets a list of // available target VPN gateways by making a list() request. func (r *TargetVpnGatewaysService) Get(project string, region string, targetVpnGateway string) *TargetVpnGatewaysGetCall { c := &TargetVpnGatewaysGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -77867,7 +83695,7 @@ func (c *TargetVpnGatewaysGetCall) Do(opts ...googleapi.CallOption) (*TargetVpnG } return ret, nil // { - // "description": "Returns the specified target VPN gateway. Get a list of available target VPN gateways by making a list() request.", + // "description": "Returns the specified target VPN gateway. Gets a list of available target VPN gateways by making a list() request.", // "httpMethod": "GET", // "id": "compute.targetVpnGateways.get", // "parameterOrder": [ @@ -78103,32 +83931,28 @@ func (r *TargetVpnGatewaysService) List(project string, region string) *TargetVp return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *TargetVpnGatewaysListCall) Filter(filter string) *TargetVpnGatewaysListCall { c.urlParams_.Set("filter", filter) return c @@ -78274,7 +84098,7 @@ func (c *TargetVpnGatewaysListCall) Do(opts ...googleapi.CallOption) (*TargetVpn // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -78518,7 +84342,7 @@ type UrlMapsGetCall struct { header_ http.Header } -// Get: Returns the specified UrlMap resource. Get a list of available +// Get: Returns the specified UrlMap resource. Gets a list of available // URL maps by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/urlMaps/get func (r *UrlMapsService) Get(project string, urlMap string) *UrlMapsGetCall { @@ -78623,7 +84447,7 @@ func (c *UrlMapsGetCall) Do(opts ...googleapi.CallOption) (*UrlMap, error) { } return ret, nil // { - // "description": "Returns the specified UrlMap resource. Get a list of available URL maps by making a list() request.", + // "description": "Returns the specified UrlMap resource. Gets a list of available URL maps by making a list() request.", // "httpMethod": "GET", // "id": "compute.urlMaps.get", // "parameterOrder": [ @@ -79011,32 +84835,28 @@ func (r *UrlMapsService) List(project string) *UrlMapsListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *UrlMapsListCall) Filter(filter string) *UrlMapsListCall { c.urlParams_.Set("filter", filter) return c @@ -79180,7 +85000,7 @@ func (c *UrlMapsListCall) Do(opts ...googleapi.CallOption) (*UrlMapList, error) // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -79756,32 +85576,28 @@ func (r *VpnTunnelsService) AggregatedList(project string) *VpnTunnelsAggregated return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *VpnTunnelsAggregatedListCall) Filter(filter string) *VpnTunnelsAggregatedListCall { c.urlParams_.Set("filter", filter) return c @@ -79925,7 +85741,7 @@ func (c *VpnTunnelsAggregatedListCall) Do(opts ...googleapi.CallOption) (*VpnTun // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -80173,7 +85989,7 @@ type VpnTunnelsGetCall struct { header_ http.Header } -// Get: Returns the specified VpnTunnel resource. Get a list of +// Get: Returns the specified VpnTunnel resource. Gets a list of // available VPN tunnels by making a list() request. func (r *VpnTunnelsService) Get(project string, region string, vpnTunnel string) *VpnTunnelsGetCall { c := &VpnTunnelsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -80279,7 +86095,7 @@ func (c *VpnTunnelsGetCall) Do(opts ...googleapi.CallOption) (*VpnTunnel, error) } return ret, nil // { - // "description": "Returns the specified VpnTunnel resource. Get a list of available VPN tunnels by making a list() request.", + // "description": "Returns the specified VpnTunnel resource. Gets a list of available VPN tunnels by making a list() request.", // "httpMethod": "GET", // "id": "compute.vpnTunnels.get", // "parameterOrder": [ @@ -80515,32 +86331,28 @@ func (r *VpnTunnelsService) List(project string, region string) *VpnTunnelsListC return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *VpnTunnelsListCall) Filter(filter string) *VpnTunnelsListCall { c.urlParams_.Set("filter", filter) return c @@ -80686,7 +86498,7 @@ func (c *VpnTunnelsListCall) Do(opts ...googleapi.CallOption) (*VpnTunnelList, e // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -81062,32 +86874,28 @@ func (r *ZoneOperationsService) List(project string, zone string) *ZoneOperation return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ZoneOperationsListCall) Filter(filter string) *ZoneOperationsListCall { c.urlParams_.Set("filter", filter) return c @@ -81233,7 +87041,7 @@ func (c *ZoneOperationsListCall) Do(opts ...googleapi.CallOption) (*OperationLis // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, @@ -81316,7 +87124,7 @@ type ZonesGetCall struct { header_ http.Header } -// Get: Returns the specified Zone resource. Get a list of available +// Get: Returns the specified Zone resource. Gets a list of available // zones by making a list() request. // For details, see https://cloud.google.com/compute/docs/reference/latest/zones/get func (r *ZonesService) Get(project string, zone string) *ZonesGetCall { @@ -81421,7 +87229,7 @@ func (c *ZonesGetCall) Do(opts ...googleapi.CallOption) (*Zone, error) { } return ret, nil // { - // "description": "Returns the specified Zone resource. Get a list of available zones by making a list() request.", + // "description": "Returns the specified Zone resource. Gets a list of available zones by making a list() request.", // "httpMethod": "GET", // "id": "compute.zones.get", // "parameterOrder": [ @@ -81477,32 +87285,28 @@ func (r *ZonesService) List(project string) *ZonesListCall { return c } -// Filter sets the optional parameter "filter": Sets a filter -// {expression} for filtering listed resources. Your {expression} must -// be in the format: field_name comparison_string literal_string. +// 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 <. // -// The field_name is the name of the field you want to compare. Only -// atomic field types are supported (string, number, boolean). The -// comparison_string must be either eq (equals) or ne (not equals). The -// literal_string is the string value to filter to. The literal value -// must be valid for the type of field you are filtering by (string, -// number, boolean). For string fields, the literal value is interpreted -// as a regular expression using RE2 syntax. The literal value must -// match the entire field. +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. // -// For example, to filter for instances that do not have a name of -// example-instance, you would use name ne example-instance. -// -// You can filter on nested fields. For example, you could filter on -// instances that have set the scheduling.automaticRestart field to -// true. Use filtering on nested fields to take advantage of labels to -// organize and search for results based on label values. +// 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 eq -// true) (zone eq us-central1-f). Multiple expressions are treated as -// AND expressions, meaning that resources must match all expressions to -// pass the filters. +// 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 *ZonesListCall) Filter(filter string) *ZonesListCall { c.urlParams_.Set("filter", filter) return c @@ -81646,7 +87450,7 @@ func (c *ZonesListCall) Do(opts ...googleapi.CallOption) (*ZoneList, error) { // ], // "parameters": { // "filter": { - // "description": "Sets a filter {expression} for filtering listed resources. Your {expression} must be in the format: field_name comparison_string literal_string.\n\nThe field_name is the name of the field you want to compare. Only atomic field types are supported (string, number, boolean). The comparison_string must be either eq (equals) or ne (not equals). The literal_string is the string value to filter to. The literal value must be valid for the type of field you are filtering by (string, number, boolean). For string fields, the literal value is interpreted as a regular expression using RE2 syntax. The literal value must match the entire field.\n\nFor example, to filter for instances that do not have a name of example-instance, you would use name ne example-instance.\n\nYou can filter on nested fields. For example, you could filter on instances that have set the scheduling.automaticRestart field to true. Use filtering on nested fields to take advantage of labels to organize and search for results based on label values.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart eq true) (zone eq us-central1-f). Multiple expressions are treated as AND expressions, meaning that resources must match all expressions to pass the filters.", + // "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" // }, 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 ef673823839..a8631cee235 100644 --- a/vendor/google.golang.org/api/container/v1/container-api.json +++ b/vendor/google.golang.org/api/container/v1/container-api.json @@ -117,6 +117,969 @@ "resources": { "projects": { "resources": { + "locations": { + "methods": { + "getServerConfig": { + "description": "Returns configuration info about the Kubernetes Engine service.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/serverConfig", + "httpMethod": "GET", + "id": "container.projects.locations.getServerConfig", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project and location) of the server config to get\nSpecified in the format 'projects/*/locations/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+$", + "required": true, + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) to return operations for.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + } + }, + "path": "v1/{+name}/serverConfig", + "response": { + "$ref": "ServerConfig" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + } + }, + "resources": { + "clusters": { + "methods": { + "completeIpRotation": { + "description": "Completes master IP rotation.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:completeIpRotation", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.completeIpRotation", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster id) of the cluster to complete IP\nrotation. Specified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:completeIpRotation", + "request": { + "$ref": "CompleteIPRotationRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "create": { + "description": "Creates a cluster, consisting of the specified number and type of Google\nCompute Engine instances.\n\nBy default, the cluster is created in the project's\n[default network](/compute/docs/networks-and-firewalls#networks).\n\nOne firewall is added for the cluster. After cluster creation,\nthe cluster creates routes for each node to allow the containers\non that node to communicate with all other instances in the\ncluster.\n\nFinally, an entry is added to the project's global metadata indicating\nwhich CIDR range is being used by the cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.create", + "parameterOrder": [ + "parent" + ], + "parameters": { + "parent": { + "description": "The parent (project and location) where the cluster will be created.\nSpecified in the format 'projects/*/locations/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+parent}/clusters", + "request": { + "$ref": "CreateClusterRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "delete": { + "description": "Deletes the cluster, including the Kubernetes endpoint and all worker\nnodes.\n\nFirewalls and routes that were configured during cluster creation\nare also deleted.\n\nOther Google Compute Engine resources that might be in use by the cluster\n(e.g. load balancer resources) will not be deleted if they weren't present\nat the initial create time.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}", + "httpMethod": "DELETE", + "id": "container.projects.locations.clusters.delete", + "parameterOrder": [ + "name" + ], + "parameters": { + "clusterId": { + "description": "Deprecated. The name of the cluster to delete.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster) of the cluster to delete.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + } + }, + "path": "v1/{+name}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "get": { + "description": "Gets the details of a specific cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}", + "httpMethod": "GET", + "id": "container.projects.locations.clusters.get", + "parameterOrder": [ + "name" + ], + "parameters": { + "clusterId": { + "description": "Deprecated. The name of the cluster to retrieve.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster) of the cluster to retrieve.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + } + }, + "path": "v1/{+name}", + "response": { + "$ref": "Cluster" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "list": { + "description": "Lists all clusters owned by a project in either the specified zone or all\nzones.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters", + "httpMethod": "GET", + "id": "container.projects.locations.clusters.list", + "parameterOrder": [ + "parent" + ], + "parameters": { + "parent": { + "description": "The parent (project and location) where the clusters will be listed.\nSpecified in the format 'projects/*/locations/*'.\nLocation \"-\" matches all zones and all regions.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+$", + "required": true, + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the parent field.", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides, or \"-\" for all zones.\nThis field has been deprecated and replaced by the parent field.", + "location": "query", + "type": "string" + } + }, + "path": "v1/{+parent}/clusters", + "response": { + "$ref": "ListClustersResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setAddons": { + "description": "Sets the addons for a specific cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setAddons", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.setAddons", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster) of the cluster to set addons.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setAddons", + "request": { + "$ref": "SetAddonsConfigRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setLegacyAbac": { + "description": "Enables or disables the ABAC authorization mechanism on a cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setLegacyAbac", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.setLegacyAbac", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster id) of the cluster to set legacy abac.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setLegacyAbac", + "request": { + "$ref": "SetLegacyAbacRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setLocations": { + "description": "Sets the locations for a specific cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setLocations", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.setLocations", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster) of the cluster to set locations.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setLocations", + "request": { + "$ref": "SetLocationsRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setLogging": { + "description": "Sets the logging service for a specific cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setLogging", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.setLogging", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster) of the cluster to set logging.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setLogging", + "request": { + "$ref": "SetLoggingServiceRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setMaintenancePolicy": { + "description": "Sets the maintenance policy for a cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setMaintenancePolicy", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.setMaintenancePolicy", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster id) of the cluster to set maintenance\npolicy.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setMaintenancePolicy", + "request": { + "$ref": "SetMaintenancePolicyRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setMasterAuth": { + "description": "Used to set master auth materials. Currently supports :-\nChanging the admin password for a specific cluster.\nThis can be either via password generation or explicitly set the password.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setMasterAuth", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.setMasterAuth", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster) of the cluster to set auth.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setMasterAuth", + "request": { + "$ref": "SetMasterAuthRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setMonitoring": { + "description": "Sets the monitoring service for a specific cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setMonitoring", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.setMonitoring", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster) of the cluster to set monitoring.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setMonitoring", + "request": { + "$ref": "SetMonitoringServiceRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setNetworkPolicy": { + "description": "Enables/Disables Network Policy for a cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setNetworkPolicy", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.setNetworkPolicy", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster id) of the cluster to set networking\npolicy. Specified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setNetworkPolicy", + "request": { + "$ref": "SetNetworkPolicyRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setResourceLabels": { + "description": "Sets labels on a cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setResourceLabels", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.setResourceLabels", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster id) of the cluster to set labels.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setResourceLabels", + "request": { + "$ref": "SetLabelsRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "startIpRotation": { + "description": "Start master IP rotation.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:startIpRotation", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.startIpRotation", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster id) of the cluster to start IP\nrotation. Specified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:startIpRotation", + "request": { + "$ref": "StartIPRotationRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "update": { + "description": "Updates the settings of a specific cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}", + "httpMethod": "PUT", + "id": "container.projects.locations.clusters.update", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster) of the cluster to update.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}", + "request": { + "$ref": "UpdateClusterRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "updateMaster": { + "description": "Updates the master for a specific cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:updateMaster", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.updateMaster", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster) of the cluster to update.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:updateMaster", + "request": { + "$ref": "UpdateMasterRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + } + }, + "resources": { + "nodePools": { + "methods": { + "create": { + "description": "Creates a node pool for a cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.nodePools.create", + "parameterOrder": [ + "parent" + ], + "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/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+parent}/nodePools", + "request": { + "$ref": "CreateNodePoolRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "delete": { + "description": "Deletes a node pool from a cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}", + "httpMethod": "DELETE", + "id": "container.projects.locations.clusters.nodePools.delete", + "parameterOrder": [ + "name" + ], + "parameters": { + "clusterId": { + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster, node pool id) of the node pool to\ndelete. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + "required": true, + "type": "string" + }, + "nodePoolId": { + "description": "Deprecated. The name of the node pool to delete.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + } + }, + "path": "v1/{+name}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "get": { + "description": "Retrieves the node pool requested.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}", + "httpMethod": "GET", + "id": "container.projects.locations.clusters.nodePools.get", + "parameterOrder": [ + "name" + ], + "parameters": { + "clusterId": { + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster, node pool id) of the node pool to\nget. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + "required": true, + "type": "string" + }, + "nodePoolId": { + "description": "Deprecated. The name of the node pool.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + } + }, + "path": "v1/{+name}", + "response": { + "$ref": "NodePool" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "list": { + "description": "Lists the node pools for a cluster.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools", + "httpMethod": "GET", + "id": "container.projects.locations.clusters.nodePools.list", + "parameterOrder": [ + "parent" + ], + "parameters": { + "clusterId": { + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the parent field.", + "location": "query", + "type": "string" + }, + "parent": { + "description": "The parent (project, location, cluster id) where the node pools will be\nlisted. Specified in the format 'projects/*/locations/*/clusters/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + "required": true, + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the parent field.", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the parent field.", + "location": "query", + "type": "string" + } + }, + "path": "v1/{+parent}/nodePools", + "response": { + "$ref": "ListNodePoolsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "rollback": { + "description": "Roll back the previously Aborted or Failed NodePool upgrade.\nThis will be an no-op if the last upgrade successfully completed.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}:rollback", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.nodePools.rollback", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster, node pool id) of the node poll to\nrollback upgrade.\nSpecified in the format 'projects/*/locations/*/clusters/*/nodePools/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:rollback", + "request": { + "$ref": "RollbackNodePoolUpgradeRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setAutoscaling": { + "description": "Sets the autoscaling settings for a specific node pool.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}:setAutoscaling", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.nodePools.setAutoscaling", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster, node pool) of the node pool to set\nautoscaler settings. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setAutoscaling", + "request": { + "$ref": "SetNodePoolAutoscalingRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setManagement": { + "description": "Sets the NodeManagement options for a node pool.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}:setManagement", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.nodePools.setManagement", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster, node pool id) of the node pool to set\nmanagement properties. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setManagement", + "request": { + "$ref": "SetNodePoolManagementRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "setSize": { + "description": "Sets the size for a specific node pool.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}:setSize", + "httpMethod": "POST", + "id": "container.projects.locations.clusters.nodePools.setSize", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster, node pool id) of the node pool to set\nsize.\nSpecified in the format 'projects/*/locations/*/clusters/*/nodePools/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:setSize", + "request": { + "$ref": "SetNodePoolSizeRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "update": { + "description": "Updates the version and/or image type for a specific node pool.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}", + "httpMethod": "PUT", + "id": "container.projects.locations.clusters.nodePools.update", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, cluster, node pool) of the node pool to\nupdate. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}", + "request": { + "$ref": "UpdateNodePoolRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + } + } + } + } + }, + "operations": { + "methods": { + "cancel": { + "description": "Cancels the specified operation.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}:cancel", + "httpMethod": "POST", + "id": "container.projects.locations.operations.cancel", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, operation id) of the operation to cancel.\nSpecified in the format 'projects/*/locations/*/operations/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/operations/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}:cancel", + "request": { + "$ref": "CancelOperationRequest" + }, + "response": { + "$ref": "Empty" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "get": { + "description": "Gets the specified operation.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}", + "httpMethod": "GET", + "id": "container.projects.locations.operations.get", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name (project, location, operation id) of the operation to get.\nSpecified in the format 'projects/*/locations/*/operations/*'.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/operations/[^/]+$", + "required": true, + "type": "string" + }, + "operationId": { + "description": "Deprecated. The server-assigned `name` of the operation.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "location": "query", + "type": "string" + } + }, + "path": "v1/{+name}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "list": { + "description": "Lists all operations in a project in a specific zone or all zones.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations", + "httpMethod": "GET", + "id": "container.projects.locations.operations.list", + "parameterOrder": [ + "parent" + ], + "parameters": { + "parent": { + "description": "The parent (project and location) where the operations will be listed.\nSpecified in the format 'projects/*/locations/*'.\nLocation \"-\" matches all zones and all regions.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+$", + "required": true, + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the parent field.", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) to return operations for, or `-` for\nall zones. This field has been deprecated and replaced by the parent field.", + "location": "query", + "type": "string" + } + }, + "path": "v1/{+parent}/operations", + "response": { + "$ref": "ListOperationsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + } + } + } + } + }, "zones": { "methods": { "getServerconfig": { @@ -129,14 +1092,19 @@ "zone" ], "parameters": { + "name": { + "description": "The name (project and location) of the server config to get\nSpecified in the format 'projects/*/locations/*'.", + "location": "query", + "type": "string" + }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine [zone](/compute/docs/zones#available)\nto return operations for.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) to return operations for.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -155,7 +1123,7 @@ "clusters": { "methods": { "addons": { - "description": "Sets the addons of a specific cluster.", + "description": "Sets the addons for a specific cluster.", "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/addons", "httpMethod": "POST", "id": "container.projects.zones.clusters.addons", @@ -166,19 +1134,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to upgrade.", + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -207,19 +1175,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster.", + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -247,13 +1215,13 @@ ], "parameters": { "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" @@ -282,19 +1250,24 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to delete.", + "description": "Deprecated. The name of the cluster to delete.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, + "name": { + "description": "The name (project, location, cluster) of the cluster to delete.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "query", + "type": "string" + }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -320,19 +1293,24 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to retrieve.", + "description": "Deprecated. The name of the cluster to retrieve.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, + "name": { + "description": "The name (project, location, cluster) of the cluster to retrieve.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "location": "query", + "type": "string" + }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -358,19 +1336,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to update.", + "description": "Deprecated. The name of the cluster to update.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -397,14 +1375,19 @@ "zone" ], "parameters": { + "parent": { + "description": "The parent (project and location) where the clusters will be listed.\nSpecified in the format 'projects/*/locations/*'.\nLocation \"-\" matches all zones and all regions.", + "location": "query", + "type": "string" + }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides, or \"-\" for all zones.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides, or \"-\" for all zones.\nThis field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" @@ -419,7 +1402,7 @@ ] }, "locations": { - "description": "Sets the locations of a specific cluster.", + "description": "Sets the locations for a specific cluster.", "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/locations", "httpMethod": "POST", "id": "container.projects.zones.clusters.locations", @@ -430,19 +1413,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to upgrade.", + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -460,7 +1443,7 @@ ] }, "logging": { - "description": "Sets the logging service of a specific cluster.", + "description": "Sets the logging service for a specific cluster.", "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/logging", "httpMethod": "POST", "id": "container.projects.zones.clusters.logging", @@ -471,19 +1454,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to upgrade.", + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -501,7 +1484,7 @@ ] }, "master": { - "description": "Updates the master of a specific cluster.", + "description": "Updates the master for a specific cluster.", "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/master", "httpMethod": "POST", "id": "container.projects.zones.clusters.master", @@ -512,19 +1495,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to upgrade.", + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -542,7 +1525,7 @@ ] }, "monitoring": { - "description": "Sets the monitoring service of a specific cluster.", + "description": "Sets the monitoring service for a specific cluster.", "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/monitoring", "httpMethod": "POST", "id": "container.projects.zones.clusters.monitoring", @@ -553,19 +1536,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to upgrade.", + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -594,19 +1577,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster.", + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -665,7 +1648,7 @@ ] }, "setMasterAuth": { - "description": "Used to set master auth materials. Currently supports :-\nChanging the admin password of a specific cluster.\nThis can be either via password generation or explicitly set the password.", + "description": "Used to set master auth materials. Currently supports :-\nChanging the admin password for a specific cluster.\nThis can be either via password generation or explicitly set the password.", "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}:setMasterAuth", "httpMethod": "POST", "id": "container.projects.zones.clusters.setMasterAuth", @@ -676,19 +1659,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to upgrade.", + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -717,19 +1700,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster.", + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -758,19 +1741,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster.", + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -799,19 +1782,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to upgrade.", + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -833,7 +1816,7 @@ "nodePools": { "methods": { "autoscaling": { - "description": "Sets the autoscaling settings of a specific node pool.", + "description": "Sets the autoscaling settings for a specific node pool.", "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}/autoscaling", "httpMethod": "POST", "id": "container.projects.zones.clusters.nodePools.autoscaling", @@ -845,25 +1828,25 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to upgrade.", + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "nodePoolId": { - "description": "The name of the node pool to upgrade.", + "description": "Deprecated. The name of the node pool to upgrade.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -892,19 +1875,19 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster.", + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" @@ -934,25 +1917,30 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster.", + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, + "name": { + "description": "The name (project, location, cluster, node pool id) of the node pool to\ndelete. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "location": "query", + "type": "string" + }, "nodePoolId": { - "description": "The name of the node pool to delete.", + "description": "Deprecated. The name of the node pool to delete.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -979,25 +1967,30 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster.", + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, + "name": { + "description": "The name (project, location, cluster, node pool id) of the node pool to\nget. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "location": "query", + "type": "string" + }, "nodePoolId": { - "description": "The name of the node pool.", + "description": "Deprecated. The name of the node pool.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -1023,19 +2016,24 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster.", + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" }, + "parent": { + "description": "The parent (project, location, cluster id) where the node pools will be\nlisted. Specified in the format 'projects/*/locations/*/clusters/*'.", + "location": "query", + "type": "string" + }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" @@ -1062,25 +2060,25 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to rollback.", + "description": "Deprecated. The name of the cluster to rollback.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "nodePoolId": { - "description": "The name of the node pool to rollback.", + "description": "Deprecated. The name of the node pool to rollback.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -1110,25 +2108,25 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to update.", + "description": "Deprecated. The name of the cluster to update.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "nodePoolId": { - "description": "The name of the node pool to update.", + "description": "Deprecated. The name of the node pool to update.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -1146,7 +2144,7 @@ ] }, "setSize": { - "description": "Sets the size of a specific node pool.", + "description": "Sets the size for a specific node pool.", "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}/setSize", "httpMethod": "POST", "id": "container.projects.zones.clusters.nodePools.setSize", @@ -1158,25 +2156,25 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to update.", + "description": "Deprecated. The name of the cluster to update.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "nodePoolId": { - "description": "The name of the node pool to update.", + "description": "Deprecated. The name of the node pool to update.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -1194,7 +2192,7 @@ ] }, "update": { - "description": "Updates the version and/or image type of a specific node pool.", + "description": "Updates the version and/or image type for a specific node pool.", "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}/update", "httpMethod": "POST", "id": "container.projects.zones.clusters.nodePools.update", @@ -1206,25 +2204,25 @@ ], "parameters": { "clusterId": { - "description": "The name of the cluster to upgrade.", + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "nodePoolId": { - "description": "The name of the node pool to upgrade.", + "description": "Deprecated. The name of the node pool to upgrade.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -1259,19 +2257,19 @@ ], "parameters": { "operationId": { - "description": "The server-assigned `name` of the operation.", + "description": "Deprecated. The server-assigned `name` of the operation.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the operation resides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the operation resides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -1299,20 +2297,25 @@ "operationId" ], "parameters": { + "name": { + "description": "The name (project, location, operation id) of the operation to get.\nSpecified in the format 'projects/*/locations/*/operations/*'.", + "location": "query", + "type": "string" + }, "operationId": { - "description": "The server-assigned `name` of the operation.", + "description": "Deprecated. The server-assigned `name` of the operation.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "location": "path", "required": true, "type": "string" @@ -1336,14 +2339,19 @@ "zone" ], "parameters": { + "parent": { + "description": "The parent (project and location) where the operations will be listed.\nSpecified in the format 'projects/*/locations/*'.\nLocation \"-\" matches all zones and all regions.", + "location": "query", + "type": "string" + }, "projectId": { - "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine [zone](/compute/docs/zones#available)\nto return operations for, or `-` for all zones.", + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) to return operations for, or `-` for\nall zones. This field has been deprecated and replaced by the parent field.", "location": "path", "required": true, "type": "string" @@ -1364,7 +2372,7 @@ } } }, - "revision": "20180213", + "revision": "20180504", "rootUrl": "https://container.googleapis.com/", "schemas": { "AcceleratorConfig": { @@ -1424,7 +2432,24 @@ "CancelOperationRequest": { "description": "CancelOperationRequest cancels a single operation.", "id": "CancelOperationRequest", - "properties": {}, + "properties": { + "name": { + "description": "The name (project, location, operation id) of the operation to cancel.\nSpecified in the format 'projects/*/locations/*/operations/*'.", + "type": "string" + }, + "operationId": { + "description": "Deprecated. The server-assigned `name` of the operation.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the operation resides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + } + }, "type": "object" }, "CidrBlock": { @@ -1499,7 +2524,7 @@ "type": "string" }, "initialClusterVersion": { - "description": "The initial Kubernetes version for this cluster. Valid versions are those\nfound in validMasterVersions returned by getServerConfig. The version can\nbe upgraded over time; such upgrades are reflected in\ncurrentMasterVersion and currentNodeVersion.", + "description": "The initial Kubernetes version for this cluster. Valid versions are those\nfound in validMasterVersions returned by getServerConfig. The version can\nbe upgraded over time; such upgrades are reflected in\ncurrentMasterVersion and currentNodeVersion.\n\nUsers may specify either explicit versions offered by\nKubernetes Engine or version aliases, which have the following behavior:\n\n- \"latest\": picks the highest valid Kubernetes version\n- \"1.X\": picks the highest valid patch+gke.N patch in the 1.X version\n- \"1.X.Y\": picks the highest valid gke.N patch in the 1.X.Y version\n- \"1.X.Y-gke.N\": picks an explicit Kubernetes version\n- \"\",\"-\": picks the default Kubernetes version", "type": "string" }, "initialNodeCount": { @@ -1526,6 +2551,10 @@ "$ref": "LegacyAbac", "description": "Configuration for the legacy ABAC authorization mode." }, + "location": { + "description": "[Output only] The name of the Google Compute Engine\n[zone](/compute/docs/regions-zones/regions-zones#available) or\n[region](/compute/docs/regions-zones/regions-zones#available) in which\nthe cluster resides.", + "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.", "items": { @@ -1547,7 +2576,7 @@ }, "masterAuthorizedNetworksConfig": { "$ref": "MasterAuthorizedNetworksConfig", - "description": "Master authorized networks is a Beta feature.\nThe configuration options for master authorized networks feature." + "description": "The configuration options for master authorized networks feature." }, "monitoringService": { "description": "The monitoring service the cluster should use to write metrics.\nCurrently available options:\n\n* `monitoring.googleapis.com` - the Google Cloud Monitoring service.\n* `none` - no metrics will be exported from the cluster.\n* if left as an empty string, `monitoring.googleapis.com` will be used.", @@ -1604,7 +2633,8 @@ "RUNNING", "RECONCILING", "STOPPING", - "ERROR" + "ERROR", + "DEGRADED" ], "enumDescriptions": [ "Not set.", @@ -1612,7 +2642,8 @@ "The RUNNING state indicates the cluster has been created and is fully\nusable.", "The RECONCILING state indicates that some work is actively being done on\nthe cluster, such as upgrading the master or node software. Details can\nbe found in the `statusMessage` field.", "The STOPPING state indicates the cluster is being deleted.", - "The ERROR state indicates the cluster may be unusable. Details\ncan be found in the `statusMessage` field." + "The ERROR state indicates the cluster may be unusable. Details\ncan be found in the `statusMessage` field.", + "The DEGRADED state indicates the cluster requires user action to restore\nfull functionality. Details can be found in the `statusMessage` field." ], "type": "string" }, @@ -1625,7 +2656,7 @@ "type": "string" }, "zone": { - "description": "[Output only] The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "description": "[Output only] The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field is deprecated, use location instead.", "type": "string" } }, @@ -1652,10 +2683,10 @@ }, "desiredMasterAuthorizedNetworksConfig": { "$ref": "MasterAuthorizedNetworksConfig", - "description": "Master authorized networks is a Beta feature.\nThe desired configuration options for master authorized networks feature." + "description": "The desired configuration options for master authorized networks feature." }, "desiredMasterVersion": { - "description": "The Kubernetes version to change the master to. The only valid value is the\nlatest supported version. Use \"-\" to have the server automatically select\nthe latest version.", + "description": "The Kubernetes version to change the master to.\n\nUsers may specify either explicit versions offered by\nKubernetes Engine or version aliases, which have the following behavior:\n\n- \"latest\": picks the highest valid Kubernetes version\n- \"1.X\": picks the highest valid patch+gke.N patch in the 1.X version\n- \"1.X.Y\": picks the highest valid gke.N patch in the 1.X.Y version\n- \"1.X.Y-gke.N\": picks an explicit Kubernetes version\n- \"-\": picks the default Kubernetes version", "type": "string" }, "desiredMonitoringService": { @@ -1671,7 +2702,7 @@ "type": "string" }, "desiredNodeVersion": { - "description": "The Kubernetes version to change the nodes to (typically an\nupgrade). Use `-` to upgrade to the latest version supported by\nthe server.", + "description": "The Kubernetes version to change the nodes to (typically an\nupgrade).\n\nUsers may specify either explicit versions offered by\nKubernetes Engine or version aliases, which have the following behavior:\n\n- \"latest\": picks the highest valid Kubernetes version\n- \"1.X\": picks the highest valid patch+gke.N patch in the 1.X version\n- \"1.X.Y\": picks the highest valid gke.N patch in the 1.X.Y version\n- \"1.X.Y-gke.N\": picks an explicit Kubernetes version\n- \"-\": picks the Kubernetes master version", "type": "string" } }, @@ -1680,7 +2711,24 @@ "CompleteIPRotationRequest": { "description": "CompleteIPRotationRequest moves the cluster master back into single-IP mode.", "id": "CompleteIPRotationRequest", - "properties": {}, + "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster id) of the cluster to complete IP\nrotation. Specified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + } + }, "type": "object" }, "CreateClusterRequest": { @@ -1690,6 +2738,18 @@ "cluster": { "$ref": "Cluster", "description": "A [cluster\nresource](/container-engine/reference/rest/v1/projects.zones.clusters)" + }, + "parent": { + "description": "The parent (project and location) where the cluster will be created.\nSpecified in the format 'projects/*/locations/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the parent field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the parent field.", + "type": "string" } }, "type": "object" @@ -1698,9 +2758,25 @@ "description": "CreateNodePoolRequest creates a node pool for a cluster.", "id": "CreateNodePoolRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the parent field.", + "type": "string" + }, "nodePool": { "$ref": "NodePool", "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/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the parent field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the parent field.", + "type": "string" } }, "type": "object" @@ -1931,7 +3007,7 @@ "type": "object" }, "MasterAuthorizedNetworksConfig": { - "description": "Master authorized networks is a Beta feature.\nConfiguration options for the master authorized networks feature. Enabled\nmaster authorized networks will disallow all external traffic to access\nKubernetes master through HTTPS except traffic from the given CIDR blocks,\nGoogle Compute Engine Public IPs and Google Prod IPs.", + "description": "Configuration options for the master authorized networks feature. Enabled\nmaster authorized networks will disallow all external traffic to access\nKubernetes master through HTTPS except traffic from the given CIDR blocks,\nGoogle Compute Engine Public IPs and Google Prod IPs.", "id": "MasterAuthorizedNetworksConfig", "properties": { "cidrBlocks": { @@ -2026,7 +3102,7 @@ "type": "object" }, "minCpuPlatform": { - "description": "Minimum CPU platform to be used by this instance. The instance may be\nscheduled on the specified or newer CPU platform. Applicable values are the\nfriendly names of CPU platforms, such as\n\u003ccode\u003eminCpuPlatform: \u0026quot;Intel Haswell\u0026quot;\u003c/code\u003e or\n\u003ccode\u003eminCpuPlatform: \u0026quot;Intel Sandy Bridge\u0026quot;\u003c/code\u003e. For more\ninformation, read [how to specify min CPU platform](https://cloud.google.com/compute/docs/instances/specify-min-cpu-platform)", + "description": "Minimum CPU platform to be used by this instance. The instance may be\nscheduled on the specified or newer CPU platform. Applicable values are the\nfriendly names of CPU platforms, such as\n\u003ccode\u003eminCpuPlatform: \u0026quot;Intel Haswell\u0026quot;\u003c/code\u003e or\n\u003ccode\u003eminCpuPlatform: \u0026quot;Intel Sandy Bridge\u0026quot;\u003c/code\u003e. For more\ninformation, read [how to specify min CPU\nplatform](https://cloud.google.com/compute/docs/instances/specify-min-cpu-platform)", "type": "string" }, "oauthScopes": { @@ -2175,6 +3251,10 @@ "description": "[Output only] The time the operation completed, in\n[RFC3339](https://www.ietf.org/rfc/rfc3339.txt) text format.", "type": "string" }, + "location": { + "description": "[Output only] The name of the Google Compute Engine\n[zone](/compute/docs/regions-zones/regions-zones#available) or\n[region](/compute/docs/regions-zones/regions-zones#available) in which\nthe cluster resides.", + "type": "string" + }, "name": { "description": "The server-assigned ID for the operation.", "type": "string" @@ -2256,7 +3336,7 @@ "type": "string" }, "zone": { - "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the operation\nis taking place.", + "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the operation\nis taking place.\nThis field is deprecated, use location instead.", "type": "string" } }, @@ -2265,7 +3345,28 @@ "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", - "properties": {}, + "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster to rollback.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster, node pool id) of the node poll to\nrollback upgrade.\nSpecified in the format 'projects/*/locations/*/clusters/*/nodePools/*'.", + "type": "string" + }, + "nodePoolId": { + "description": "Deprecated. The name of the node pool to rollback.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + } + }, "type": "object" }, "ServerConfig": { @@ -2311,6 +3412,22 @@ "addonsConfig": { "$ref": "AddonsConfig", "description": "The desired configurations for the various addons available to run in the\ncluster." + }, + "clusterId": { + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster) of the cluster to set addons.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2319,16 +3436,32 @@ "description": "SetLabelsRequest sets the Google Cloud Platform labels on a Google Container\nEngine cluster, which will in turn set them for Google Compute Engine\nresources used by that cluster", "id": "SetLabelsRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, "labelFingerprint": { "description": "The fingerprint of the previous set of labels for this resource,\nused to detect conflicts. The fingerprint is initially generated by\nKubernetes Engine and changes after every request to modify or update\nlabels. You must always provide an up-to-date fingerprint hash when\nupdating or changing labels. Make a \u003ccode\u003eget()\u003c/code\u003e request to the\nresource to get the latest fingerprint.", "type": "string" }, + "name": { + "description": "The name (project, location, cluster id) of the cluster to set labels.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, "resourceLabels": { "additionalProperties": { "type": "string" }, "description": "The labels to set for that cluster.", "type": "object" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2337,9 +3470,25 @@ "description": "SetLegacyAbacRequest enables or disables the ABAC authorization mechanism for\na cluster.", "id": "SetLegacyAbacRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster to update.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, "enabled": { "description": "Whether ABAC authorization will be enabled in the cluster.", "type": "boolean" + }, + "name": { + "description": "The name (project, location, cluster id) of the cluster to set legacy abac.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2348,12 +3497,28 @@ "description": "SetLocationsRequest sets the locations of the cluster.", "id": "SetLocationsRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", + "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.", "items": { "type": "string" }, "type": "array" + }, + "name": { + "description": "The name (project, location, cluster) of the cluster to set locations.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2362,9 +3527,25 @@ "description": "SetLoggingServiceRequest sets the logging service of a cluster.", "id": "SetLoggingServiceRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, "loggingService": { "description": "The logging service the cluster should use to write metrics.\nCurrently available options:\n\n* \"logging.googleapis.com\" - the Google Cloud Logging service\n* \"none\" - no metrics will be exported from the cluster", "type": "string" + }, + "name": { + "description": "The name (project, location, cluster) of the cluster to set logging.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2373,9 +3554,25 @@ "description": "SetMaintenancePolicyRequest sets the maintenance policy for a cluster.", "id": "SetMaintenancePolicyRequest", "properties": { + "clusterId": { + "description": "The name of the cluster to update.", + "type": "string" + }, "maintenancePolicy": { "$ref": "MaintenancePolicy", "description": "The maintenance policy to be set for the cluster. An empty field\nclears the existing maintenance policy." + }, + "name": { + "description": "The name (project, location, cluster id) of the cluster to set maintenance\npolicy.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + "type": "string" + }, + "zone": { + "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + "type": "string" } }, "type": "object" @@ -2400,9 +3597,25 @@ ], "type": "string" }, + "clusterId": { + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster) of the cluster to set auth.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, "update": { "$ref": "MasterAuth", "description": "A description of the update." + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2411,9 +3624,25 @@ "description": "SetMonitoringServiceRequest sets the monitoring service of a cluster.", "id": "SetMonitoringServiceRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, "monitoringService": { "description": "The monitoring service the cluster should use to write metrics.\nCurrently available options:\n\n* \"monitoring.googleapis.com\" - the Google Cloud Monitoring service\n* \"none\" - no metrics will be exported from the cluster", "type": "string" + }, + "name": { + "description": "The name (project, location, cluster) of the cluster to set monitoring.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2422,9 +3651,25 @@ "description": "SetNetworkPolicyRequest enables/disables network policy for a cluster.", "id": "SetNetworkPolicyRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster id) of the cluster to set networking\npolicy. Specified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, "networkPolicy": { "$ref": "NetworkPolicy", "description": "Configuration options for the NetworkPolicy feature." + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2436,6 +3681,26 @@ "autoscaling": { "$ref": "NodePoolAutoscaling", "description": "Autoscaling configuration for the node pool." + }, + "clusterId": { + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster, node pool) of the node pool to set\nautoscaler settings. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "type": "string" + }, + "nodePoolId": { + "description": "Deprecated. The name of the node pool to upgrade.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2444,9 +3709,29 @@ "description": "SetNodePoolManagementRequest sets the node management properties of a node\npool.", "id": "SetNodePoolManagementRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster to update.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, "management": { "$ref": "NodeManagement", "description": "NodeManagement configuration for the node pool." + }, + "name": { + "description": "The name (project, location, cluster, node pool id) of the node pool to set\nmanagement properties. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "type": "string" + }, + "nodePoolId": { + "description": "Deprecated. The name of the node pool to update.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2455,10 +3740,30 @@ "description": "SetNodePoolSizeRequest sets the size a node\npool.", "id": "SetNodePoolSizeRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster to update.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster, node pool id) of the node pool to set\nsize.\nSpecified in the format 'projects/*/locations/*/clusters/*/nodePools/*'.", + "type": "string" + }, "nodeCount": { "description": "The desired node count for the pool.", "format": "int32", "type": "integer" + }, + "nodePoolId": { + "description": "Deprecated. The name of the node pool to update.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2466,16 +3771,53 @@ "StartIPRotationRequest": { "description": "StartIPRotationRequest creates a new IP for the cluster and then performs\na node upgrade on each node pool to point to the new IP.", "id": "StartIPRotationRequest", - "properties": {}, + "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster id) of the cluster to start IP\nrotation. Specified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "rotateCredentials": { + "description": "Whether to rotate credentials during IP rotation.", + "type": "boolean" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + } + }, "type": "object" }, "UpdateClusterRequest": { "description": "UpdateClusterRequest updates the settings of a cluster.", "id": "UpdateClusterRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster) of the cluster to update.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, "update": { "$ref": "ClusterUpdate", "description": "A description of the update." + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + "type": "string" } }, "type": "object" @@ -2484,8 +3826,24 @@ "description": "UpdateMasterRequest updates the master of the cluster.", "id": "UpdateMasterRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, "masterVersion": { - "description": "The Kubernetes version to change the master to. Use \"-\" to have the server\nautomatically select the default version.", + "description": "The Kubernetes version to change the master to.\n\nUsers may specify either explicit versions offered by Kubernetes Engine or\nversion aliases, which have the following behavior:\n\n- \"latest\": picks the highest valid Kubernetes version\n- \"1.X\": picks the highest valid patch+gke.N patch in the 1.X version\n- \"1.X.Y\": picks the highest valid gke.N patch in the 1.X.Y version\n- \"1.X.Y-gke.N\": picks an explicit Kubernetes version\n- \"-\": picks the default Kubernetes version", + "type": "string" + }, + "name": { + "description": "The name (project, location, cluster) of the cluster to update.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "type": "string" } }, @@ -2495,12 +3853,32 @@ "description": "UpdateNodePoolRequests update a node pool's image and/or version.", "id": "UpdateNodePoolRequest", "properties": { + "clusterId": { + "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, "imageType": { "description": "The desired image type for the node pool.", "type": "string" }, + "name": { + "description": "The name (project, location, cluster, node pool) of the node pool to\nupdate. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "type": "string" + }, + "nodePoolId": { + "description": "Deprecated. The name of the node pool to upgrade.\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, "nodeVersion": { - "description": "The Kubernetes version to change the nodes to (typically an\nupgrade). Use `-` to upgrade to the latest version supported by\nthe server.", + "description": "The Kubernetes version to change the nodes to (typically an\nupgrade).\n\nUsers may specify either explicit versions offered by Kubernetes Engine or\nversion aliases, which have the following behavior:\n\n- \"latest\": picks the highest valid Kubernetes version\n- \"1.X\": picks the highest valid patch+gke.N patch in the 1.X version\n- \"1.X.Y\": picks the highest valid gke.N patch in the 1.X.Y version\n- \"1.X.Y-gke.N\": picks an explicit Kubernetes version\n- \"-\": picks the Kubernetes master version", + "type": "string" + }, + "projectId": { + "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + "type": "string" + }, + "zone": { + "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", "type": "string" } }, @@ -2508,6 +3886,6 @@ } }, "servicePath": "", - "title": "Google Kubernetes Engine API", + "title": "Kubernetes Engine API", "version": "v1" } \ No newline at end of file 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 c14d4997f16..0650b9387c7 100644 --- a/vendor/google.golang.org/api/container/v1/container-gen.go +++ b/vendor/google.golang.org/api/container/v1/container-gen.go @@ -1,4 +1,4 @@ -// Package container provides access to the Google Kubernetes Engine API. +// Package container provides access to the Kubernetes Engine API. // // See https://cloud.google.com/container-engine/ // @@ -77,6 +77,7 @@ func (s *Service) userAgent() string { func NewProjectsService(s *Service) *ProjectsService { rs := &ProjectsService{s: s} + rs.Locations = NewProjectsLocationsService(s) rs.Zones = NewProjectsZonesService(s) return rs } @@ -84,9 +85,56 @@ func NewProjectsService(s *Service) *ProjectsService { type ProjectsService struct { s *Service + Locations *ProjectsLocationsService + Zones *ProjectsZonesService } +func NewProjectsLocationsService(s *Service) *ProjectsLocationsService { + rs := &ProjectsLocationsService{s: s} + rs.Clusters = NewProjectsLocationsClustersService(s) + rs.Operations = NewProjectsLocationsOperationsService(s) + return rs +} + +type ProjectsLocationsService struct { + s *Service + + Clusters *ProjectsLocationsClustersService + + Operations *ProjectsLocationsOperationsService +} + +func NewProjectsLocationsClustersService(s *Service) *ProjectsLocationsClustersService { + rs := &ProjectsLocationsClustersService{s: s} + rs.NodePools = NewProjectsLocationsClustersNodePoolsService(s) + return rs +} + +type ProjectsLocationsClustersService struct { + s *Service + + NodePools *ProjectsLocationsClustersNodePoolsService +} + +func NewProjectsLocationsClustersNodePoolsService(s *Service) *ProjectsLocationsClustersNodePoolsService { + rs := &ProjectsLocationsClustersNodePoolsService{s: s} + return rs +} + +type ProjectsLocationsClustersNodePoolsService struct { + s *Service +} + +func NewProjectsLocationsOperationsService(s *Service) *ProjectsLocationsOperationsService { + rs := &ProjectsLocationsOperationsService{s: s} + return rs +} + +type ProjectsLocationsOperationsService struct { + s *Service +} + func NewProjectsZonesService(s *Service) *ProjectsZonesService { rs := &ProjectsZonesService{s: s} rs.Clusters = NewProjectsZonesClustersService(s) @@ -264,6 +312,51 @@ func (s *AutoUpgradeOptions) MarshalJSON() ([]byte, error) { // CancelOperationRequest: CancelOperationRequest cancels a single // operation. type CancelOperationRequest struct { + // Name: The name (project, location, operation id) of the operation to + // cancel. + // Specified in the format 'projects/*/locations/*/operations/*'. + Name string `json:"name,omitempty"` + + // OperationId: Deprecated. The server-assigned `name` of the + // operation. + // This field has been deprecated and replaced by the name field. + OperationId string `json:"operationId,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the operation + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,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 *CancelOperationRequest) MarshalJSON() ([]byte, error) { + type NoMethod CancelOperationRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } // CidrBlock: CidrBlock contains an optional name and one CIDR block. @@ -403,6 +496,17 @@ type Cluster struct { // be upgraded over time; such upgrades are reflected // in // currentMasterVersion and currentNodeVersion. + // + // Users may specify either explicit versions offered by + // Kubernetes Engine or version aliases, which have the following + // behavior: + // + // - "latest": picks the highest valid Kubernetes version + // - "1.X": picks the highest valid patch+gke.N patch in the 1.X + // version + // - "1.X.Y": picks the highest valid gke.N patch in the 1.X.Y version + // - "1.X.Y-gke.N": picks an explicit Kubernetes version + // - "","-": picks the default Kubernetes version InitialClusterVersion string `json:"initialClusterVersion,omitempty"` // InitialNodeCount: The number of nodes to create in this cluster. You @@ -434,6 +538,15 @@ type Cluster struct { // LegacyAbac: Configuration for the legacy ABAC authorization mode. LegacyAbac *LegacyAbac `json:"legacyAbac,omitempty"` + // Location: [Output only] The name of the Google Compute + // Engine + // [zone](/compute/docs/regions-zones/regions-zones#available) + // or + // [region](/compute/docs/regions-zones/regions-zones#available) in + // which + // the cluster resides. + Location string `json:"location,omitempty"` + // Locations: The list of Google Compute // Engine // [locations](/compute/docs/zones#available) in which the cluster's @@ -457,9 +570,8 @@ type Cluster struct { // endpoint. MasterAuth *MasterAuth `json:"masterAuth,omitempty"` - // MasterAuthorizedNetworksConfig: Master authorized networks is a Beta - // feature. - // The configuration options for master authorized networks feature. + // MasterAuthorizedNetworksConfig: The configuration options for master + // authorized networks feature. MasterAuthorizedNetworksConfig *MasterAuthorizedNetworksConfig `json:"masterAuthorizedNetworksConfig,omitempty"` // MonitoringService: The monitoring service the cluster should use to @@ -560,6 +672,10 @@ type Cluster struct { // "ERROR" - The ERROR state indicates the cluster may be unusable. // Details // can be found in the `statusMessage` field. + // "DEGRADED" - The DEGRADED state indicates the cluster requires user + // action to restore + // full functionality. Details can be found in the `statusMessage` + // field. Status string `json:"status,omitempty"` // StatusMessage: [Output only] Additional information about the current @@ -575,8 +691,10 @@ type Cluster struct { // Zone: [Output only] The name of the Google Compute // Engine - // [zone](/compute/docs/zones#available) in which the cluster + // [zone](/compute/docs/zones#available) in which the + // cluster // resides. + // This field is deprecated, use location instead. Zone string `json:"zone,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -633,17 +751,23 @@ type ClusterUpdate struct { // This list must always include the cluster's primary zone. DesiredLocations []string `json:"desiredLocations,omitempty"` - // DesiredMasterAuthorizedNetworksConfig: Master authorized networks is - // a Beta feature. - // The desired configuration options for master authorized networks - // feature. + // DesiredMasterAuthorizedNetworksConfig: The desired configuration + // options for master authorized networks feature. DesiredMasterAuthorizedNetworksConfig *MasterAuthorizedNetworksConfig `json:"desiredMasterAuthorizedNetworksConfig,omitempty"` - // DesiredMasterVersion: The Kubernetes version to change the master to. - // The only valid value is the - // latest supported version. Use "-" to have the server automatically - // select - // the latest version. + // DesiredMasterVersion: The Kubernetes version to change the master + // to. + // + // Users may specify either explicit versions offered by + // Kubernetes Engine or version aliases, which have the following + // behavior: + // + // - "latest": picks the highest valid Kubernetes version + // - "1.X": picks the highest valid patch+gke.N patch in the 1.X + // version + // - "1.X.Y": picks the highest valid gke.N patch in the 1.X.Y version + // - "1.X.Y-gke.N": picks an explicit Kubernetes version + // - "-": picks the default Kubernetes version DesiredMasterVersion string `json:"desiredMasterVersion,omitempty"` // DesiredMonitoringService: The monitoring service the cluster should @@ -672,8 +796,18 @@ type ClusterUpdate struct { // DesiredNodeVersion: The Kubernetes version to change the nodes to // (typically an - // upgrade). Use `-` to upgrade to the latest version supported by - // the server. + // upgrade). + // + // Users may specify either explicit versions offered by + // Kubernetes Engine or version aliases, which have the following + // behavior: + // + // - "latest": picks the highest valid Kubernetes version + // - "1.X": picks the highest valid patch+gke.N patch in the 1.X + // version + // - "1.X.Y": picks the highest valid gke.N patch in the 1.X.Y version + // - "1.X.Y-gke.N": picks an explicit Kubernetes version + // - "-": picks the Kubernetes master version DesiredNodeVersion string `json:"desiredNodeVersion,omitempty"` // ForceSendFields is a list of field names (e.g. "DesiredAddonsConfig") @@ -703,6 +837,52 @@ func (s *ClusterUpdate) MarshalJSON() ([]byte, error) { // CompleteIPRotationRequest: CompleteIPRotationRequest moves the // cluster master back into single-IP mode. type CompleteIPRotationRequest struct { + // ClusterId: Deprecated. The name of the cluster. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + + // Name: The name (project, location, cluster id) of the cluster to + // complete IP + // rotation. Specified in the format + // 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://developers.google.com/console/help/new/#projec + // tnumber). + // This field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ClusterId") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *CompleteIPRotationRequest) MarshalJSON() ([]byte, error) { + type NoMethod CompleteIPRotationRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } // CreateClusterRequest: CreateClusterRequest creates a cluster. @@ -713,6 +893,26 @@ type CreateClusterRequest struct { // clusters) Cluster *Cluster `json:"cluster,omitempty"` + // Parent: The parent (project and location) where the cluster will be + // created. + // Specified in the format 'projects/*/locations/*'. + Parent string `json:"parent,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the parent field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the parent field. + Zone string `json:"zone,omitempty"` + // ForceSendFields is a list of field names (e.g. "Cluster") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -739,10 +939,36 @@ func (s *CreateClusterRequest) MarshalJSON() ([]byte, error) { // CreateNodePoolRequest: CreateNodePoolRequest creates a node pool for // a cluster. type CreateNodePoolRequest struct { + // ClusterId: Deprecated. The name of the cluster. + // This field has been deprecated and replaced by the parent field. + ClusterId string `json:"clusterId,omitempty"` + // NodePool: The node pool to create. NodePool *NodePool `json:"nodePool,omitempty"` - // ForceSendFields is a list of field names (e.g. "NodePool") to + // Parent: The parent (project, location, cluster id) where the node + // pool will be + // created. Specified in the + // format + // 'projects/*/locations/*/clusters/*/nodePools/*'. + Parent string `json:"parent,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://developers.google.com/console/help/new/#projec + // tnumber). + // This field has been deprecated and replaced by the parent field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the parent field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -750,7 +976,7 @@ type CreateNodePoolRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "NodePool") to include in + // NullFields is a list of field names (e.g. "ClusterId") to include in // API requests with the JSON null value. By default, fields with empty // values are omitted from API requests. However, any field with an // empty value appearing in NullFields will be sent to the server as @@ -1345,10 +1571,8 @@ func (s *MasterAuth) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// MasterAuthorizedNetworksConfig: Master authorized networks is a Beta -// feature. -// Configuration options for the master authorized networks feature. -// Enabled +// MasterAuthorizedNetworksConfig: Configuration options for the master +// authorized networks feature. Enabled // master authorized networks will disallow all external traffic to // access // Kubernetes master through HTTPS except traffic from the given CIDR @@ -1552,9 +1776,10 @@ type NodeConfig struct { // or // minCpuPlatform: "Intel Sandy Bridge". For // more - // information, read [how to specify min CPU - // platform](https://cloud.google.com/compute/docs/instances/specify-min- - // cpu-platform) + // information, read [how to specify min + // CPU + // platform](https://cloud.google.com/compute/docs/instances/specify- + // min-cpu-platform) MinCpuPlatform string `json:"minCpuPlatform,omitempty"` // OauthScopes: The set of Google API scopes to be made available on all @@ -1830,6 +2055,15 @@ type Operation struct { // [RFC3339](https://www.ietf.org/rfc/rfc3339.txt) text format. EndTime string `json:"endTime,omitempty"` + // Location: [Output only] The name of the Google Compute + // Engine + // [zone](/compute/docs/regions-zones/regions-zones#available) + // or + // [region](/compute/docs/regions-zones/regions-zones#available) in + // which + // the cluster resides. + Location string `json:"location,omitempty"` + // Name: The server-assigned ID for the operation. Name string `json:"name,omitempty"` @@ -1884,6 +2118,7 @@ type Operation struct { // Engine // [zone](/compute/docs/zones#available) in which the operation // is taking place. + // This field is deprecated, use location instead. Zone string `json:"zone,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -1919,6 +2154,57 @@ func (s *Operation) MarshalJSON() ([]byte, error) { // successfully // completed. type RollbackNodePoolUpgradeRequest struct { + // ClusterId: Deprecated. The name of the cluster to rollback. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + + // Name: The name (project, location, cluster, node pool id) of the node + // poll to + // rollback upgrade. + // Specified in the format + // 'projects/*/locations/*/clusters/*/nodePools/*'. + Name string `json:"name,omitempty"` + + // NodePoolId: Deprecated. The name of the node pool to rollback. + // This field has been deprecated and replaced by the name field. + NodePoolId string `json:"nodePoolId,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ClusterId") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *RollbackNodePoolUpgradeRequest) MarshalJSON() ([]byte, error) { + type NoMethod RollbackNodePoolUpgradeRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } // ServerConfig: Kubernetes Engine service configuration. @@ -1976,6 +2262,30 @@ type SetAddonsConfigRequest struct { // cluster. AddonsConfig *AddonsConfig `json:"addonsConfig,omitempty"` + // ClusterId: Deprecated. The name of the cluster to upgrade. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + + // Name: The name (project, location, cluster) of the cluster to set + // addons. + // Specified in the format 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + // ForceSendFields is a list of field names (e.g. "AddonsConfig") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -2005,6 +2315,10 @@ func (s *SetAddonsConfigRequest) MarshalJSON() ([]byte, error) { // Engine // resources used by that cluster type SetLabelsRequest struct { + // ClusterId: Deprecated. The name of the cluster. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + // LabelFingerprint: The fingerprint of the previous set of labels for // this resource, // used to detect conflicts. The fingerprint is initially generated @@ -2018,10 +2332,30 @@ type SetLabelsRequest struct { // resource to get the latest fingerprint. LabelFingerprint string `json:"labelFingerprint,omitempty"` + // Name: The name (project, location, cluster id) of the cluster to set + // labels. + // Specified in the format 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://developers.google.com/console/help/new/#projec + // tnumber). + // This field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + // ResourceLabels: The labels to set for that cluster. ResourceLabels map[string]string `json:"resourceLabels,omitempty"` - // ForceSendFields is a list of field names (e.g. "LabelFingerprint") to + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2029,13 +2363,12 @@ type SetLabelsRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "LabelFingerprint") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an 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. "ClusterId") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` } @@ -2049,10 +2382,34 @@ func (s *SetLabelsRequest) MarshalJSON() ([]byte, error) { // ABAC authorization mechanism for // a cluster. type SetLegacyAbacRequest struct { + // ClusterId: Deprecated. The name of the cluster to update. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + // Enabled: Whether ABAC authorization will be enabled in the cluster. Enabled bool `json:"enabled,omitempty"` - // ForceSendFields is a list of field names (e.g. "Enabled") to + // Name: The name (project, location, cluster id) of the cluster to set + // legacy abac. + // Specified in the format 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2060,7 +2417,7 @@ type SetLegacyAbacRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Enabled") to include in + // NullFields is a list of field names (e.g. "ClusterId") to include in // API requests with the JSON null value. By default, fields with empty // values are omitted from API requests. However, any field with an // empty value appearing in NullFields will be sent to the server as @@ -2078,6 +2435,10 @@ func (s *SetLegacyAbacRequest) MarshalJSON() ([]byte, error) { // SetLocationsRequest: SetLocationsRequest sets the locations of the // cluster. type SetLocationsRequest struct { + // ClusterId: Deprecated. The name of the cluster to upgrade. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + // Locations: The desired list of Google Compute // Engine // [locations](/compute/docs/zones#available) in which the cluster's @@ -2091,7 +2452,27 @@ type SetLocationsRequest struct { // This list must always include the cluster's primary zone. Locations []string `json:"locations,omitempty"` - // ForceSendFields is a list of field names (e.g. "Locations") to + // Name: The name (project, location, cluster) of the cluster to set + // locations. + // Specified in the format 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2099,7 +2480,7 @@ type SetLocationsRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Locations") to include in + // NullFields is a list of field names (e.g. "ClusterId") to include in // API requests with the JSON null value. By default, fields with empty // values are omitted from API requests. However, any field with an // empty value appearing in NullFields will be sent to the server as @@ -2117,6 +2498,10 @@ func (s *SetLocationsRequest) MarshalJSON() ([]byte, error) { // SetLoggingServiceRequest: SetLoggingServiceRequest sets the logging // service of a cluster. type SetLoggingServiceRequest struct { + // ClusterId: Deprecated. The name of the cluster to upgrade. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + // LoggingService: The logging service the cluster should use to write // metrics. // Currently available options: @@ -2125,7 +2510,27 @@ type SetLoggingServiceRequest struct { // * "none" - no metrics will be exported from the cluster LoggingService string `json:"loggingService,omitempty"` - // ForceSendFields is a list of field names (e.g. "LoggingService") to + // Name: The name (project, location, cluster) of the cluster to set + // logging. + // Specified in the format 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2133,13 +2538,12 @@ type SetLoggingServiceRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "LoggingService") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an 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. "ClusterId") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` } @@ -2152,26 +2556,45 @@ func (s *SetLoggingServiceRequest) MarshalJSON() ([]byte, error) { // SetMaintenancePolicyRequest: SetMaintenancePolicyRequest sets the // maintenance policy for a cluster. type SetMaintenancePolicyRequest struct { + // ClusterId: The name of the cluster to update. + ClusterId string `json:"clusterId,omitempty"` + // MaintenancePolicy: The maintenance policy to be set for the cluster. // An empty field // clears the existing maintenance policy. MaintenancePolicy *MaintenancePolicy `json:"maintenancePolicy,omitempty"` - // ForceSendFields is a list of field names (e.g. "MaintenancePolicy") - // to unconditionally include in API requests. By default, fields with + // Name: The name (project, location, cluster id) of the cluster to set + // maintenance + // policy. + // Specified in the format 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + + // ProjectId: The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + ProjectId string `json:"projectId,omitempty"` + + // Zone: The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the cluster + // resides. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to + // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "MaintenancePolicy") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an 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. "ClusterId") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` } @@ -2199,9 +2622,33 @@ type SetMasterAuthRequest struct { // one. Action string `json:"action,omitempty"` + // ClusterId: Deprecated. The name of the cluster to upgrade. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + + // Name: The name (project, location, cluster) of the cluster to set + // auth. + // Specified in the format 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + // Update: A description of the update. Update *MasterAuth `json:"update,omitempty"` + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,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, @@ -2228,6 +2675,10 @@ func (s *SetMasterAuthRequest) MarshalJSON() ([]byte, error) { // SetMonitoringServiceRequest: SetMonitoringServiceRequest sets the // monitoring service of a cluster. type SetMonitoringServiceRequest struct { + // ClusterId: Deprecated. The name of the cluster to upgrade. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + // MonitoringService: The monitoring service the cluster should use to // write metrics. // Currently available options: @@ -2236,21 +2687,40 @@ type SetMonitoringServiceRequest struct { // * "none" - no metrics will be exported from the cluster MonitoringService string `json:"monitoringService,omitempty"` - // ForceSendFields is a list of field names (e.g. "MonitoringService") - // to unconditionally include in API requests. By default, fields with + // Name: The name (project, location, cluster) of the cluster to set + // monitoring. + // Specified in the format 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to + // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "MonitoringService") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an 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. "ClusterId") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` } @@ -2263,10 +2733,34 @@ func (s *SetMonitoringServiceRequest) MarshalJSON() ([]byte, error) { // SetNetworkPolicyRequest: SetNetworkPolicyRequest enables/disables // network policy for a cluster. type SetNetworkPolicyRequest struct { + // ClusterId: Deprecated. The name of the cluster. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + + // Name: The name (project, location, cluster id) of the cluster to set + // networking + // policy. Specified in the format 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + // NetworkPolicy: Configuration options for the NetworkPolicy feature. NetworkPolicy *NetworkPolicy `json:"networkPolicy,omitempty"` - // ForceSendFields is a list of field names (e.g. "NetworkPolicy") to + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://developers.google.com/console/help/new/#projec + // tnumber). + // This field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2274,10 +2768,10 @@ type SetNetworkPolicyRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "NetworkPolicy") to include - // in API requests with the JSON null value. By default, fields with - // 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. "ClusterId") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` @@ -2295,6 +2789,36 @@ type SetNodePoolAutoscalingRequest struct { // Autoscaling: Autoscaling configuration for the node pool. Autoscaling *NodePoolAutoscaling `json:"autoscaling,omitempty"` + // ClusterId: Deprecated. The name of the cluster to upgrade. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + + // Name: The name (project, location, cluster, node pool) of the node + // pool to set + // autoscaler settings. Specified in the + // format + // 'projects/*/locations/*/clusters/*/nodePools/*'. + Name string `json:"name,omitempty"` + + // NodePoolId: Deprecated. The name of the node pool to upgrade. + // This field has been deprecated and replaced by the name field. + NodePoolId string `json:"nodePoolId,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + // ForceSendFields is a list of field names (e.g. "Autoscaling") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -2322,10 +2846,40 @@ func (s *SetNodePoolAutoscalingRequest) MarshalJSON() ([]byte, error) { // node management properties of a node // pool. type SetNodePoolManagementRequest struct { + // ClusterId: Deprecated. The name of the cluster to update. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + // Management: NodeManagement configuration for the node pool. Management *NodeManagement `json:"management,omitempty"` - // ForceSendFields is a list of field names (e.g. "Management") to + // Name: The name (project, location, cluster, node pool id) of the node + // pool to set + // management properties. Specified in the + // format + // 'projects/*/locations/*/clusters/*/nodePools/*'. + Name string `json:"name,omitempty"` + + // NodePoolId: Deprecated. The name of the node pool to update. + // This field has been deprecated and replaced by the name field. + NodePoolId string `json:"nodePoolId,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2333,7 +2887,7 @@ type SetNodePoolManagementRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Management") to include in + // NullFields is a list of field names (e.g. "ClusterId") to include in // API requests with the JSON null value. By default, fields with empty // values are omitted from API requests. However, any field with an // empty value appearing in NullFields will be sent to the server as @@ -2352,10 +2906,40 @@ func (s *SetNodePoolManagementRequest) MarshalJSON() ([]byte, error) { // node // pool. type SetNodePoolSizeRequest struct { + // ClusterId: Deprecated. The name of the cluster to update. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + + // Name: The name (project, location, cluster, node pool id) of the node + // pool to set + // size. + // Specified in the format + // 'projects/*/locations/*/clusters/*/nodePools/*'. + Name string `json:"name,omitempty"` + // NodeCount: The desired node count for the pool. NodeCount int64 `json:"nodeCount,omitempty"` - // ForceSendFields is a list of field names (e.g. "NodeCount") to + // NodePoolId: Deprecated. The name of the node pool to update. + // This field has been deprecated and replaced by the name field. + NodePoolId string `json:"nodePoolId,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2363,7 +2947,7 @@ type SetNodePoolSizeRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "NodeCount") to include in + // NullFields is a list of field names (e.g. "ClusterId") to include in // API requests with the JSON null value. By default, fields with empty // values are omitted from API requests. However, any field with an // empty value appearing in NullFields will be sent to the server as @@ -2382,15 +2966,35 @@ func (s *SetNodePoolSizeRequest) MarshalJSON() ([]byte, error) { // the cluster and then performs // a node upgrade on each node pool to point to the new IP. type StartIPRotationRequest struct { -} + // ClusterId: Deprecated. The name of the cluster. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` -// UpdateClusterRequest: UpdateClusterRequest updates the settings of a -// cluster. -type UpdateClusterRequest struct { - // Update: A description of the update. - Update *ClusterUpdate `json:"update,omitempty"` + // Name: The name (project, location, cluster id) of the cluster to + // start IP + // rotation. Specified in the format + // 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` - // ForceSendFields is a list of field names (e.g. "Update") to + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://developers.google.com/console/help/new/#projec + // tnumber). + // This field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // RotateCredentials: Whether to rotate credentials during IP rotation. + RotateCredentials bool `json:"rotateCredentials,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2398,8 +3002,61 @@ type UpdateClusterRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Update") to include in API - // requests with the JSON null value. By default, fields with empty + // NullFields is a list of field names (e.g. "ClusterId") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *StartIPRotationRequest) MarshalJSON() ([]byte, error) { + type NoMethod StartIPRotationRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// UpdateClusterRequest: UpdateClusterRequest updates the settings of a +// cluster. +type UpdateClusterRequest struct { + // ClusterId: Deprecated. The name of the cluster to upgrade. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + + // Name: The name (project, location, cluster) of the cluster to + // update. + // Specified in the format 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Update: A description of the update. + Update *ClusterUpdate `json:"update,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ClusterId") to include in + // API requests with the JSON null value. By default, fields with empty // values are omitted from API requests. However, any field with an // empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. @@ -2416,12 +3073,45 @@ func (s *UpdateClusterRequest) MarshalJSON() ([]byte, error) { // UpdateMasterRequest: UpdateMasterRequest updates the master of the // cluster. type UpdateMasterRequest struct { - // MasterVersion: The Kubernetes version to change the master to. Use - // "-" to have the server - // automatically select the default version. + // ClusterId: Deprecated. The name of the cluster to upgrade. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + + // MasterVersion: The Kubernetes version to change the master to. + // + // Users may specify either explicit versions offered by Kubernetes + // Engine or + // version aliases, which have the following behavior: + // + // - "latest": picks the highest valid Kubernetes version + // - "1.X": picks the highest valid patch+gke.N patch in the 1.X + // version + // - "1.X.Y": picks the highest valid gke.N patch in the 1.X.Y version + // - "1.X.Y-gke.N": picks an explicit Kubernetes version + // - "-": picks the default Kubernetes version MasterVersion string `json:"masterVersion,omitempty"` - // ForceSendFields is a list of field names (e.g. "MasterVersion") to + // Name: The name (project, location, cluster) of the cluster to + // update. + // Specified in the format 'projects/*/locations/*/clusters/*'. + Name string `json:"name,omitempty"` + + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2429,10 +3119,10 @@ type UpdateMasterRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "MasterVersion") to include - // in API requests with the JSON null value. By default, fields with - // 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. "ClusterId") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` @@ -2447,16 +3137,56 @@ func (s *UpdateMasterRequest) MarshalJSON() ([]byte, error) { // UpdateNodePoolRequest: UpdateNodePoolRequests update a node pool's // image and/or version. type UpdateNodePoolRequest struct { + // ClusterId: Deprecated. The name of the cluster to upgrade. + // This field has been deprecated and replaced by the name field. + ClusterId string `json:"clusterId,omitempty"` + // ImageType: The desired image type for the node pool. ImageType string `json:"imageType,omitempty"` + // Name: The name (project, location, cluster, node pool) of the node + // pool to + // update. Specified in the + // format + // 'projects/*/locations/*/clusters/*/nodePools/*'. + Name string `json:"name,omitempty"` + + // NodePoolId: Deprecated. The name of the node pool to upgrade. + // This field has been deprecated and replaced by the name field. + NodePoolId string `json:"nodePoolId,omitempty"` + // NodeVersion: The Kubernetes version to change the nodes to (typically // an - // upgrade). Use `-` to upgrade to the latest version supported by - // the server. + // upgrade). + // + // Users may specify either explicit versions offered by Kubernetes + // Engine or + // version aliases, which have the following behavior: + // + // - "latest": picks the highest valid Kubernetes version + // - "1.X": picks the highest valid patch+gke.N patch in the 1.X + // version + // - "1.X.Y": picks the highest valid gke.N patch in the 1.X.Y version + // - "1.X.Y-gke.N": picks an explicit Kubernetes version + // - "-": picks the Kubernetes master version NodeVersion string `json:"nodeVersion,omitempty"` - // ForceSendFields is a list of field names (e.g. "ImageType") to + // ProjectId: Deprecated. The Google Developers Console [project ID or + // project + // number](https://support.google.com/cloud/answer/6158840). + // This + // field has been deprecated and replaced by the name field. + ProjectId string `json:"projectId,omitempty"` + + // Zone: Deprecated. The name of the Google Compute + // Engine + // [zone](/compute/docs/zones#available) in which the + // cluster + // resides. + // This field has been deprecated and replaced by the name field. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ClusterId") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2464,7 +3194,7 @@ type UpdateNodePoolRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "ImageType") to include in + // NullFields is a list of field names (e.g. "ClusterId") to include in // API requests with the JSON null value. By default, fields with empty // values are omitted from API requests. However, any field with an // empty value appearing in NullFields will be sent to the server as @@ -2479,6 +3209,4493 @@ func (s *UpdateNodePoolRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// method id "container.projects.locations.getServerConfig": + +type ProjectsLocationsGetServerConfigCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetServerConfig: Returns configuration info about the Kubernetes +// Engine service. +func (r *ProjectsLocationsService) GetServerConfig(name string) *ProjectsLocationsGetServerConfigCall { + c := &ProjectsLocationsGetServerConfigCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// ProjectId sets the optional parameter "projectId": Deprecated. The +// Google Developers Console [project ID or +// project +// number](https://support.google.com/cloud/answer/6158840). +// This +// field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsGetServerConfigCall) ProjectId(projectId string) *ProjectsLocationsGetServerConfigCall { + c.urlParams_.Set("projectId", projectId) + return c +} + +// Zone sets the optional parameter "zone": Deprecated. The name of the +// Google Compute Engine +// [zone](/compute/docs/zones#available) to return operations for. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsGetServerConfigCall) Zone(zone string) *ProjectsLocationsGetServerConfigCall { + c.urlParams_.Set("zone", zone) + 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 *ProjectsLocationsGetServerConfigCall) Fields(s ...googleapi.Field) *ProjectsLocationsGetServerConfigCall { + 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 *ProjectsLocationsGetServerConfigCall) IfNoneMatch(entityTag string) *ProjectsLocationsGetServerConfigCall { + 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 *ProjectsLocationsGetServerConfigCall) Context(ctx context.Context) *ProjectsLocationsGetServerConfigCall { + 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 *ProjectsLocationsGetServerConfigCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsGetServerConfigCall) 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, "v1/{+name}/serverConfig") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", 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 "container.projects.locations.getServerConfig" call. +// Exactly one of *ServerConfig or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *ServerConfig.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 *ProjectsLocationsGetServerConfigCall) Do(opts ...googleapi.CallOption) (*ServerConfig, 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 := &ServerConfig{ + 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 configuration info about the Kubernetes Engine service.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/serverConfig", + // "httpMethod": "GET", + // "id": "container.projects.locations.getServerConfig", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project and location) of the server config to get\nSpecified in the format 'projects/*/locations/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "projectId": { + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) to return operations for.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+name}/serverConfig", + // "response": { + // "$ref": "ServerConfig" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.completeIpRotation": + +type ProjectsLocationsClustersCompleteIpRotationCall struct { + s *Service + name string + completeiprotationrequest *CompleteIPRotationRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// CompleteIpRotation: Completes master IP rotation. +func (r *ProjectsLocationsClustersService) CompleteIpRotation(name string, completeiprotationrequest *CompleteIPRotationRequest) *ProjectsLocationsClustersCompleteIpRotationCall { + c := &ProjectsLocationsClustersCompleteIpRotationCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.completeiprotationrequest = completeiprotationrequest + 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 *ProjectsLocationsClustersCompleteIpRotationCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersCompleteIpRotationCall { + 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 *ProjectsLocationsClustersCompleteIpRotationCall) Context(ctx context.Context) *ProjectsLocationsClustersCompleteIpRotationCall { + 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 *ProjectsLocationsClustersCompleteIpRotationCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersCompleteIpRotationCall) 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.completeiprotationrequest) + 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}:completeIpRotation") + 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 "container.projects.locations.clusters.completeIpRotation" 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 *ProjectsLocationsClustersCompleteIpRotationCall) 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": "Completes master IP rotation.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:completeIpRotation", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.completeIpRotation", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster id) of the cluster to complete IP\nrotation. Specified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:completeIpRotation", + // "request": { + // "$ref": "CompleteIPRotationRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.create": + +type ProjectsLocationsClustersCreateCall struct { + s *Service + parent string + createclusterrequest *CreateClusterRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Create: Creates a cluster, consisting of the specified number and +// type of Google +// Compute Engine instances. +// +// By default, the cluster is created in the project's +// [default +// network](/compute/docs/networks-and-firewalls#networks). +// +// One firewall is added for the cluster. After cluster creation, +// the cluster creates routes for each node to allow the containers +// on that node to communicate with all other instances in +// the +// cluster. +// +// Finally, an entry is added to the project's global metadata +// indicating +// which CIDR range is being used by the cluster. +func (r *ProjectsLocationsClustersService) Create(parent string, createclusterrequest *CreateClusterRequest) *ProjectsLocationsClustersCreateCall { + c := &ProjectsLocationsClustersCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + c.createclusterrequest = createclusterrequest + 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 *ProjectsLocationsClustersCreateCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersCreateCall { + 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 *ProjectsLocationsClustersCreateCall) Context(ctx context.Context) *ProjectsLocationsClustersCreateCall { + 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 *ProjectsLocationsClustersCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersCreateCall) 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.createclusterrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/clusters") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", 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 "container.projects.locations.clusters.create" 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 *ProjectsLocationsClustersCreateCall) 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 cluster, consisting of the specified number and type of Google\nCompute Engine instances.\n\nBy default, the cluster is created in the project's\n[default network](/compute/docs/networks-and-firewalls#networks).\n\nOne firewall is added for the cluster. After cluster creation,\nthe cluster creates routes for each node to allow the containers\non that node to communicate with all other instances in the\ncluster.\n\nFinally, an entry is added to the project's global metadata indicating\nwhich CIDR range is being used by the cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.create", + // "parameterOrder": [ + // "parent" + // ], + // "parameters": { + // "parent": { + // "description": "The parent (project and location) where the cluster will be created.\nSpecified in the format 'projects/*/locations/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/clusters", + // "request": { + // "$ref": "CreateClusterRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.delete": + +type ProjectsLocationsClustersDeleteCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the cluster, including the Kubernetes endpoint and +// all worker +// nodes. +// +// Firewalls and routes that were configured during cluster creation +// are also deleted. +// +// Other Google Compute Engine resources that might be in use by the +// cluster +// (e.g. load balancer resources) will not be deleted if they weren't +// present +// at the initial create time. +func (r *ProjectsLocationsClustersService) Delete(name string) *ProjectsLocationsClustersDeleteCall { + c := &ProjectsLocationsClustersDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// ClusterId sets the optional parameter "clusterId": Deprecated. The +// name of the cluster to delete. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersDeleteCall) ClusterId(clusterId string) *ProjectsLocationsClustersDeleteCall { + c.urlParams_.Set("clusterId", clusterId) + return c +} + +// ProjectId sets the optional parameter "projectId": Deprecated. The +// Google Developers Console [project ID or +// project +// number](https://support.google.com/cloud/answer/6158840). +// This +// field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersDeleteCall) ProjectId(projectId string) *ProjectsLocationsClustersDeleteCall { + c.urlParams_.Set("projectId", projectId) + return c +} + +// Zone sets the optional parameter "zone": Deprecated. The name of the +// Google Compute Engine +// [zone](/compute/docs/zones#available) in which the +// cluster +// resides. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersDeleteCall) Zone(zone string) *ProjectsLocationsClustersDeleteCall { + c.urlParams_.Set("zone", zone) + 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 *ProjectsLocationsClustersDeleteCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersDeleteCall { + 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 *ProjectsLocationsClustersDeleteCall) Context(ctx context.Context) *ProjectsLocationsClustersDeleteCall { + 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 *ProjectsLocationsClustersDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersDeleteCall) 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, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", 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 "container.projects.locations.clusters.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 *ProjectsLocationsClustersDeleteCall) 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 cluster, including the Kubernetes endpoint and all worker\nnodes.\n\nFirewalls and routes that were configured during cluster creation\nare also deleted.\n\nOther Google Compute Engine resources that might be in use by the cluster\n(e.g. load balancer resources) will not be deleted if they weren't present\nat the initial create time.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}", + // "httpMethod": "DELETE", + // "id": "container.projects.locations.clusters.delete", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "clusterId": { + // "description": "Deprecated. The name of the cluster to delete.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "name": { + // "description": "The name (project, location, cluster) of the cluster to delete.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "projectId": { + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.get": + +type ProjectsLocationsClustersGetCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Gets the details of a specific cluster. +func (r *ProjectsLocationsClustersService) Get(name string) *ProjectsLocationsClustersGetCall { + c := &ProjectsLocationsClustersGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// ClusterId sets the optional parameter "clusterId": Deprecated. The +// name of the cluster to retrieve. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersGetCall) ClusterId(clusterId string) *ProjectsLocationsClustersGetCall { + c.urlParams_.Set("clusterId", clusterId) + return c +} + +// ProjectId sets the optional parameter "projectId": Deprecated. The +// Google Developers Console [project ID or +// project +// number](https://support.google.com/cloud/answer/6158840). +// This +// field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersGetCall) ProjectId(projectId string) *ProjectsLocationsClustersGetCall { + c.urlParams_.Set("projectId", projectId) + return c +} + +// Zone sets the optional parameter "zone": Deprecated. The name of the +// Google Compute Engine +// [zone](/compute/docs/zones#available) in which the +// cluster +// resides. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersGetCall) Zone(zone string) *ProjectsLocationsClustersGetCall { + c.urlParams_.Set("zone", zone) + 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 *ProjectsLocationsClustersGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersGetCall { + 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 *ProjectsLocationsClustersGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsClustersGetCall { + 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 *ProjectsLocationsClustersGetCall) Context(ctx context.Context) *ProjectsLocationsClustersGetCall { + 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 *ProjectsLocationsClustersGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersGetCall) 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, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", 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 "container.projects.locations.clusters.get" call. +// Exactly one of *Cluster or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Cluster.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 *ProjectsLocationsClustersGetCall) Do(opts ...googleapi.CallOption) (*Cluster, 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 := &Cluster{ + 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 details of a specific cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}", + // "httpMethod": "GET", + // "id": "container.projects.locations.clusters.get", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "clusterId": { + // "description": "Deprecated. The name of the cluster to retrieve.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "name": { + // "description": "The name (project, location, cluster) of the cluster to retrieve.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "projectId": { + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "response": { + // "$ref": "Cluster" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.list": + +type ProjectsLocationsClustersListCall struct { + s *Service + parent string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists all clusters owned by a project in either the specified +// zone or all +// zones. +func (r *ProjectsLocationsClustersService) List(parent string) *ProjectsLocationsClustersListCall { + c := &ProjectsLocationsClustersListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + return c +} + +// ProjectId sets the optional parameter "projectId": Deprecated. The +// Google Developers Console [project ID or +// project +// number](https://support.google.com/cloud/answer/6158840). +// This +// field has been deprecated and replaced by the parent field. +func (c *ProjectsLocationsClustersListCall) ProjectId(projectId string) *ProjectsLocationsClustersListCall { + c.urlParams_.Set("projectId", projectId) + return c +} + +// Zone sets the optional parameter "zone": Deprecated. The name of the +// Google Compute Engine +// [zone](/compute/docs/zones#available) in which the cluster +// resides, or "-" for all zones. +// This field has been deprecated and replaced by the parent field. +func (c *ProjectsLocationsClustersListCall) Zone(zone string) *ProjectsLocationsClustersListCall { + c.urlParams_.Set("zone", zone) + 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 *ProjectsLocationsClustersListCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersListCall { + 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 *ProjectsLocationsClustersListCall) IfNoneMatch(entityTag string) *ProjectsLocationsClustersListCall { + 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 *ProjectsLocationsClustersListCall) Context(ctx context.Context) *ProjectsLocationsClustersListCall { + 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 *ProjectsLocationsClustersListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersListCall) 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, "v1/{+parent}/clusters") + 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 "container.projects.locations.clusters.list" call. +// Exactly one of *ListClustersResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *ListClustersResponse.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 *ProjectsLocationsClustersListCall) Do(opts ...googleapi.CallOption) (*ListClustersResponse, 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 := &ListClustersResponse{ + 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 all clusters owned by a project in either the specified zone or all\nzones.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters", + // "httpMethod": "GET", + // "id": "container.projects.locations.clusters.list", + // "parameterOrder": [ + // "parent" + // ], + // "parameters": { + // "parent": { + // "description": "The parent (project and location) where the clusters will be listed.\nSpecified in the format 'projects/*/locations/*'.\nLocation \"-\" matches all zones and all regions.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "projectId": { + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the parent field.", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides, or \"-\" for all zones.\nThis field has been deprecated and replaced by the parent field.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/clusters", + // "response": { + // "$ref": "ListClustersResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.setAddons": + +type ProjectsLocationsClustersSetAddonsCall struct { + s *Service + name string + setaddonsconfigrequest *SetAddonsConfigRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetAddons: Sets the addons for a specific cluster. +func (r *ProjectsLocationsClustersService) SetAddons(name string, setaddonsconfigrequest *SetAddonsConfigRequest) *ProjectsLocationsClustersSetAddonsCall { + c := &ProjectsLocationsClustersSetAddonsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setaddonsconfigrequest = setaddonsconfigrequest + 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 *ProjectsLocationsClustersSetAddonsCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersSetAddonsCall { + 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 *ProjectsLocationsClustersSetAddonsCall) Context(ctx context.Context) *ProjectsLocationsClustersSetAddonsCall { + 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 *ProjectsLocationsClustersSetAddonsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersSetAddonsCall) 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.setaddonsconfigrequest) + 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}:setAddons") + 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 "container.projects.locations.clusters.setAddons" 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 *ProjectsLocationsClustersSetAddonsCall) 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 addons for a specific cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setAddons", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.setAddons", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster) of the cluster to set addons.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setAddons", + // "request": { + // "$ref": "SetAddonsConfigRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.setLegacyAbac": + +type ProjectsLocationsClustersSetLegacyAbacCall struct { + s *Service + name string + setlegacyabacrequest *SetLegacyAbacRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetLegacyAbac: Enables or disables the ABAC authorization mechanism +// on a cluster. +func (r *ProjectsLocationsClustersService) SetLegacyAbac(name string, setlegacyabacrequest *SetLegacyAbacRequest) *ProjectsLocationsClustersSetLegacyAbacCall { + c := &ProjectsLocationsClustersSetLegacyAbacCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setlegacyabacrequest = setlegacyabacrequest + 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 *ProjectsLocationsClustersSetLegacyAbacCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersSetLegacyAbacCall { + 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 *ProjectsLocationsClustersSetLegacyAbacCall) Context(ctx context.Context) *ProjectsLocationsClustersSetLegacyAbacCall { + 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 *ProjectsLocationsClustersSetLegacyAbacCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersSetLegacyAbacCall) 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.setlegacyabacrequest) + 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}:setLegacyAbac") + 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 "container.projects.locations.clusters.setLegacyAbac" 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 *ProjectsLocationsClustersSetLegacyAbacCall) 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": "Enables or disables the ABAC authorization mechanism on a cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setLegacyAbac", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.setLegacyAbac", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster id) of the cluster to set legacy abac.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setLegacyAbac", + // "request": { + // "$ref": "SetLegacyAbacRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.setLocations": + +type ProjectsLocationsClustersSetLocationsCall struct { + s *Service + name string + setlocationsrequest *SetLocationsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetLocations: Sets the locations for a specific cluster. +func (r *ProjectsLocationsClustersService) SetLocations(name string, setlocationsrequest *SetLocationsRequest) *ProjectsLocationsClustersSetLocationsCall { + c := &ProjectsLocationsClustersSetLocationsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setlocationsrequest = setlocationsrequest + 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 *ProjectsLocationsClustersSetLocationsCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersSetLocationsCall { + 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 *ProjectsLocationsClustersSetLocationsCall) Context(ctx context.Context) *ProjectsLocationsClustersSetLocationsCall { + 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 *ProjectsLocationsClustersSetLocationsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersSetLocationsCall) 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.setlocationsrequest) + 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}:setLocations") + 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 "container.projects.locations.clusters.setLocations" 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 *ProjectsLocationsClustersSetLocationsCall) 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 locations for a specific cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setLocations", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.setLocations", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster) of the cluster to set locations.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setLocations", + // "request": { + // "$ref": "SetLocationsRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.setLogging": + +type ProjectsLocationsClustersSetLoggingCall struct { + s *Service + name string + setloggingservicerequest *SetLoggingServiceRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetLogging: Sets the logging service for a specific cluster. +func (r *ProjectsLocationsClustersService) SetLogging(name string, setloggingservicerequest *SetLoggingServiceRequest) *ProjectsLocationsClustersSetLoggingCall { + c := &ProjectsLocationsClustersSetLoggingCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setloggingservicerequest = setloggingservicerequest + 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 *ProjectsLocationsClustersSetLoggingCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersSetLoggingCall { + 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 *ProjectsLocationsClustersSetLoggingCall) Context(ctx context.Context) *ProjectsLocationsClustersSetLoggingCall { + 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 *ProjectsLocationsClustersSetLoggingCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersSetLoggingCall) 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.setloggingservicerequest) + 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}:setLogging") + 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 "container.projects.locations.clusters.setLogging" 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 *ProjectsLocationsClustersSetLoggingCall) 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 logging service for a specific cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setLogging", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.setLogging", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster) of the cluster to set logging.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setLogging", + // "request": { + // "$ref": "SetLoggingServiceRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.setMaintenancePolicy": + +type ProjectsLocationsClustersSetMaintenancePolicyCall struct { + s *Service + name string + setmaintenancepolicyrequest *SetMaintenancePolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetMaintenancePolicy: Sets the maintenance policy for a cluster. +func (r *ProjectsLocationsClustersService) SetMaintenancePolicy(name string, setmaintenancepolicyrequest *SetMaintenancePolicyRequest) *ProjectsLocationsClustersSetMaintenancePolicyCall { + c := &ProjectsLocationsClustersSetMaintenancePolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setmaintenancepolicyrequest = setmaintenancepolicyrequest + 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 *ProjectsLocationsClustersSetMaintenancePolicyCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersSetMaintenancePolicyCall { + 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 *ProjectsLocationsClustersSetMaintenancePolicyCall) Context(ctx context.Context) *ProjectsLocationsClustersSetMaintenancePolicyCall { + 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 *ProjectsLocationsClustersSetMaintenancePolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersSetMaintenancePolicyCall) 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.setmaintenancepolicyrequest) + 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}:setMaintenancePolicy") + 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 "container.projects.locations.clusters.setMaintenancePolicy" 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 *ProjectsLocationsClustersSetMaintenancePolicyCall) 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 maintenance policy for a cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setMaintenancePolicy", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.setMaintenancePolicy", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster id) of the cluster to set maintenance\npolicy.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setMaintenancePolicy", + // "request": { + // "$ref": "SetMaintenancePolicyRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.setMasterAuth": + +type ProjectsLocationsClustersSetMasterAuthCall struct { + s *Service + name string + setmasterauthrequest *SetMasterAuthRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetMasterAuth: Used to set master auth materials. Currently supports +// :- +// Changing the admin password for a specific cluster. +// This can be either via password generation or explicitly set the +// password. +func (r *ProjectsLocationsClustersService) SetMasterAuth(name string, setmasterauthrequest *SetMasterAuthRequest) *ProjectsLocationsClustersSetMasterAuthCall { + c := &ProjectsLocationsClustersSetMasterAuthCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setmasterauthrequest = setmasterauthrequest + 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 *ProjectsLocationsClustersSetMasterAuthCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersSetMasterAuthCall { + 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 *ProjectsLocationsClustersSetMasterAuthCall) Context(ctx context.Context) *ProjectsLocationsClustersSetMasterAuthCall { + 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 *ProjectsLocationsClustersSetMasterAuthCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersSetMasterAuthCall) 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.setmasterauthrequest) + 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}:setMasterAuth") + 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 "container.projects.locations.clusters.setMasterAuth" 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 *ProjectsLocationsClustersSetMasterAuthCall) 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": "Used to set master auth materials. Currently supports :-\nChanging the admin password for a specific cluster.\nThis can be either via password generation or explicitly set the password.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setMasterAuth", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.setMasterAuth", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster) of the cluster to set auth.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setMasterAuth", + // "request": { + // "$ref": "SetMasterAuthRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.setMonitoring": + +type ProjectsLocationsClustersSetMonitoringCall struct { + s *Service + name string + setmonitoringservicerequest *SetMonitoringServiceRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetMonitoring: Sets the monitoring service for a specific cluster. +func (r *ProjectsLocationsClustersService) SetMonitoring(name string, setmonitoringservicerequest *SetMonitoringServiceRequest) *ProjectsLocationsClustersSetMonitoringCall { + c := &ProjectsLocationsClustersSetMonitoringCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setmonitoringservicerequest = setmonitoringservicerequest + 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 *ProjectsLocationsClustersSetMonitoringCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersSetMonitoringCall { + 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 *ProjectsLocationsClustersSetMonitoringCall) Context(ctx context.Context) *ProjectsLocationsClustersSetMonitoringCall { + 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 *ProjectsLocationsClustersSetMonitoringCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersSetMonitoringCall) 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.setmonitoringservicerequest) + 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}:setMonitoring") + 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 "container.projects.locations.clusters.setMonitoring" 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 *ProjectsLocationsClustersSetMonitoringCall) 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 monitoring service for a specific cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setMonitoring", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.setMonitoring", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster) of the cluster to set monitoring.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setMonitoring", + // "request": { + // "$ref": "SetMonitoringServiceRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.setNetworkPolicy": + +type ProjectsLocationsClustersSetNetworkPolicyCall struct { + s *Service + name string + setnetworkpolicyrequest *SetNetworkPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetNetworkPolicy: Enables/Disables Network Policy for a cluster. +func (r *ProjectsLocationsClustersService) SetNetworkPolicy(name string, setnetworkpolicyrequest *SetNetworkPolicyRequest) *ProjectsLocationsClustersSetNetworkPolicyCall { + c := &ProjectsLocationsClustersSetNetworkPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setnetworkpolicyrequest = setnetworkpolicyrequest + 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 *ProjectsLocationsClustersSetNetworkPolicyCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersSetNetworkPolicyCall { + 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 *ProjectsLocationsClustersSetNetworkPolicyCall) Context(ctx context.Context) *ProjectsLocationsClustersSetNetworkPolicyCall { + 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 *ProjectsLocationsClustersSetNetworkPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersSetNetworkPolicyCall) 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.setnetworkpolicyrequest) + 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}:setNetworkPolicy") + 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 "container.projects.locations.clusters.setNetworkPolicy" 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 *ProjectsLocationsClustersSetNetworkPolicyCall) 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": "Enables/Disables Network Policy for a cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setNetworkPolicy", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.setNetworkPolicy", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster id) of the cluster to set networking\npolicy. Specified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setNetworkPolicy", + // "request": { + // "$ref": "SetNetworkPolicyRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.setResourceLabels": + +type ProjectsLocationsClustersSetResourceLabelsCall struct { + s *Service + name string + setlabelsrequest *SetLabelsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetResourceLabels: Sets labels on a cluster. +func (r *ProjectsLocationsClustersService) SetResourceLabels(name string, setlabelsrequest *SetLabelsRequest) *ProjectsLocationsClustersSetResourceLabelsCall { + c := &ProjectsLocationsClustersSetResourceLabelsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setlabelsrequest = setlabelsrequest + 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 *ProjectsLocationsClustersSetResourceLabelsCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersSetResourceLabelsCall { + 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 *ProjectsLocationsClustersSetResourceLabelsCall) Context(ctx context.Context) *ProjectsLocationsClustersSetResourceLabelsCall { + 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 *ProjectsLocationsClustersSetResourceLabelsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersSetResourceLabelsCall) 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.setlabelsrequest) + 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}:setResourceLabels") + 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 "container.projects.locations.clusters.setResourceLabels" 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 *ProjectsLocationsClustersSetResourceLabelsCall) 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 labels on a cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:setResourceLabels", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.setResourceLabels", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster id) of the cluster to set labels.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setResourceLabels", + // "request": { + // "$ref": "SetLabelsRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.startIpRotation": + +type ProjectsLocationsClustersStartIpRotationCall struct { + s *Service + name string + startiprotationrequest *StartIPRotationRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// StartIpRotation: Start master IP rotation. +func (r *ProjectsLocationsClustersService) StartIpRotation(name string, startiprotationrequest *StartIPRotationRequest) *ProjectsLocationsClustersStartIpRotationCall { + c := &ProjectsLocationsClustersStartIpRotationCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.startiprotationrequest = startiprotationrequest + 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 *ProjectsLocationsClustersStartIpRotationCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersStartIpRotationCall { + 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 *ProjectsLocationsClustersStartIpRotationCall) Context(ctx context.Context) *ProjectsLocationsClustersStartIpRotationCall { + 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 *ProjectsLocationsClustersStartIpRotationCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersStartIpRotationCall) 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.startiprotationrequest) + 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}:startIpRotation") + 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 "container.projects.locations.clusters.startIpRotation" 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 *ProjectsLocationsClustersStartIpRotationCall) 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": "Start master IP rotation.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:startIpRotation", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.startIpRotation", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster id) of the cluster to start IP\nrotation. Specified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:startIpRotation", + // "request": { + // "$ref": "StartIPRotationRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.update": + +type ProjectsLocationsClustersUpdateCall struct { + s *Service + name string + updateclusterrequest *UpdateClusterRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Update: Updates the settings of a specific cluster. +func (r *ProjectsLocationsClustersService) Update(name string, updateclusterrequest *UpdateClusterRequest) *ProjectsLocationsClustersUpdateCall { + c := &ProjectsLocationsClustersUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.updateclusterrequest = updateclusterrequest + 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 *ProjectsLocationsClustersUpdateCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersUpdateCall { + 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 *ProjectsLocationsClustersUpdateCall) Context(ctx context.Context) *ProjectsLocationsClustersUpdateCall { + 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 *ProjectsLocationsClustersUpdateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersUpdateCall) 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.updateclusterrequest) + 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}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PUT", 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 "container.projects.locations.clusters.update" 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 *ProjectsLocationsClustersUpdateCall) 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 settings of a specific cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}", + // "httpMethod": "PUT", + // "id": "container.projects.locations.clusters.update", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster) of the cluster to update.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "request": { + // "$ref": "UpdateClusterRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.updateMaster": + +type ProjectsLocationsClustersUpdateMasterCall struct { + s *Service + name string + updatemasterrequest *UpdateMasterRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// UpdateMaster: Updates the master for a specific cluster. +func (r *ProjectsLocationsClustersService) UpdateMaster(name string, updatemasterrequest *UpdateMasterRequest) *ProjectsLocationsClustersUpdateMasterCall { + c := &ProjectsLocationsClustersUpdateMasterCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.updatemasterrequest = updatemasterrequest + 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 *ProjectsLocationsClustersUpdateMasterCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersUpdateMasterCall { + 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 *ProjectsLocationsClustersUpdateMasterCall) Context(ctx context.Context) *ProjectsLocationsClustersUpdateMasterCall { + 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 *ProjectsLocationsClustersUpdateMasterCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersUpdateMasterCall) 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.updatemasterrequest) + 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}:updateMaster") + 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 "container.projects.locations.clusters.updateMaster" 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 *ProjectsLocationsClustersUpdateMasterCall) 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 master for a specific cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}:updateMaster", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.updateMaster", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster) of the cluster to update.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:updateMaster", + // "request": { + // "$ref": "UpdateMasterRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.nodePools.create": + +type ProjectsLocationsClustersNodePoolsCreateCall struct { + s *Service + parent string + createnodepoolrequest *CreateNodePoolRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Create: Creates a node pool for a cluster. +func (r *ProjectsLocationsClustersNodePoolsService) Create(parent string, createnodepoolrequest *CreateNodePoolRequest) *ProjectsLocationsClustersNodePoolsCreateCall { + c := &ProjectsLocationsClustersNodePoolsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + c.createnodepoolrequest = createnodepoolrequest + 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 *ProjectsLocationsClustersNodePoolsCreateCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersNodePoolsCreateCall { + 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 *ProjectsLocationsClustersNodePoolsCreateCall) Context(ctx context.Context) *ProjectsLocationsClustersNodePoolsCreateCall { + 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 *ProjectsLocationsClustersNodePoolsCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersNodePoolsCreateCall) 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.createnodepoolrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/nodePools") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", 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 "container.projects.locations.clusters.nodePools.create" 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 *ProjectsLocationsClustersNodePoolsCreateCall) 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 node pool for a cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.nodePools.create", + // "parameterOrder": [ + // "parent" + // ], + // "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/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/nodePools", + // "request": { + // "$ref": "CreateNodePoolRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.nodePools.delete": + +type ProjectsLocationsClustersNodePoolsDeleteCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes a node pool from a cluster. +func (r *ProjectsLocationsClustersNodePoolsService) Delete(name string) *ProjectsLocationsClustersNodePoolsDeleteCall { + c := &ProjectsLocationsClustersNodePoolsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// ClusterId sets the optional parameter "clusterId": Deprecated. The +// name of the cluster. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersNodePoolsDeleteCall) ClusterId(clusterId string) *ProjectsLocationsClustersNodePoolsDeleteCall { + c.urlParams_.Set("clusterId", clusterId) + return c +} + +// NodePoolId sets the optional parameter "nodePoolId": Deprecated. The +// name of the node pool to delete. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersNodePoolsDeleteCall) NodePoolId(nodePoolId string) *ProjectsLocationsClustersNodePoolsDeleteCall { + c.urlParams_.Set("nodePoolId", nodePoolId) + return c +} + +// ProjectId sets the optional parameter "projectId": Deprecated. The +// Google Developers Console [project ID or +// project +// number](https://developers.google.com/console/help/new/#projec +// tnumber). +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersNodePoolsDeleteCall) ProjectId(projectId string) *ProjectsLocationsClustersNodePoolsDeleteCall { + c.urlParams_.Set("projectId", projectId) + return c +} + +// Zone sets the optional parameter "zone": Deprecated. The name of the +// Google Compute Engine +// [zone](/compute/docs/zones#available) in which the +// cluster +// resides. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersNodePoolsDeleteCall) Zone(zone string) *ProjectsLocationsClustersNodePoolsDeleteCall { + c.urlParams_.Set("zone", zone) + 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 *ProjectsLocationsClustersNodePoolsDeleteCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersNodePoolsDeleteCall { + 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 *ProjectsLocationsClustersNodePoolsDeleteCall) Context(ctx context.Context) *ProjectsLocationsClustersNodePoolsDeleteCall { + 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 *ProjectsLocationsClustersNodePoolsDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersNodePoolsDeleteCall) 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, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", 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 "container.projects.locations.clusters.nodePools.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 *ProjectsLocationsClustersNodePoolsDeleteCall) 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 node pool from a cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}", + // "httpMethod": "DELETE", + // "id": "container.projects.locations.clusters.nodePools.delete", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "clusterId": { + // "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "name": { + // "description": "The name (project, location, cluster, node pool id) of the node pool to\ndelete. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "nodePoolId": { + // "description": "Deprecated. The name of the node pool to delete.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "projectId": { + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.nodePools.get": + +type ProjectsLocationsClustersNodePoolsGetCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Retrieves the node pool requested. +func (r *ProjectsLocationsClustersNodePoolsService) Get(name string) *ProjectsLocationsClustersNodePoolsGetCall { + c := &ProjectsLocationsClustersNodePoolsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// ClusterId sets the optional parameter "clusterId": Deprecated. The +// name of the cluster. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersNodePoolsGetCall) ClusterId(clusterId string) *ProjectsLocationsClustersNodePoolsGetCall { + c.urlParams_.Set("clusterId", clusterId) + return c +} + +// NodePoolId sets the optional parameter "nodePoolId": Deprecated. The +// name of the node pool. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersNodePoolsGetCall) NodePoolId(nodePoolId string) *ProjectsLocationsClustersNodePoolsGetCall { + c.urlParams_.Set("nodePoolId", nodePoolId) + return c +} + +// ProjectId sets the optional parameter "projectId": Deprecated. The +// Google Developers Console [project ID or +// project +// number](https://developers.google.com/console/help/new/#projec +// tnumber). +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersNodePoolsGetCall) ProjectId(projectId string) *ProjectsLocationsClustersNodePoolsGetCall { + c.urlParams_.Set("projectId", projectId) + return c +} + +// Zone sets the optional parameter "zone": Deprecated. The name of the +// Google Compute Engine +// [zone](/compute/docs/zones#available) in which the +// cluster +// resides. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsClustersNodePoolsGetCall) Zone(zone string) *ProjectsLocationsClustersNodePoolsGetCall { + c.urlParams_.Set("zone", zone) + 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 *ProjectsLocationsClustersNodePoolsGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersNodePoolsGetCall { + 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 *ProjectsLocationsClustersNodePoolsGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsClustersNodePoolsGetCall { + 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 *ProjectsLocationsClustersNodePoolsGetCall) Context(ctx context.Context) *ProjectsLocationsClustersNodePoolsGetCall { + 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 *ProjectsLocationsClustersNodePoolsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersNodePoolsGetCall) 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, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", 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 "container.projects.locations.clusters.nodePools.get" call. +// Exactly one of *NodePool or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *NodePool.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 *ProjectsLocationsClustersNodePoolsGetCall) Do(opts ...googleapi.CallOption) (*NodePool, 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 := &NodePool{ + 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 node pool requested.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}", + // "httpMethod": "GET", + // "id": "container.projects.locations.clusters.nodePools.get", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "clusterId": { + // "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "name": { + // "description": "The name (project, location, cluster, node pool id) of the node pool to\nget. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "nodePoolId": { + // "description": "Deprecated. The name of the node pool.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "projectId": { + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "response": { + // "$ref": "NodePool" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.nodePools.list": + +type ProjectsLocationsClustersNodePoolsListCall struct { + s *Service + parent string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists the node pools for a cluster. +func (r *ProjectsLocationsClustersNodePoolsService) List(parent string) *ProjectsLocationsClustersNodePoolsListCall { + c := &ProjectsLocationsClustersNodePoolsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + return c +} + +// ClusterId sets the optional parameter "clusterId": Deprecated. The +// name of the cluster. +// This field has been deprecated and replaced by the parent field. +func (c *ProjectsLocationsClustersNodePoolsListCall) ClusterId(clusterId string) *ProjectsLocationsClustersNodePoolsListCall { + c.urlParams_.Set("clusterId", clusterId) + return c +} + +// ProjectId sets the optional parameter "projectId": Deprecated. The +// Google Developers Console [project ID or +// project +// number](https://developers.google.com/console/help/new/#projec +// tnumber). +// This field has been deprecated and replaced by the parent field. +func (c *ProjectsLocationsClustersNodePoolsListCall) ProjectId(projectId string) *ProjectsLocationsClustersNodePoolsListCall { + c.urlParams_.Set("projectId", projectId) + return c +} + +// Zone sets the optional parameter "zone": Deprecated. The name of the +// Google Compute Engine +// [zone](/compute/docs/zones#available) in which the +// cluster +// resides. +// This field has been deprecated and replaced by the parent field. +func (c *ProjectsLocationsClustersNodePoolsListCall) Zone(zone string) *ProjectsLocationsClustersNodePoolsListCall { + c.urlParams_.Set("zone", zone) + 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 *ProjectsLocationsClustersNodePoolsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersNodePoolsListCall { + 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 *ProjectsLocationsClustersNodePoolsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsClustersNodePoolsListCall { + 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 *ProjectsLocationsClustersNodePoolsListCall) Context(ctx context.Context) *ProjectsLocationsClustersNodePoolsListCall { + 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 *ProjectsLocationsClustersNodePoolsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersNodePoolsListCall) 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, "v1/{+parent}/nodePools") + 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 "container.projects.locations.clusters.nodePools.list" call. +// Exactly one of *ListNodePoolsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *ListNodePoolsResponse.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 *ProjectsLocationsClustersNodePoolsListCall) Do(opts ...googleapi.CallOption) (*ListNodePoolsResponse, 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 := &ListNodePoolsResponse{ + 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 node pools for a cluster.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools", + // "httpMethod": "GET", + // "id": "container.projects.locations.clusters.nodePools.list", + // "parameterOrder": [ + // "parent" + // ], + // "parameters": { + // "clusterId": { + // "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the parent field.", + // "location": "query", + // "type": "string" + // }, + // "parent": { + // "description": "The parent (project, location, cluster id) where the node pools will be\nlisted. Specified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "projectId": { + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the parent field.", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the parent field.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/nodePools", + // "response": { + // "$ref": "ListNodePoolsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.nodePools.rollback": + +type ProjectsLocationsClustersNodePoolsRollbackCall struct { + s *Service + name string + rollbacknodepoolupgraderequest *RollbackNodePoolUpgradeRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Rollback: Roll back the previously Aborted or Failed NodePool +// upgrade. +// This will be an no-op if the last upgrade successfully completed. +func (r *ProjectsLocationsClustersNodePoolsService) Rollback(name string, rollbacknodepoolupgraderequest *RollbackNodePoolUpgradeRequest) *ProjectsLocationsClustersNodePoolsRollbackCall { + c := &ProjectsLocationsClustersNodePoolsRollbackCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.rollbacknodepoolupgraderequest = rollbacknodepoolupgraderequest + 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 *ProjectsLocationsClustersNodePoolsRollbackCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersNodePoolsRollbackCall { + 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 *ProjectsLocationsClustersNodePoolsRollbackCall) Context(ctx context.Context) *ProjectsLocationsClustersNodePoolsRollbackCall { + 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 *ProjectsLocationsClustersNodePoolsRollbackCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersNodePoolsRollbackCall) 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.rollbacknodepoolupgraderequest) + 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}:rollback") + 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 "container.projects.locations.clusters.nodePools.rollback" 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 *ProjectsLocationsClustersNodePoolsRollbackCall) 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": "Roll back the previously Aborted or Failed NodePool upgrade.\nThis will be an no-op if the last upgrade successfully completed.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}:rollback", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.nodePools.rollback", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster, node pool id) of the node poll to\nrollback upgrade.\nSpecified in the format 'projects/*/locations/*/clusters/*/nodePools/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:rollback", + // "request": { + // "$ref": "RollbackNodePoolUpgradeRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.nodePools.setAutoscaling": + +type ProjectsLocationsClustersNodePoolsSetAutoscalingCall struct { + s *Service + name string + setnodepoolautoscalingrequest *SetNodePoolAutoscalingRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetAutoscaling: Sets the autoscaling settings for a specific node +// pool. +func (r *ProjectsLocationsClustersNodePoolsService) SetAutoscaling(name string, setnodepoolautoscalingrequest *SetNodePoolAutoscalingRequest) *ProjectsLocationsClustersNodePoolsSetAutoscalingCall { + c := &ProjectsLocationsClustersNodePoolsSetAutoscalingCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setnodepoolautoscalingrequest = setnodepoolautoscalingrequest + 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 *ProjectsLocationsClustersNodePoolsSetAutoscalingCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersNodePoolsSetAutoscalingCall { + 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 *ProjectsLocationsClustersNodePoolsSetAutoscalingCall) Context(ctx context.Context) *ProjectsLocationsClustersNodePoolsSetAutoscalingCall { + 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 *ProjectsLocationsClustersNodePoolsSetAutoscalingCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersNodePoolsSetAutoscalingCall) 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.setnodepoolautoscalingrequest) + 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}:setAutoscaling") + 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 "container.projects.locations.clusters.nodePools.setAutoscaling" 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 *ProjectsLocationsClustersNodePoolsSetAutoscalingCall) 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 autoscaling settings for a specific node pool.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}:setAutoscaling", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.nodePools.setAutoscaling", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster, node pool) of the node pool to set\nautoscaler settings. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setAutoscaling", + // "request": { + // "$ref": "SetNodePoolAutoscalingRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.nodePools.setManagement": + +type ProjectsLocationsClustersNodePoolsSetManagementCall struct { + s *Service + name string + setnodepoolmanagementrequest *SetNodePoolManagementRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetManagement: Sets the NodeManagement options for a node pool. +func (r *ProjectsLocationsClustersNodePoolsService) SetManagement(name string, setnodepoolmanagementrequest *SetNodePoolManagementRequest) *ProjectsLocationsClustersNodePoolsSetManagementCall { + c := &ProjectsLocationsClustersNodePoolsSetManagementCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setnodepoolmanagementrequest = setnodepoolmanagementrequest + 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 *ProjectsLocationsClustersNodePoolsSetManagementCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersNodePoolsSetManagementCall { + 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 *ProjectsLocationsClustersNodePoolsSetManagementCall) Context(ctx context.Context) *ProjectsLocationsClustersNodePoolsSetManagementCall { + 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 *ProjectsLocationsClustersNodePoolsSetManagementCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersNodePoolsSetManagementCall) 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.setnodepoolmanagementrequest) + 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}:setManagement") + 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 "container.projects.locations.clusters.nodePools.setManagement" 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 *ProjectsLocationsClustersNodePoolsSetManagementCall) 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 NodeManagement options for a node pool.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}:setManagement", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.nodePools.setManagement", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster, node pool id) of the node pool to set\nmanagement properties. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setManagement", + // "request": { + // "$ref": "SetNodePoolManagementRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.nodePools.setSize": + +type ProjectsLocationsClustersNodePoolsSetSizeCall struct { + s *Service + name string + setnodepoolsizerequest *SetNodePoolSizeRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetSize: Sets the size for a specific node pool. +func (r *ProjectsLocationsClustersNodePoolsService) SetSize(name string, setnodepoolsizerequest *SetNodePoolSizeRequest) *ProjectsLocationsClustersNodePoolsSetSizeCall { + c := &ProjectsLocationsClustersNodePoolsSetSizeCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.setnodepoolsizerequest = setnodepoolsizerequest + 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 *ProjectsLocationsClustersNodePoolsSetSizeCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersNodePoolsSetSizeCall { + 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 *ProjectsLocationsClustersNodePoolsSetSizeCall) Context(ctx context.Context) *ProjectsLocationsClustersNodePoolsSetSizeCall { + 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 *ProjectsLocationsClustersNodePoolsSetSizeCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersNodePoolsSetSizeCall) 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.setnodepoolsizerequest) + 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}:setSize") + 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 "container.projects.locations.clusters.nodePools.setSize" 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 *ProjectsLocationsClustersNodePoolsSetSizeCall) 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 size for a specific node pool.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}:setSize", + // "httpMethod": "POST", + // "id": "container.projects.locations.clusters.nodePools.setSize", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster, node pool id) of the node pool to set\nsize.\nSpecified in the format 'projects/*/locations/*/clusters/*/nodePools/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:setSize", + // "request": { + // "$ref": "SetNodePoolSizeRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.clusters.nodePools.update": + +type ProjectsLocationsClustersNodePoolsUpdateCall struct { + s *Service + name string + updatenodepoolrequest *UpdateNodePoolRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Update: Updates the version and/or image type for a specific node +// pool. +func (r *ProjectsLocationsClustersNodePoolsService) Update(name string, updatenodepoolrequest *UpdateNodePoolRequest) *ProjectsLocationsClustersNodePoolsUpdateCall { + c := &ProjectsLocationsClustersNodePoolsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.updatenodepoolrequest = updatenodepoolrequest + 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 *ProjectsLocationsClustersNodePoolsUpdateCall) Fields(s ...googleapi.Field) *ProjectsLocationsClustersNodePoolsUpdateCall { + 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 *ProjectsLocationsClustersNodePoolsUpdateCall) Context(ctx context.Context) *ProjectsLocationsClustersNodePoolsUpdateCall { + 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 *ProjectsLocationsClustersNodePoolsUpdateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsClustersNodePoolsUpdateCall) 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.updatenodepoolrequest) + 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}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PUT", 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 "container.projects.locations.clusters.nodePools.update" 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 *ProjectsLocationsClustersNodePoolsUpdateCall) 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 version and/or image type for a specific node pool.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/clusters/{clustersId}/nodePools/{nodePoolsId}", + // "httpMethod": "PUT", + // "id": "container.projects.locations.clusters.nodePools.update", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, cluster, node pool) of the node pool to\nupdate. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+/nodePools/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "request": { + // "$ref": "UpdateNodePoolRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.operations.cancel": + +type ProjectsLocationsOperationsCancelCall struct { + s *Service + name string + canceloperationrequest *CancelOperationRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Cancel: Cancels the specified operation. +func (r *ProjectsLocationsOperationsService) Cancel(name string, canceloperationrequest *CancelOperationRequest) *ProjectsLocationsOperationsCancelCall { + c := &ProjectsLocationsOperationsCancelCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.canceloperationrequest = canceloperationrequest + 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 *ProjectsLocationsOperationsCancelCall) Fields(s ...googleapi.Field) *ProjectsLocationsOperationsCancelCall { + 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 *ProjectsLocationsOperationsCancelCall) Context(ctx context.Context) *ProjectsLocationsOperationsCancelCall { + 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 *ProjectsLocationsOperationsCancelCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsOperationsCancelCall) 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.canceloperationrequest) + 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}:cancel") + 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 "container.projects.locations.operations.cancel" 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 *ProjectsLocationsOperationsCancelCall) 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": "Cancels the specified operation.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}:cancel", + // "httpMethod": "POST", + // "id": "container.projects.locations.operations.cancel", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, operation id) of the operation to cancel.\nSpecified in the format 'projects/*/locations/*/operations/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/operations/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:cancel", + // "request": { + // "$ref": "CancelOperationRequest" + // }, + // "response": { + // "$ref": "Empty" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.operations.get": + +type ProjectsLocationsOperationsGetCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Gets the specified operation. +func (r *ProjectsLocationsOperationsService) Get(name string) *ProjectsLocationsOperationsGetCall { + c := &ProjectsLocationsOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// OperationId sets the optional parameter "operationId": Deprecated. +// The server-assigned `name` of the operation. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsOperationsGetCall) OperationId(operationId string) *ProjectsLocationsOperationsGetCall { + c.urlParams_.Set("operationId", operationId) + return c +} + +// ProjectId sets the optional parameter "projectId": Deprecated. The +// Google Developers Console [project ID or +// project +// number](https://support.google.com/cloud/answer/6158840). +// This +// field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsOperationsGetCall) ProjectId(projectId string) *ProjectsLocationsOperationsGetCall { + c.urlParams_.Set("projectId", projectId) + return c +} + +// Zone sets the optional parameter "zone": Deprecated. The name of the +// Google Compute Engine +// [zone](/compute/docs/zones#available) in which the +// cluster +// resides. +// This field has been deprecated and replaced by the name field. +func (c *ProjectsLocationsOperationsGetCall) Zone(zone string) *ProjectsLocationsOperationsGetCall { + c.urlParams_.Set("zone", zone) + 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 *ProjectsLocationsOperationsGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsOperationsGetCall { + 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 *ProjectsLocationsOperationsGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsOperationsGetCall { + 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 *ProjectsLocationsOperationsGetCall) Context(ctx context.Context) *ProjectsLocationsOperationsGetCall { + 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 *ProjectsLocationsOperationsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsOperationsGetCall) 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, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", 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 "container.projects.locations.operations.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 *ProjectsLocationsOperationsGetCall) 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": "Gets the specified operation.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}", + // "httpMethod": "GET", + // "id": "container.projects.locations.operations.get", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name (project, location, operation id) of the operation to get.\nSpecified in the format 'projects/*/locations/*/operations/*'.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/operations/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "operationId": { + // "description": "Deprecated. The server-assigned `name` of the operation.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "projectId": { + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "container.projects.locations.operations.list": + +type ProjectsLocationsOperationsListCall struct { + s *Service + parent string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists all operations in a project in a specific zone or all +// zones. +func (r *ProjectsLocationsOperationsService) List(parent string) *ProjectsLocationsOperationsListCall { + c := &ProjectsLocationsOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + return c +} + +// ProjectId sets the optional parameter "projectId": Deprecated. The +// Google Developers Console [project ID or +// project +// number](https://support.google.com/cloud/answer/6158840). +// This +// field has been deprecated and replaced by the parent field. +func (c *ProjectsLocationsOperationsListCall) ProjectId(projectId string) *ProjectsLocationsOperationsListCall { + c.urlParams_.Set("projectId", projectId) + return c +} + +// Zone sets the optional parameter "zone": Deprecated. The name of the +// Google Compute Engine +// [zone](/compute/docs/zones#available) to return operations for, or +// `-` for +// all zones. This field has been deprecated and replaced by the parent +// field. +func (c *ProjectsLocationsOperationsListCall) Zone(zone string) *ProjectsLocationsOperationsListCall { + c.urlParams_.Set("zone", zone) + 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 *ProjectsLocationsOperationsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsOperationsListCall { + 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 *ProjectsLocationsOperationsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsOperationsListCall { + 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 *ProjectsLocationsOperationsListCall) Context(ctx context.Context) *ProjectsLocationsOperationsListCall { + 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 *ProjectsLocationsOperationsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsOperationsListCall) 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, "v1/{+parent}/operations") + 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 "container.projects.locations.operations.list" call. +// Exactly one of *ListOperationsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *ListOperationsResponse.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 *ProjectsLocationsOperationsListCall) Do(opts ...googleapi.CallOption) (*ListOperationsResponse, 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 := &ListOperationsResponse{ + 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 all operations in a project in a specific zone or all zones.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations", + // "httpMethod": "GET", + // "id": "container.projects.locations.operations.list", + // "parameterOrder": [ + // "parent" + // ], + // "parameters": { + // "parent": { + // "description": "The parent (project and location) where the operations will be listed.\nSpecified in the format 'projects/*/locations/*'.\nLocation \"-\" matches all zones and all regions.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "projectId": { + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the parent field.", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) to return operations for, or `-` for\nall zones. This field has been deprecated and replaced by the parent field.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/operations", + // "response": { + // "$ref": "ListOperationsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + // method id "container.projects.zones.getServerconfig": type ProjectsZonesGetServerconfigCall struct { @@ -2500,6 +7717,14 @@ func (r *ProjectsZonesService) GetServerconfig(projectId string, zone string) *P return c } +// Name sets the optional parameter "name": The name (project and +// location) of the server config to get +// Specified in the format 'projects/*/locations/*'. +func (c *ProjectsZonesGetServerconfigCall) Name(name string) *ProjectsZonesGetServerconfigCall { + 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. @@ -2604,14 +7829,19 @@ func (c *ProjectsZonesGetServerconfigCall) Do(opts ...googleapi.CallOption) (*Se // "zone" // ], // "parameters": { + // "name": { + // "description": "The name (project and location) of the server config to get\nSpecified in the format 'projects/*/locations/*'.", + // "location": "query", + // "type": "string" + // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine [zone](/compute/docs/zones#available)\nto return operations for.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) to return operations for.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -2641,7 +7871,7 @@ type ProjectsZonesClustersAddonsCall struct { header_ http.Header } -// Addons: Sets the addons of a specific cluster. +// Addons: Sets the addons for a specific cluster. func (r *ProjectsZonesClustersService) Addons(projectId string, zone string, clusterId string, setaddonsconfigrequest *SetAddonsConfigRequest) *ProjectsZonesClustersAddonsCall { c := &ProjectsZonesClustersAddonsCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.projectId = projectId @@ -2739,7 +7969,7 @@ func (c *ProjectsZonesClustersAddonsCall) Do(opts ...googleapi.CallOption) (*Ope } return ret, nil // { - // "description": "Sets the addons of a specific cluster.", + // "description": "Sets the addons for a specific cluster.", // "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/addons", // "httpMethod": "POST", // "id": "container.projects.zones.clusters.addons", @@ -2750,19 +7980,19 @@ func (c *ProjectsZonesClustersAddonsCall) Do(opts ...googleapi.CallOption) (*Ope // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to upgrade.", + // "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -2904,19 +8134,19 @@ func (c *ProjectsZonesClustersCompleteIpRotationCall) Do(opts ...googleapi.CallO // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster.", + // "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -3070,13 +8300,13 @@ func (c *ProjectsZonesClustersCreateCall) Do(opts ...googleapi.CallOption) (*Ope // ], // "parameters": { // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" @@ -3128,6 +8358,14 @@ func (r *ProjectsZonesClustersService) Delete(projectId string, zone string, clu return c } +// Name sets the optional parameter "name": The name (project, location, +// cluster) of the cluster to delete. +// Specified in the format 'projects/*/locations/*/clusters/*'. +func (c *ProjectsZonesClustersDeleteCall) Name(name string) *ProjectsZonesClustersDeleteCall { + 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. @@ -3222,19 +8460,24 @@ func (c *ProjectsZonesClustersDeleteCall) Do(opts ...googleapi.CallOption) (*Ope // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to delete.", + // "description": "Deprecated. The name of the cluster to delete.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, + // "name": { + // "description": "The name (project, location, cluster) of the cluster to delete.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "query", + // "type": "string" + // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -3273,6 +8516,14 @@ func (r *ProjectsZonesClustersService) Get(projectId string, zone string, cluste return c } +// Name sets the optional parameter "name": The name (project, location, +// cluster) of the cluster to retrieve. +// Specified in the format 'projects/*/locations/*/clusters/*'. +func (c *ProjectsZonesClustersGetCall) Name(name string) *ProjectsZonesClustersGetCall { + 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. @@ -3380,19 +8631,24 @@ func (c *ProjectsZonesClustersGetCall) Do(opts ...googleapi.CallOption) (*Cluste // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to retrieve.", + // "description": "Deprecated. The name of the cluster to retrieve.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, + // "name": { + // "description": "The name (project, location, cluster) of the cluster to retrieve.\nSpecified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "query", + // "type": "string" + // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -3532,19 +8788,19 @@ func (c *ProjectsZonesClustersLegacyAbacCall) Do(opts ...googleapi.CallOption) ( // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to update.", + // "description": "Deprecated. The name of the cluster to update.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -3586,6 +8842,15 @@ func (r *ProjectsZonesClustersService) List(projectId string, zone string) *Proj return c } +// Parent sets the optional parameter "parent": The parent (project and +// location) where the clusters will be listed. +// Specified in the format 'projects/*/locations/*'. +// Location "-" matches all zones and all regions. +func (c *ProjectsZonesClustersListCall) Parent(parent string) *ProjectsZonesClustersListCall { + c.urlParams_.Set("parent", parent) + return c +} + // Fields allows partial responses to be retrieved. See // https://developers.google.com/gdata/docs/2.0/basics#PartialResponse // for more information. @@ -3690,14 +8955,19 @@ func (c *ProjectsZonesClustersListCall) Do(opts ...googleapi.CallOption) (*ListC // "zone" // ], // "parameters": { + // "parent": { + // "description": "The parent (project and location) where the clusters will be listed.\nSpecified in the format 'projects/*/locations/*'.\nLocation \"-\" matches all zones and all regions.", + // "location": "query", + // "type": "string" + // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides, or \"-\" for all zones.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides, or \"-\" for all zones.\nThis field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" @@ -3727,7 +8997,7 @@ type ProjectsZonesClustersLocationsCall struct { header_ http.Header } -// Locations: Sets the locations of a specific cluster. +// Locations: Sets the locations for a specific cluster. func (r *ProjectsZonesClustersService) Locations(projectId string, zone string, clusterId string, setlocationsrequest *SetLocationsRequest) *ProjectsZonesClustersLocationsCall { c := &ProjectsZonesClustersLocationsCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.projectId = projectId @@ -3825,7 +9095,7 @@ func (c *ProjectsZonesClustersLocationsCall) Do(opts ...googleapi.CallOption) (* } return ret, nil // { - // "description": "Sets the locations of a specific cluster.", + // "description": "Sets the locations for a specific cluster.", // "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/locations", // "httpMethod": "POST", // "id": "container.projects.zones.clusters.locations", @@ -3836,19 +9106,19 @@ func (c *ProjectsZonesClustersLocationsCall) Do(opts ...googleapi.CallOption) (* // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to upgrade.", + // "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -3881,7 +9151,7 @@ type ProjectsZonesClustersLoggingCall struct { header_ http.Header } -// Logging: Sets the logging service of a specific cluster. +// Logging: Sets the logging service for a specific cluster. func (r *ProjectsZonesClustersService) Logging(projectId string, zone string, clusterId string, setloggingservicerequest *SetLoggingServiceRequest) *ProjectsZonesClustersLoggingCall { c := &ProjectsZonesClustersLoggingCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.projectId = projectId @@ -3979,7 +9249,7 @@ func (c *ProjectsZonesClustersLoggingCall) Do(opts ...googleapi.CallOption) (*Op } return ret, nil // { - // "description": "Sets the logging service of a specific cluster.", + // "description": "Sets the logging service for a specific cluster.", // "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/logging", // "httpMethod": "POST", // "id": "container.projects.zones.clusters.logging", @@ -3990,19 +9260,19 @@ func (c *ProjectsZonesClustersLoggingCall) Do(opts ...googleapi.CallOption) (*Op // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to upgrade.", + // "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -4035,7 +9305,7 @@ type ProjectsZonesClustersMasterCall struct { header_ http.Header } -// Master: Updates the master of a specific cluster. +// Master: Updates the master for a specific cluster. func (r *ProjectsZonesClustersService) Master(projectId string, zone string, clusterId string, updatemasterrequest *UpdateMasterRequest) *ProjectsZonesClustersMasterCall { c := &ProjectsZonesClustersMasterCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.projectId = projectId @@ -4133,7 +9403,7 @@ func (c *ProjectsZonesClustersMasterCall) Do(opts ...googleapi.CallOption) (*Ope } return ret, nil // { - // "description": "Updates the master of a specific cluster.", + // "description": "Updates the master for a specific cluster.", // "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/master", // "httpMethod": "POST", // "id": "container.projects.zones.clusters.master", @@ -4144,19 +9414,19 @@ func (c *ProjectsZonesClustersMasterCall) Do(opts ...googleapi.CallOption) (*Ope // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to upgrade.", + // "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -4189,7 +9459,7 @@ type ProjectsZonesClustersMonitoringCall struct { header_ http.Header } -// Monitoring: Sets the monitoring service of a specific cluster. +// Monitoring: Sets the monitoring service for a specific cluster. func (r *ProjectsZonesClustersService) Monitoring(projectId string, zone string, clusterId string, setmonitoringservicerequest *SetMonitoringServiceRequest) *ProjectsZonesClustersMonitoringCall { c := &ProjectsZonesClustersMonitoringCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.projectId = projectId @@ -4287,7 +9557,7 @@ func (c *ProjectsZonesClustersMonitoringCall) Do(opts ...googleapi.CallOption) ( } return ret, nil // { - // "description": "Sets the monitoring service of a specific cluster.", + // "description": "Sets the monitoring service for a specific cluster.", // "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/monitoring", // "httpMethod": "POST", // "id": "container.projects.zones.clusters.monitoring", @@ -4298,19 +9568,19 @@ func (c *ProjectsZonesClustersMonitoringCall) Do(opts ...googleapi.CallOption) ( // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to upgrade.", + // "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -4452,19 +9722,19 @@ func (c *ProjectsZonesClustersResourceLabelsCall) Do(opts ...googleapi.CallOptio // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster.", + // "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -4653,7 +9923,7 @@ type ProjectsZonesClustersSetMasterAuthCall struct { // SetMasterAuth: Used to set master auth materials. Currently supports // :- -// Changing the admin password of a specific cluster. +// Changing the admin password for a specific cluster. // This can be either via password generation or explicitly set the // password. func (r *ProjectsZonesClustersService) SetMasterAuth(projectId string, zone string, clusterId string, setmasterauthrequest *SetMasterAuthRequest) *ProjectsZonesClustersSetMasterAuthCall { @@ -4753,7 +10023,7 @@ func (c *ProjectsZonesClustersSetMasterAuthCall) Do(opts ...googleapi.CallOption } return ret, nil // { - // "description": "Used to set master auth materials. Currently supports :-\nChanging the admin password of a specific cluster.\nThis can be either via password generation or explicitly set the password.", + // "description": "Used to set master auth materials. Currently supports :-\nChanging the admin password for a specific cluster.\nThis can be either via password generation or explicitly set the password.", // "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}:setMasterAuth", // "httpMethod": "POST", // "id": "container.projects.zones.clusters.setMasterAuth", @@ -4764,19 +10034,19 @@ func (c *ProjectsZonesClustersSetMasterAuthCall) Do(opts ...googleapi.CallOption // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to upgrade.", + // "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -4918,19 +10188,19 @@ func (c *ProjectsZonesClustersSetNetworkPolicyCall) Do(opts ...googleapi.CallOpt // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster.", + // "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -5072,19 +10342,19 @@ func (c *ProjectsZonesClustersStartIpRotationCall) Do(opts ...googleapi.CallOpti // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster.", + // "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -5226,19 +10496,19 @@ func (c *ProjectsZonesClustersUpdateCall) Do(opts ...googleapi.CallOption) (*Ope // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to upgrade.", + // "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -5272,7 +10542,7 @@ type ProjectsZonesClustersNodePoolsAutoscalingCall struct { header_ http.Header } -// Autoscaling: Sets the autoscaling settings of a specific node pool. +// Autoscaling: Sets the autoscaling settings for a specific node pool. func (r *ProjectsZonesClustersNodePoolsService) Autoscaling(projectId string, zone string, clusterId string, nodePoolId string, setnodepoolautoscalingrequest *SetNodePoolAutoscalingRequest) *ProjectsZonesClustersNodePoolsAutoscalingCall { c := &ProjectsZonesClustersNodePoolsAutoscalingCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.projectId = projectId @@ -5372,7 +10642,7 @@ func (c *ProjectsZonesClustersNodePoolsAutoscalingCall) Do(opts ...googleapi.Cal } return ret, nil // { - // "description": "Sets the autoscaling settings of a specific node pool.", + // "description": "Sets the autoscaling settings for a specific node pool.", // "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}/autoscaling", // "httpMethod": "POST", // "id": "container.projects.zones.clusters.nodePools.autoscaling", @@ -5384,25 +10654,25 @@ func (c *ProjectsZonesClustersNodePoolsAutoscalingCall) Do(opts ...googleapi.Cal // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to upgrade.", + // "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "nodePoolId": { - // "description": "The name of the node pool to upgrade.", + // "description": "Deprecated. The name of the node pool to upgrade.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -5544,19 +10814,19 @@ func (c *ProjectsZonesClustersNodePoolsCreateCall) Do(opts ...googleapi.CallOpti // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster.", + // "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" @@ -5599,6 +10869,16 @@ func (r *ProjectsZonesClustersNodePoolsService) Delete(projectId string, zone st return c } +// Name sets the optional parameter "name": The name (project, location, +// cluster, node pool id) of the node pool to +// delete. Specified in the +// format +// 'projects/*/locations/*/clusters/*/nodePools/*'. +func (c *ProjectsZonesClustersNodePoolsDeleteCall) Name(name string) *ProjectsZonesClustersNodePoolsDeleteCall { + 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. @@ -5695,25 +10975,30 @@ func (c *ProjectsZonesClustersNodePoolsDeleteCall) Do(opts ...googleapi.CallOpti // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster.", + // "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, + // "name": { + // "description": "The name (project, location, cluster, node pool id) of the node pool to\ndelete. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + // "location": "query", + // "type": "string" + // }, // "nodePoolId": { - // "description": "The name of the node pool to delete.", + // "description": "Deprecated. The name of the node pool to delete.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -5754,6 +11039,16 @@ func (r *ProjectsZonesClustersNodePoolsService) Get(projectId string, zone strin return c } +// Name sets the optional parameter "name": The name (project, location, +// cluster, node pool id) of the node pool to +// get. Specified in the +// format +// 'projects/*/locations/*/clusters/*/nodePools/*'. +func (c *ProjectsZonesClustersNodePoolsGetCall) Name(name string) *ProjectsZonesClustersNodePoolsGetCall { + 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. @@ -5863,25 +11158,30 @@ func (c *ProjectsZonesClustersNodePoolsGetCall) Do(opts ...googleapi.CallOption) // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster.", + // "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, + // "name": { + // "description": "The name (project, location, cluster, node pool id) of the node pool to\nget. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + // "location": "query", + // "type": "string" + // }, // "nodePoolId": { - // "description": "The name of the node pool.", + // "description": "Deprecated. The name of the node pool.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -5920,6 +11220,14 @@ func (r *ProjectsZonesClustersNodePoolsService) List(projectId string, zone stri return c } +// Parent sets the optional parameter "parent": The parent (project, +// location, cluster id) where the node pools will be +// listed. Specified in the format 'projects/*/locations/*/clusters/*'. +func (c *ProjectsZonesClustersNodePoolsListCall) Parent(parent string) *ProjectsZonesClustersNodePoolsListCall { + c.urlParams_.Set("parent", parent) + return c +} + // Fields allows partial responses to be retrieved. See // https://developers.google.com/gdata/docs/2.0/basics#PartialResponse // for more information. @@ -6027,19 +11335,24 @@ func (c *ProjectsZonesClustersNodePoolsListCall) Do(opts ...googleapi.CallOption // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster.", + // "description": "Deprecated. The name of the cluster.\nThis field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" // }, + // "parent": { + // "description": "The parent (project, location, cluster id) where the node pools will be\nlisted. Specified in the format 'projects/*/locations/*/clusters/*'.", + // "location": "query", + // "type": "string" + // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://developers.google.com/console/help/new/#projectnumber).\nThis field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" @@ -6184,25 +11497,25 @@ func (c *ProjectsZonesClustersNodePoolsRollbackCall) Do(opts ...googleapi.CallOp // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to rollback.", + // "description": "Deprecated. The name of the cluster to rollback.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "nodePoolId": { - // "description": "The name of the node pool to rollback.", + // "description": "Deprecated. The name of the node pool to rollback.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -6348,25 +11661,25 @@ func (c *ProjectsZonesClustersNodePoolsSetManagementCall) Do(opts ...googleapi.C // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to update.", + // "description": "Deprecated. The name of the cluster to update.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "nodePoolId": { - // "description": "The name of the node pool to update.", + // "description": "Deprecated. The name of the node pool to update.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -6400,7 +11713,7 @@ type ProjectsZonesClustersNodePoolsSetSizeCall struct { header_ http.Header } -// SetSize: Sets the size of a specific node pool. +// SetSize: Sets the size for a specific node pool. func (r *ProjectsZonesClustersNodePoolsService) SetSize(projectId string, zone string, clusterId string, nodePoolId string, setnodepoolsizerequest *SetNodePoolSizeRequest) *ProjectsZonesClustersNodePoolsSetSizeCall { c := &ProjectsZonesClustersNodePoolsSetSizeCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.projectId = projectId @@ -6500,7 +11813,7 @@ func (c *ProjectsZonesClustersNodePoolsSetSizeCall) Do(opts ...googleapi.CallOpt } return ret, nil // { - // "description": "Sets the size of a specific node pool.", + // "description": "Sets the size for a specific node pool.", // "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}/setSize", // "httpMethod": "POST", // "id": "container.projects.zones.clusters.nodePools.setSize", @@ -6512,25 +11825,25 @@ func (c *ProjectsZonesClustersNodePoolsSetSizeCall) Do(opts ...googleapi.CallOpt // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to update.", + // "description": "Deprecated. The name of the cluster to update.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "nodePoolId": { - // "description": "The name of the node pool to update.", + // "description": "Deprecated. The name of the node pool to update.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -6564,7 +11877,7 @@ type ProjectsZonesClustersNodePoolsUpdateCall struct { header_ http.Header } -// Update: Updates the version and/or image type of a specific node +// Update: Updates the version and/or image type for a specific node // pool. func (r *ProjectsZonesClustersNodePoolsService) Update(projectId string, zone string, clusterId string, nodePoolId string, updatenodepoolrequest *UpdateNodePoolRequest) *ProjectsZonesClustersNodePoolsUpdateCall { c := &ProjectsZonesClustersNodePoolsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -6665,7 +11978,7 @@ func (c *ProjectsZonesClustersNodePoolsUpdateCall) Do(opts ...googleapi.CallOpti } return ret, nil // { - // "description": "Updates the version and/or image type of a specific node pool.", + // "description": "Updates the version and/or image type for a specific node pool.", // "flatPath": "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}/update", // "httpMethod": "POST", // "id": "container.projects.zones.clusters.nodePools.update", @@ -6677,25 +11990,25 @@ func (c *ProjectsZonesClustersNodePoolsUpdateCall) Do(opts ...googleapi.CallOpti // ], // "parameters": { // "clusterId": { - // "description": "The name of the cluster to upgrade.", + // "description": "Deprecated. The name of the cluster to upgrade.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "nodePoolId": { - // "description": "The name of the node pool to upgrade.", + // "description": "Deprecated. The name of the node pool to upgrade.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -6837,19 +12150,19 @@ func (c *ProjectsZonesOperationsCancelCall) Do(opts ...googleapi.CallOption) (*E // ], // "parameters": { // "operationId": { - // "description": "The server-assigned `name` of the operation.", + // "description": "Deprecated. The server-assigned `name` of the operation.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the operation resides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the operation resides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -6891,6 +12204,14 @@ func (r *ProjectsZonesOperationsService) Get(projectId string, zone string, oper return c } +// Name sets the optional parameter "name": The name (project, location, +// operation id) of the operation to get. +// Specified in the format 'projects/*/locations/*/operations/*'. +func (c *ProjectsZonesOperationsGetCall) Name(name string) *ProjectsZonesOperationsGetCall { + 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. @@ -6997,20 +12318,25 @@ func (c *ProjectsZonesOperationsGetCall) Do(opts ...googleapi.CallOption) (*Oper // "operationId" // ], // "parameters": { + // "name": { + // "description": "The name (project, location, operation id) of the operation to get.\nSpecified in the format 'projects/*/locations/*/operations/*'.", + // "location": "query", + // "type": "string" + // }, // "operationId": { - // "description": "The server-assigned `name` of the operation.", + // "description": "Deprecated. The server-assigned `name` of the operation.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) in which the cluster\nresides.\nThis field has been deprecated and replaced by the name field.", // "location": "path", // "required": true, // "type": "string" @@ -7048,6 +12374,15 @@ func (r *ProjectsZonesOperationsService) List(projectId string, zone string) *Pr return c } +// Parent sets the optional parameter "parent": The parent (project and +// location) where the operations will be listed. +// Specified in the format 'projects/*/locations/*'. +// Location "-" matches all zones and all regions. +func (c *ProjectsZonesOperationsListCall) Parent(parent string) *ProjectsZonesOperationsListCall { + c.urlParams_.Set("parent", parent) + return c +} + // Fields allows partial responses to be retrieved. See // https://developers.google.com/gdata/docs/2.0/basics#PartialResponse // for more information. @@ -7152,14 +12487,19 @@ func (c *ProjectsZonesOperationsListCall) Do(opts ...googleapi.CallOption) (*Lis // "zone" // ], // "parameters": { + // "parent": { + // "description": "The parent (project and location) where the operations will be listed.\nSpecified in the format 'projects/*/locations/*'.\nLocation \"-\" matches all zones and all regions.", + // "location": "query", + // "type": "string" + // }, // "projectId": { - // "description": "The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).", + // "description": "Deprecated. The Google Developers Console [project ID or project\nnumber](https://support.google.com/cloud/answer/6158840).\nThis field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" // }, // "zone": { - // "description": "The name of the Google Compute Engine [zone](/compute/docs/zones#available)\nto return operations for, or `-` for all zones.", + // "description": "Deprecated. The name of the Google Compute Engine\n[zone](/compute/docs/zones#available) to return operations for, or `-` for\nall zones. This field has been deprecated and replaced by the parent field.", // "location": "path", // "required": true, // "type": "string" diff --git a/vendor/google.golang.org/api/gensupport/media.go b/vendor/google.golang.org/api/gensupport/media.go index 5a2674104ef..5895fef8896 100644 --- a/vendor/google.golang.org/api/gensupport/media.go +++ b/vendor/google.golang.org/api/gensupport/media.go @@ -13,6 +13,7 @@ import ( "net/http" "net/textproto" "strings" + "sync" "google.golang.org/api/googleapi" ) @@ -105,12 +106,13 @@ type typeReader struct { typ string } -// multipartReader combines the contents of multiple readers to creat a multipart/related HTTP body. +// multipartReader combines the contents of multiple readers to create a multipart/related HTTP body. // Close must be called if reads from the multipartReader are abandoned before reaching EOF. type multipartReader struct { pr *io.PipeReader - pipeOpen bool ctype string + mu sync.Mutex + pipeOpen bool } func newMultipartReader(parts []typeReader) *multipartReader { @@ -146,10 +148,13 @@ func (mp *multipartReader) Read(data []byte) (n int, err error) { } func (mp *multipartReader) Close() error { + mp.mu.Lock() if !mp.pipeOpen { + mp.mu.Unlock() return nil } mp.pipeOpen = false + mp.mu.Unlock() return mp.pr.Close() } 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 26af780de9f..34c62f5ffd6 100644 --- a/vendor/google.golang.org/api/logging/v2beta1/logging-api.json +++ b/vendor/google.golang.org/api/logging/v2beta1/logging-api.json @@ -224,7 +224,7 @@ ] }, "write": { - "description": "Log entry resourcesWrites 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.", + "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)", "flatPath": "v2beta1/entries:write", "httpMethod": "POST", "id": "logging.entries.write", @@ -755,7 +755,7 @@ } } }, - "revision": "20180213", + "revision": "20180424", "rootUrl": "https://logging.googleapis.com/", "schemas": { "BucketOptions": { @@ -1102,6 +1102,10 @@ "description": "Required. The resource name of the log to which this log entry belongs:\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]\"\nA project number may optionally be used in place of PROJECT_ID. The project number is translated to its corresponding PROJECT_ID internally and the log_name field will contain PROJECT_ID in queries and exports.[LOG_ID] must be URL-encoded within log_name. Example: \"organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Factivity\". [LOG_ID] must be less than 512 characters long and can only include the following characters: upper and lower case alphanumeric characters, forward-slash, underscore, hyphen, and period.For backward compatibility, if log_name begins with a forward-slash, such as /projects/..., then the log entry is ingested as usual but the forward-slash is removed. Listing the log entry will not show the leading slash and filtering for a log name with a leading slash will never return any results.", "type": "string" }, + "metadata": { + "$ref": "MonitoredResourceMetadata", + "description": "Output only. Additional metadata about the monitored resource. Only k8s_container, k8s_pod, and k8s_node MonitoredResources have this field populated." + }, "operation": { "$ref": "LogEntryOperation", "description": "Optional. Information about an operation associated with the log entry, if applicable." @@ -1121,7 +1125,7 @@ }, "resource": { "$ref": "MonitoredResource", - "description": "Required. The monitored resource associated with this log entry. Example: a log entry that reports a database error would be associated with the monitored resource designating the particular database that reported the error." + "description": "Required. The primary monitored resource associated with this log entry. Example: a log entry that reports a database error would be associated with the monitored resource designating the particular database that reported the error." }, "severity": { "description": "Optional. The severity of the log entry. The default value is LogSeverity.DEFAULT.", @@ -1162,7 +1166,7 @@ "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.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 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.", "format": "google-datetime", "type": "string" }, @@ -1483,6 +1487,28 @@ }, "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.", + "id": "MonitoredResourceMetadata", + "properties": { + "systemLabels": { + "additionalProperties": { + "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", + "type": "object" + }, + "userLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "Output only. A map of user-defined metadata labels.", + "type": "object" + } + }, + "type": "object" + }, "RequestLog": { "description": "Complete log information about a single HTTP request to an App Engine application.", "id": "RequestLog", 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 b0d5104ba5c..12a8cef8706 100644 --- a/vendor/google.golang.org/api/logging/v2beta1/logging-gen.go +++ b/vendor/google.golang.org/api/logging/v2beta1/logging-gen.go @@ -865,6 +865,11 @@ type LogEntry struct { // never return any results. LogName string `json:"logName,omitempty"` + // Metadata: Output only. Additional metadata about the monitored + // resource. Only k8s_container, k8s_pod, and k8s_node + // MonitoredResources have this field populated. + Metadata *MonitoredResourceMetadata `json:"metadata,omitempty"` + // Operation: Optional. Information about an operation associated with // the log entry, if applicable. Operation *LogEntryOperation `json:"operation,omitempty"` @@ -878,10 +883,10 @@ type LogEntry struct { // Stackdriver Logging. ReceiveTimestamp string `json:"receiveTimestamp,omitempty"` - // Resource: Required. The monitored resource associated with this log - // entry. Example: a log entry that reports a database error would be - // associated with the monitored resource designating the particular - // database that reported the error. + // Resource: Required. The primary monitored resource associated with + // this log entry. Example: a log entry that reports a database error + // would be associated with the monitored resource designating the + // particular database that reported the error. Resource *MonitoredResource `json:"resource,omitempty"` // Severity: Optional. The severity of the log entry. The default value @@ -919,12 +924,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.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 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. Timestamp string `json:"timestamp,omitempty"` // Trace: Optional. Resource name of the trace associated with the log @@ -1575,6 +1582,52 @@ func (s *MonitoredResourceDescriptor) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// 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. +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: + // { "name": "my-test-instance", + // "security_group": ["a", "b", "c"], + // "spot_instance": false } + // + SystemLabels googleapi.RawMessage `json:"systemLabels,omitempty"` + + // UserLabels: Output only. A map of user-defined metadata labels. + UserLabels map[string]string `json:"userLabels,omitempty"` + + // ForceSendFields is a list of field names (e.g. "SystemLabels") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "SystemLabels") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *MonitoredResourceMetadata) MarshalJSON() ([]byte, error) { + type NoMethod MonitoredResourceMetadata + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // RequestLog: Complete log information about a single HTTP request to // an App Engine application. type RequestLog struct { @@ -2385,11 +2438,13 @@ type EntriesWriteCall struct { header_ http.Header } -// Write: Log entry resourcesWrites 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. +// 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) func (r *EntriesService) Write(writelogentriesrequest *WriteLogEntriesRequest) *EntriesWriteCall { c := &EntriesWriteCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.writelogentriesrequest = writelogentriesrequest @@ -2479,7 +2534,7 @@ func (c *EntriesWriteCall) Do(opts ...googleapi.CallOption) (*WriteLogEntriesRes } return ret, nil // { - // "description": "Log entry resourcesWrites 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.", + // "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)", // "flatPath": "v2beta1/entries:write", // "httpMethod": "POST", // "id": "logging.entries.write", 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 49ddaf87f03..6127fd1b919 100644 --- a/vendor/google.golang.org/api/monitoring/v3/monitoring-api.json +++ b/vendor/google.golang.org/api/monitoring/v3/monitoring-api.json @@ -126,6 +126,175 @@ "resources": { "projects": { "resources": { + "alertPolicies": { + "methods": { + "create": { + "description": "Creates a new alerting policy.", + "flatPath": "v3/projects/{projectsId}/alertPolicies", + "httpMethod": "POST", + "id": "monitoring.projects.alertPolicies.create", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The project in which to create the alerting policy. The format is projects/[PROJECT_ID].Note that this field names the parent container in which the alerting policy will be written, not the name of the created policy. The alerting policy that is returned will have a name that contains a normalized representation of this name as a prefix but adds a suffix of the form /alertPolicies/[POLICY_ID], identifying the policy in the container.", + "location": "path", + "pattern": "^projects/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v3/{+name}/alertPolicies", + "request": { + "$ref": "AlertPolicy" + }, + "response": { + "$ref": "AlertPolicy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring" + ] + }, + "delete": { + "description": "Deletes an alerting policy.", + "flatPath": "v3/projects/{projectsId}/alertPolicies/{alertPoliciesId}", + "httpMethod": "DELETE", + "id": "monitoring.projects.alertPolicies.delete", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The alerting policy to delete. The format is:\nprojects/[PROJECT_ID]/alertPolicies/[ALERT_POLICY_ID]\nFor more information, see AlertPolicy.", + "location": "path", + "pattern": "^projects/[^/]+/alertPolicies/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v3/{+name}", + "response": { + "$ref": "Empty" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring" + ] + }, + "get": { + "description": "Gets a single alerting policy.", + "flatPath": "v3/projects/{projectsId}/alertPolicies/{alertPoliciesId}", + "httpMethod": "GET", + "id": "monitoring.projects.alertPolicies.get", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The alerting policy to retrieve. The format is\nprojects/[PROJECT_ID]/alertPolicies/[ALERT_POLICY_ID]\n", + "location": "path", + "pattern": "^projects/[^/]+/alertPolicies/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v3/{+name}", + "response": { + "$ref": "AlertPolicy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read" + ] + }, + "list": { + "description": "Lists the existing alerting policies for the project.", + "flatPath": "v3/projects/{projectsId}/alertPolicies", + "httpMethod": "GET", + "id": "monitoring.projects.alertPolicies.list", + "parameterOrder": [ + "name" + ], + "parameters": { + "filter": { + "description": "If provided, this field specifies the criteria that must be met by alert policies to be included in the response.For more details, see sorting and filtering.", + "location": "query", + "type": "string" + }, + "name": { + "description": "The project whose alert policies are to be listed. The format is\nprojects/[PROJECT_ID]\nNote that this field names the parent container in which the alerting policies to be listed are stored. To retrieve a single alerting policy by name, use the GetAlertPolicy operation, instead.", + "location": "path", + "pattern": "^projects/[^/]+$", + "required": true, + "type": "string" + }, + "orderBy": { + "description": "A comma-separated list of fields by which to sort the result. Supports the same set of field references as the filter field. Entries can be prefixed with a minus sign to sort by the field in descending order.For more details, see sorting and filtering.", + "location": "query", + "type": "string" + }, + "pageSize": { + "description": "The maximum number of results to return in a single response.", + "format": "int32", + "location": "query", + "type": "integer" + }, + "pageToken": { + "description": "If this field is not empty then it must contain the nextPageToken value returned by a previous call to this method. Using this field causes the method to return more results from the previous method call.", + "location": "query", + "type": "string" + } + }, + "path": "v3/{+name}/alertPolicies", + "response": { + "$ref": "ListAlertPoliciesResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read" + ] + }, + "patch": { + "description": "Updates an alerting policy. You can either replace the entire policy with a new one or replace only certain fields in the current alerting policy by specifying the fields to be updated via updateMask. Returns the updated alerting policy.", + "flatPath": "v3/projects/{projectsId}/alertPolicies/{alertPoliciesId}", + "httpMethod": "PATCH", + "id": "monitoring.projects.alertPolicies.patch", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "Required if the policy exists. The resource name for this policy. The syntax is:\nprojects/[PROJECT_ID]/alertPolicies/[ALERT_POLICY_ID]\n[ALERT_POLICY_ID] is assigned by Stackdriver Monitoring when the policy is created. When calling the alertPolicies.create method, do not include the name field in the alerting policy passed as part of the request.", + "location": "path", + "pattern": "^projects/[^/]+/alertPolicies/[^/]+$", + "required": true, + "type": "string" + }, + "updateMask": { + "description": "Optional. A list of alerting policy field names. If this field is not empty, each listed field in the existing alerting policy is set to the value of the corresponding field in the supplied policy (alert_policy), or to the field's default value if the field is not in the supplied alerting policy. Fields not listed retain their previous value.Examples of valid field masks include display_name, documentation, documentation.content, documentation.mime_type, user_labels, user_label.nameofkey, enabled, conditions, combiner, etc.If this field is empty, then the supplied alerting policy replaces the existing policy. It is the same as deleting the existing policy and adding the supplied policy, except for the following:\nThe new policy will have the same [ALERT_POLICY_ID] as the former policy. This gives you continuity with the former policy in your notifications and incidents.\nConditions in the new policy will keep their former [CONDITION_ID] if the supplied condition includes the name field with that [CONDITION_ID]. If the supplied condition omits the name field, then a new [CONDITION_ID] is created.", + "format": "google-fieldmask", + "location": "query", + "type": "string" + } + }, + "path": "v3/{+name}", + "request": { + "$ref": "AlertPolicy" + }, + "response": { + "$ref": "AlertPolicy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring" + ] + } + } + }, "collectdTimeSeries": { "methods": { "create": { @@ -607,6 +776,336 @@ } } }, + "notificationChannelDescriptors": { + "methods": { + "get": { + "description": "Gets a single channel descriptor. The descriptor indicates which fields are expected / permitted for a notification channel of the given type.", + "flatPath": "v3/projects/{projectsId}/notificationChannelDescriptors/{notificationChannelDescriptorsId}", + "httpMethod": "GET", + "id": "monitoring.projects.notificationChannelDescriptors.get", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The channel type for which to execute the request. The format is projects/[PROJECT_ID]/notificationChannelDescriptors/{channel_type}.", + "location": "path", + "pattern": "^projects/[^/]+/notificationChannelDescriptors/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v3/{+name}", + "response": { + "$ref": "NotificationChannelDescriptor" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read" + ] + }, + "list": { + "description": "Lists the descriptors for supported channel types. The use of descriptors makes it possible for new channel types to be dynamically added.", + "flatPath": "v3/projects/{projectsId}/notificationChannelDescriptors", + "httpMethod": "GET", + "id": "monitoring.projects.notificationChannelDescriptors.list", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The REST resource name of the parent from which to retrieve the notification channel descriptors. The expected syntax is:\nprojects/[PROJECT_ID]\nNote that this names the parent container in which to look for the descriptors; to retrieve a single descriptor by name, use the GetNotificationChannelDescriptor operation, instead.", + "location": "path", + "pattern": "^projects/[^/]+$", + "required": true, + "type": "string" + }, + "pageSize": { + "description": "The maximum number of results to return in a single response. If not set to a positive number, a reasonable value will be chosen by the service.", + "format": "int32", + "location": "query", + "type": "integer" + }, + "pageToken": { + "description": "If non-empty, page_token must contain a value returned as the next_page_token in a previous response to request the next set of results.", + "location": "query", + "type": "string" + } + }, + "path": "v3/{+name}/notificationChannelDescriptors", + "response": { + "$ref": "ListNotificationChannelDescriptorsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read" + ] + } + } + }, + "notificationChannels": { + "methods": { + "create": { + "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", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The project on which to execute the request. The format is:\nprojects/[PROJECT_ID]\nNote that this names the container into which the channel will be written. This does not name the newly created channel. The resulting channel's name will have a normalized version of this field as a prefix, but will add /notificationChannels/[CHANNEL_ID] to identify the channel.", + "location": "path", + "pattern": "^projects/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v3/{+name}/notificationChannels", + "request": { + "$ref": "NotificationChannel" + }, + "response": { + "$ref": "NotificationChannel" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring" + ] + }, + "delete": { + "description": "Deletes a notification channel.", + "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}", + "httpMethod": "DELETE", + "id": "monitoring.projects.notificationChannels.delete", + "parameterOrder": [ + "name" + ], + "parameters": { + "force": { + "description": "If true, the notification channel will be deleted regardless of its use in alert policies (the policies will be updated to remove the channel). If false, channels that are still referenced by an existing alerting policy will fail to be deleted in a delete operation.", + "location": "query", + "type": "boolean" + }, + "name": { + "description": "The channel for which to execute the request. The format is projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID].", + "location": "path", + "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v3/{+name}", + "response": { + "$ref": "Empty" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring" + ] + }, + "get": { + "description": "Gets a single notification channel. The channel includes the relevant configuration details with which the channel was created. However, the response may truncate or omit passwords, API keys, or other private key matter and thus the response may not be 100% identical to the information that was supplied in the call to the create method.", + "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}", + "httpMethod": "GET", + "id": "monitoring.projects.notificationChannels.get", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The channel for which to execute the request. The format is projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID].", + "location": "path", + "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v3/{+name}", + "response": { + "$ref": "NotificationChannel" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read" + ] + }, + "getVerificationCode": { + "description": "Requests a verification code for an already verified channel that can then be used in a call to VerifyNotificationChannel() on a different channel with an equivalent identity in the same or in a different project. This makes it possible to copy a channel between projects without requiring manual reverification of the channel. If the channel is not in the verified state, this method will fail (in other words, this may only be used if the SendNotificationChannelVerificationCode and VerifyNotificationChannel paths have already been used to put the given channel into the verified state).There is no guarantee that the verification codes returned by this method will be of a similar structure or form as the ones that are delivered to the channel via SendNotificationChannelVerificationCode; while VerifyNotificationChannel() will recognize both the codes delivered via SendNotificationChannelVerificationCode() and returned from GetNotificationChannelVerificationCode(), it is typically the case that the verification codes delivered via SendNotificationChannelVerificationCode() will be shorter and also have a shorter expiration (e.g. codes such as \"G-123456\") whereas GetVerificationCode() will typically return a much longer, websafe base 64 encoded string that has a longer expiration time.", + "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}:getVerificationCode", + "httpMethod": "POST", + "id": "monitoring.projects.notificationChannels.getVerificationCode", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The notification channel for which a verification code is to be generated and retrieved. This must name a channel that is already verified; if the specified channel is not verified, the request will fail.", + "location": "path", + "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v3/{+name}:getVerificationCode", + "request": { + "$ref": "GetNotificationChannelVerificationCodeRequest" + }, + "response": { + "$ref": "GetNotificationChannelVerificationCodeResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring" + ] + }, + "list": { + "description": "Lists the notification channels that have been created for the project.", + "flatPath": "v3/projects/{projectsId}/notificationChannels", + "httpMethod": "GET", + "id": "monitoring.projects.notificationChannels.list", + "parameterOrder": [ + "name" + ], + "parameters": { + "filter": { + "description": "If provided, this field specifies the criteria that must be met by notification channels to be included in the response.For more details, see sorting and filtering.", + "location": "query", + "type": "string" + }, + "name": { + "description": "The project on which to execute the request. The format is projects/[PROJECT_ID]. That is, this names the container in which to look for the notification channels; it does not name a specific channel. To query a specific channel by REST resource name, use the GetNotificationChannel operation.", + "location": "path", + "pattern": "^projects/[^/]+$", + "required": true, + "type": "string" + }, + "orderBy": { + "description": "A comma-separated list of fields by which to sort the result. Supports the same set of fields as in filter. Entries can be prefixed with a minus sign to sort in descending rather than ascending order.For more details, see sorting and filtering.", + "location": "query", + "type": "string" + }, + "pageSize": { + "description": "The maximum number of results to return in a single response. If not set to a positive number, a reasonable value will be chosen by the service.", + "format": "int32", + "location": "query", + "type": "integer" + }, + "pageToken": { + "description": "If non-empty, page_token must contain a value returned as the next_page_token in a previous response to request the next set of results.", + "location": "query", + "type": "string" + } + }, + "path": "v3/{+name}/notificationChannels", + "response": { + "$ref": "ListNotificationChannelsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read" + ] + }, + "patch": { + "description": "Updates a notification channel. Fields not specified in the field mask remain unchanged.", + "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}", + "httpMethod": "PATCH", + "id": "monitoring.projects.notificationChannels.patch", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The full REST resource name for this channel. The syntax is:\nprojects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID]\nThe [CHANNEL_ID] is automatically assigned by the server on creation.", + "location": "path", + "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + "required": true, + "type": "string" + }, + "updateMask": { + "description": "The fields to update.", + "format": "google-fieldmask", + "location": "query", + "type": "string" + } + }, + "path": "v3/{+name}", + "request": { + "$ref": "NotificationChannel" + }, + "response": { + "$ref": "NotificationChannel" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring" + ] + }, + "sendVerificationCode": { + "description": "Causes a verification code to be delivered to the channel. The code can then be supplied in VerifyNotificationChannel to verify the channel.", + "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}:sendVerificationCode", + "httpMethod": "POST", + "id": "monitoring.projects.notificationChannels.sendVerificationCode", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The notification channel to which to send a verification code.", + "location": "path", + "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v3/{+name}:sendVerificationCode", + "request": { + "$ref": "SendNotificationChannelVerificationCodeRequest" + }, + "response": { + "$ref": "Empty" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring" + ] + }, + "verify": { + "description": "Verifies a NotificationChannel by proving receipt of the code delivered to the channel as a result of calling SendNotificationChannelVerificationCode.", + "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}:verify", + "httpMethod": "POST", + "id": "monitoring.projects.notificationChannels.verify", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The notification channel to verify.", + "location": "path", + "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v3/{+name}:verify", + "request": { + "$ref": "VerifyNotificationChannelRequest" + }, + "response": { + "$ref": "NotificationChannel" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring" + ] + } + } + }, "timeSeries": { "methods": { "create": { @@ -737,7 +1236,7 @@ "type": "string" }, "pageSize": { - "description": "A positive number that is the maximum number of results to return. When view field sets to FULL, it limits the number of Points server will return; if view field is HEADERS, it limits the number of TimeSeries server will return.", + "description": "A positive number that is the maximum number of results to return. If page_size is empty or more than 100,000 results, the effective page_size is 100,000 results. If view is set to FULL, this is the maximum number of Points returned. If view is set to HEADERS, this is the maximum number of TimeSeries returned.", "format": "int32", "location": "query", "type": "integer" @@ -964,9 +1463,178 @@ } } }, - "revision": "20180225", + "revision": "20180529", "rootUrl": "https://monitoring.googleapis.com/", "schemas": { + "Aggregation": { + "description": "Describes how to combine multiple time series to provide different views of the data. Aggregation consists of an alignment step on individual time series (alignment_period and per_series_aligner) followed by an optional reduction step of the data across the aligned time series (cross_series_reducer and group_by_fields). For more details, see Aggregation.", + "id": "Aggregation", + "properties": { + "alignmentPeriod": { + "description": "The alignment period for per-time series alignment. If present, alignmentPeriod must be at least 60 seconds. After per-time series alignment, each time series will contain data points only on the period boundaries. If perSeriesAligner is not specified or equals ALIGN_NONE, then this field is ignored. If perSeriesAligner is specified and does not equal ALIGN_NONE, then this field must be defined; otherwise an error is returned.", + "format": "google-duration", + "type": "string" + }, + "crossSeriesReducer": { + "description": "The approach to be used to combine time series. Not all reducer functions may be applied to all time series, depending on the metric type and the value type of the original time series. Reduction may change the metric type of value type of the time series.Time series data must be aligned in order to perform cross-time series reduction. If crossSeriesReducer is specified, then perSeriesAligner must be specified and not equal ALIGN_NONE and alignmentPeriod must be specified; otherwise, an error is returned.", + "enum": [ + "REDUCE_NONE", + "REDUCE_MEAN", + "REDUCE_MIN", + "REDUCE_MAX", + "REDUCE_SUM", + "REDUCE_STDDEV", + "REDUCE_COUNT", + "REDUCE_COUNT_TRUE", + "REDUCE_COUNT_FALSE", + "REDUCE_FRACTION_TRUE", + "REDUCE_PERCENTILE_99", + "REDUCE_PERCENTILE_95", + "REDUCE_PERCENTILE_50", + "REDUCE_PERCENTILE_05" + ], + "enumDescriptions": [ + "No cross-time series reduction. The output of the aligner is returned.", + "Reduce by computing the mean across time series for each alignment period. This reducer is valid for delta and gauge metrics with numeric or distribution values. The value type of the output is DOUBLE.", + "Reduce by computing the minimum across time series for each alignment period. This reducer is valid for delta and gauge metrics with numeric values. The value type of the output is the same as the value type of the input.", + "Reduce by computing the maximum across time series for each alignment period. This reducer is valid for delta and gauge metrics with numeric values. The value type of the output is the same as the value type of the input.", + "Reduce by computing the sum across time series for each alignment period. This reducer is valid for delta and gauge metrics with numeric and distribution values. The value type of the output is the same as the value type of the input.", + "Reduce by computing the standard deviation across time series for each alignment period. This reducer is valid for delta and gauge metrics with numeric or distribution values. The value type of the output is DOUBLE.", + "Reduce by computing the count of data points across time series for each alignment period. This reducer is valid for delta and gauge metrics of numeric, Boolean, distribution, and string value type. The value type of the output is INT64.", + "Reduce by computing the count of True-valued data points across time series for each alignment period. This reducer is valid for delta and gauge metrics of Boolean value type. The value type of the output is INT64.", + "Reduce by computing the count of False-valued data points across time series for each alignment period. This reducer is valid for delta and gauge metrics of Boolean value type. The value type of the output is INT64.", + "Reduce by computing the fraction of True-valued data points across time series for each alignment period. This reducer is valid for delta and gauge metrics of Boolean value type. The output value is in the range 0, 1 and has value type DOUBLE.", + "Reduce by computing 99th percentile of data points across time series for each alignment period. This reducer is valid for gauge and delta metrics of numeric and distribution type. The value of the output is DOUBLE", + "Reduce by computing 95th percentile of data points across time series for each alignment period. This reducer is valid for gauge and delta metrics of numeric and distribution type. The value of the output is DOUBLE", + "Reduce by computing 50th percentile of data points across time series for each alignment period. This reducer is valid for gauge and delta metrics of numeric and distribution type. The value of the output is DOUBLE", + "Reduce by computing 5th percentile of data points across time series for each alignment period. This reducer is valid for gauge and delta metrics of numeric and distribution type. The value of the output is DOUBLE" + ], + "type": "string" + }, + "groupByFields": { + "description": "The set of fields to preserve when crossSeriesReducer is specified. The groupByFields determine how the time series are partitioned into subsets prior to applying the aggregation function. Each subset contains time series that have the same value for each of the grouping fields. Each individual time series is a member of exactly one subset. The crossSeriesReducer is applied to each subset of time series. It is not possible to reduce across different resource types, so this field implicitly contains resource.type. Fields not specified in groupByFields are aggregated away. If groupByFields is not specified and all the time series have the same resource type, then the time series are aggregated into a single output time series. If crossSeriesReducer is not defined, this field is ignored.", + "items": { + "type": "string" + }, + "type": "array" + }, + "perSeriesAligner": { + "description": "The approach to be used to align individual time series. Not all alignment functions may be applied to all time series, depending on the metric type and value type of the original time series. Alignment may change the metric type or the value type of the time series.Time series data must be aligned in order to perform cross-time series reduction. If crossSeriesReducer is specified, then perSeriesAligner must be specified and not equal ALIGN_NONE and alignmentPeriod must be specified; otherwise, an error is returned.", + "enum": [ + "ALIGN_NONE", + "ALIGN_DELTA", + "ALIGN_RATE", + "ALIGN_INTERPOLATE", + "ALIGN_NEXT_OLDER", + "ALIGN_MIN", + "ALIGN_MAX", + "ALIGN_MEAN", + "ALIGN_COUNT", + "ALIGN_SUM", + "ALIGN_STDDEV", + "ALIGN_COUNT_TRUE", + "ALIGN_COUNT_FALSE", + "ALIGN_FRACTION_TRUE", + "ALIGN_PERCENTILE_99", + "ALIGN_PERCENTILE_95", + "ALIGN_PERCENTILE_50", + "ALIGN_PERCENTILE_05", + "ALIGN_PERCENT_CHANGE" + ], + "enumDescriptions": [ + "No alignment. Raw data is returned. Not valid if cross-time series reduction is requested. The value type of the result is the same as the value type of the input.", + "Align and convert to delta metric type. This alignment is valid for cumulative metrics and delta metrics. Aligning an existing delta metric to a delta metric requires that the alignment period be increased. The value type of the result is the same as the value type of the input.One can think of this aligner as a rate but without time units; that is, the output is conceptually (second_point - first_point).", + "Align and convert to a rate. This alignment is valid for cumulative metrics and delta metrics with numeric values. The output is a gauge metric with value type DOUBLE.One can think of this aligner as conceptually providing the slope of the line that passes through the value at the start and end of the window. In other words, this is conceptually ((y1 - y0)/(t1 - t0)), and the output unit is one that has a \"/time\" dimension.If, by rate, you are looking for percentage change, see the ALIGN_PERCENT_CHANGE aligner option.", + "Align by interpolating between adjacent points around the period boundary. This alignment is valid for gauge metrics with numeric values. The value type of the result is the same as the value type of the input.", + "Align by shifting the oldest data point before the period boundary to the boundary. This alignment is valid for gauge metrics. The value type of the result is the same as the value type of the input.", + "Align time series via aggregation. The resulting data point in the alignment period is the minimum of all data points in the period. This alignment is valid for gauge and delta metrics with numeric values. The value type of the result is the same as the value type of the input.", + "Align time series via aggregation. The resulting data point in the alignment period is the maximum of all data points in the period. This alignment is valid for gauge and delta metrics with numeric values. The value type of the result is the same as the value type of the input.", + "Align time series via aggregation. The resulting data point in the alignment period is the average or arithmetic mean of all data points in the period. This alignment is valid for gauge and delta metrics with numeric values. The value type of the output is DOUBLE.", + "Align time series via aggregation. The resulting data point in the alignment period is the count of all data points in the period. This alignment is valid for gauge and delta metrics with numeric or Boolean values. The value type of the output is INT64.", + "Align time series via aggregation. The resulting data point in the alignment period is the sum of all data points in the period. This alignment is valid for gauge and delta metrics with numeric and distribution values. The value type of the output is the same as the value type of the input.", + "Align time series via aggregation. The resulting data point in the alignment period is the standard deviation of all data points in the period. This alignment is valid for gauge and delta metrics with numeric values. The value type of the output is DOUBLE.", + "Align time series via aggregation. The resulting data point in the alignment period is the count of True-valued data points in the period. This alignment is valid for gauge metrics with Boolean values. The value type of the output is INT64.", + "Align time series via aggregation. The resulting data point in the alignment period is the count of False-valued data points in the period. This alignment is valid for gauge metrics with Boolean values. The value type of the output is INT64.", + "Align time series via aggregation. The resulting data point in the alignment period is the fraction of True-valued data points in the period. This alignment is valid for gauge metrics with Boolean values. The output value is in the range 0, 1 and has value type DOUBLE.", + "Align time series via aggregation. The resulting data point in the alignment period is the 99th percentile of all data points in the period. This alignment is valid for gauge and delta metrics with distribution values. The output is a gauge metric with value type DOUBLE.", + "Align time series via aggregation. The resulting data point in the alignment period is the 95th percentile of all data points in the period. This alignment is valid for gauge and delta metrics with distribution values. The output is a gauge metric with value type DOUBLE.", + "Align time series via aggregation. The resulting data point in the alignment period is the 50th percentile of all data points in the period. This alignment is valid for gauge and delta metrics with distribution values. The output is a gauge metric with value type DOUBLE.", + "Align time series via aggregation. The resulting data point in the alignment period is the 5th percentile of all data points in the period. This alignment is valid for gauge and delta metrics with distribution values. The output is a gauge metric with value type DOUBLE.", + "Align and convert to a percentage change. This alignment is valid for gauge and delta metrics with numeric values. This alignment conceptually computes the equivalent of \"((current - previous)/previous)*100\" where previous value is determined based on the alignmentPeriod. In the event that previous is 0 the calculated value is infinity with the exception that if both (current - previous) and previous are 0 the calculated value is 0. A 10 minute moving mean is computed at each point of the time window prior to the above calculation to smooth the metric and prevent false positives from very short lived spikes. Only applicable for data that is \u003e= 0. Any values \u003c 0 are treated as no data. While delta metrics are accepted by this alignment special care should be taken that the values for the metric will always be positive. The output is a gauge metric with value type DOUBLE." + ], + "type": "string" + } + }, + "type": "object" + }, + "AlertPolicy": { + "description": "A description of the conditions under which some aspect of your system is considered to be \"unhealthy\" and the ways to notify people or services about this state. For an overview of alert policies, see Introduction to Alerting.", + "id": "AlertPolicy", + "properties": { + "combiner": { + "description": "How to combine the results of multiple conditions to determine if an incident should be opened.", + "enum": [ + "COMBINE_UNSPECIFIED", + "AND", + "OR", + "AND_WITH_MATCHING_RESOURCE" + ], + "enumDescriptions": [ + "An unspecified combiner.", + "Combine conditions using the logical AND operator. An incident is created only if all conditions are met simultaneously. This combiner is satisfied if all conditions are met, even if they are met on completely different resources.", + "Combine conditions using the logical OR operator. An incident is created if any of the listed conditions is met.", + "Combine conditions using logical AND operator, but unlike the regular AND option, an incident is created only if all conditions are met simultaneously on at least one resource." + ], + "type": "string" + }, + "conditions": { + "description": "A list of conditions for the policy. The conditions are combined by AND or OR according to the combiner field. If the combined conditions evaluate to true, then an incident is created. A policy can have from one to six conditions.", + "items": { + "$ref": "Condition" + }, + "type": "array" + }, + "creationRecord": { + "$ref": "MutationRecord", + "description": "A read-only record of the creation of the alerting policy. If provided in a call to create or update, this field will be ignored." + }, + "displayName": { + "description": "A short name or phrase used to identify the policy in dashboards, notifications, and incidents. To avoid confusion, don't use the same display name for multiple policies in the same project. The name is limited to 512 Unicode characters.", + "type": "string" + }, + "documentation": { + "$ref": "Documentation", + "description": "Documentation that is included with notifications and incidents related to this policy. Best practice is for the documentation to include information to help responders understand, mitigate, escalate, and correct the underlying problems detected by the alerting policy. Notification channels that have limited capacity might not show this documentation." + }, + "enabled": { + "description": "Whether or not the policy is enabled. On write, the default interpretation if unset is that the policy is enabled. On read, clients should not make any assumption about the state if it has not been populated. The field should always be populated on List and Get operations, unless a field projection has been specified that strips it out.", + "type": "boolean" + }, + "mutationRecord": { + "$ref": "MutationRecord", + "description": "A read-only record of the most recent change to the alerting policy. If provided in a call to create or update, this field will be ignored." + }, + "name": { + "description": "Required if the policy exists. The resource name for this policy. The syntax is:\nprojects/[PROJECT_ID]/alertPolicies/[ALERT_POLICY_ID]\n[ALERT_POLICY_ID] is assigned by Stackdriver Monitoring when the policy is created. When calling the alertPolicies.create method, do not include the name field in the alerting policy passed as part of the request.", + "type": "string" + }, + "notificationChannels": { + "description": "Identifies the notification channels to which notifications should be sent when incidents are opened or closed or when new violations occur on an already opened incident. Each element of this array corresponds to the name field in each of the NotificationChannel objects that are returned from the ListNotificationChannels method. The syntax of the entries in this field is:\nprojects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID]\n", + "items": { + "type": "string" + }, + "type": "array" + }, + "userLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "User-supplied key/value data to be used for organizing and identifying the AlertPolicy objects.The field can contain up to 64 entries. Each key and value is limited to 63 Unicode characters or 128 bytes, whichever is smaller. Labels and values can contain only lowercase letters, numerals, underscores, and dashes. Keys must begin with a letter.", + "type": "object" + } + }, + "type": "object" + }, "BasicAuthentication": { "description": "A type of authentication to perform against the specified resource or URL that uses username and password. Currently, only Basic authentication is supported in Uptime Monitoring.", "id": "BasicAuthentication", @@ -1120,6 +1788,29 @@ }, "type": "object" }, + "Condition": { + "description": "A condition is a true/false test that determines when an alerting policy should open an incident. If a condition evaluates to true, it signifies that something is wrong.", + "id": "Condition", + "properties": { + "conditionAbsent": { + "$ref": "MetricAbsence", + "description": "A condition that checks that a time series continues to receive new data points." + }, + "conditionThreshold": { + "$ref": "MetricThreshold", + "description": "A condition that compares a time series against a threshold." + }, + "displayName": { + "description": "A short name or phrase used to identify the condition in dashboards, notifications, and incidents. To avoid confusion, don't use the same display name for multiple conditions in the same policy.", + "type": "string" + }, + "name": { + "description": "Required if the condition exists. The unique resource name for this condition. Its syntax is:\nprojects/[PROJECT_ID]/alertPolicies/[POLICY_ID]/conditions/[CONDITION_ID]\n[CONDITION_ID] is assigned by Stackdriver Monitoring when the condition is created as part of a new or updated alerting policy.When calling the alertPolicies.create method, do not include the name field in the conditions of the requested alerting policy. Stackdriver Monitoring creates the condition identifiers and includes them in the new policy.When calling the alertPolicies.update method to update a policy, including a condition name causes the existing condition to be updated. Conditions without names are added to the updated policy. Existing conditions are deleted if they are not updated.Best practice is to preserve [CONDITION_ID] if you make only small changes, such as those to condition thresholds, durations, or trigger values. Otherwise, treat the change as a new condition and let the existing condition be deleted.", + "type": "string" + } + }, + "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.", "id": "ContentMatcher", @@ -1202,6 +1893,13 @@ "format": "int64", "type": "string" }, + "exemplars": { + "description": "Must be in increasing order of |value| field. The current requirement enforced by the backend is that at most one Exemplar will fall into any bucket.", + "items": { + "$ref": "Exemplar" + }, + "type": "array" + }, "mean": { "description": "The arithmetic mean of the values in the population. If count is zero then this field must be zero.", "format": "double", @@ -1219,12 +1917,55 @@ }, "type": "object" }, + "Documentation": { + "description": "A content string and a MIME type that describes the content string's format.", + "id": "Documentation", + "properties": { + "content": { + "description": "The text of the documentation, interpreted according to mime_type. The content may not exceed 8,192 Unicode characters and may not exceed more than 10,240 bytes when encoded in UTF-8 format, whichever is smaller.", + "type": "string" + }, + "mimeType": { + "description": "The format of the content field. Presently, only the value \"text/markdown\" is supported. See Markdown (https://en.wikipedia.org/wiki/Markdown) for more information.", + "type": "string" + } + }, + "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", "properties": {}, "type": "object" }, + "Exemplar": { + "description": "Exemplars are example points that may be used to annotate aggregated distribution values. They are metadata that gives information about a particular value added to a Distribution bucket, such as a trace ID that was active when a value was added. They may contain further information, such as a example values and timestamps, origin, etc.", + "id": "Exemplar", + "properties": { + "attachments": { + "description": "Contextual information about the example value. Examples are:Trace ID: type.googleapis.com/google.devtools.cloudtrace.v1.TraceLiteral string: type.googleapis.com/google.protobuf.StringValueLabels dropped during aggregation: type.googleapis.com/google.monitoring.v3.DroppedLabelsThere may be only a single attachment of any given message type in a single exemplar, and this is enforced by the system.", + "items": { + "additionalProperties": { + "description": "Properties of the object. Contains field @type with type URL.", + "type": "any" + }, + "type": "object" + }, + "type": "array" + }, + "timestamp": { + "description": "The observation (sampling) time of the above value.", + "format": "google-datetime", + "type": "string" + }, + "value": { + "description": "Value of the exemplar point. This value determines to which bucket the exemplar belongs.", + "format": "double", + "type": "number" + } + }, + "type": "object" + }, "Explicit": { "description": "Specifies a set of buckets with arbitrary widths.There are size(bounds) + 1 (= N) buckets. Bucket i has the following boundaries:Upper bound (0 \u003c= i \u003c N-1): boundsi Lower bound (1 \u003c= i \u003c N); boundsi - 1The bounds field must contain at least one element. If bounds has only one element, then there are no finite buckets, and that single element is the common boundary of the overflow and underflow buckets.", "id": "Explicit", @@ -1368,6 +2109,34 @@ }, "type": "object" }, + "GetNotificationChannelVerificationCodeRequest": { + "description": "The GetNotificationChannelVerificationCode request.", + "id": "GetNotificationChannelVerificationCodeRequest", + "properties": { + "expireTime": { + "description": "The desired expiration time. If specified, the API will guarantee that the returned code will not be valid after the specified timestamp; however, the API cannot guarantee that the returned code will be valid for at least as long as the requested time (the API puts an upper bound on the amount of time for which a code may be valid). If omitted, a default expiration will be used, which may be less than the max permissible expiration (so specifying an expiration may extend the code's lifetime over omitting an expiration, even though the API does impose an upper limit on the maximum expiration that is permitted).", + "format": "google-datetime", + "type": "string" + } + }, + "type": "object" + }, + "GetNotificationChannelVerificationCodeResponse": { + "description": "The GetNotificationChannelVerificationCode request.", + "id": "GetNotificationChannelVerificationCodeResponse", + "properties": { + "code": { + "description": "The verification code, which may be used to verify other channels that have an equivalent identity (i.e. other channels of the same type with the same fingerprint such as other email channels with the same email address or other sms channels with the same number).", + "type": "string" + }, + "expireTime": { + "description": "The expiration time associated with the code that was returned. If an expiration was provided in the request, this is the minimum of the requested expiration in the request and the max permitted expiration.", + "format": "google-datetime", + "type": "string" + } + }, + "type": "object" + }, "Group": { "description": "The description of a dynamic collection of monitored resources. Each group has a filter that is matched against monitored resources and their associated metadata. If a group's filter matches an available monitored resource, then that resource is a member of that group. Groups can contain any number of monitored resources, and each monitored resource can be a member of any number of groups.Groups can be nested in parent-child hierarchies. The parentName field identifies an optional parent for each group. If a group has a parent, then the only monitored resources available to be matched by the group's filter are the resources contained in the parent group. In other words, a group contains the monitored resources that match its filter and the filters of all the group's ancestors. A group without a parent can contain any monitored resource.For example, consider an infrastructure running a set of instances with two user-defined tags: \"environment\" and \"role\". A parent group has a filter, environment=\"production\". A child of that parent group has a filter, role=\"transcoder\". The parent group contains all instances in the production environment, regardless of their roles. The child group contains instances that have the transcoder role and are in the production environment.The monitored resources contained in a group can change at any moment, depending on what resources exist and what filters are associated with the group and its ancestors.", "id": "Group", @@ -1508,6 +2277,24 @@ }, "type": "object" }, + "ListAlertPoliciesResponse": { + "description": "The protocol for the ListAlertPolicies response.", + "id": "ListAlertPoliciesResponse", + "properties": { + "alertPolicies": { + "description": "The returned alert policies.", + "items": { + "$ref": "AlertPolicy" + }, + "type": "array" + }, + "nextPageToken": { + "description": "If there might be more results than were returned, then this field is set to a non-empty value. To see the additional results, use that value as pageToken in the next call to this method.", + "type": "string" + } + }, + "type": "object" + }, "ListGroupMembersResponse": { "description": "The ListGroupMembers response.", "id": "ListGroupMembersResponse", @@ -1585,10 +2372,53 @@ }, "type": "object" }, + "ListNotificationChannelDescriptorsResponse": { + "description": "The ListNotificationChannelDescriptors response.", + "id": "ListNotificationChannelDescriptorsResponse", + "properties": { + "channelDescriptors": { + "description": "The monitored resource descriptors supported for the specified project, optionally filtered.", + "items": { + "$ref": "NotificationChannelDescriptor" + }, + "type": "array" + }, + "nextPageToken": { + "description": "If not empty, indicates that there may be more results that match the request. Use the value in the page_token field in a subsequent request to fetch the next set of results. If empty, all results have been returned.", + "type": "string" + } + }, + "type": "object" + }, + "ListNotificationChannelsResponse": { + "description": "The ListNotificationChannels response.", + "id": "ListNotificationChannelsResponse", + "properties": { + "nextPageToken": { + "description": "If not empty, indicates that there may be more results that match the request. Use the value in the page_token field in a subsequent request to fetch the next set of results. If empty, all results have been returned.", + "type": "string" + }, + "notificationChannels": { + "description": "The notification channels defined for the specified project.", + "items": { + "$ref": "NotificationChannel" + }, + "type": "array" + } + }, + "type": "object" + }, "ListTimeSeriesResponse": { "description": "The ListTimeSeries response.", "id": "ListTimeSeriesResponse", "properties": { + "executionErrors": { + "description": "Query execution errors that may have caused the time series data returned to be incomplete.", + "items": { + "$ref": "Status" + }, + "type": "array" + }, "nextPageToken": { "description": "If there are more results than have been returned, then this field is set to a non-empty value. To see the additional results, use that value as pageToken in the next call to this method.", "type": "string" @@ -1662,6 +2492,33 @@ }, "type": "object" }, + "MetricAbsence": { + "description": "A condition type that checks that monitored resources are reporting data. The configuration defines a metric and a set of monitored resources. The predicate is considered in violation when a time series for the specified metric of a monitored resource does not include any data in the specified duration.", + "id": "MetricAbsence", + "properties": { + "aggregations": { + "description": "Specifies the alignment of data points in individual time series as well as how to combine the retrieved time series together (such as when aggregating multiple streams on each resource to a single stream for each resource or when aggregating streams across all members of a group of resrouces). Multiple aggregations are applied in the order specified.This field is similar to the one in the MetricService.ListTimeSeries request. It is advisable to use the ListTimeSeries method when debugging this field.", + "items": { + "$ref": "Aggregation" + }, + "type": "array" + }, + "duration": { + "description": "The amount of time that a time series must fail to report new data to be considered failing. Currently, only values that are a multiple of a minute--e.g. 60, 120, or 300 seconds--are supported. If an invalid value is given, an error will be returned. The Duration.nanos field is ignored.", + "format": "google-duration", + "type": "string" + }, + "filter": { + "description": "A filter that identifies which time series should be compared with the threshold.The filter is similar to the one that is specified in the MetricService.ListTimeSeries request (that call is useful to verify the time series that will be retrieved / processed) and must specify the metric type and optionally may contain restrictions on resource type, resource labels, and metric labels. This field may not exceed 2048 Unicode characters in length.", + "type": "string" + }, + "trigger": { + "$ref": "Trigger", + "description": "The number/percent of time series for which the comparison must hold in order for the condition to trigger. If unspecified, then the condition will trigger if the comparison is true for any of the time series that have been identified by filter and aggregations." + } + }, + "type": "object" + }, "MetricDescriptor": { "description": "Defines a metric type and its schema. Once a metric descriptor is created, deleting or altering it stops data collection and makes the metric type's existing data unusable.", "id": "MetricDescriptor", @@ -1734,6 +2591,71 @@ }, "type": "object" }, + "MetricThreshold": { + "description": "A condition type that compares a collection of time series against a threshold.", + "id": "MetricThreshold", + "properties": { + "aggregations": { + "description": "Specifies the alignment of data points in individual time series as well as how to combine the retrieved time series together (such as when aggregating multiple streams on each resource to a single stream for each resource or when aggregating streams across all members of a group of resrouces). Multiple aggregations are applied in the order specified.This field is similar to the one in the MetricService.ListTimeSeries request. It is advisable to use the ListTimeSeries method when debugging this field.", + "items": { + "$ref": "Aggregation" + }, + "type": "array" + }, + "comparison": { + "description": "The comparison to apply between the time series (indicated by filter and aggregation) and the threshold (indicated by threshold_value). The comparison is applied on each time series, with the time series on the left-hand side and the threshold on the right-hand side.Only COMPARISON_LT and COMPARISON_GT are supported currently.", + "enum": [ + "COMPARISON_UNSPECIFIED", + "COMPARISON_GT", + "COMPARISON_GE", + "COMPARISON_LT", + "COMPARISON_LE", + "COMPARISON_EQ", + "COMPARISON_NE" + ], + "enumDescriptions": [ + "No ordering relationship is specified.", + "The left argument is greater than the right argument.", + "The left argument is greater than or equal to the right argument.", + "The left argument is less than the right argument.", + "The left argument is less than or equal to the right argument.", + "The left argument is equal to the right argument.", + "The left argument is not equal to the right argument." + ], + "type": "string" + }, + "denominatorAggregations": { + "description": "Specifies the alignment of data points in individual time series selected by denominatorFilter as well as how to combine the retrieved time series together (such as when aggregating multiple streams on each resource to a single stream for each resource or when aggregating streams across all members of a group of resources).When computing ratios, the aggregations and denominator_aggregations fields must use the same alignment period and produce time series that have the same periodicity and labels.This field is similar to the one in the MetricService.ListTimeSeries request. It is advisable to use the ListTimeSeries method when debugging this field.", + "items": { + "$ref": "Aggregation" + }, + "type": "array" + }, + "denominatorFilter": { + "description": "A filter that identifies a time series that should be used as the denominator of a ratio that will be compared with the threshold. If a denominator_filter is specified, the time series specified by the filter field will be used as the numerator.The filter is similar to the one that is specified in the MetricService.ListTimeSeries request (that call is useful to verify the time series that will be retrieved / processed) and must specify the metric type and optionally may contain restrictions on resource type, resource labels, and metric labels. This field may not exceed 2048 Unicode characters in length.", + "type": "string" + }, + "duration": { + "description": "The amount of time that a time series must violate the threshold to be considered failing. Currently, only values that are a multiple of a minute--e.g., 0, 60, 120, or 300 seconds--are supported. If an invalid value is given, an error will be returned. When choosing a duration, it is useful to keep in mind the frequency of the underlying time series data (which may also be affected by any alignments specified in the aggregations field); a good duration is long enough so that a single outlier does not generate spurious alerts, but short enough that unhealthy states are detected and alerted on quickly.", + "format": "google-duration", + "type": "string" + }, + "filter": { + "description": "A filter that identifies which time series should be compared with the threshold.The filter is similar to the one that is specified in the MetricService.ListTimeSeries request (that call is useful to verify the time series that will be retrieved / processed) and must specify the metric type and optionally may contain restrictions on resource type, resource labels, and metric labels. This field may not exceed 2048 Unicode characters in length.", + "type": "string" + }, + "thresholdValue": { + "description": "A value against which to compare the time series.", + "format": "double", + "type": "number" + }, + "trigger": { + "$ref": "Trigger", + "description": "The number/percent of time series for which the comparison must hold in order for the condition to trigger. If unspecified, then the condition will trigger if the comparison is true for any of the time series that have been identified by filter and aggregations, or by the ratio, if denominator_filter and denominator_aggregations are specified." + } + }, + "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", @@ -1804,6 +2726,124 @@ }, "type": "object" }, + "MutationRecord": { + "description": "Describes a change made to a configuration.", + "id": "MutationRecord", + "properties": { + "mutateTime": { + "description": "When the change occurred.", + "format": "google-datetime", + "type": "string" + }, + "mutatedBy": { + "description": "The email address of the user making the change.", + "type": "string" + } + }, + "type": "object" + }, + "NotificationChannel": { + "description": "A NotificationChannel is a medium through which an alert is delivered when a policy violation is detected. Examples of channels include email, SMS, and third-party messaging applications. Fields containing sensitive information like authentication tokens or contact info are only partially populated on retrieval.", + "id": "NotificationChannel", + "properties": { + "description": { + "description": "An optional human-readable description of this notification channel. This description may provide additional details, beyond the display name, for the channel. This may not exceeed 1024 Unicode characters.", + "type": "string" + }, + "displayName": { + "description": "An optional human-readable name for this notification channel. It is recommended that you specify a non-empty and unique name in order to make it easier to identify the channels in your project, though this is not enforced. The display name is limited to 512 Unicode characters.", + "type": "string" + }, + "enabled": { + "description": "Whether notifications are forwarded to the described channel. This makes it possible to disable delivery of notifications to a particular channel without removing the channel from all alerting policies that reference the channel. This is a more convenient approach when the change is temporary and you want to receive notifications from the same set of alerting policies on the channel at some point in the future.", + "type": "boolean" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "Configuration fields that define the channel and its behavior. The permissible and required labels are specified in the NotificationChannelDescriptor.labels of the NotificationChannelDescriptor corresponding to the type field.", + "type": "object" + }, + "name": { + "description": "The full REST resource name for this channel. The syntax is:\nprojects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID]\nThe [CHANNEL_ID] is automatically assigned by the server on creation.", + "type": "string" + }, + "type": { + "description": "The type of the notification channel. This field matches the value of the NotificationChannelDescriptor.type field.", + "type": "string" + }, + "userLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "User-supplied key/value data that does not need to conform to the corresponding NotificationChannelDescriptor's schema, unlike the labels field. This field is intended to be used for organizing and identifying the NotificationChannel objects.The field can contain up to 64 entries. Each key and value is limited to 63 Unicode characters or 128 bytes, whichever is smaller. Labels and values can contain only lowercase letters, numerals, underscores, and dashes. Keys must begin with a letter.", + "type": "object" + }, + "verificationStatus": { + "description": "Indicates whether this channel has been verified or not. On a ListNotificationChannels or GetNotificationChannel operation, this field is expected to be populated.If the value is UNVERIFIED, then it indicates that the channel is non-functioning (it both requires verification and lacks verification); otherwise, it is assumed that the channel works.If the channel is neither VERIFIED nor UNVERIFIED, it implies that the channel is of a type that does not require verification or that this specific channel has been exempted from verification because it was created prior to verification being required for channels of this type.This field cannot be modified using a standard UpdateNotificationChannel operation. To change the value of this field, you must call VerifyNotificationChannel.", + "enum": [ + "VERIFICATION_STATUS_UNSPECIFIED", + "UNVERIFIED", + "VERIFIED" + ], + "enumDescriptions": [ + "Sentinel value used to indicate that the state is unknown, omitted, or is not applicable (as in the case of channels that neither support nor require verification in order to function).", + "The channel has yet to be verified and requires verification to function. Note that this state also applies to the case where the verification process has been initiated by sending a verification code but where the verification code has not been submitted to complete the process.", + "It has been proven that notifications can be received on this notification channel and that someone on the project has access to messages that are delivered to that channel." + ], + "type": "string" + } + }, + "type": "object" + }, + "NotificationChannelDescriptor": { + "description": "A description of a notification channel. The descriptor includes the properties of the channel and the set of labels or fields that must be specified to configure channels of a given type.", + "id": "NotificationChannelDescriptor", + "properties": { + "description": { + "description": "A human-readable description of the notification channel type. The description may include a description of the properties of the channel and pointers to external documentation.", + "type": "string" + }, + "displayName": { + "description": "A human-readable name for the notification channel type. This form of the name is suitable for a user interface.", + "type": "string" + }, + "labels": { + "description": "The set of labels that must be defined to identify a particular channel of the corresponding type. Each label includes a description for how that field should be populated.", + "items": { + "$ref": "LabelDescriptor" + }, + "type": "array" + }, + "name": { + "description": "The full REST resource name for this descriptor. The syntax is:\nprojects/[PROJECT_ID]/notificationChannelDescriptors/[TYPE]\nIn the above, [TYPE] is the value of the type field.", + "type": "string" + }, + "supportedTiers": { + "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)." + ], + "items": { + "enum": [ + "SERVICE_TIER_UNSPECIFIED", + "SERVICE_TIER_BASIC", + "SERVICE_TIER_PREMIUM" + ], + "type": "string" + }, + "type": "array" + }, + "type": { + "description": "The type of notification channel, such as \"email\", \"sms\", etc. Notification channel types are globally unique.", + "type": "string" + } + }, + "type": "object" + }, "Option": { "description": "A protocol buffer option, which can be attached to a message, field, enumeration, etc.", "id": "Option", @@ -1880,6 +2920,12 @@ }, "type": "object" }, + "SendNotificationChannelVerificationCodeRequest": { + "description": "The SendNotificationChannelVerificationCode request.", + "id": "SendNotificationChannelVerificationCodeRequest", + "properties": {}, + "type": "object" + }, "SourceContext": { "description": "SourceContext represents information about the source of a protobuf element, like the file in which it is defined.", "id": "SourceContext", @@ -2011,6 +3057,23 @@ }, "type": "object" }, + "Trigger": { + "description": "Specifies how many time series must fail a predicate to trigger a condition. If not specified, then a {count: 1} trigger is used.", + "id": "Trigger", + "properties": { + "count": { + "description": "The absolute number of time series that must fail the predicate for the condition to be triggered.", + "format": "int32", + "type": "integer" + }, + "percent": { + "description": "The percentage of time series that must fail the predicate for the condition to be triggered.", + "format": "double", + "type": "number" + } + }, + "type": "object" + }, "Type": { "description": "A protocol buffer message type.", "id": "Type", @@ -2127,7 +3190,7 @@ "type": "string" }, "period": { - "description": "How often, in seconds, the uptime check is performed. Currently, the only supported values are 60s (1 minute), 300s (5 minutes), 600s (10 minutes), and 900s (15 minutes). Required.", + "description": "How often, in seconds, the uptime check is performed. Currently, the only supported values are 60s (1 minute), 300s (5 minutes), 600s (10 minutes), and 900s (15 minutes). Optional, defaults to 300s.", "format": "google-duration", "type": "string" }, @@ -2200,6 +3263,17 @@ } }, "type": "object" + }, + "VerifyNotificationChannelRequest": { + "description": "The VerifyNotificationChannel request.", + "id": "VerifyNotificationChannelRequest", + "properties": { + "code": { + "description": "The verification code that was delivered to the channel as a result of invoking the SendNotificationChannelVerificationCode API method or that was retrieved from a verified channel via GetNotificationChannelVerificationCode. For example, one might have \"G-123456\" or \"TKNZGhhd2EyN3I1MnRnMjRv\" (in general, one is only guaranteed that the code is valid UTF-8; one should not make any assumptions regarding the structure or format of the code).", + "type": "string" + } + }, + "type": "object" } }, "servicePath": "", 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 3c01ac199a6..9b44ae6599a 100644 --- a/vendor/google.golang.org/api/monitoring/v3/monitoring-gen.go +++ b/vendor/google.golang.org/api/monitoring/v3/monitoring-gen.go @@ -91,10 +91,13 @@ func (s *Service) userAgent() string { func NewProjectsService(s *Service) *ProjectsService { rs := &ProjectsService{s: s} + rs.AlertPolicies = NewProjectsAlertPoliciesService(s) rs.CollectdTimeSeries = NewProjectsCollectdTimeSeriesService(s) rs.Groups = NewProjectsGroupsService(s) rs.MetricDescriptors = NewProjectsMetricDescriptorsService(s) rs.MonitoredResourceDescriptors = NewProjectsMonitoredResourceDescriptorsService(s) + rs.NotificationChannelDescriptors = NewProjectsNotificationChannelDescriptorsService(s) + rs.NotificationChannels = NewProjectsNotificationChannelsService(s) rs.TimeSeries = NewProjectsTimeSeriesService(s) rs.UptimeCheckConfigs = NewProjectsUptimeCheckConfigsService(s) return rs @@ -103,6 +106,8 @@ func NewProjectsService(s *Service) *ProjectsService { type ProjectsService struct { s *Service + AlertPolicies *ProjectsAlertPoliciesService + CollectdTimeSeries *ProjectsCollectdTimeSeriesService Groups *ProjectsGroupsService @@ -111,11 +116,24 @@ type ProjectsService struct { MonitoredResourceDescriptors *ProjectsMonitoredResourceDescriptorsService + NotificationChannelDescriptors *ProjectsNotificationChannelDescriptorsService + + NotificationChannels *ProjectsNotificationChannelsService + TimeSeries *ProjectsTimeSeriesService UptimeCheckConfigs *ProjectsUptimeCheckConfigsService } +func NewProjectsAlertPoliciesService(s *Service) *ProjectsAlertPoliciesService { + rs := &ProjectsAlertPoliciesService{s: s} + return rs +} + +type ProjectsAlertPoliciesService struct { + s *Service +} + func NewProjectsCollectdTimeSeriesService(s *Service) *ProjectsCollectdTimeSeriesService { rs := &ProjectsCollectdTimeSeriesService{s: s} return rs @@ -164,6 +182,24 @@ type ProjectsMonitoredResourceDescriptorsService struct { s *Service } +func NewProjectsNotificationChannelDescriptorsService(s *Service) *ProjectsNotificationChannelDescriptorsService { + rs := &ProjectsNotificationChannelDescriptorsService{s: s} + return rs +} + +type ProjectsNotificationChannelDescriptorsService struct { + s *Service +} + +func NewProjectsNotificationChannelsService(s *Service) *ProjectsNotificationChannelsService { + rs := &ProjectsNotificationChannelsService{s: s} + return rs +} + +type ProjectsNotificationChannelsService struct { + s *Service +} + func NewProjectsTimeSeriesService(s *Service) *ProjectsTimeSeriesService { rs := &ProjectsTimeSeriesService{s: s} return rs @@ -191,6 +227,361 @@ type UptimeCheckIpsService struct { s *Service } +// Aggregation: Describes how to combine multiple time series to provide +// different views of the data. Aggregation consists of an alignment +// step on individual time series (alignment_period and +// per_series_aligner) followed by an optional reduction step of the +// data across the aligned time series (cross_series_reducer and +// group_by_fields). For more details, see Aggregation. +type Aggregation struct { + // AlignmentPeriod: The alignment period for per-time series alignment. + // If present, alignmentPeriod must be at least 60 seconds. After + // per-time series alignment, each time series will contain data points + // only on the period boundaries. If perSeriesAligner is not specified + // or equals ALIGN_NONE, then this field is ignored. If perSeriesAligner + // is specified and does not equal ALIGN_NONE, then this field must be + // defined; otherwise an error is returned. + AlignmentPeriod string `json:"alignmentPeriod,omitempty"` + + // CrossSeriesReducer: The approach to be used to combine time series. + // Not all reducer functions may be applied to all time series, + // depending on the metric type and the value type of the original time + // series. Reduction may change the metric type of value type of the + // time series.Time series data must be aligned in order to perform + // cross-time series reduction. If crossSeriesReducer is specified, then + // perSeriesAligner must be specified and not equal ALIGN_NONE and + // alignmentPeriod must be specified; otherwise, an error is returned. + // + // Possible values: + // "REDUCE_NONE" - No cross-time series reduction. The output of the + // aligner is returned. + // "REDUCE_MEAN" - Reduce by computing the mean across time series for + // each alignment period. This reducer is valid for delta and gauge + // metrics with numeric or distribution values. The value type of the + // output is DOUBLE. + // "REDUCE_MIN" - Reduce by computing the minimum across time series + // for each alignment period. This reducer is valid for delta and gauge + // metrics with numeric values. The value type of the output is the same + // as the value type of the input. + // "REDUCE_MAX" - Reduce by computing the maximum across time series + // for each alignment period. This reducer is valid for delta and gauge + // metrics with numeric values. The value type of the output is the same + // as the value type of the input. + // "REDUCE_SUM" - Reduce by computing the sum across time series for + // each alignment period. This reducer is valid for delta and gauge + // metrics with numeric and distribution values. The value type of the + // output is the same as the value type of the input. + // "REDUCE_STDDEV" - Reduce by computing the standard deviation across + // time series for each alignment period. This reducer is valid for + // delta and gauge metrics with numeric or distribution values. The + // value type of the output is DOUBLE. + // "REDUCE_COUNT" - Reduce by computing the count of data points + // across time series for each alignment period. This reducer is valid + // for delta and gauge metrics of numeric, Boolean, distribution, and + // string value type. The value type of the output is INT64. + // "REDUCE_COUNT_TRUE" - Reduce by computing the count of True-valued + // data points across time series for each alignment period. This + // reducer is valid for delta and gauge metrics of Boolean value type. + // The value type of the output is INT64. + // "REDUCE_COUNT_FALSE" - Reduce by computing the count of + // False-valued data points across time series for each alignment + // period. This reducer is valid for delta and gauge metrics of Boolean + // value type. The value type of the output is INT64. + // "REDUCE_FRACTION_TRUE" - Reduce by computing the fraction of + // True-valued data points across time series for each alignment period. + // This reducer is valid for delta and gauge metrics of Boolean value + // type. The output value is in the range 0, 1 and has value type + // DOUBLE. + // "REDUCE_PERCENTILE_99" - Reduce by computing 99th percentile of + // data points across time series for each alignment period. This + // reducer is valid for gauge and delta metrics of numeric and + // distribution type. The value of the output is DOUBLE + // "REDUCE_PERCENTILE_95" - Reduce by computing 95th percentile of + // data points across time series for each alignment period. This + // reducer is valid for gauge and delta metrics of numeric and + // distribution type. The value of the output is DOUBLE + // "REDUCE_PERCENTILE_50" - Reduce by computing 50th percentile of + // data points across time series for each alignment period. This + // reducer is valid for gauge and delta metrics of numeric and + // distribution type. The value of the output is DOUBLE + // "REDUCE_PERCENTILE_05" - Reduce by computing 5th percentile of data + // points across time series for each alignment period. This reducer is + // valid for gauge and delta metrics of numeric and distribution type. + // The value of the output is DOUBLE + CrossSeriesReducer string `json:"crossSeriesReducer,omitempty"` + + // GroupByFields: The set of fields to preserve when crossSeriesReducer + // is specified. The groupByFields determine how the time series are + // partitioned into subsets prior to applying the aggregation function. + // Each subset contains time series that have the same value for each of + // the grouping fields. Each individual time series is a member of + // exactly one subset. The crossSeriesReducer is applied to each subset + // of time series. It is not possible to reduce across different + // resource types, so this field implicitly contains resource.type. + // Fields not specified in groupByFields are aggregated away. If + // groupByFields is not specified and all the time series have the same + // resource type, then the time series are aggregated into a single + // output time series. If crossSeriesReducer is not defined, this field + // is ignored. + GroupByFields []string `json:"groupByFields,omitempty"` + + // PerSeriesAligner: The approach to be used to align individual time + // series. Not all alignment functions may be applied to all time + // series, depending on the metric type and value type of the original + // time series. Alignment may change the metric type or the value type + // of the time series.Time series data must be aligned in order to + // perform cross-time series reduction. If crossSeriesReducer is + // specified, then perSeriesAligner must be specified and not equal + // ALIGN_NONE and alignmentPeriod must be specified; otherwise, an error + // is returned. + // + // Possible values: + // "ALIGN_NONE" - No alignment. Raw data is returned. Not valid if + // cross-time series reduction is requested. The value type of the + // result is the same as the value type of the input. + // "ALIGN_DELTA" - Align and convert to delta metric type. This + // alignment is valid for cumulative metrics and delta metrics. Aligning + // an existing delta metric to a delta metric requires that the + // alignment period be increased. The value type of the result is the + // same as the value type of the input.One can think of this aligner as + // a rate but without time units; that is, the output is conceptually + // (second_point - first_point). + // "ALIGN_RATE" - Align and convert to a rate. This alignment is valid + // for cumulative metrics and delta metrics with numeric values. The + // output is a gauge metric with value type DOUBLE.One can think of this + // aligner as conceptually providing the slope of the line that passes + // through the value at the start and end of the window. In other words, + // this is conceptually ((y1 - y0)/(t1 - t0)), and the output unit is + // one that has a "/time" dimension.If, by rate, you are looking for + // percentage change, see the ALIGN_PERCENT_CHANGE aligner option. + // "ALIGN_INTERPOLATE" - Align by interpolating between adjacent + // points around the period boundary. This alignment is valid for gauge + // metrics with numeric values. The value type of the result is the same + // as the value type of the input. + // "ALIGN_NEXT_OLDER" - Align by shifting the oldest data point before + // the period boundary to the boundary. This alignment is valid for + // gauge metrics. The value type of the result is the same as the value + // type of the input. + // "ALIGN_MIN" - Align time series via aggregation. The resulting data + // point in the alignment period is the minimum of all data points in + // the period. This alignment is valid for gauge and delta metrics with + // numeric values. The value type of the result is the same as the value + // type of the input. + // "ALIGN_MAX" - Align time series via aggregation. The resulting data + // point in the alignment period is the maximum of all data points in + // the period. This alignment is valid for gauge and delta metrics with + // numeric values. The value type of the result is the same as the value + // type of the input. + // "ALIGN_MEAN" - Align time series via aggregation. The resulting + // data point in the alignment period is the average or arithmetic mean + // of all data points in the period. This alignment is valid for gauge + // and delta metrics with numeric values. The value type of the output + // is DOUBLE. + // "ALIGN_COUNT" - Align time series via aggregation. The resulting + // data point in the alignment period is the count of all data points in + // the period. This alignment is valid for gauge and delta metrics with + // numeric or Boolean values. The value type of the output is INT64. + // "ALIGN_SUM" - Align time series via aggregation. The resulting data + // point in the alignment period is the sum of all data points in the + // period. This alignment is valid for gauge and delta metrics with + // numeric and distribution values. The value type of the output is the + // same as the value type of the input. + // "ALIGN_STDDEV" - Align time series via aggregation. The resulting + // data point in the alignment period is the standard deviation of all + // data points in the period. This alignment is valid for gauge and + // delta metrics with numeric values. The value type of the output is + // DOUBLE. + // "ALIGN_COUNT_TRUE" - Align time series via aggregation. The + // resulting data point in the alignment period is the count of + // True-valued data points in the period. This alignment is valid for + // gauge metrics with Boolean values. The value type of the output is + // INT64. + // "ALIGN_COUNT_FALSE" - Align time series via aggregation. The + // resulting data point in the alignment period is the count of + // False-valued data points in the period. This alignment is valid for + // gauge metrics with Boolean values. The value type of the output is + // INT64. + // "ALIGN_FRACTION_TRUE" - Align time series via aggregation. The + // resulting data point in the alignment period is the fraction of + // True-valued data points in the period. This alignment is valid for + // gauge metrics with Boolean values. The output value is in the range + // 0, 1 and has value type DOUBLE. + // "ALIGN_PERCENTILE_99" - Align time series via aggregation. The + // resulting data point in the alignment period is the 99th percentile + // of all data points in the period. This alignment is valid for gauge + // and delta metrics with distribution values. The output is a gauge + // metric with value type DOUBLE. + // "ALIGN_PERCENTILE_95" - Align time series via aggregation. The + // resulting data point in the alignment period is the 95th percentile + // of all data points in the period. This alignment is valid for gauge + // and delta metrics with distribution values. The output is a gauge + // metric with value type DOUBLE. + // "ALIGN_PERCENTILE_50" - Align time series via aggregation. The + // resulting data point in the alignment period is the 50th percentile + // of all data points in the period. This alignment is valid for gauge + // and delta metrics with distribution values. The output is a gauge + // metric with value type DOUBLE. + // "ALIGN_PERCENTILE_05" - Align time series via aggregation. The + // resulting data point in the alignment period is the 5th percentile of + // all data points in the period. This alignment is valid for gauge and + // delta metrics with distribution values. The output is a gauge metric + // with value type DOUBLE. + // "ALIGN_PERCENT_CHANGE" - Align and convert to a percentage change. + // This alignment is valid for gauge and delta metrics with numeric + // values. This alignment conceptually computes the equivalent of + // "((current - previous)/previous)*100" where previous value is + // determined based on the alignmentPeriod. In the event that previous + // is 0 the calculated value is infinity with the exception that if both + // (current - previous) and previous are 0 the calculated value is 0. A + // 10 minute moving mean is computed at each point of the time window + // prior to the above calculation to smooth the metric and prevent false + // positives from very short lived spikes. Only applicable for data that + // is >= 0. Any values < 0 are treated as no data. While delta metrics + // are accepted by this alignment special care should be taken that the + // values for the metric will always be positive. The output is a gauge + // metric with value type DOUBLE. + PerSeriesAligner string `json:"perSeriesAligner,omitempty"` + + // ForceSendFields is a list of field names (e.g. "AlignmentPeriod") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AlignmentPeriod") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *Aggregation) MarshalJSON() ([]byte, error) { + type NoMethod Aggregation + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AlertPolicy: A description of the conditions under which some aspect +// of your system is considered to be "unhealthy" and the ways to notify +// people or services about this state. For an overview of alert +// policies, see Introduction to Alerting. +type AlertPolicy struct { + // Combiner: How to combine the results of multiple conditions to + // determine if an incident should be opened. + // + // Possible values: + // "COMBINE_UNSPECIFIED" - An unspecified combiner. + // "AND" - Combine conditions using the logical AND operator. An + // incident is created only if all conditions are met simultaneously. + // This combiner is satisfied if all conditions are met, even if they + // are met on completely different resources. + // "OR" - Combine conditions using the logical OR operator. An + // incident is created if any of the listed conditions is met. + // "AND_WITH_MATCHING_RESOURCE" - Combine conditions using logical AND + // operator, but unlike the regular AND option, an incident is created + // only if all conditions are met simultaneously on at least one + // resource. + Combiner string `json:"combiner,omitempty"` + + // Conditions: A list of conditions for the policy. The conditions are + // combined by AND or OR according to the combiner field. If the + // combined conditions evaluate to true, then an incident is created. A + // policy can have from one to six conditions. + Conditions []*Condition `json:"conditions,omitempty"` + + // CreationRecord: A read-only record of the creation of the alerting + // policy. If provided in a call to create or update, this field will be + // ignored. + CreationRecord *MutationRecord `json:"creationRecord,omitempty"` + + // DisplayName: A short name or phrase used to identify the policy in + // dashboards, notifications, and incidents. To avoid confusion, don't + // use the same display name for multiple policies in the same project. + // The name is limited to 512 Unicode characters. + DisplayName string `json:"displayName,omitempty"` + + // Documentation: Documentation that is included with notifications and + // incidents related to this policy. Best practice is for the + // documentation to include information to help responders understand, + // mitigate, escalate, and correct the underlying problems detected by + // the alerting policy. Notification channels that have limited capacity + // might not show this documentation. + Documentation *Documentation `json:"documentation,omitempty"` + + // Enabled: Whether or not the policy is enabled. On write, the default + // interpretation if unset is that the policy is enabled. On read, + // clients should not make any assumption about the state if it has not + // been populated. The field should always be populated on List and Get + // operations, unless a field projection has been specified that strips + // it out. + Enabled bool `json:"enabled,omitempty"` + + // MutationRecord: A read-only record of the most recent change to the + // alerting policy. If provided in a call to create or update, this + // field will be ignored. + MutationRecord *MutationRecord `json:"mutationRecord,omitempty"` + + // Name: Required if the policy exists. The resource name for this + // policy. The syntax + // is: + // projects/[PROJECT_ID]/alertPolicies/[ALERT_POLICY_ID] + // [ALERT_POLIC + // Y_ID] is assigned by Stackdriver Monitoring when the policy is + // created. When calling the alertPolicies.create method, do not include + // the name field in the alerting policy passed as part of the request. + Name string `json:"name,omitempty"` + + // NotificationChannels: Identifies the notification channels to which + // notifications should be sent when incidents are opened or closed or + // when new violations occur on an already opened incident. Each element + // of this array corresponds to the name field in each of the + // NotificationChannel objects that are returned from the + // ListNotificationChannels method. The syntax of the entries in this + // field is: + // projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID] + // + NotificationChannels []string `json:"notificationChannels,omitempty"` + + // UserLabels: User-supplied key/value data to be used for organizing + // and identifying the AlertPolicy objects.The field can contain up to + // 64 entries. Each key and value is limited to 63 Unicode characters or + // 128 bytes, whichever is smaller. Labels and values can contain only + // lowercase letters, numerals, underscores, and dashes. Keys must begin + // with a letter. + UserLabels map[string]string `json:"userLabels,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Combiner") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Combiner") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AlertPolicy) MarshalJSON() ([]byte, error) { + type NoMethod AlertPolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // BasicAuthentication: A type of authentication to perform against the // specified resource or URL that uses username and password. Currently, // only Basic authentication is supported in Uptime Monitoring. @@ -446,6 +837,67 @@ func (s *CollectdValueError) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// Condition: A condition is a true/false test that determines when an +// alerting policy should open an incident. If a condition evaluates to +// true, it signifies that something is wrong. +type Condition struct { + // ConditionAbsent: A condition that checks that a time series continues + // to receive new data points. + ConditionAbsent *MetricAbsence `json:"conditionAbsent,omitempty"` + + // ConditionThreshold: A condition that compares a time series against a + // threshold. + ConditionThreshold *MetricThreshold `json:"conditionThreshold,omitempty"` + + // DisplayName: A short name or phrase used to identify the condition in + // dashboards, notifications, and incidents. To avoid confusion, don't + // use the same display name for multiple conditions in the same policy. + DisplayName string `json:"displayName,omitempty"` + + // Name: Required if the condition exists. The unique resource name for + // this condition. Its syntax + // is: + // projects/[PROJECT_ID]/alertPolicies/[POLICY_ID]/conditions/[CONDIT + // ION_ID] + // [CONDITION_ID] is assigned by Stackdriver Monitoring when the + // condition is created as part of a new or updated alerting policy.When + // calling the alertPolicies.create method, do not include the name + // field in the conditions of the requested alerting policy. Stackdriver + // Monitoring creates the condition identifiers and includes them in the + // new policy.When calling the alertPolicies.update method to update a + // policy, including a condition name causes the existing condition to + // be updated. Conditions without names are added to the updated policy. + // Existing conditions are deleted if they are not updated.Best practice + // is to preserve [CONDITION_ID] if you make only small changes, such as + // those to condition thresholds, durations, or trigger values. + // Otherwise, treat the change as a new condition and let the existing + // condition be deleted. + Name string `json:"name,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ConditionAbsent") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ConditionAbsent") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field 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) +} + // 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. @@ -616,6 +1068,11 @@ type Distribution struct { // histogram is provided. Count int64 `json:"count,omitempty,string"` + // Exemplars: Must be in increasing order of |value| field. The current + // requirement enforced by the backend is that at most one Exemplar will + // fall into any bucket. + Exemplars []*Exemplar `json:"exemplars,omitempty"` + // Mean: The arithmetic mean of the values in the population. If count // is zero then this field must be zero. Mean float64 `json:"mean,omitempty"` @@ -673,6 +1130,43 @@ func (s *Distribution) UnmarshalJSON(data []byte) error { return nil } +// Documentation: A content string and a MIME type that describes the +// content string's format. +type Documentation struct { + // Content: The text of the documentation, interpreted according to + // mime_type. The content may not exceed 8,192 Unicode characters and + // may not exceed more than 10,240 bytes when encoded in UTF-8 format, + // whichever is smaller. + Content string `json:"content,omitempty"` + + // MimeType: The format of the content field. Presently, only the value + // "text/markdown" is supported. See Markdown + // (https://en.wikipedia.org/wiki/Markdown) for more information. + MimeType string `json:"mimeType,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Content") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Content") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Documentation) MarshalJSON() ([]byte, error) { + type NoMethod Documentation + 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 @@ -688,6 +1182,67 @@ type Empty struct { googleapi.ServerResponse `json:"-"` } +// Exemplar: Exemplars are example points that may be used to annotate +// aggregated distribution values. They are metadata that gives +// information about a particular value added to a Distribution bucket, +// such as a trace ID that was active when a value was added. They may +// contain further information, such as a example values and timestamps, +// origin, etc. +type Exemplar struct { + // Attachments: Contextual information about the example value. Examples + // are:Trace ID: + // type.googleapis.com/google.devtools.cloudtrace.v1.TraceLiteral + // string: type.googleapis.com/google.protobuf.StringValueLabels dropped + // during aggregation: + // type.googleapis.com/google.monitoring.v3.DroppedLabelsThere may be + // only a single attachment of any given message type in a single + // exemplar, and this is enforced by the system. + Attachments []googleapi.RawMessage `json:"attachments,omitempty"` + + // Timestamp: The observation (sampling) time of the above value. + Timestamp string `json:"timestamp,omitempty"` + + // Value: Value of the exemplar point. This value determines to which + // bucket the exemplar belongs. + Value float64 `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Attachments") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Attachments") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Exemplar) MarshalJSON() ([]byte, error) { + type NoMethod Exemplar + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +func (s *Exemplar) UnmarshalJSON(data []byte) error { + type NoMethod Exemplar + 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 +} + // Explicit: Specifies a set of buckets with arbitrary widths.There are // size(bounds) + 1 (= N) buckets. Bucket i has the following // boundaries:Upper bound (0 <= i < N-1): boundsi Lower bound (1 <= i < @@ -866,6 +1421,86 @@ func (s *Field) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// GetNotificationChannelVerificationCodeRequest: The +// GetNotificationChannelVerificationCode request. +type GetNotificationChannelVerificationCodeRequest struct { + // ExpireTime: The desired expiration time. If specified, the API will + // guarantee that the returned code will not be valid after the + // specified timestamp; however, the API cannot guarantee that the + // returned code will be valid for at least as long as the requested + // time (the API puts an upper bound on the amount of time for which a + // code may be valid). If omitted, a default expiration will be used, + // which may be less than the max permissible expiration (so specifying + // an expiration may extend the code's lifetime over omitting an + // expiration, even though the API does impose an upper limit on the + // maximum expiration that is permitted). + ExpireTime string `json:"expireTime,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ExpireTime") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ExpireTime") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GetNotificationChannelVerificationCodeRequest) MarshalJSON() ([]byte, error) { + type NoMethod GetNotificationChannelVerificationCodeRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// GetNotificationChannelVerificationCodeResponse: The +// GetNotificationChannelVerificationCode request. +type GetNotificationChannelVerificationCodeResponse struct { + // Code: The verification code, which may be used to verify other + // channels that have an equivalent identity (i.e. other channels of the + // same type with the same fingerprint such as other email channels with + // the same email address or other sms channels with the same number). + Code string `json:"code,omitempty"` + + // ExpireTime: The expiration time associated with the code that was + // returned. If an expiration was provided in the request, this is the + // minimum of the requested expiration in the request and the max + // permitted expiration. + ExpireTime string `json:"expireTime,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // 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 *GetNotificationChannelVerificationCodeResponse) MarshalJSON() ([]byte, error) { + type NoMethod GetNotificationChannelVerificationCodeResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Group: The description of a dynamic collection of monitored // resources. Each group has a filter that is matched against monitored // resources and their associated metadata. If a group's filter matches @@ -1142,6 +1777,44 @@ func (s *Linear) UnmarshalJSON(data []byte) error { return nil } +// ListAlertPoliciesResponse: The protocol for the ListAlertPolicies +// response. +type ListAlertPoliciesResponse struct { + // AlertPolicies: The returned alert policies. + AlertPolicies []*AlertPolicy `json:"alertPolicies,omitempty"` + + // NextPageToken: If there might be more results than were returned, + // then this field is set to a non-empty value. To see the additional + // results, use that value as pageToken in the next call to this method. + 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. "AlertPolicies") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AlertPolicies") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ListAlertPoliciesResponse) MarshalJSON() ([]byte, error) { + type NoMethod ListAlertPoliciesResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // ListGroupMembersResponse: The ListGroupMembers response. type ListGroupMembersResponse struct { // Members: A set of monitored resources in the group. @@ -1297,16 +1970,59 @@ func (s *ListMonitoredResourceDescriptorsResponse) MarshalJSON() ([]byte, error) return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// ListTimeSeriesResponse: The ListTimeSeries response. -type ListTimeSeriesResponse struct { - // NextPageToken: If there are more results than have been returned, - // then this field is set to a non-empty value. To see the additional - // results, use that value as pageToken in the next call to this method. +// ListNotificationChannelDescriptorsResponse: The +// ListNotificationChannelDescriptors response. +type ListNotificationChannelDescriptorsResponse struct { + // ChannelDescriptors: The monitored resource descriptors supported for + // the specified project, optionally filtered. + ChannelDescriptors []*NotificationChannelDescriptor `json:"channelDescriptors,omitempty"` + + // NextPageToken: If not empty, indicates that there may be more results + // that match the request. Use the value in the page_token field in a + // subsequent request to fetch the next set of results. If empty, all + // results have been returned. NextPageToken string `json:"nextPageToken,omitempty"` - // TimeSeries: One or more time series that match the filter included in - // the request. - TimeSeries []*TimeSeries `json:"timeSeries,omitempty"` + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "ChannelDescriptors") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ChannelDescriptors") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *ListNotificationChannelDescriptorsResponse) MarshalJSON() ([]byte, error) { + type NoMethod ListNotificationChannelDescriptorsResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ListNotificationChannelsResponse: The ListNotificationChannels +// response. +type ListNotificationChannelsResponse struct { + // NextPageToken: If not empty, indicates that there may be more results + // that match the request. Use the value in the page_token field in a + // subsequent request to fetch the next set of results. If empty, all + // results have been returned. + NextPageToken string `json:"nextPageToken,omitempty"` + + // NotificationChannels: The notification channels defined for the + // specified project. + NotificationChannels []*NotificationChannel `json:"notificationChannels,omitempty"` // ServerResponse contains the HTTP response code and headers from the // server. @@ -1329,6 +2045,49 @@ type ListTimeSeriesResponse struct { NullFields []string `json:"-"` } +func (s *ListNotificationChannelsResponse) MarshalJSON() ([]byte, error) { + type NoMethod ListNotificationChannelsResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ListTimeSeriesResponse: The ListTimeSeries response. +type ListTimeSeriesResponse struct { + // ExecutionErrors: Query execution errors that may have caused the time + // series data returned to be incomplete. + ExecutionErrors []*Status `json:"executionErrors,omitempty"` + + // NextPageToken: If there are more results than have been returned, + // then this field is set to a non-empty value. To see the additional + // results, use that value as pageToken in the next call to this method. + NextPageToken string `json:"nextPageToken,omitempty"` + + // TimeSeries: One or more time series that match the filter included in + // the request. + TimeSeries []*TimeSeries `json:"timeSeries,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "ExecutionErrors") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ExecutionErrors") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + func (s *ListTimeSeriesResponse) MarshalJSON() ([]byte, error) { type NoMethod ListTimeSeriesResponse raw := NoMethod(*s) @@ -1455,6 +2214,67 @@ func (s *Metric) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// MetricAbsence: A condition type that checks that monitored resources +// are reporting data. The configuration defines a metric and a set of +// monitored resources. The predicate is considered in violation when a +// time series for the specified metric of a monitored resource does not +// include any data in the specified duration. +type MetricAbsence struct { + // Aggregations: Specifies the alignment of data points in individual + // time series as well as how to combine the retrieved time series + // together (such as when aggregating multiple streams on each resource + // to a single stream for each resource or when aggregating streams + // across all members of a group of resrouces). Multiple aggregations + // are applied in the order specified.This field is similar to the one + // in the MetricService.ListTimeSeries request. It is advisable to use + // the ListTimeSeries method when debugging this field. + Aggregations []*Aggregation `json:"aggregations,omitempty"` + + // Duration: The amount of time that a time series must fail to report + // new data to be considered failing. Currently, only values that are a + // multiple of a minute--e.g. 60, 120, or 300 seconds--are supported. If + // an invalid value is given, an error will be returned. The + // Duration.nanos field is ignored. + Duration string `json:"duration,omitempty"` + + // Filter: A filter that identifies which time series should be compared + // with the threshold.The filter is similar to the one that is specified + // in the MetricService.ListTimeSeries request (that call is useful to + // verify the time series that will be retrieved / processed) and must + // specify the metric type and optionally may contain restrictions on + // resource type, resource labels, and metric labels. This field may not + // exceed 2048 Unicode characters in length. + Filter string `json:"filter,omitempty"` + + // Trigger: The number/percent of time series for which the comparison + // must hold in order for the condition to trigger. If unspecified, then + // the condition will trigger if the comparison is true for any of the + // time series that have been identified by filter and aggregations. + Trigger *Trigger `json:"trigger,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Aggregations") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Aggregations") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *MetricAbsence) MarshalJSON() ([]byte, error) { + type NoMethod MetricAbsence + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // MetricDescriptor: Defines a metric type and its schema. Once a metric // descriptor is created, deleting or altering it stops data collection // and makes the metric type's existing data unusable. @@ -1557,6 +2377,135 @@ func (s *MetricDescriptor) MarshalJSON() ([]byte, error) { 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 { + // Aggregations: Specifies the alignment of data points in individual + // time series as well as how to combine the retrieved time series + // together (such as when aggregating multiple streams on each resource + // to a single stream for each resource or when aggregating streams + // across all members of a group of resrouces). Multiple aggregations + // are applied in the order specified.This field is similar to the one + // in the MetricService.ListTimeSeries request. It is advisable to use + // the ListTimeSeries method when debugging this field. + Aggregations []*Aggregation `json:"aggregations,omitempty"` + + // Comparison: The comparison to apply between the time series + // (indicated by filter and aggregation) and the threshold (indicated by + // threshold_value). The comparison is applied on each time series, with + // the time series on the left-hand side and the threshold on the + // right-hand side.Only COMPARISON_LT and COMPARISON_GT are supported + // currently. + // + // Possible values: + // "COMPARISON_UNSPECIFIED" - No ordering relationship is specified. + // "COMPARISON_GT" - The left argument is greater than the right + // argument. + // "COMPARISON_GE" - The left argument is greater than or equal to the + // right argument. + // "COMPARISON_LT" - The left argument is less than the right + // argument. + // "COMPARISON_LE" - The left argument is less than or equal to the + // right argument. + // "COMPARISON_EQ" - The left argument is equal to the right argument. + // "COMPARISON_NE" - The left argument is not equal to the right + // argument. + Comparison string `json:"comparison,omitempty"` + + // DenominatorAggregations: Specifies the alignment of data points in + // individual time series selected by denominatorFilter as well as how + // to combine the retrieved time series together (such as when + // aggregating multiple streams on each resource to a single stream for + // each resource or when aggregating streams across all members of a + // group of resources).When computing ratios, the aggregations and + // denominator_aggregations fields must use the same alignment period + // and produce time series that have the same periodicity and + // labels.This field is similar to the one in the + // MetricService.ListTimeSeries request. It is advisable to use the + // ListTimeSeries method when debugging this field. + DenominatorAggregations []*Aggregation `json:"denominatorAggregations,omitempty"` + + // DenominatorFilter: A filter that identifies a time series that should + // be used as the denominator of a ratio that will be compared with the + // threshold. If a denominator_filter is specified, the time series + // specified by the filter field will be used as the numerator.The + // filter is similar to the one that is specified in the + // MetricService.ListTimeSeries request (that call is useful to verify + // the time series that will be retrieved / processed) and must specify + // the metric type and optionally may contain restrictions on resource + // type, resource labels, and metric labels. This field may not exceed + // 2048 Unicode characters in length. + DenominatorFilter string `json:"denominatorFilter,omitempty"` + + // Duration: The amount of time that a time series must violate the + // threshold to be considered failing. Currently, only values that are a + // multiple of a minute--e.g., 0, 60, 120, or 300 seconds--are + // supported. If an invalid value is given, an error will be returned. + // When choosing a duration, it is useful to keep in mind the frequency + // of the underlying time series data (which may also be affected by any + // alignments specified in the aggregations field); a good duration is + // long enough so that a single outlier does not generate spurious + // alerts, but short enough that unhealthy states are detected and + // alerted on quickly. + Duration string `json:"duration,omitempty"` + + // Filter: A filter that identifies which time series should be compared + // with the threshold.The filter is similar to the one that is specified + // in the MetricService.ListTimeSeries request (that call is useful to + // verify the time series that will be retrieved / processed) and must + // specify the metric type and optionally may contain restrictions on + // resource type, resource labels, and metric labels. This field may not + // exceed 2048 Unicode characters in length. + Filter string `json:"filter,omitempty"` + + // ThresholdValue: A value against which to compare the time series. + ThresholdValue float64 `json:"thresholdValue,omitempty"` + + // Trigger: The number/percent of time series for which the comparison + // must hold in order for the condition to trigger. If unspecified, then + // the condition will trigger if the comparison is true for any of the + // time series that have been identified by filter and aggregations, or + // by the ratio, if denominator_filter and denominator_aggregations are + // specified. + Trigger *Trigger `json:"trigger,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Aggregations") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Aggregations") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *MetricThreshold) MarshalJSON() ([]byte, error) { + type NoMethod MetricThreshold + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +func (s *MetricThreshold) UnmarshalJSON(data []byte) error { + type NoMethod MetricThreshold + var s1 struct { + ThresholdValue gensupport.JSONFloat64 `json:"thresholdValue"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.ThresholdValue = float64(s1.ThresholdValue) + return nil +} + // 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 @@ -1717,6 +2666,222 @@ func (s *MonitoredResourceMetadata) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// MutationRecord: Describes a change made to a configuration. +type MutationRecord struct { + // MutateTime: When the change occurred. + MutateTime string `json:"mutateTime,omitempty"` + + // MutatedBy: The email address of the user making the change. + MutatedBy string `json:"mutatedBy,omitempty"` + + // ForceSendFields is a list of field names (e.g. "MutateTime") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "MutateTime") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *MutationRecord) MarshalJSON() ([]byte, error) { + type NoMethod MutationRecord + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NotificationChannel: A NotificationChannel is a medium through which +// an alert is delivered when a policy violation is detected. Examples +// of channels include email, SMS, and third-party messaging +// applications. Fields containing sensitive information like +// authentication tokens or contact info are only partially populated on +// retrieval. +type NotificationChannel struct { + // Description: An optional human-readable description of this + // notification channel. This description may provide additional + // details, beyond the display name, for the channel. This may not + // exceeed 1024 Unicode characters. + Description string `json:"description,omitempty"` + + // DisplayName: An optional human-readable name for this notification + // channel. It is recommended that you specify a non-empty and unique + // name in order to make it easier to identify the channels in your + // project, though this is not enforced. The display name is limited to + // 512 Unicode characters. + DisplayName string `json:"displayName,omitempty"` + + // Enabled: Whether notifications are forwarded to the described + // channel. This makes it possible to disable delivery of notifications + // to a particular channel without removing the channel from all + // alerting policies that reference the channel. This is a more + // convenient approach when the change is temporary and you want to + // receive notifications from the same set of alerting policies on the + // channel at some point in the future. + Enabled bool `json:"enabled,omitempty"` + + // Labels: Configuration fields that define the channel and its + // behavior. The permissible and required labels are specified in the + // NotificationChannelDescriptor.labels of the + // NotificationChannelDescriptor corresponding to the type field. + Labels map[string]string `json:"labels,omitempty"` + + // Name: The full REST resource name for this channel. The syntax + // is: + // projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID] + // The [CHANNEL_ID] is automatically assigned by the server on creation. + Name string `json:"name,omitempty"` + + // Type: The type of the notification channel. This field matches the + // value of the NotificationChannelDescriptor.type field. + Type string `json:"type,omitempty"` + + // UserLabels: User-supplied key/value data that does not need to + // conform to the corresponding NotificationChannelDescriptor's schema, + // unlike the labels field. This field is intended to be used for + // organizing and identifying the NotificationChannel objects.The field + // can contain up to 64 entries. Each key and value is limited to 63 + // Unicode characters or 128 bytes, whichever is smaller. Labels and + // values can contain only lowercase letters, numerals, underscores, and + // dashes. Keys must begin with a letter. + UserLabels map[string]string `json:"userLabels,omitempty"` + + // VerificationStatus: Indicates whether this channel has been verified + // or not. On a ListNotificationChannels or GetNotificationChannel + // operation, this field is expected to be populated.If the value is + // UNVERIFIED, then it indicates that the channel is non-functioning (it + // both requires verification and lacks verification); otherwise, it is + // assumed that the channel works.If the channel is neither VERIFIED nor + // UNVERIFIED, it implies that the channel is of a type that does not + // require verification or that this specific channel has been exempted + // from verification because it was created prior to verification being + // required for channels of this type.This field cannot be modified + // using a standard UpdateNotificationChannel operation. To change the + // value of this field, you must call VerifyNotificationChannel. + // + // Possible values: + // "VERIFICATION_STATUS_UNSPECIFIED" - Sentinel value used to indicate + // that the state is unknown, omitted, or is not applicable (as in the + // case of channels that neither support nor require verification in + // order to function). + // "UNVERIFIED" - The channel has yet to be verified and requires + // verification to function. Note that this state also applies to the + // case where the verification process has been initiated by sending a + // verification code but where the verification code has not been + // submitted to complete the process. + // "VERIFIED" - It has been proven that notifications can be received + // on this notification channel and that someone on the project has + // access to messages that are delivered to that channel. + VerificationStatus string `json:"verificationStatus,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // 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 *NotificationChannel) MarshalJSON() ([]byte, error) { + type NoMethod NotificationChannel + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NotificationChannelDescriptor: A description of a notification +// channel. The descriptor includes the properties of the channel and +// the set of labels or fields that must be specified to configure +// channels of a given type. +type NotificationChannelDescriptor struct { + // Description: A human-readable description of the notification channel + // type. The description may include a description of the properties of + // the channel and pointers to external documentation. + Description string `json:"description,omitempty"` + + // DisplayName: A human-readable name for the notification channel type. + // This form of the name is suitable for a user interface. + DisplayName string `json:"displayName,omitempty"` + + // Labels: The set of labels that must be defined to identify a + // particular channel of the corresponding type. Each label includes a + // description for how that field should be populated. + Labels []*LabelDescriptor `json:"labels,omitempty"` + + // Name: The full REST resource name for this descriptor. The syntax + // is: + // projects/[PROJECT_ID]/notificationChannelDescriptors/[TYPE] + // In the above, [TYPE] is the value of the type field. + Name string `json:"name,omitempty"` + + // SupportedTiers: The tiers that support this notification channel; the + // project service tier must be one of the supported_tiers. + // + // Possible values: + // "SERVICE_TIER_UNSPECIFIED" - An invalid sentinel value, used to + // indicate that a tier has not been provided explicitly. + // "SERVICE_TIER_BASIC" - 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). + // "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). + SupportedTiers []string `json:"supportedTiers,omitempty"` + + // Type: The type of notification channel, such as "email", "sms", etc. + // Notification channel types are globally unique. + 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. "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 *NotificationChannelDescriptor) MarshalJSON() ([]byte, error) { + type NoMethod NotificationChannelDescriptor + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Option: A protocol buffer option, which can be attached to a message, // field, enumeration, etc. type Option struct { @@ -1882,6 +3047,11 @@ func (s *ResourceGroup) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// SendNotificationChannelVerificationCodeRequest: The +// SendNotificationChannelVerificationCode request. +type SendNotificationChannelVerificationCodeRequest struct { +} + // SourceContext: SourceContext represents information about the source // of a protobuf element, like the file in which it is defined. type SourceContext struct { @@ -2144,6 +3314,55 @@ func (s *TimeSeries) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// Trigger: Specifies how many time series must fail a predicate to +// trigger a condition. If not specified, then a {count: 1} trigger is +// used. +type Trigger struct { + // Count: The absolute number of time series that must fail the + // predicate for the condition to be triggered. + Count int64 `json:"count,omitempty"` + + // Percent: The percentage of time series that must fail the predicate + // for the condition to be triggered. + Percent float64 `json:"percent,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 *Trigger) MarshalJSON() ([]byte, error) { + type NoMethod Trigger + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +func (s *Trigger) UnmarshalJSON(data []byte) error { + type NoMethod Trigger + var s1 struct { + Percent gensupport.JSONFloat64 `json:"percent"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.Percent = float64(s1.Percent) + return nil +} + // Type: A protocol buffer message type. type Type struct { // Fields: The list of fields. @@ -2297,7 +3516,8 @@ type UptimeCheckConfig struct { // Period: How often, in seconds, the uptime check is performed. // Currently, the only supported values are 60s (1 minute), 300s (5 - // minutes), 600s (10 minutes), and 900s (15 minutes). Required. + // minutes), 600s (10 minutes), and 900s (15 minutes). Optional, + // defaults to 300s. Period string `json:"period,omitempty"` // ResourceGroup: The group resource associated with the configuration. @@ -2412,6 +3632,830 @@ func (s *UptimeCheckIp) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// VerifyNotificationChannelRequest: The VerifyNotificationChannel +// request. +type VerifyNotificationChannelRequest struct { + // Code: The verification code that was delivered to the channel as a + // result of invoking the SendNotificationChannelVerificationCode API + // method or that was retrieved from a verified channel via + // GetNotificationChannelVerificationCode. For example, one might have + // "G-123456" or "TKNZGhhd2EyN3I1MnRnMjRv" (in general, one is only + // guaranteed that the code is valid UTF-8; one should not make any + // assumptions regarding the structure or format of the code). + Code string `json:"code,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 *VerifyNotificationChannelRequest) MarshalJSON() ([]byte, error) { + type NoMethod VerifyNotificationChannelRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// method id "monitoring.projects.alertPolicies.create": + +type ProjectsAlertPoliciesCreateCall struct { + s *Service + name string + alertpolicy *AlertPolicy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Create: Creates a new alerting policy. +func (r *ProjectsAlertPoliciesService) Create(name string, alertpolicy *AlertPolicy) *ProjectsAlertPoliciesCreateCall { + c := &ProjectsAlertPoliciesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.alertpolicy = alertpolicy + 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 *ProjectsAlertPoliciesCreateCall) Fields(s ...googleapi.Field) *ProjectsAlertPoliciesCreateCall { + 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 *ProjectsAlertPoliciesCreateCall) Context(ctx context.Context) *ProjectsAlertPoliciesCreateCall { + 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 *ProjectsAlertPoliciesCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsAlertPoliciesCreateCall) 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.alertpolicy) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/alertPolicies") + 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 "monitoring.projects.alertPolicies.create" call. +// Exactly one of *AlertPolicy or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *AlertPolicy.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 *ProjectsAlertPoliciesCreateCall) Do(opts ...googleapi.CallOption) (*AlertPolicy, 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 := &AlertPolicy{ + 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 alerting policy.", + // "flatPath": "v3/projects/{projectsId}/alertPolicies", + // "httpMethod": "POST", + // "id": "monitoring.projects.alertPolicies.create", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The project in which to create the alerting policy. The format is projects/[PROJECT_ID].Note that this field names the parent container in which the alerting policy will be written, not the name of the created policy. The alerting policy that is returned will have a name that contains a normalized representation of this name as a prefix but adds a suffix of the form /alertPolicies/[POLICY_ID], identifying the policy in the container.", + // "location": "path", + // "pattern": "^projects/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v3/{+name}/alertPolicies", + // "request": { + // "$ref": "AlertPolicy" + // }, + // "response": { + // "$ref": "AlertPolicy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring" + // ] + // } + +} + +// method id "monitoring.projects.alertPolicies.delete": + +type ProjectsAlertPoliciesDeleteCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes an alerting policy. +func (r *ProjectsAlertPoliciesService) Delete(name string) *ProjectsAlertPoliciesDeleteCall { + c := &ProjectsAlertPoliciesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.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 *ProjectsAlertPoliciesDeleteCall) Fields(s ...googleapi.Field) *ProjectsAlertPoliciesDeleteCall { + 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 *ProjectsAlertPoliciesDeleteCall) Context(ctx context.Context) *ProjectsAlertPoliciesDeleteCall { + 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 *ProjectsAlertPoliciesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsAlertPoliciesDeleteCall) 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, "v3/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", 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 "monitoring.projects.alertPolicies.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 *ProjectsAlertPoliciesDeleteCall) 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 an alerting policy.", + // "flatPath": "v3/projects/{projectsId}/alertPolicies/{alertPoliciesId}", + // "httpMethod": "DELETE", + // "id": "monitoring.projects.alertPolicies.delete", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The alerting policy to delete. The format is:\nprojects/[PROJECT_ID]/alertPolicies/[ALERT_POLICY_ID]\nFor more information, see AlertPolicy.", + // "location": "path", + // "pattern": "^projects/[^/]+/alertPolicies/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v3/{+name}", + // "response": { + // "$ref": "Empty" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring" + // ] + // } + +} + +// method id "monitoring.projects.alertPolicies.get": + +type ProjectsAlertPoliciesGetCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Gets a single alerting policy. +func (r *ProjectsAlertPoliciesService) Get(name string) *ProjectsAlertPoliciesGetCall { + c := &ProjectsAlertPoliciesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.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 *ProjectsAlertPoliciesGetCall) Fields(s ...googleapi.Field) *ProjectsAlertPoliciesGetCall { + 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 *ProjectsAlertPoliciesGetCall) IfNoneMatch(entityTag string) *ProjectsAlertPoliciesGetCall { + 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 *ProjectsAlertPoliciesGetCall) Context(ctx context.Context) *ProjectsAlertPoliciesGetCall { + 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 *ProjectsAlertPoliciesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsAlertPoliciesGetCall) 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, "v3/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", 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 "monitoring.projects.alertPolicies.get" call. +// Exactly one of *AlertPolicy or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *AlertPolicy.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 *ProjectsAlertPoliciesGetCall) Do(opts ...googleapi.CallOption) (*AlertPolicy, 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 := &AlertPolicy{ + 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 single alerting policy.", + // "flatPath": "v3/projects/{projectsId}/alertPolicies/{alertPoliciesId}", + // "httpMethod": "GET", + // "id": "monitoring.projects.alertPolicies.get", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The alerting policy to retrieve. The format is\nprojects/[PROJECT_ID]/alertPolicies/[ALERT_POLICY_ID]\n", + // "location": "path", + // "pattern": "^projects/[^/]+/alertPolicies/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v3/{+name}", + // "response": { + // "$ref": "AlertPolicy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring", + // "https://www.googleapis.com/auth/monitoring.read" + // ] + // } + +} + +// method id "monitoring.projects.alertPolicies.list": + +type ProjectsAlertPoliciesListCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists the existing alerting policies for the project. +func (r *ProjectsAlertPoliciesService) List(name string) *ProjectsAlertPoliciesListCall { + c := &ProjectsAlertPoliciesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// Filter sets the optional parameter "filter": If provided, this field +// specifies the criteria that must be met by alert policies to be +// included in the response.For more details, see sorting and filtering. +func (c *ProjectsAlertPoliciesListCall) Filter(filter string) *ProjectsAlertPoliciesListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// OrderBy sets the optional parameter "orderBy": A comma-separated list +// of fields by which to sort the result. Supports the same set of field +// references as the filter field. Entries can be prefixed with a minus +// sign to sort by the field in descending order.For more details, see +// sorting and filtering. +func (c *ProjectsAlertPoliciesListCall) OrderBy(orderBy string) *ProjectsAlertPoliciesListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageSize sets the optional parameter "pageSize": The maximum number +// of results to return in a single response. +func (c *ProjectsAlertPoliciesListCall) PageSize(pageSize int64) *ProjectsAlertPoliciesListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": If this field is +// not empty then it must contain the nextPageToken value returned by a +// previous call to this method. Using this field causes the method to +// return more results from the previous method call. +func (c *ProjectsAlertPoliciesListCall) PageToken(pageToken string) *ProjectsAlertPoliciesListCall { + 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 *ProjectsAlertPoliciesListCall) Fields(s ...googleapi.Field) *ProjectsAlertPoliciesListCall { + 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 *ProjectsAlertPoliciesListCall) IfNoneMatch(entityTag string) *ProjectsAlertPoliciesListCall { + 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 *ProjectsAlertPoliciesListCall) Context(ctx context.Context) *ProjectsAlertPoliciesListCall { + 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 *ProjectsAlertPoliciesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsAlertPoliciesListCall) 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, "v3/{+name}/alertPolicies") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", 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 "monitoring.projects.alertPolicies.list" call. +// Exactly one of *ListAlertPoliciesResponse or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *ListAlertPoliciesResponse.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 *ProjectsAlertPoliciesListCall) Do(opts ...googleapi.CallOption) (*ListAlertPoliciesResponse, 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 := &ListAlertPoliciesResponse{ + 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 existing alerting policies for the project.", + // "flatPath": "v3/projects/{projectsId}/alertPolicies", + // "httpMethod": "GET", + // "id": "monitoring.projects.alertPolicies.list", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "filter": { + // "description": "If provided, this field specifies the criteria that must be met by alert policies to be included in the response.For more details, see sorting and filtering.", + // "location": "query", + // "type": "string" + // }, + // "name": { + // "description": "The project whose alert policies are to be listed. The format is\nprojects/[PROJECT_ID]\nNote that this field names the parent container in which the alerting policies to be listed are stored. To retrieve a single alerting policy by name, use the GetAlertPolicy operation, instead.", + // "location": "path", + // "pattern": "^projects/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "orderBy": { + // "description": "A comma-separated list of fields by which to sort the result. Supports the same set of field references as the filter field. Entries can be prefixed with a minus sign to sort by the field in descending order.For more details, see sorting and filtering.", + // "location": "query", + // "type": "string" + // }, + // "pageSize": { + // "description": "The maximum number of results to return in a single response.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "pageToken": { + // "description": "If this field is not empty then it must contain the nextPageToken value returned by a previous call to this method. Using this field causes the method to return more results from the previous method call.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v3/{+name}/alertPolicies", + // "response": { + // "$ref": "ListAlertPoliciesResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring", + // "https://www.googleapis.com/auth/monitoring.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 *ProjectsAlertPoliciesListCall) Pages(ctx context.Context, f func(*ListAlertPoliciesResponse) 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 "monitoring.projects.alertPolicies.patch": + +type ProjectsAlertPoliciesPatchCall struct { + s *Service + name string + alertpolicy *AlertPolicy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Updates an alerting policy. You can either replace the entire +// policy with a new one or replace only certain fields in the current +// alerting policy by specifying the fields to be updated via +// updateMask. Returns the updated alerting policy. +func (r *ProjectsAlertPoliciesService) Patch(name string, alertpolicy *AlertPolicy) *ProjectsAlertPoliciesPatchCall { + c := &ProjectsAlertPoliciesPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.alertpolicy = alertpolicy + return c +} + +// UpdateMask sets the optional parameter "updateMask": A list of +// alerting policy field names. If this field is not empty, each listed +// field in the existing alerting policy is set to the value of the +// corresponding field in the supplied policy (alert_policy), or to the +// field's default value if the field is not in the supplied alerting +// policy. Fields not listed retain their previous value.Examples of +// valid field masks include display_name, documentation, +// documentation.content, documentation.mime_type, user_labels, +// user_label.nameofkey, enabled, conditions, combiner, etc.If this +// field is empty, then the supplied alerting policy replaces the +// existing policy. It is the same as deleting the existing policy and +// adding the supplied policy, except for the following: +// The new policy will have the same [ALERT_POLICY_ID] as the former +// policy. This gives you continuity with the former policy in your +// notifications and incidents. +// Conditions in the new policy will keep their former [CONDITION_ID] if +// the supplied condition includes the name field with that +// [CONDITION_ID]. If the supplied condition omits the name field, then +// a new [CONDITION_ID] is created. +func (c *ProjectsAlertPoliciesPatchCall) UpdateMask(updateMask string) *ProjectsAlertPoliciesPatchCall { + c.urlParams_.Set("updateMask", updateMask) + 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 *ProjectsAlertPoliciesPatchCall) Fields(s ...googleapi.Field) *ProjectsAlertPoliciesPatchCall { + 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 *ProjectsAlertPoliciesPatchCall) Context(ctx context.Context) *ProjectsAlertPoliciesPatchCall { + 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 *ProjectsAlertPoliciesPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsAlertPoliciesPatchCall) 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.alertpolicy) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PATCH", 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 "monitoring.projects.alertPolicies.patch" call. +// Exactly one of *AlertPolicy or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *AlertPolicy.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 *ProjectsAlertPoliciesPatchCall) Do(opts ...googleapi.CallOption) (*AlertPolicy, 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 := &AlertPolicy{ + 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 alerting policy. You can either replace the entire policy with a new one or replace only certain fields in the current alerting policy by specifying the fields to be updated via updateMask. Returns the updated alerting policy.", + // "flatPath": "v3/projects/{projectsId}/alertPolicies/{alertPoliciesId}", + // "httpMethod": "PATCH", + // "id": "monitoring.projects.alertPolicies.patch", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "Required if the policy exists. The resource name for this policy. The syntax is:\nprojects/[PROJECT_ID]/alertPolicies/[ALERT_POLICY_ID]\n[ALERT_POLICY_ID] is assigned by Stackdriver Monitoring when the policy is created. When calling the alertPolicies.create method, do not include the name field in the alerting policy passed as part of the request.", + // "location": "path", + // "pattern": "^projects/[^/]+/alertPolicies/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "updateMask": { + // "description": "Optional. A list of alerting policy field names. If this field is not empty, each listed field in the existing alerting policy is set to the value of the corresponding field in the supplied policy (alert_policy), or to the field's default value if the field is not in the supplied alerting policy. Fields not listed retain their previous value.Examples of valid field masks include display_name, documentation, documentation.content, documentation.mime_type, user_labels, user_label.nameofkey, enabled, conditions, combiner, etc.If this field is empty, then the supplied alerting policy replaces the existing policy. It is the same as deleting the existing policy and adding the supplied policy, except for the following:\nThe new policy will have the same [ALERT_POLICY_ID] as the former policy. This gives you continuity with the former policy in your notifications and incidents.\nConditions in the new policy will keep their former [CONDITION_ID] if the supplied condition includes the name field with that [CONDITION_ID]. If the supplied condition omits the name field, then a new [CONDITION_ID] is created.", + // "format": "google-fieldmask", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v3/{+name}", + // "request": { + // "$ref": "AlertPolicy" + // }, + // "response": { + // "$ref": "AlertPolicy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring" + // ] + // } + +} + // method id "monitoring.projects.collectdTimeSeries.create": type ProjectsCollectdTimeSeriesCreateCall struct { @@ -4550,6 +6594,1570 @@ func (c *ProjectsMonitoredResourceDescriptorsListCall) Pages(ctx context.Context } } +// method id "monitoring.projects.notificationChannelDescriptors.get": + +type ProjectsNotificationChannelDescriptorsGetCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Gets a single channel descriptor. The descriptor indicates which +// fields are expected / permitted for a notification channel of the +// given type. +func (r *ProjectsNotificationChannelDescriptorsService) Get(name string) *ProjectsNotificationChannelDescriptorsGetCall { + c := &ProjectsNotificationChannelDescriptorsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.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 *ProjectsNotificationChannelDescriptorsGetCall) Fields(s ...googleapi.Field) *ProjectsNotificationChannelDescriptorsGetCall { + 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 *ProjectsNotificationChannelDescriptorsGetCall) IfNoneMatch(entityTag string) *ProjectsNotificationChannelDescriptorsGetCall { + 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 *ProjectsNotificationChannelDescriptorsGetCall) Context(ctx context.Context) *ProjectsNotificationChannelDescriptorsGetCall { + 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 *ProjectsNotificationChannelDescriptorsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsNotificationChannelDescriptorsGetCall) 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, "v3/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", 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 "monitoring.projects.notificationChannelDescriptors.get" call. +// Exactly one of *NotificationChannelDescriptor or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *NotificationChannelDescriptor.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 *ProjectsNotificationChannelDescriptorsGetCall) Do(opts ...googleapi.CallOption) (*NotificationChannelDescriptor, 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 := &NotificationChannelDescriptor{ + 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 single channel descriptor. The descriptor indicates which fields are expected / permitted for a notification channel of the given type.", + // "flatPath": "v3/projects/{projectsId}/notificationChannelDescriptors/{notificationChannelDescriptorsId}", + // "httpMethod": "GET", + // "id": "monitoring.projects.notificationChannelDescriptors.get", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The channel type for which to execute the request. The format is projects/[PROJECT_ID]/notificationChannelDescriptors/{channel_type}.", + // "location": "path", + // "pattern": "^projects/[^/]+/notificationChannelDescriptors/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v3/{+name}", + // "response": { + // "$ref": "NotificationChannelDescriptor" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring", + // "https://www.googleapis.com/auth/monitoring.read" + // ] + // } + +} + +// method id "monitoring.projects.notificationChannelDescriptors.list": + +type ProjectsNotificationChannelDescriptorsListCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists the descriptors for supported channel types. The use of +// descriptors makes it possible for new channel types to be dynamically +// added. +func (r *ProjectsNotificationChannelDescriptorsService) List(name string) *ProjectsNotificationChannelDescriptorsListCall { + c := &ProjectsNotificationChannelDescriptorsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// PageSize sets the optional parameter "pageSize": The maximum number +// of results to return in a single response. If not set to a positive +// number, a reasonable value will be chosen by the service. +func (c *ProjectsNotificationChannelDescriptorsListCall) PageSize(pageSize int64) *ProjectsNotificationChannelDescriptorsListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": If non-empty, +// page_token must contain a value returned as the next_page_token in a +// previous response to request the next set of results. +func (c *ProjectsNotificationChannelDescriptorsListCall) PageToken(pageToken string) *ProjectsNotificationChannelDescriptorsListCall { + 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 *ProjectsNotificationChannelDescriptorsListCall) Fields(s ...googleapi.Field) *ProjectsNotificationChannelDescriptorsListCall { + 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 *ProjectsNotificationChannelDescriptorsListCall) IfNoneMatch(entityTag string) *ProjectsNotificationChannelDescriptorsListCall { + 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 *ProjectsNotificationChannelDescriptorsListCall) Context(ctx context.Context) *ProjectsNotificationChannelDescriptorsListCall { + 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 *ProjectsNotificationChannelDescriptorsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsNotificationChannelDescriptorsListCall) 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, "v3/{+name}/notificationChannelDescriptors") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", 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 "monitoring.projects.notificationChannelDescriptors.list" call. +// Exactly one of *ListNotificationChannelDescriptorsResponse or error +// will be non-nil. Any non-2xx status code is an error. Response +// headers are in either +// *ListNotificationChannelDescriptorsResponse.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 *ProjectsNotificationChannelDescriptorsListCall) Do(opts ...googleapi.CallOption) (*ListNotificationChannelDescriptorsResponse, 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 := &ListNotificationChannelDescriptorsResponse{ + 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 descriptors for supported channel types. The use of descriptors makes it possible for new channel types to be dynamically added.", + // "flatPath": "v3/projects/{projectsId}/notificationChannelDescriptors", + // "httpMethod": "GET", + // "id": "monitoring.projects.notificationChannelDescriptors.list", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The REST resource name of the parent from which to retrieve the notification channel descriptors. The expected syntax is:\nprojects/[PROJECT_ID]\nNote that this names the parent container in which to look for the descriptors; to retrieve a single descriptor by name, use the GetNotificationChannelDescriptor operation, instead.", + // "location": "path", + // "pattern": "^projects/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "pageSize": { + // "description": "The maximum number of results to return in a single response. If not set to a positive number, a reasonable value will be chosen by the service.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "pageToken": { + // "description": "If non-empty, page_token must contain a value returned as the next_page_token in a previous response to request the next set of results.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v3/{+name}/notificationChannelDescriptors", + // "response": { + // "$ref": "ListNotificationChannelDescriptorsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring", + // "https://www.googleapis.com/auth/monitoring.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 *ProjectsNotificationChannelDescriptorsListCall) Pages(ctx context.Context, f func(*ListNotificationChannelDescriptorsResponse) 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 "monitoring.projects.notificationChannels.create": + +type ProjectsNotificationChannelsCreateCall struct { + s *Service + name string + notificationchannel *NotificationChannel + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Create: Creates a new notification channel, representing a single +// notification endpoint such as an email address, SMS number, or +// pagerduty service. +func (r *ProjectsNotificationChannelsService) Create(name string, notificationchannel *NotificationChannel) *ProjectsNotificationChannelsCreateCall { + c := &ProjectsNotificationChannelsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.notificationchannel = notificationchannel + 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 *ProjectsNotificationChannelsCreateCall) Fields(s ...googleapi.Field) *ProjectsNotificationChannelsCreateCall { + 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 *ProjectsNotificationChannelsCreateCall) Context(ctx context.Context) *ProjectsNotificationChannelsCreateCall { + 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 *ProjectsNotificationChannelsCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsNotificationChannelsCreateCall) 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.notificationchannel) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/notificationChannels") + 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 "monitoring.projects.notificationChannels.create" call. +// Exactly one of *NotificationChannel or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *NotificationChannel.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 *ProjectsNotificationChannelsCreateCall) Do(opts ...googleapi.CallOption) (*NotificationChannel, 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 := &NotificationChannel{ + 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 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", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The project on which to execute the request. The format is:\nprojects/[PROJECT_ID]\nNote that this names the container into which the channel will be written. This does not name the newly created channel. The resulting channel's name will have a normalized version of this field as a prefix, but will add /notificationChannels/[CHANNEL_ID] to identify the channel.", + // "location": "path", + // "pattern": "^projects/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v3/{+name}/notificationChannels", + // "request": { + // "$ref": "NotificationChannel" + // }, + // "response": { + // "$ref": "NotificationChannel" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring" + // ] + // } + +} + +// method id "monitoring.projects.notificationChannels.delete": + +type ProjectsNotificationChannelsDeleteCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes a notification channel. +func (r *ProjectsNotificationChannelsService) Delete(name string) *ProjectsNotificationChannelsDeleteCall { + c := &ProjectsNotificationChannelsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// Force sets the optional parameter "force": If true, the notification +// channel will be deleted regardless of its use in alert policies (the +// policies will be updated to remove the channel). If false, channels +// that are still referenced by an existing alerting policy will fail to +// be deleted in a delete operation. +func (c *ProjectsNotificationChannelsDeleteCall) Force(force bool) *ProjectsNotificationChannelsDeleteCall { + c.urlParams_.Set("force", fmt.Sprint(force)) + 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 *ProjectsNotificationChannelsDeleteCall) Fields(s ...googleapi.Field) *ProjectsNotificationChannelsDeleteCall { + 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 *ProjectsNotificationChannelsDeleteCall) Context(ctx context.Context) *ProjectsNotificationChannelsDeleteCall { + 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 *ProjectsNotificationChannelsDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsNotificationChannelsDeleteCall) 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, "v3/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("DELETE", 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 "monitoring.projects.notificationChannels.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 *ProjectsNotificationChannelsDeleteCall) 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 a notification channel.", + // "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}", + // "httpMethod": "DELETE", + // "id": "monitoring.projects.notificationChannels.delete", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "force": { + // "description": "If true, the notification channel will be deleted regardless of its use in alert policies (the policies will be updated to remove the channel). If false, channels that are still referenced by an existing alerting policy will fail to be deleted in a delete operation.", + // "location": "query", + // "type": "boolean" + // }, + // "name": { + // "description": "The channel for which to execute the request. The format is projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID].", + // "location": "path", + // "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v3/{+name}", + // "response": { + // "$ref": "Empty" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring" + // ] + // } + +} + +// method id "monitoring.projects.notificationChannels.get": + +type ProjectsNotificationChannelsGetCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Gets a single notification channel. The channel includes the +// relevant configuration details with which the channel was created. +// However, the response may truncate or omit passwords, API keys, or +// other private key matter and thus the response may not be 100% +// identical to the information that was supplied in the call to the +// create method. +func (r *ProjectsNotificationChannelsService) Get(name string) *ProjectsNotificationChannelsGetCall { + c := &ProjectsNotificationChannelsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.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 *ProjectsNotificationChannelsGetCall) Fields(s ...googleapi.Field) *ProjectsNotificationChannelsGetCall { + 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 *ProjectsNotificationChannelsGetCall) IfNoneMatch(entityTag string) *ProjectsNotificationChannelsGetCall { + 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 *ProjectsNotificationChannelsGetCall) Context(ctx context.Context) *ProjectsNotificationChannelsGetCall { + 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 *ProjectsNotificationChannelsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsNotificationChannelsGetCall) 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, "v3/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", 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 "monitoring.projects.notificationChannels.get" call. +// Exactly one of *NotificationChannel or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *NotificationChannel.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 *ProjectsNotificationChannelsGetCall) Do(opts ...googleapi.CallOption) (*NotificationChannel, 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 := &NotificationChannel{ + 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 single notification channel. The channel includes the relevant configuration details with which the channel was created. However, the response may truncate or omit passwords, API keys, or other private key matter and thus the response may not be 100% identical to the information that was supplied in the call to the create method.", + // "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}", + // "httpMethod": "GET", + // "id": "monitoring.projects.notificationChannels.get", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The channel for which to execute the request. The format is projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID].", + // "location": "path", + // "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v3/{+name}", + // "response": { + // "$ref": "NotificationChannel" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring", + // "https://www.googleapis.com/auth/monitoring.read" + // ] + // } + +} + +// method id "monitoring.projects.notificationChannels.getVerificationCode": + +type ProjectsNotificationChannelsGetVerificationCodeCall struct { + s *Service + name string + getnotificationchannelverificationcoderequest *GetNotificationChannelVerificationCodeRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// GetVerificationCode: Requests a verification code for an already +// verified channel that can then be used in a call to +// VerifyNotificationChannel() on a different channel with an equivalent +// identity in the same or in a different project. This makes it +// possible to copy a channel between projects without requiring manual +// reverification of the channel. If the channel is not in the verified +// state, this method will fail (in other words, this may only be used +// if the SendNotificationChannelVerificationCode and +// VerifyNotificationChannel paths have already been used to put the +// given channel into the verified state).There is no guarantee that the +// verification codes returned by this method will be of a similar +// structure or form as the ones that are delivered to the channel via +// SendNotificationChannelVerificationCode; while +// VerifyNotificationChannel() will recognize both the codes delivered +// via SendNotificationChannelVerificationCode() and returned from +// GetNotificationChannelVerificationCode(), it is typically the case +// that the verification codes delivered via +// SendNotificationChannelVerificationCode() will be shorter and also +// have a shorter expiration (e.g. codes such as "G-123456") whereas +// GetVerificationCode() will typically return a much longer, websafe +// base 64 encoded string that has a longer expiration time. +func (r *ProjectsNotificationChannelsService) GetVerificationCode(name string, getnotificationchannelverificationcoderequest *GetNotificationChannelVerificationCodeRequest) *ProjectsNotificationChannelsGetVerificationCodeCall { + c := &ProjectsNotificationChannelsGetVerificationCodeCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.getnotificationchannelverificationcoderequest = getnotificationchannelverificationcoderequest + 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 *ProjectsNotificationChannelsGetVerificationCodeCall) Fields(s ...googleapi.Field) *ProjectsNotificationChannelsGetVerificationCodeCall { + 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 *ProjectsNotificationChannelsGetVerificationCodeCall) Context(ctx context.Context) *ProjectsNotificationChannelsGetVerificationCodeCall { + 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 *ProjectsNotificationChannelsGetVerificationCodeCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsNotificationChannelsGetVerificationCodeCall) 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.getnotificationchannelverificationcoderequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}:getVerificationCode") + 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 "monitoring.projects.notificationChannels.getVerificationCode" call. +// Exactly one of *GetNotificationChannelVerificationCodeResponse or +// error will be non-nil. Any non-2xx status code is an error. Response +// headers are in either +// *GetNotificationChannelVerificationCodeResponse.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 *ProjectsNotificationChannelsGetVerificationCodeCall) Do(opts ...googleapi.CallOption) (*GetNotificationChannelVerificationCodeResponse, 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 := &GetNotificationChannelVerificationCodeResponse{ + 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": "Requests a verification code for an already verified channel that can then be used in a call to VerifyNotificationChannel() on a different channel with an equivalent identity in the same or in a different project. This makes it possible to copy a channel between projects without requiring manual reverification of the channel. If the channel is not in the verified state, this method will fail (in other words, this may only be used if the SendNotificationChannelVerificationCode and VerifyNotificationChannel paths have already been used to put the given channel into the verified state).There is no guarantee that the verification codes returned by this method will be of a similar structure or form as the ones that are delivered to the channel via SendNotificationChannelVerificationCode; while VerifyNotificationChannel() will recognize both the codes delivered via SendNotificationChannelVerificationCode() and returned from GetNotificationChannelVerificationCode(), it is typically the case that the verification codes delivered via SendNotificationChannelVerificationCode() will be shorter and also have a shorter expiration (e.g. codes such as \"G-123456\") whereas GetVerificationCode() will typically return a much longer, websafe base 64 encoded string that has a longer expiration time.", + // "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}:getVerificationCode", + // "httpMethod": "POST", + // "id": "monitoring.projects.notificationChannels.getVerificationCode", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The notification channel for which a verification code is to be generated and retrieved. This must name a channel that is already verified; if the specified channel is not verified, the request will fail.", + // "location": "path", + // "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v3/{+name}:getVerificationCode", + // "request": { + // "$ref": "GetNotificationChannelVerificationCodeRequest" + // }, + // "response": { + // "$ref": "GetNotificationChannelVerificationCodeResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring" + // ] + // } + +} + +// method id "monitoring.projects.notificationChannels.list": + +type ProjectsNotificationChannelsListCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists the notification channels that have been created for the +// project. +func (r *ProjectsNotificationChannelsService) List(name string) *ProjectsNotificationChannelsListCall { + c := &ProjectsNotificationChannelsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// Filter sets the optional parameter "filter": If provided, this field +// specifies the criteria that must be met by notification channels to +// be included in the response.For more details, see sorting and +// filtering. +func (c *ProjectsNotificationChannelsListCall) Filter(filter string) *ProjectsNotificationChannelsListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// OrderBy sets the optional parameter "orderBy": A comma-separated list +// of fields by which to sort the result. Supports the same set of +// fields as in filter. Entries can be prefixed with a minus sign to +// sort in descending rather than ascending order.For more details, see +// sorting and filtering. +func (c *ProjectsNotificationChannelsListCall) OrderBy(orderBy string) *ProjectsNotificationChannelsListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageSize sets the optional parameter "pageSize": The maximum number +// of results to return in a single response. If not set to a positive +// number, a reasonable value will be chosen by the service. +func (c *ProjectsNotificationChannelsListCall) PageSize(pageSize int64) *ProjectsNotificationChannelsListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": If non-empty, +// page_token must contain a value returned as the next_page_token in a +// previous response to request the next set of results. +func (c *ProjectsNotificationChannelsListCall) PageToken(pageToken string) *ProjectsNotificationChannelsListCall { + 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 *ProjectsNotificationChannelsListCall) Fields(s ...googleapi.Field) *ProjectsNotificationChannelsListCall { + 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 *ProjectsNotificationChannelsListCall) IfNoneMatch(entityTag string) *ProjectsNotificationChannelsListCall { + 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 *ProjectsNotificationChannelsListCall) Context(ctx context.Context) *ProjectsNotificationChannelsListCall { + 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 *ProjectsNotificationChannelsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsNotificationChannelsListCall) 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, "v3/{+name}/notificationChannels") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", 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 "monitoring.projects.notificationChannels.list" call. +// Exactly one of *ListNotificationChannelsResponse or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *ListNotificationChannelsResponse.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 *ProjectsNotificationChannelsListCall) Do(opts ...googleapi.CallOption) (*ListNotificationChannelsResponse, 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 := &ListNotificationChannelsResponse{ + 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 notification channels that have been created for the project.", + // "flatPath": "v3/projects/{projectsId}/notificationChannels", + // "httpMethod": "GET", + // "id": "monitoring.projects.notificationChannels.list", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "filter": { + // "description": "If provided, this field specifies the criteria that must be met by notification channels to be included in the response.For more details, see sorting and filtering.", + // "location": "query", + // "type": "string" + // }, + // "name": { + // "description": "The project on which to execute the request. The format is projects/[PROJECT_ID]. That is, this names the container in which to look for the notification channels; it does not name a specific channel. To query a specific channel by REST resource name, use the GetNotificationChannel operation.", + // "location": "path", + // "pattern": "^projects/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "orderBy": { + // "description": "A comma-separated list of fields by which to sort the result. Supports the same set of fields as in filter. Entries can be prefixed with a minus sign to sort in descending rather than ascending order.For more details, see sorting and filtering.", + // "location": "query", + // "type": "string" + // }, + // "pageSize": { + // "description": "The maximum number of results to return in a single response. If not set to a positive number, a reasonable value will be chosen by the service.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "pageToken": { + // "description": "If non-empty, page_token must contain a value returned as the next_page_token in a previous response to request the next set of results.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v3/{+name}/notificationChannels", + // "response": { + // "$ref": "ListNotificationChannelsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring", + // "https://www.googleapis.com/auth/monitoring.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 *ProjectsNotificationChannelsListCall) Pages(ctx context.Context, f func(*ListNotificationChannelsResponse) 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 "monitoring.projects.notificationChannels.patch": + +type ProjectsNotificationChannelsPatchCall struct { + s *Service + name string + notificationchannel *NotificationChannel + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Updates a notification channel. Fields not specified in the +// field mask remain unchanged. +func (r *ProjectsNotificationChannelsService) Patch(name string, notificationchannel *NotificationChannel) *ProjectsNotificationChannelsPatchCall { + c := &ProjectsNotificationChannelsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.notificationchannel = notificationchannel + return c +} + +// UpdateMask sets the optional parameter "updateMask": The fields to +// update. +func (c *ProjectsNotificationChannelsPatchCall) UpdateMask(updateMask string) *ProjectsNotificationChannelsPatchCall { + c.urlParams_.Set("updateMask", updateMask) + 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 *ProjectsNotificationChannelsPatchCall) Fields(s ...googleapi.Field) *ProjectsNotificationChannelsPatchCall { + 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 *ProjectsNotificationChannelsPatchCall) Context(ctx context.Context) *ProjectsNotificationChannelsPatchCall { + 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 *ProjectsNotificationChannelsPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsNotificationChannelsPatchCall) 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.notificationchannel) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PATCH", 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 "monitoring.projects.notificationChannels.patch" call. +// Exactly one of *NotificationChannel or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *NotificationChannel.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 *ProjectsNotificationChannelsPatchCall) Do(opts ...googleapi.CallOption) (*NotificationChannel, 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 := &NotificationChannel{ + 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 notification channel. Fields not specified in the field mask remain unchanged.", + // "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}", + // "httpMethod": "PATCH", + // "id": "monitoring.projects.notificationChannels.patch", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The full REST resource name for this channel. The syntax is:\nprojects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID]\nThe [CHANNEL_ID] is automatically assigned by the server on creation.", + // "location": "path", + // "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "updateMask": { + // "description": "The fields to update.", + // "format": "google-fieldmask", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v3/{+name}", + // "request": { + // "$ref": "NotificationChannel" + // }, + // "response": { + // "$ref": "NotificationChannel" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring" + // ] + // } + +} + +// method id "monitoring.projects.notificationChannels.sendVerificationCode": + +type ProjectsNotificationChannelsSendVerificationCodeCall struct { + s *Service + name string + sendnotificationchannelverificationcoderequest *SendNotificationChannelVerificationCodeRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SendVerificationCode: Causes a verification code to be delivered to +// the channel. The code can then be supplied in +// VerifyNotificationChannel to verify the channel. +func (r *ProjectsNotificationChannelsService) SendVerificationCode(name string, sendnotificationchannelverificationcoderequest *SendNotificationChannelVerificationCodeRequest) *ProjectsNotificationChannelsSendVerificationCodeCall { + c := &ProjectsNotificationChannelsSendVerificationCodeCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.sendnotificationchannelverificationcoderequest = sendnotificationchannelverificationcoderequest + 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 *ProjectsNotificationChannelsSendVerificationCodeCall) Fields(s ...googleapi.Field) *ProjectsNotificationChannelsSendVerificationCodeCall { + 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 *ProjectsNotificationChannelsSendVerificationCodeCall) Context(ctx context.Context) *ProjectsNotificationChannelsSendVerificationCodeCall { + 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 *ProjectsNotificationChannelsSendVerificationCodeCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsNotificationChannelsSendVerificationCodeCall) 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.sendnotificationchannelverificationcoderequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}:sendVerificationCode") + 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 "monitoring.projects.notificationChannels.sendVerificationCode" 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 *ProjectsNotificationChannelsSendVerificationCodeCall) 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": "Causes a verification code to be delivered to the channel. The code can then be supplied in VerifyNotificationChannel to verify the channel.", + // "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}:sendVerificationCode", + // "httpMethod": "POST", + // "id": "monitoring.projects.notificationChannels.sendVerificationCode", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The notification channel to which to send a verification code.", + // "location": "path", + // "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v3/{+name}:sendVerificationCode", + // "request": { + // "$ref": "SendNotificationChannelVerificationCodeRequest" + // }, + // "response": { + // "$ref": "Empty" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring" + // ] + // } + +} + +// method id "monitoring.projects.notificationChannels.verify": + +type ProjectsNotificationChannelsVerifyCall struct { + s *Service + name string + verifynotificationchannelrequest *VerifyNotificationChannelRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Verify: Verifies a NotificationChannel by proving receipt of the code +// delivered to the channel as a result of calling +// SendNotificationChannelVerificationCode. +func (r *ProjectsNotificationChannelsService) Verify(name string, verifynotificationchannelrequest *VerifyNotificationChannelRequest) *ProjectsNotificationChannelsVerifyCall { + c := &ProjectsNotificationChannelsVerifyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.verifynotificationchannelrequest = verifynotificationchannelrequest + 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 *ProjectsNotificationChannelsVerifyCall) Fields(s ...googleapi.Field) *ProjectsNotificationChannelsVerifyCall { + 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 *ProjectsNotificationChannelsVerifyCall) Context(ctx context.Context) *ProjectsNotificationChannelsVerifyCall { + 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 *ProjectsNotificationChannelsVerifyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsNotificationChannelsVerifyCall) 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.verifynotificationchannelrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}:verify") + 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 "monitoring.projects.notificationChannels.verify" call. +// Exactly one of *NotificationChannel or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *NotificationChannel.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 *ProjectsNotificationChannelsVerifyCall) Do(opts ...googleapi.CallOption) (*NotificationChannel, 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 := &NotificationChannel{ + 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": "Verifies a NotificationChannel by proving receipt of the code delivered to the channel as a result of calling SendNotificationChannelVerificationCode.", + // "flatPath": "v3/projects/{projectsId}/notificationChannels/{notificationChannelsId}:verify", + // "httpMethod": "POST", + // "id": "monitoring.projects.notificationChannels.verify", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The notification channel to verify.", + // "location": "path", + // "pattern": "^projects/[^/]+/notificationChannels/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v3/{+name}:verify", + // "request": { + // "$ref": "VerifyNotificationChannelRequest" + // }, + // "response": { + // "$ref": "NotificationChannel" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/monitoring" + // ] + // } + +} + // method id "monitoring.projects.timeSeries.create": type ProjectsTimeSeriesCreateCall struct { @@ -4845,10 +8453,11 @@ func (c *ProjectsTimeSeriesListCall) OrderBy(orderBy string) *ProjectsTimeSeries } // PageSize sets the optional parameter "pageSize": A positive number -// that is the maximum number of results to return. When view field sets -// to FULL, it limits the number of Points server will return; if view -// field is HEADERS, it limits the number of TimeSeries server will -// return. +// that is the maximum number of results to return. If page_size is +// empty or more than 100,000 results, the effective page_size is +// 100,000 results. If view is set to FULL, this is the maximum number +// of Points returned. If view is set to HEADERS, this is the maximum +// number of TimeSeries returned. func (c *ProjectsTimeSeriesListCall) PageSize(pageSize int64) *ProjectsTimeSeriesListCall { c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) return c @@ -5065,7 +8674,7 @@ func (c *ProjectsTimeSeriesListCall) Do(opts ...googleapi.CallOption) (*ListTime // "type": "string" // }, // "pageSize": { - // "description": "A positive number that is the maximum number of results to return. When view field sets to FULL, it limits the number of Points server will return; if view field is HEADERS, it limits the number of TimeSeries server will return.", + // "description": "A positive number that is the maximum number of results to return. If page_size is empty or more than 100,000 results, the effective page_size is 100,000 results. If view is set to FULL, this is the maximum number of Points returned. If view is set to HEADERS, this is the maximum number of TimeSeries returned.", // "format": "int32", // "location": "query", // "type": "integer" 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 412a30ff859..d8be67b5373 100644 --- a/vendor/google.golang.org/api/pubsub/v1/pubsub-api.json +++ b/vendor/google.golang.org/api/pubsub/v1/pubsub-api.json @@ -122,7 +122,7 @@ "snapshots": { "methods": { "create": { - "description": "Creates a snapshot from the requested subscription.\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.\n\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, conforming\nto the\n[resource name\nformat](https://cloud.google.com/pubsub/docs/overview#names). The 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.\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.", "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", "httpMethod": "PUT", "id": "pubsub.projects.snapshots.create", @@ -151,7 +151,7 @@ ] }, "delete": { - "description": "Removes an existing snapshot. 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. \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.", "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", "httpMethod": "DELETE", "id": "pubsub.projects.snapshots.delete", @@ -177,7 +177,7 @@ ] }, "get": { - "description": "Gets the configuration details of a snapshot.", + "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.", "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", "httpMethod": "GET", "id": "pubsub.projects.snapshots.get", @@ -229,7 +229,7 @@ ] }, "list": { - "description": "Lists the existing snapshots.", + "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.", "flatPath": "v1/projects/{projectsId}/snapshots", "httpMethod": "GET", "id": "pubsub.projects.snapshots.list", @@ -266,7 +266,7 @@ ] }, "patch": { - "description": "Updates an existing snapshot. Note that certain properties of a\nsnapshot are not modifiable.", + "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.", "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", "httpMethod": "PATCH", "id": "pubsub.projects.snapshots.patch", @@ -386,7 +386,7 @@ ] }, "create": { - "description": "Creates a subscription to a given topic.\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=\"/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.", "flatPath": "v1/projects/{projectsId}/subscriptions/{subscriptionsId}", "httpMethod": "PUT", "id": "pubsub.projects.subscriptions.create", @@ -646,7 +646,7 @@ ] }, "seek": { - "description": "Seeks an existing subscription to a point in time or to a given snapshot,\nwhichever is provided in the request.", + "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.", "flatPath": "v1/projects/{projectsId}/subscriptions/{subscriptionsId}:seek", "httpMethod": "POST", "id": "pubsub.projects.subscriptions.seek", @@ -737,7 +737,7 @@ "topics": { "methods": { "create": { - "description": "Creates the given topic with the given name.", + "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.", "flatPath": "v1/projects/{projectsId}/topics/{topicsId}", "httpMethod": "PUT", "id": "pubsub.projects.topics.create", @@ -972,7 +972,7 @@ "snapshots": { "methods": { "list": { - "description": "Lists the names of the snapshots on this topic.", + "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.", "flatPath": "v1/projects/{projectsId}/topics/{topicsId}/snapshots", "httpMethod": "GET", "id": "pubsub.projects.topics.snapshots.list", @@ -1056,7 +1056,7 @@ } } }, - "revision": "20180129", + "revision": "20180522", "rootUrl": "https://pubsub.googleapis.com/", "schemas": { "AcknowledgeRequest": { @@ -1078,7 +1078,7 @@ "id": "Binding", "properties": { "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` or `joe@example.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", + "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": { "type": "string" }, @@ -1092,7 +1092,7 @@ "type": "object" }, "CreateSnapshotRequest": { - "description": "Request for the `CreateSnapshot` method.", + "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.", "id": "CreateSnapshotRequest", "properties": { "subscription": { @@ -1109,7 +1109,7 @@ "type": "object" }, "ListSnapshotsResponse": { - "description": "Response for the `ListSnapshots` method.", + "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.", "id": "ListSnapshotsResponse", "properties": { "nextPageToken": { @@ -1145,7 +1145,7 @@ "type": "object" }, "ListTopicSnapshotsResponse": { - "description": "Response for the `ListTopicSnapshots` method.", + "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.", "id": "ListTopicSnapshotsResponse", "properties": { "nextPageToken": { @@ -1229,7 +1229,7 @@ "type": "object" }, "Policy": { - "description": "Defines an Identity and Access Management (IAM) policy. It is used to\nspecify access control policies for Cloud Platform resources.\n\n\nA `Policy` consists of a list of `bindings`. A `Binding` binds a list of\n`members` to a `role`, where the members can be user accounts, Google groups,\nGoogle domains, and service accounts. A `role` is a named list of permissions\ndefined by IAM.\n\n**Example**\n\n {\n \"bindings\": [\n {\n \"role\": \"roles/owner\",\n \"members\": [\n \"user:mike@example.com\",\n \"group:admins@example.com\",\n \"domain:google.com\",\n \"serviceAccount:my-other-app@appspot.gserviceaccount.com\",\n ]\n },\n {\n \"role\": \"roles/viewer\",\n \"members\": [\"user:sean@example.com\"]\n }\n ]\n }\n\nFor a description of IAM and its features, see the\n[IAM developer's guide](https://cloud.google.com/iam/docs).", + "description": "Defines an Identity and Access Management (IAM) policy. It is used to\nspecify access control policies for Cloud Platform resources.\n\n\nA `Policy` consists of a list of `bindings`. A `binding` binds a list of\n`members` to a `role`, where the members can be user accounts, Google groups,\nGoogle domains, and service accounts. A `role` is a named list of permissions\ndefined by IAM.\n\n**JSON Example**\n\n {\n \"bindings\": [\n {\n \"role\": \"roles/owner\",\n \"members\": [\n \"user:mike@example.com\",\n \"group:admins@example.com\",\n \"domain:google.com\",\n \"serviceAccount:my-other-app@appspot.gserviceaccount.com\"\n ]\n },\n {\n \"role\": \"roles/viewer\",\n \"members\": [\"user:sean@example.com\"]\n }\n ]\n }\n\n**YAML Example**\n\n bindings:\n - members:\n - user:mike@example.com\n - group:admins@example.com\n - domain:google.com\n - serviceAccount:my-other-app@appspot.gserviceaccount.com\n role: roles/owner\n - members:\n - user:sean@example.com\n role: roles/viewer\n\n\nFor a description of IAM and its features, see the\n[IAM developer's guide](https://cloud.google.com/iam/docs).", "id": "Policy", "properties": { "bindings": { @@ -1372,7 +1372,7 @@ "type": "object" }, "SeekRequest": { - "description": "Request for the `Seek` method.", + "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.", "id": "SeekRequest", "properties": { "snapshot": { @@ -1404,7 +1404,7 @@ "type": "object" }, "Snapshot": { - "description": "A snapshot resource.", + "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.", "id": "Snapshot", "properties": { "expireTime": { @@ -1433,7 +1433,7 @@ "type": "integer" }, "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.", + "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.", "format": "google-duration", "type": "string" }, @@ -1446,7 +1446,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.", + "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.", "type": "boolean" }, "topic": { @@ -1496,12 +1496,12 @@ "type": "object" }, "UpdateSnapshotRequest": { - "description": "Request for the UpdateSnapshot method.", + "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.", "id": "UpdateSnapshotRequest", "properties": { "snapshot": { "$ref": "Snapshot", - "description": "The updated snpashot object." + "description": "The updated snapshot object." }, "updateMask": { "description": "Indicates which fields in the provided snapshot to update.\nMust be specified and non-empty.", @@ -1529,6 +1529,6 @@ } }, "servicePath": "", - "title": "Google Cloud Pub/Sub API", + "title": "Cloud Pub/Sub API", "version": "v1" } \ No newline at end of file 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 f1b82ac6dad..d44985ffeeb 100644 --- a/vendor/google.golang.org/api/pubsub/v1/pubsub-gen.go +++ b/vendor/google.golang.org/api/pubsub/v1/pubsub-gen.go @@ -1,4 +1,4 @@ -// Package pubsub provides access to the Google Cloud Pub/Sub API. +// Package pubsub provides access to the Cloud Pub/Sub API. // // See https://cloud.google.com/pubsub/docs // @@ -193,7 +193,7 @@ type Binding struct { // // * `user:{emailid}`: An email address that represents a specific // Google - // account. For example, `alice@gmail.com` or `joe@example.com`. + // account. For example, `alice@gmail.com` . // // // * `serviceAccount:{emailid}`: An email address that represents a @@ -243,7 +243,13 @@ func (s *Binding) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// CreateSnapshotRequest: Request for the `CreateSnapshot` method. +// CreateSnapshotRequest: Request for the `CreateSnapshot` +// method.

+// ALPHA: This feature is part of an alpha 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 { // Subscription: The subscription whose backlog the snapshot // retains. @@ -300,7 +306,13 @@ type Empty struct { googleapi.ServerResponse `json:"-"` } -// ListSnapshotsResponse: Response for the `ListSnapshots` method. +// ListSnapshotsResponse: Response for the `ListSnapshots` +// method.

+// ALPHA: This feature is part of an alpha 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 ListSnapshotsResponse struct { // NextPageToken: If not empty, indicates that there may be more // snapshot that match the @@ -378,7 +390,12 @@ func (s *ListSubscriptionsResponse) MarshalJSON() ([]byte, error) { } // ListTopicSnapshotsResponse: Response for the `ListTopicSnapshots` -// method. +// method.

+// ALPHA: This feature is part of an alpha 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 ListTopicSnapshotsResponse struct { // NextPageToken: If not empty, indicates that there may be more // snapshots that match @@ -573,7 +590,7 @@ func (s *ModifyPushConfigRequest) MarshalJSON() ([]byte, error) { // specify access control policies for Cloud Platform resources. // // -// A `Policy` consists of a list of `bindings`. A `Binding` binds a list +// 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, @@ -581,7 +598,7 @@ func (s *ModifyPushConfigRequest) MarshalJSON() ([]byte, error) { // permissions // defined by IAM. // -// **Example** +// **JSON Example** // // { // "bindings": [ @@ -592,7 +609,7 @@ func (s *ModifyPushConfigRequest) MarshalJSON() ([]byte, error) { // "group:admins@example.com", // "domain:google.com", // -// "serviceAccount:my-other-app@appspot.gserviceaccount.com", +// "serviceAccount:my-other-app@appspot.gserviceaccount.com" // ] // }, // { @@ -602,6 +619,20 @@ func (s *ModifyPushConfigRequest) MarshalJSON() ([]byte, error) { // ] // } // +// **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 { @@ -951,7 +982,12 @@ func (s *ReceivedMessage) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// SeekRequest: Request for the `Seek` method. +// SeekRequest: Request for the `Seek` method.

+// ALPHA: This feature is part of an alpha 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 SeekRequest struct { // Snapshot: The snapshot to seek to. The snapshot's topic must be the // same as that of @@ -1042,7 +1078,12 @@ func (s *SetIamPolicyRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// Snapshot: A snapshot resource. +// Snapshot: A snapshot resource.

+// ALPHA: This feature is part of an alpha 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 Snapshot struct { // ExpireTime: The snapshot is guaranteed to exist up until this time. // A newly-created snapshot expires no later than 7 days from the time @@ -1141,7 +1182,12 @@ type Subscription struct { // `Seek` // can be done. Defaults to 7 days. Cannot be more than 7 days or less // than 10 - // minutes. + // minutes.

+ // ALPHA: This feature is part of an alpha 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. MessageRetentionDuration string `json:"messageRetentionDuration,omitempty"` // Name: The name of the subscription. It must have the @@ -1170,7 +1216,12 @@ type Subscription struct { // they are // acknowledged, until they fall out of the // `message_retention_duration` - // window. + // window.

+ // ALPHA: This feature is part of an alpha 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. RetainAckedMessages bool `json:"retainAckedMessages,omitempty"` // Topic: The name of the topic from which this subscription is @@ -1321,9 +1372,15 @@ func (s *Topic) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// UpdateSnapshotRequest: Request for the UpdateSnapshot method. +// UpdateSnapshotRequest: Request for the UpdateSnapshot +// method.

+// ALPHA: This feature is part of an alpha 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 UpdateSnapshotRequest struct { - // Snapshot: The updated snpashot object. + // Snapshot: The updated snapshot object. Snapshot *Snapshot `json:"snapshot,omitempty"` // UpdateMask: Indicates which fields in the provided snapshot to @@ -1398,24 +1455,27 @@ type ProjectsSnapshotsCreateCall struct { header_ http.Header } -// Create: Creates a snapshot from the requested subscription. +// Create: Creates a snapshot from the requested +// subscription.

+// ALPHA: This feature is part of an alpha 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. // 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 // snapshot // would expire in less than 1 hour -- then `FAILED_PRECONDITION` is // returned. -// See also the `Snapshot.expire_time` field. -// -// If the name is not provided in the request, the server will assign a -// random +// See also the `Snapshot.expire_time` field. If the name is not +// provided in +// the request, the server will assign a random // name for this snapshot on the same project as the subscription, // conforming -// to the -// [resource -// name -// format](https://cloud.google.com/pubsub/docs/overview#names). The -// generated +// 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. @@ -1512,7 +1572,7 @@ func (c *ProjectsSnapshotsCreateCall) Do(opts ...googleapi.CallOption) (*Snapsho } return ret, nil // { - // "description": "Creates a snapshot from the requested subscription.\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.\n\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, conforming\nto the\n[resource name\nformat](https://cloud.google.com/pubsub/docs/overview#names). The 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.\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.", // "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", // "httpMethod": "PUT", // "id": "pubsub.projects.snapshots.create", @@ -1553,7 +1613,13 @@ type ProjectsSnapshotsDeleteCall struct { header_ http.Header } -// Delete: Removes an existing snapshot. All messages retained in the +// Delete: Removes an existing snapshot.

+// ALPHA: This feature is part of an alpha 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. +// When the snapshot is deleted, all messages retained in the // snapshot // are immediately dropped. After a snapshot is deleted, a new one may // be @@ -1648,7 +1714,7 @@ func (c *ProjectsSnapshotsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, } return ret, nil // { - // "description": "Removes an existing snapshot. 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. \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.", // "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", // "httpMethod": "DELETE", // "id": "pubsub.projects.snapshots.delete", @@ -1687,7 +1753,13 @@ type ProjectsSnapshotsGetCall struct { header_ http.Header } -// Get: Gets the configuration details of a snapshot. +// Get: Gets the configuration details of a +// snapshot.

+// ALPHA: This feature is part of an alpha 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. func (r *ProjectsSnapshotsService) Get(snapshot string) *ProjectsSnapshotsGetCall { c := &ProjectsSnapshotsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.snapshot = snapshot @@ -1788,7 +1860,7 @@ func (c *ProjectsSnapshotsGetCall) Do(opts ...googleapi.CallOption) (*Snapshot, } return ret, nil // { - // "description": "Gets the configuration details of a snapshot.", + // "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.", // "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", // "httpMethod": "GET", // "id": "pubsub.projects.snapshots.get", @@ -1970,7 +2042,12 @@ type ProjectsSnapshotsListCall struct { header_ http.Header } -// List: Lists the existing snapshots. +// List: Lists the existing snapshots.

+// ALPHA: This feature is part of an alpha 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. func (r *ProjectsSnapshotsService) List(project string) *ProjectsSnapshotsListCall { c := &ProjectsSnapshotsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -2088,7 +2165,7 @@ func (c *ProjectsSnapshotsListCall) Do(opts ...googleapi.CallOption) (*ListSnaps } return ret, nil // { - // "description": "Lists the existing snapshots.", + // "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.", // "flatPath": "v1/projects/{projectsId}/snapshots", // "httpMethod": "GET", // "id": "pubsub.projects.snapshots.list", @@ -2159,9 +2236,13 @@ type ProjectsSnapshotsPatchCall struct { header_ http.Header } -// Patch: Updates an existing snapshot. Note that certain properties of -// a -// snapshot are not modifiable. +// Patch: Updates an existing snapshot.

+// ALPHA: This feature is part of an alpha 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. +// Note that certain properties of a snapshot are not modifiable. func (r *ProjectsSnapshotsService) Patch(name string, updatesnapshotrequest *UpdateSnapshotRequest) *ProjectsSnapshotsPatchCall { c := &ProjectsSnapshotsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.name = name @@ -2255,7 +2336,7 @@ func (c *ProjectsSnapshotsPatchCall) Do(opts ...googleapi.CallOption) (*Snapshot } return ret, nil // { - // "description": "Updates an existing snapshot. Note that certain properties of a\nsnapshot are not modifiable.", + // "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.", // "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", // "httpMethod": "PATCH", // "id": "pubsub.projects.snapshots.patch", @@ -2727,7 +2808,9 @@ type ProjectsSubscriptionsCreateCall struct { header_ http.Header } -// Create: Creates a subscription to a given topic. +// Create: Creates a subscription to a given topic. See the +// resource name +// rules. // If the subscription already exists, returns `ALREADY_EXISTS`. // If the corresponding topic doesn't exist, returns `NOT_FOUND`. // @@ -2835,7 +2918,7 @@ func (c *ProjectsSubscriptionsCreateCall) Do(opts ...googleapi.CallOption) (*Sub } return ret, nil // { - // "description": "Creates a subscription to a given topic.\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=\"/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.", // "flatPath": "v1/projects/{projectsId}/subscriptions/{subscriptionsId}", // "httpMethod": "PUT", // "id": "pubsub.projects.subscriptions.create", @@ -4055,7 +4138,12 @@ type ProjectsSubscriptionsSeekCall struct { // Seek: Seeks an existing subscription to a point in time or to a given // snapshot, -// whichever is provided in the request. +// whichever is provided in the request.

+// ALPHA: This feature is part of an alpha 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. func (r *ProjectsSubscriptionsService) Seek(subscription string, seekrequest *SeekRequest) *ProjectsSubscriptionsSeekCall { c := &ProjectsSubscriptionsSeekCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.subscription = subscription @@ -4149,7 +4237,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.", + // "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.", // "flatPath": "v1/projects/{projectsId}/subscriptions/{subscriptionsId}:seek", // "httpMethod": "POST", // "id": "pubsub.projects.subscriptions.seek", @@ -4475,7 +4563,8 @@ type ProjectsTopicsCreateCall struct { header_ http.Header } -// Create: Creates the given topic with the given name. +// Create: Creates the given topic with the given name. See the +// resource name rules. func (r *ProjectsTopicsService) Create(name string, topic *Topic) *ProjectsTopicsCreateCall { c := &ProjectsTopicsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.name = name @@ -4569,7 +4658,7 @@ func (c *ProjectsTopicsCreateCall) Do(opts ...googleapi.CallOption) (*Topic, err } return ret, nil // { - // "description": "Creates the given topic with the given name.", + // "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.", // "flatPath": "v1/projects/{projectsId}/topics/{topicsId}", // "httpMethod": "PUT", // "id": "pubsub.projects.topics.create", @@ -5641,7 +5730,13 @@ type ProjectsTopicsSnapshotsListCall struct { header_ http.Header } -// List: Lists the names of the snapshots on this topic. +// List: Lists the names of the snapshots on this +// topic.

+// ALPHA: This feature is part of an alpha 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. func (r *ProjectsTopicsSnapshotsService) List(topic string) *ProjectsTopicsSnapshotsListCall { c := &ProjectsTopicsSnapshotsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.topic = topic @@ -5759,7 +5854,7 @@ func (c *ProjectsTopicsSnapshotsListCall) Do(opts ...googleapi.CallOption) (*Lis } return ret, nil // { - // "description": "Lists the names of the snapshots on this topic.", + // "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.", // "flatPath": "v1/projects/{projectsId}/topics/{topicsId}/snapshots", // "httpMethod": "GET", // "id": "pubsub.projects.topics.snapshots.list", diff --git a/vendor/google.golang.org/api/tpu/v1alpha1/BUILD b/vendor/google.golang.org/api/tpu/v1/BUILD similarity index 93% rename from vendor/google.golang.org/api/tpu/v1alpha1/BUILD rename to vendor/google.golang.org/api/tpu/v1/BUILD index 58995a7c742..0797d6ea40c 100644 --- a/vendor/google.golang.org/api/tpu/v1alpha1/BUILD +++ b/vendor/google.golang.org/api/tpu/v1/BUILD @@ -3,7 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = ["tpu-gen.go"], - importpath = "google.golang.org/api/tpu/v1alpha1", + importpath = "google.golang.org/api/tpu/v1", visibility = ["//visibility:public"], deps = [ "//vendor/golang.org/x/net/context:go_default_library", diff --git a/vendor/google.golang.org/api/tpu/v1alpha1/tpu-api.json b/vendor/google.golang.org/api/tpu/v1/tpu-api.json similarity index 84% rename from vendor/google.golang.org/api/tpu/v1alpha1/tpu-api.json rename to vendor/google.golang.org/api/tpu/v1/tpu-api.json index 990cd1594dc..2ccfe3ac0fd 100644 --- a/vendor/google.golang.org/api/tpu/v1alpha1/tpu-api.json +++ b/vendor/google.golang.org/api/tpu/v1/tpu-api.json @@ -20,7 +20,7 @@ "x16": "http://www.google.com/images/icons/product/search-16.gif", "x32": "http://www.google.com/images/icons/product/search-32.gif" }, - "id": "tpu:v1alpha1", + "id": "tpu:v1", "kind": "discovery#restDescription", "name": "tpu", "ownerDomain": "google.com", @@ -60,11 +60,6 @@ "location": "query", "type": "string" }, - "bearer_token": { - "description": "OAuth bearer token.", - "location": "query", - "type": "string" - }, "callback": { "description": "JSONP", "location": "query", @@ -85,12 +80,6 @@ "location": "query", "type": "string" }, - "pp": { - "default": "true", - "description": "Pretty-print response.", - "location": "query", - "type": "boolean" - }, "prettyPrint": { "default": "true", "description": "Returns response with indentations and line breaks.", @@ -120,8 +109,8 @@ "locations": { "methods": { "get": { - "description": "Get information about a location.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}", + "description": "Gets information about a location.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}", "httpMethod": "GET", "id": "tpu.projects.locations.get", "parameterOrder": [ @@ -136,7 +125,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}", + "path": "v1/{+name}", "response": { "$ref": "Location" }, @@ -146,7 +135,7 @@ }, "list": { "description": "Lists information about the supported locations for this service.", - "flatPath": "v1alpha1/projects/{projectsId}/locations", + "flatPath": "v1/projects/{projectsId}/locations", "httpMethod": "GET", "id": "tpu.projects.locations.list", "parameterOrder": [ @@ -177,7 +166,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}/locations", + "path": "v1/{+name}/locations", "response": { "$ref": "ListLocationsResponse" }, @@ -187,11 +176,86 @@ } }, "resources": { + "acceleratorTypes": { + "methods": { + "get": { + "description": "Gets AcceleratorType.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/acceleratorTypes/{acceleratorTypesId}", + "httpMethod": "GET", + "id": "tpu.projects.locations.acceleratorTypes.get", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The resource name.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+/acceleratorTypes/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}", + "response": { + "$ref": "AcceleratorType" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "list": { + "description": "Lists accelerator types supported by this API.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/acceleratorTypes", + "httpMethod": "GET", + "id": "tpu.projects.locations.acceleratorTypes.list", + "parameterOrder": [ + "parent" + ], + "parameters": { + "filter": { + "description": "List filter.", + "location": "query", + "type": "string" + }, + "orderBy": { + "description": "Sort results.", + "location": "query", + "type": "string" + }, + "pageSize": { + "description": "The maximum number of items to return.", + "format": "int32", + "location": "query", + "type": "integer" + }, + "pageToken": { + "description": "The next_page_token value returned from a previous List request, if any.", + "location": "query", + "type": "string" + }, + "parent": { + "description": "The parent resource name.", + "location": "path", + "pattern": "^projects/[^/]+/locations/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+parent}/acceleratorTypes", + "response": { + "$ref": "ListAcceleratorTypesResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + } + } + }, "nodes": { "methods": { "create": { "description": "Creates a node.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes", "httpMethod": "POST", "id": "tpu.projects.locations.nodes.create", "parameterOrder": [ @@ -211,7 +275,7 @@ "type": "string" } }, - "path": "v1alpha1/{+parent}/nodes", + "path": "v1/{+parent}/nodes", "request": { "$ref": "Node" }, @@ -224,7 +288,7 @@ }, "delete": { "description": "Deletes a node.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}", "httpMethod": "DELETE", "id": "tpu.projects.locations.nodes.delete", "parameterOrder": [ @@ -239,7 +303,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}", + "path": "v1/{+name}", "response": { "$ref": "Operation" }, @@ -249,7 +313,7 @@ }, "get": { "description": "Gets the details of a node.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}", "httpMethod": "GET", "id": "tpu.projects.locations.nodes.get", "parameterOrder": [ @@ -264,7 +328,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}", + "path": "v1/{+name}", "response": { "$ref": "Node" }, @@ -274,7 +338,7 @@ }, "list": { "description": "Lists nodes.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes", "httpMethod": "GET", "id": "tpu.projects.locations.nodes.list", "parameterOrder": [ @@ -300,7 +364,7 @@ "type": "string" } }, - "path": "v1alpha1/{+parent}/nodes", + "path": "v1/{+parent}/nodes", "response": { "$ref": "ListNodesResponse" }, @@ -310,7 +374,7 @@ }, "reimage": { "description": "Reimages a node's OS.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:reimage", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:reimage", "httpMethod": "POST", "id": "tpu.projects.locations.nodes.reimage", "parameterOrder": [ @@ -325,7 +389,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}:reimage", + "path": "v1/{+name}:reimage", "request": { "$ref": "ReimageNodeRequest" }, @@ -338,7 +402,7 @@ }, "reset": { "description": "Resets a node, which stops and starts the VM.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:reset", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:reset", "httpMethod": "POST", "id": "tpu.projects.locations.nodes.reset", "parameterOrder": [ @@ -353,7 +417,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}:reset", + "path": "v1/{+name}:reset", "request": { "$ref": "ResetNodeRequest" }, @@ -366,7 +430,7 @@ }, "start": { "description": "Starts a node.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:start", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:start", "httpMethod": "POST", "id": "tpu.projects.locations.nodes.start", "parameterOrder": [ @@ -381,7 +445,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}:start", + "path": "v1/{+name}:start", "request": { "$ref": "StartNodeRequest" }, @@ -394,7 +458,7 @@ }, "stop": { "description": "Stops a node.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:stop", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:stop", "httpMethod": "POST", "id": "tpu.projects.locations.nodes.stop", "parameterOrder": [ @@ -409,7 +473,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}:stop", + "path": "v1/{+name}:stop", "request": { "$ref": "StopNodeRequest" }, @@ -426,7 +490,7 @@ "methods": { "cancel": { "description": "Starts asynchronous cancellation on a long-running operation. The server\nmakes a best effort to cancel the operation, but success is not\nguaranteed. If the server doesn't support this method, it returns\n`google.rpc.Code.UNIMPLEMENTED`. Clients can use\nOperations.GetOperation or\nother methods to check whether the cancellation succeeded or whether the\noperation completed despite cancellation. On successful cancellation,\nthe operation is not deleted; instead, it becomes an operation with\nan Operation.error value with a google.rpc.Status.code of 1,\ncorresponding to `Code.CANCELLED`.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}:cancel", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}:cancel", "httpMethod": "POST", "id": "tpu.projects.locations.operations.cancel", "parameterOrder": [ @@ -441,7 +505,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}:cancel", + "path": "v1/{+name}:cancel", "response": { "$ref": "Empty" }, @@ -451,7 +515,7 @@ }, "delete": { "description": "Deletes a long-running operation. This method indicates that the client is\nno longer interested in the operation result. It does not cancel the\noperation. If the server doesn't support this method, it returns\n`google.rpc.Code.UNIMPLEMENTED`.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}", "httpMethod": "DELETE", "id": "tpu.projects.locations.operations.delete", "parameterOrder": [ @@ -466,7 +530,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}", + "path": "v1/{+name}", "response": { "$ref": "Empty" }, @@ -476,7 +540,7 @@ }, "get": { "description": "Gets the latest state of a long-running operation. Clients can use this\nmethod to poll the operation result at intervals as recommended by the API\nservice.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}", "httpMethod": "GET", "id": "tpu.projects.locations.operations.get", "parameterOrder": [ @@ -491,7 +555,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}", + "path": "v1/{+name}", "response": { "$ref": "Operation" }, @@ -501,7 +565,7 @@ }, "list": { "description": "Lists operations that match the specified filter in the request. If the\nserver doesn't support this method, it returns `UNIMPLEMENTED`.\n\nNOTE: the `name` binding allows API services to override the binding\nto use different resource name schemes, such as `users/*/operations`. To\noverride the binding, API services can add a binding such as\n`\"/v1/{name=users/*}/operations\"` to their service configuration.\nFor backwards compatibility, the default name includes the operations\ncollection id, however overriding users must ensure the name binding\nis the parent resource, without the operations collection id.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/operations", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations", "httpMethod": "GET", "id": "tpu.projects.locations.operations.list", "parameterOrder": [ @@ -532,7 +596,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}/operations", + "path": "v1/{+name}/operations", "response": { "$ref": "ListOperationsResponse" }, @@ -546,7 +610,7 @@ "methods": { "get": { "description": "Gets TensorFlow Version.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/tensorflowVersions/{tensorflowVersionsId}", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/tensorflowVersions/{tensorflowVersionsId}", "httpMethod": "GET", "id": "tpu.projects.locations.tensorflowVersions.get", "parameterOrder": [ @@ -561,7 +625,7 @@ "type": "string" } }, - "path": "v1alpha1/{+name}", + "path": "v1/{+name}", "response": { "$ref": "TensorFlowVersion" }, @@ -570,8 +634,8 @@ ] }, "list": { - "description": "Lists TensorFlow versions supported by this API.", - "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/tensorflowVersions", + "description": "List TensorFlow versions supported by this API.", + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/tensorflowVersions", "httpMethod": "GET", "id": "tpu.projects.locations.tensorflowVersions.list", "parameterOrder": [ @@ -607,7 +671,7 @@ "type": "string" } }, - "path": "v1alpha1/{+parent}/tensorflowVersions", + "path": "v1/{+parent}/tensorflowVersions", "response": { "$ref": "ListTensorFlowVersionsResponse" }, @@ -622,15 +686,48 @@ } } }, - "revision": "20180202", + "revision": "20180601", "rootUrl": "https://tpu.googleapis.com/", "schemas": { + "AcceleratorType": { + "description": "A accelerator type that a Node can be configured with.", + "id": "AcceleratorType", + "properties": { + "name": { + "description": "The resource name.", + "type": "string" + }, + "type": { + "description": "the accelerator type.", + "type": "string" + } + }, + "type": "object" + }, "Empty": { "description": "A generic empty message that you can re-use to avoid defining duplicated\nempty messages in your APIs. A typical example is to use it as the request\nor the response type of an API method. For instance:\n\n service Foo {\n rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);\n }\n\nThe JSON representation for `Empty` is empty JSON object `{}`.", "id": "Empty", "properties": {}, "type": "object" }, + "ListAcceleratorTypesResponse": { + "description": "Response for ListAcceleratorTypes.", + "id": "ListAcceleratorTypesResponse", + "properties": { + "acceleratorTypes": { + "description": "The listed nodes.", + "items": { + "$ref": "AcceleratorType" + }, + "type": "array" + }, + "nextPageToken": { + "description": "The next page token or empty if none.", + "type": "string" + } + }, + "type": "object" + }, "ListLocationsResponse": { "description": "The response message for Locations.ListLocations.", "id": "ListLocationsResponse", @@ -707,6 +804,10 @@ "description": "A resource that represents Google Cloud Platform location.", "id": "Location", "properties": { + "displayName": { + "description": "The friendly name for this location, typically a nearby city name.\nFor example, \"Tokyo\".", + "type": "string" + }, "labels": { "additionalProperties": { "type": "string" @@ -820,6 +921,9 @@ "description": "Output only.\nDEPRECATED! Use network_endpoints instead.\nThe network port for the TPU Node as visible to Compute Engine instances.", "type": "string" }, + "schedulingConfig": { + "$ref": "SchedulingConfig" + }, "serviceAccount": { "description": "Output only.\nThe service account used to run the tensor flow services within the node.\nTo share resources, including Google Cloud Storage data, with the\nTensorflow job running in the Node, this account must have permissions to\nthat data.", "type": "string" @@ -834,7 +938,9 @@ "REIMAGING", "DELETING", "REPAIRING", - "STOPPED" + "STOPPED", + "STOPPING", + "STARTING" ], "enumDescriptions": [ "TPU node state is not known/set.", @@ -844,7 +950,9 @@ "TPU node is undergoing reimaging.", "TPU node is being deleted.", "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." + "7 - Reserved. Was SUSPENDED.\nTPU node is stopped.", + "TPU node is currently stopping.", + "TPU node is currently starting." ], "type": "string" }, @@ -944,6 +1052,15 @@ "properties": {}, "type": "object" }, + "SchedulingConfig": { + "id": "SchedulingConfig", + "properties": { + "preemptible": { + "type": "boolean" + } + }, + "type": "object" + }, "StartNodeRequest": { "description": "Request for StartNode.", "id": "StartNodeRequest", @@ -1001,6 +1118,6 @@ }, "servicePath": "", "title": "Cloud TPU API", - "version": "v1alpha1", + "version": "v1", "version_module": true } \ No newline at end of file diff --git a/vendor/google.golang.org/api/tpu/v1alpha1/tpu-gen.go b/vendor/google.golang.org/api/tpu/v1/tpu-gen.go similarity index 84% rename from vendor/google.golang.org/api/tpu/v1alpha1/tpu-gen.go rename to vendor/google.golang.org/api/tpu/v1/tpu-gen.go index 84684fdf63b..33c972edff6 100644 --- a/vendor/google.golang.org/api/tpu/v1alpha1/tpu-gen.go +++ b/vendor/google.golang.org/api/tpu/v1/tpu-gen.go @@ -4,7 +4,7 @@ // // Usage example: // -// import "google.golang.org/api/tpu/v1alpha1" +// import "google.golang.org/api/tpu/v1" // ... // tpuService, err := tpu.New(oauthHttpClient) package tpu @@ -40,9 +40,9 @@ var _ = strings.Replace var _ = context.Canceled var _ = ctxhttp.Do -const apiId = "tpu:v1alpha1" +const apiId = "tpu:v1" const apiName = "tpu" -const apiVersion = "v1alpha1" +const apiVersion = "v1" const basePath = "https://tpu.googleapis.com/" // OAuth2 scopes used by this API. @@ -89,6 +89,7 @@ type ProjectsService struct { func NewProjectsLocationsService(s *Service) *ProjectsLocationsService { rs := &ProjectsLocationsService{s: s} + rs.AcceleratorTypes = NewProjectsLocationsAcceleratorTypesService(s) rs.Nodes = NewProjectsLocationsNodesService(s) rs.Operations = NewProjectsLocationsOperationsService(s) rs.TensorflowVersions = NewProjectsLocationsTensorflowVersionsService(s) @@ -98,6 +99,8 @@ func NewProjectsLocationsService(s *Service) *ProjectsLocationsService { type ProjectsLocationsService struct { s *Service + AcceleratorTypes *ProjectsLocationsAcceleratorTypesService + Nodes *ProjectsLocationsNodesService Operations *ProjectsLocationsOperationsService @@ -105,6 +108,15 @@ type ProjectsLocationsService struct { TensorflowVersions *ProjectsLocationsTensorflowVersionsService } +func NewProjectsLocationsAcceleratorTypesService(s *Service) *ProjectsLocationsAcceleratorTypesService { + rs := &ProjectsLocationsAcceleratorTypesService{s: s} + return rs +} + +type ProjectsLocationsAcceleratorTypesService struct { + s *Service +} + func NewProjectsLocationsNodesService(s *Service) *ProjectsLocationsNodesService { rs := &ProjectsLocationsNodesService{s: s} return rs @@ -132,6 +144,42 @@ type ProjectsLocationsTensorflowVersionsService struct { s *Service } +// AcceleratorType: A accelerator type that a Node can be configured +// with. +type AcceleratorType struct { + // Name: The resource name. + Name string `json:"name,omitempty"` + + // Type: the accelerator type. + 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. "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 *AcceleratorType) MarshalJSON() ([]byte, error) { + type NoMethod AcceleratorType + 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 @@ -150,6 +198,42 @@ type Empty struct { googleapi.ServerResponse `json:"-"` } +// ListAcceleratorTypesResponse: Response for ListAcceleratorTypes. +type ListAcceleratorTypesResponse struct { + // AcceleratorTypes: The listed nodes. + AcceleratorTypes []*AcceleratorType `json:"acceleratorTypes,omitempty"` + + // NextPageToken: The next page token or empty if none. + 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. "AcceleratorTypes") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AcceleratorTypes") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *ListAcceleratorTypesResponse) MarshalJSON() ([]byte, error) { + type NoMethod ListAcceleratorTypesResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // ListLocationsResponse: The response message for // Locations.ListLocations. type ListLocationsResponse struct { @@ -296,6 +380,11 @@ func (s *ListTensorFlowVersionsResponse) MarshalJSON() ([]byte, error) { // Location: A resource that represents Google Cloud Platform location. type Location struct { + // DisplayName: The friendly name for this location, typically a nearby + // city name. + // For example, "Tokyo". + DisplayName string `json:"displayName,omitempty"` + // Labels: Cross-service attributes for the location. For example // // {"cloud.googleapis.com/region": "us-east1"} @@ -319,7 +408,7 @@ type Location struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "Labels") to + // 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 @@ -327,10 +416,10 @@ type Location struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // 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 + // 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:"-"` @@ -457,6 +546,8 @@ type Node struct { // instances. Port string `json:"port,omitempty"` + SchedulingConfig *SchedulingConfig `json:"schedulingConfig,omitempty"` + // ServiceAccount: Output only. // The service account used to run the tensor flow services within the // node. @@ -482,6 +573,8 @@ type Node struct { // found in the `help_description` field. // "STOPPED" - 7 - Reserved. Was SUSPENDED. // TPU node is stopped. + // "STOPPING" - TPU node is currently stopping. + // "STARTING" - TPU node is currently starting. State string `json:"state,omitempty"` // TensorflowVersion: The version of Tensorflow running in the @@ -680,6 +773,32 @@ func (s *ReimageNodeRequest) MarshalJSON() ([]byte, error) { type ResetNodeRequest struct { } +type SchedulingConfig struct { + Preemptible bool `json:"preemptible,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Preemptible") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Preemptible") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SchedulingConfig) MarshalJSON() ([]byte, error) { + type NoMethod SchedulingConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // StartNodeRequest: Request for StartNode. type StartNodeRequest struct { } @@ -854,7 +973,7 @@ type ProjectsLocationsGetCall struct { header_ http.Header } -// Get: Get information about a location. +// Get: Gets information about a location. func (r *ProjectsLocationsService) Get(name string) *ProjectsLocationsGetCall { c := &ProjectsLocationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.name = name @@ -907,7 +1026,7 @@ func (c *ProjectsLocationsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("GET", urls, body) req.Header = reqHeaders @@ -955,8 +1074,8 @@ func (c *ProjectsLocationsGetCall) Do(opts ...googleapi.CallOption) (*Location, } return ret, nil // { - // "description": "Get information about a location.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}", + // "description": "Gets information about a location.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}", // "httpMethod": "GET", // "id": "tpu.projects.locations.get", // "parameterOrder": [ @@ -971,7 +1090,7 @@ func (c *ProjectsLocationsGetCall) Do(opts ...googleapi.CallOption) (*Location, // "type": "string" // } // }, - // "path": "v1alpha1/{+name}", + // "path": "v1/{+name}", // "response": { // "$ref": "Location" // }, @@ -1068,7 +1187,7 @@ func (c *ProjectsLocationsListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}/locations") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}/locations") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("GET", urls, body) req.Header = reqHeaders @@ -1117,7 +1236,7 @@ func (c *ProjectsLocationsListCall) Do(opts ...googleapi.CallOption) (*ListLocat return ret, nil // { // "description": "Lists information about the supported locations for this service.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations", + // "flatPath": "v1/projects/{projectsId}/locations", // "httpMethod": "GET", // "id": "tpu.projects.locations.list", // "parameterOrder": [ @@ -1148,7 +1267,7 @@ func (c *ProjectsLocationsListCall) Do(opts ...googleapi.CallOption) (*ListLocat // "type": "string" // } // }, - // "path": "v1alpha1/{+name}/locations", + // "path": "v1/{+name}/locations", // "response": { // "$ref": "ListLocationsResponse" // }, @@ -1180,6 +1299,352 @@ func (c *ProjectsLocationsListCall) Pages(ctx context.Context, f func(*ListLocat } } +// method id "tpu.projects.locations.acceleratorTypes.get": + +type ProjectsLocationsAcceleratorTypesGetCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Gets AcceleratorType. +func (r *ProjectsLocationsAcceleratorTypesService) Get(name string) *ProjectsLocationsAcceleratorTypesGetCall { + c := &ProjectsLocationsAcceleratorTypesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.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 *ProjectsLocationsAcceleratorTypesGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsAcceleratorTypesGetCall { + 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 *ProjectsLocationsAcceleratorTypesGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsAcceleratorTypesGetCall { + 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 *ProjectsLocationsAcceleratorTypesGetCall) Context(ctx context.Context) *ProjectsLocationsAcceleratorTypesGetCall { + 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 *ProjectsLocationsAcceleratorTypesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsAcceleratorTypesGetCall) 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, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", 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.acceleratorTypes.get" call. +// Exactly one of *AcceleratorType or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *AcceleratorType.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 *ProjectsLocationsAcceleratorTypesGetCall) Do(opts ...googleapi.CallOption) (*AcceleratorType, 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 := &AcceleratorType{ + 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 AcceleratorType.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/acceleratorTypes/{acceleratorTypesId}", + // "httpMethod": "GET", + // "id": "tpu.projects.locations.acceleratorTypes.get", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The resource name.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/acceleratorTypes/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "response": { + // "$ref": "AcceleratorType" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "tpu.projects.locations.acceleratorTypes.list": + +type ProjectsLocationsAcceleratorTypesListCall struct { + s *Service + parent string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists accelerator types supported by this API. +func (r *ProjectsLocationsAcceleratorTypesService) List(parent string) *ProjectsLocationsAcceleratorTypesListCall { + c := &ProjectsLocationsAcceleratorTypesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + return c +} + +// Filter sets the optional parameter "filter": List filter. +func (c *ProjectsLocationsAcceleratorTypesListCall) Filter(filter string) *ProjectsLocationsAcceleratorTypesListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sort results. +func (c *ProjectsLocationsAcceleratorTypesListCall) OrderBy(orderBy string) *ProjectsLocationsAcceleratorTypesListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageSize sets the optional parameter "pageSize": The maximum number +// of items to return. +func (c *ProjectsLocationsAcceleratorTypesListCall) PageSize(pageSize int64) *ProjectsLocationsAcceleratorTypesListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": The +// next_page_token value returned from a previous List request, if any. +func (c *ProjectsLocationsAcceleratorTypesListCall) PageToken(pageToken string) *ProjectsLocationsAcceleratorTypesListCall { + 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 *ProjectsLocationsAcceleratorTypesListCall) Fields(s ...googleapi.Field) *ProjectsLocationsAcceleratorTypesListCall { + 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 *ProjectsLocationsAcceleratorTypesListCall) IfNoneMatch(entityTag string) *ProjectsLocationsAcceleratorTypesListCall { + 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 *ProjectsLocationsAcceleratorTypesListCall) Context(ctx context.Context) *ProjectsLocationsAcceleratorTypesListCall { + 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 *ProjectsLocationsAcceleratorTypesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsAcceleratorTypesListCall) 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, "v1/{+parent}/acceleratorTypes") + 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 "tpu.projects.locations.acceleratorTypes.list" call. +// Exactly one of *ListAcceleratorTypesResponse or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *ListAcceleratorTypesResponse.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 *ProjectsLocationsAcceleratorTypesListCall) Do(opts ...googleapi.CallOption) (*ListAcceleratorTypesResponse, 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 := &ListAcceleratorTypesResponse{ + 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 accelerator types supported by this API.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/acceleratorTypes", + // "httpMethod": "GET", + // "id": "tpu.projects.locations.acceleratorTypes.list", + // "parameterOrder": [ + // "parent" + // ], + // "parameters": { + // "filter": { + // "description": "List filter.", + // "location": "query", + // "type": "string" + // }, + // "orderBy": { + // "description": "Sort results.", + // "location": "query", + // "type": "string" + // }, + // "pageSize": { + // "description": "The maximum number of items to return.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "pageToken": { + // "description": "The next_page_token value returned from a previous List request, if any.", + // "location": "query", + // "type": "string" + // }, + // "parent": { + // "description": "The parent resource name.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/acceleratorTypes", + // "response": { + // "$ref": "ListAcceleratorTypesResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// 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 *ProjectsLocationsAcceleratorTypesListCall) Pages(ctx context.Context, f func(*ListAcceleratorTypesResponse) 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 "tpu.projects.locations.nodes.create": type ProjectsLocationsNodesCreateCall struct { @@ -1244,7 +1709,7 @@ func (c *ProjectsLocationsNodesCreateCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+parent}/nodes") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/nodes") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("POST", urls, body) req.Header = reqHeaders @@ -1293,7 +1758,7 @@ func (c *ProjectsLocationsNodesCreateCall) Do(opts ...googleapi.CallOption) (*Op return ret, nil // { // "description": "Creates a node.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes", // "httpMethod": "POST", // "id": "tpu.projects.locations.nodes.create", // "parameterOrder": [ @@ -1313,7 +1778,7 @@ func (c *ProjectsLocationsNodesCreateCall) Do(opts ...googleapi.CallOption) (*Op // "type": "string" // } // }, - // "path": "v1alpha1/{+parent}/nodes", + // "path": "v1/{+parent}/nodes", // "request": { // "$ref": "Node" // }, @@ -1377,7 +1842,7 @@ 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) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("DELETE", urls, body) req.Header = reqHeaders @@ -1426,7 +1891,7 @@ func (c *ProjectsLocationsNodesDeleteCall) Do(opts ...googleapi.CallOption) (*Op return ret, nil // { // "description": "Deletes a node.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}", // "httpMethod": "DELETE", // "id": "tpu.projects.locations.nodes.delete", // "parameterOrder": [ @@ -1441,7 +1906,7 @@ func (c *ProjectsLocationsNodesDeleteCall) Do(opts ...googleapi.CallOption) (*Op // "type": "string" // } // }, - // "path": "v1alpha1/{+name}", + // "path": "v1/{+name}", // "response": { // "$ref": "Operation" // }, @@ -1516,7 +1981,7 @@ func (c *ProjectsLocationsNodesGetCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("GET", urls, body) req.Header = reqHeaders @@ -1565,7 +2030,7 @@ func (c *ProjectsLocationsNodesGetCall) Do(opts ...googleapi.CallOption) (*Node, return ret, nil // { // "description": "Gets the details of a node.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}", // "httpMethod": "GET", // "id": "tpu.projects.locations.nodes.get", // "parameterOrder": [ @@ -1580,7 +2045,7 @@ func (c *ProjectsLocationsNodesGetCall) Do(opts ...googleapi.CallOption) (*Node, // "type": "string" // } // }, - // "path": "v1alpha1/{+name}", + // "path": "v1/{+name}", // "response": { // "$ref": "Node" // }, @@ -1669,7 +2134,7 @@ func (c *ProjectsLocationsNodesListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+parent}/nodes") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/nodes") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("GET", urls, body) req.Header = reqHeaders @@ -1718,7 +2183,7 @@ func (c *ProjectsLocationsNodesListCall) Do(opts ...googleapi.CallOption) (*List return ret, nil // { // "description": "Lists nodes.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes", // "httpMethod": "GET", // "id": "tpu.projects.locations.nodes.list", // "parameterOrder": [ @@ -1744,7 +2209,7 @@ func (c *ProjectsLocationsNodesListCall) Do(opts ...googleapi.CallOption) (*List // "type": "string" // } // }, - // "path": "v1alpha1/{+parent}/nodes", + // "path": "v1/{+parent}/nodes", // "response": { // "$ref": "ListNodesResponse" // }, @@ -1833,7 +2298,7 @@ func (c *ProjectsLocationsNodesReimageCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}:reimage") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:reimage") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("POST", urls, body) req.Header = reqHeaders @@ -1882,7 +2347,7 @@ func (c *ProjectsLocationsNodesReimageCall) Do(opts ...googleapi.CallOption) (*O return ret, nil // { // "description": "Reimages a node's OS.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:reimage", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:reimage", // "httpMethod": "POST", // "id": "tpu.projects.locations.nodes.reimage", // "parameterOrder": [ @@ -1897,7 +2362,7 @@ func (c *ProjectsLocationsNodesReimageCall) Do(opts ...googleapi.CallOption) (*O // "type": "string" // } // }, - // "path": "v1alpha1/{+name}:reimage", + // "path": "v1/{+name}:reimage", // "request": { // "$ref": "ReimageNodeRequest" // }, @@ -1968,7 +2433,7 @@ func (c *ProjectsLocationsNodesResetCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}:reset") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:reset") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("POST", urls, body) req.Header = reqHeaders @@ -2017,7 +2482,7 @@ func (c *ProjectsLocationsNodesResetCall) Do(opts ...googleapi.CallOption) (*Ope return ret, nil // { // "description": "Resets a node, which stops and starts the VM.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:reset", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:reset", // "httpMethod": "POST", // "id": "tpu.projects.locations.nodes.reset", // "parameterOrder": [ @@ -2032,7 +2497,7 @@ func (c *ProjectsLocationsNodesResetCall) Do(opts ...googleapi.CallOption) (*Ope // "type": "string" // } // }, - // "path": "v1alpha1/{+name}:reset", + // "path": "v1/{+name}:reset", // "request": { // "$ref": "ResetNodeRequest" // }, @@ -2103,7 +2568,7 @@ func (c *ProjectsLocationsNodesStartCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}:start") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:start") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("POST", urls, body) req.Header = reqHeaders @@ -2152,7 +2617,7 @@ func (c *ProjectsLocationsNodesStartCall) Do(opts ...googleapi.CallOption) (*Ope return ret, nil // { // "description": "Starts a node.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:start", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:start", // "httpMethod": "POST", // "id": "tpu.projects.locations.nodes.start", // "parameterOrder": [ @@ -2167,7 +2632,7 @@ func (c *ProjectsLocationsNodesStartCall) Do(opts ...googleapi.CallOption) (*Ope // "type": "string" // } // }, - // "path": "v1alpha1/{+name}:start", + // "path": "v1/{+name}:start", // "request": { // "$ref": "StartNodeRequest" // }, @@ -2238,7 +2703,7 @@ func (c *ProjectsLocationsNodesStopCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}:stop") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:stop") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("POST", urls, body) req.Header = reqHeaders @@ -2287,7 +2752,7 @@ func (c *ProjectsLocationsNodesStopCall) Do(opts ...googleapi.CallOption) (*Oper return ret, nil // { // "description": "Stops a node.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:stop", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:stop", // "httpMethod": "POST", // "id": "tpu.projects.locations.nodes.stop", // "parameterOrder": [ @@ -2302,7 +2767,7 @@ func (c *ProjectsLocationsNodesStopCall) Do(opts ...googleapi.CallOption) (*Oper // "type": "string" // } // }, - // "path": "v1alpha1/{+name}:stop", + // "path": "v1/{+name}:stop", // "request": { // "$ref": "StopNodeRequest" // }, @@ -2383,7 +2848,7 @@ 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) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}:cancel") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:cancel") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("POST", urls, body) req.Header = reqHeaders @@ -2432,7 +2897,7 @@ func (c *ProjectsLocationsOperationsCancelCall) Do(opts ...googleapi.CallOption) return ret, nil // { // "description": "Starts asynchronous cancellation on a long-running operation. The server\nmakes a best effort to cancel the operation, but success is not\nguaranteed. If the server doesn't support this method, it returns\n`google.rpc.Code.UNIMPLEMENTED`. Clients can use\nOperations.GetOperation or\nother methods to check whether the cancellation succeeded or whether the\noperation completed despite cancellation. On successful cancellation,\nthe operation is not deleted; instead, it becomes an operation with\nan Operation.error value with a google.rpc.Status.code of 1,\ncorresponding to `Code.CANCELLED`.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}:cancel", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}:cancel", // "httpMethod": "POST", // "id": "tpu.projects.locations.operations.cancel", // "parameterOrder": [ @@ -2447,7 +2912,7 @@ func (c *ProjectsLocationsOperationsCancelCall) Do(opts ...googleapi.CallOption) // "type": "string" // } // }, - // "path": "v1alpha1/{+name}:cancel", + // "path": "v1/{+name}:cancel", // "response": { // "$ref": "Empty" // }, @@ -2514,7 +2979,7 @@ 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) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("DELETE", urls, body) req.Header = reqHeaders @@ -2563,7 +3028,7 @@ func (c *ProjectsLocationsOperationsDeleteCall) Do(opts ...googleapi.CallOption) return ret, nil // { // "description": "Deletes a long-running operation. This method indicates that the client is\nno longer interested in the operation result. It does not cancel the\noperation. If the server doesn't support this method, it returns\n`google.rpc.Code.UNIMPLEMENTED`.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}", // "httpMethod": "DELETE", // "id": "tpu.projects.locations.operations.delete", // "parameterOrder": [ @@ -2578,7 +3043,7 @@ func (c *ProjectsLocationsOperationsDeleteCall) Do(opts ...googleapi.CallOption) // "type": "string" // } // }, - // "path": "v1alpha1/{+name}", + // "path": "v1/{+name}", // "response": { // "$ref": "Empty" // }, @@ -2657,7 +3122,7 @@ func (c *ProjectsLocationsOperationsGetCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("GET", urls, body) req.Header = reqHeaders @@ -2706,7 +3171,7 @@ func (c *ProjectsLocationsOperationsGetCall) Do(opts ...googleapi.CallOption) (* return ret, nil // { // "description": "Gets the latest state of a long-running operation. Clients can use this\nmethod to poll the operation result at intervals as recommended by the API\nservice.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}", // "httpMethod": "GET", // "id": "tpu.projects.locations.operations.get", // "parameterOrder": [ @@ -2721,7 +3186,7 @@ func (c *ProjectsLocationsOperationsGetCall) Do(opts ...googleapi.CallOption) (* // "type": "string" // } // }, - // "path": "v1alpha1/{+name}", + // "path": "v1/{+name}", // "response": { // "$ref": "Operation" // }, @@ -2833,7 +3298,7 @@ func (c *ProjectsLocationsOperationsListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}/operations") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}/operations") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("GET", urls, body) req.Header = reqHeaders @@ -2882,7 +3347,7 @@ func (c *ProjectsLocationsOperationsListCall) Do(opts ...googleapi.CallOption) ( return ret, nil // { // "description": "Lists operations that match the specified filter in the request. If the\nserver doesn't support this method, it returns `UNIMPLEMENTED`.\n\nNOTE: the `name` binding allows API services to override the binding\nto use different resource name schemes, such as `users/*/operations`. To\noverride the binding, API services can add a binding such as\n`\"/v1/{name=users/*}/operations\"` to their service configuration.\nFor backwards compatibility, the default name includes the operations\ncollection id, however overriding users must ensure the name binding\nis the parent resource, without the operations collection id.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/operations", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/operations", // "httpMethod": "GET", // "id": "tpu.projects.locations.operations.list", // "parameterOrder": [ @@ -2913,7 +3378,7 @@ func (c *ProjectsLocationsOperationsListCall) Do(opts ...googleapi.CallOption) ( // "type": "string" // } // }, - // "path": "v1alpha1/{+name}/operations", + // "path": "v1/{+name}/operations", // "response": { // "$ref": "ListOperationsResponse" // }, @@ -3009,7 +3474,7 @@ func (c *ProjectsLocationsTensorflowVersionsGetCall) doRequest(alt string) (*htt } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+name}") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("GET", urls, body) req.Header = reqHeaders @@ -3058,7 +3523,7 @@ func (c *ProjectsLocationsTensorflowVersionsGetCall) Do(opts ...googleapi.CallOp return ret, nil // { // "description": "Gets TensorFlow Version.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/tensorflowVersions/{tensorflowVersionsId}", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/tensorflowVersions/{tensorflowVersionsId}", // "httpMethod": "GET", // "id": "tpu.projects.locations.tensorflowVersions.get", // "parameterOrder": [ @@ -3073,7 +3538,7 @@ func (c *ProjectsLocationsTensorflowVersionsGetCall) Do(opts ...googleapi.CallOp // "type": "string" // } // }, - // "path": "v1alpha1/{+name}", + // "path": "v1/{+name}", // "response": { // "$ref": "TensorFlowVersion" // }, @@ -3095,7 +3560,7 @@ type ProjectsLocationsTensorflowVersionsListCall struct { header_ http.Header } -// List: Lists TensorFlow versions supported by this API. +// List: List TensorFlow versions supported by this API. func (r *ProjectsLocationsTensorflowVersionsService) List(parent string) *ProjectsLocationsTensorflowVersionsListCall { c := &ProjectsLocationsTensorflowVersionsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.parent = parent @@ -3174,7 +3639,7 @@ func (c *ProjectsLocationsTensorflowVersionsListCall) doRequest(alt string) (*ht } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1alpha1/{+parent}/tensorflowVersions") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/tensorflowVersions") urls += "?" + c.urlParams_.Encode() req, _ := http.NewRequest("GET", urls, body) req.Header = reqHeaders @@ -3222,8 +3687,8 @@ func (c *ProjectsLocationsTensorflowVersionsListCall) Do(opts ...googleapi.CallO } return ret, nil // { - // "description": "Lists TensorFlow versions supported by this API.", - // "flatPath": "v1alpha1/projects/{projectsId}/locations/{locationsId}/tensorflowVersions", + // "description": "List TensorFlow versions supported by this API.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/tensorflowVersions", // "httpMethod": "GET", // "id": "tpu.projects.locations.tensorflowVersions.list", // "parameterOrder": [ @@ -3259,7 +3724,7 @@ func (c *ProjectsLocationsTensorflowVersionsListCall) Do(opts ...googleapi.CallO // "type": "string" // } // }, - // "path": "v1alpha1/{+parent}/tensorflowVersions", + // "path": "v1/{+parent}/tensorflowVersions", // "response": { // "$ref": "ListTensorFlowVersionsResponse" // }, diff --git a/vendor/google.golang.org/grpc/BUILD b/vendor/google.golang.org/grpc/BUILD index b266ac7de56..99e7a8d89d9 100644 --- a/vendor/google.golang.org/grpc/BUILD +++ b/vendor/google.golang.org/grpc/BUILD @@ -63,7 +63,7 @@ filegroup( "//vendor/google.golang.org/grpc/codes:all-srcs", "//vendor/google.golang.org/grpc/connectivity:all-srcs", "//vendor/google.golang.org/grpc/credentials:all-srcs", - "//vendor/google.golang.org/grpc/grpclb/grpc_lb_v1:all-srcs", + "//vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/messages:all-srcs", "//vendor/google.golang.org/grpc/grpclog:all-srcs", "//vendor/google.golang.org/grpc/health/grpc_health_v1:all-srcs", "//vendor/google.golang.org/grpc/internal:all-srcs", diff --git a/vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/doc.go b/vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/doc.go deleted file mode 100644 index aba962840c8..00000000000 --- a/vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/doc.go +++ /dev/null @@ -1,21 +0,0 @@ -/* - * - * Copyright 2017 gRPC 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 grpc_lb_v1 is the parent package of all gRPC loadbalancer -// message and service protobuf definitions. -package grpc_lb_v1 diff --git a/vendor/k8s.io/kube-openapi/pkg/handler/handler.go b/vendor/k8s.io/kube-openapi/pkg/handler/handler.go index 63c6f825bdb..c4bbc0bff34 100644 --- a/vendor/k8s.io/kube-openapi/pkg/handler/handler.go +++ b/vendor/k8s.io/kube-openapi/pkg/handler/handler.go @@ -58,7 +58,6 @@ type OpenAPIService struct { // rwMutex protects All members of this service. rwMutex sync.RWMutex - orgSpec *spec.Swagger lastModified time.Time specBytes []byte @@ -161,7 +160,6 @@ func (o *OpenAPIService) getSwaggerPbGzBytes() ([]byte, string, time.Time) { } func (o *OpenAPIService) UpdateSpec(openapiSpec *spec.Swagger) (err error) { - orgSpec := openapiSpec specBytes, err := json.MarshalIndent(openapiSpec, " ", " ") if err != nil { return err @@ -181,7 +179,6 @@ func (o *OpenAPIService) UpdateSpec(openapiSpec *spec.Swagger) (err error) { o.rwMutex.Lock() defer o.rwMutex.Unlock() - o.orgSpec = orgSpec o.specBytes = specBytes o.specPb = specPb o.specPbGz = specPbGz diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/BUILD b/vendor/k8s.io/kube-openapi/pkg/util/proto/BUILD index 4a1d70b70d7..1dc6f53a0a8 100644 --- a/vendor/k8s.io/kube-openapi/pkg/util/proto/BUILD +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/BUILD @@ -26,6 +26,7 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", + "//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:all-srcs", "//vendor/k8s.io/kube-openapi/pkg/util/proto/validation:all-srcs", ], tags = ["automanaged"], diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go index 61dbf4fc0e4..a57dcd363f6 100644 --- a/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go @@ -21,8 +21,8 @@ import ( "sort" "strings" - openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" - yaml "gopkg.in/yaml.v2" + "github.com/googleapis/gnostic/OpenAPIv2" + "gopkg.in/yaml.v2" ) func newSchemaError(path *Path, format string, a ...interface{}) error { @@ -126,12 +126,17 @@ func (d *Definitions) parseMap(s *openapi_v2.Schema, path *Path) (Schema, error) if len(s.GetType().GetValue()) != 0 && s.GetType().GetValue()[0] != object { return nil, newSchemaError(path, "invalid object type") } + var sub Schema if s.GetAdditionalProperties().GetSchema() == nil { - return nil, newSchemaError(path, "invalid object doesn't have additional properties") - } - sub, err := d.ParseSchema(s.GetAdditionalProperties().GetSchema(), path) - if err != nil { - return nil, err + sub = &Arbitrary{ + BaseSchema: d.parseBaseSchema(s, path), + } + } else { + var err error + sub, err = d.ParseSchema(s.GetAdditionalProperties().GetSchema(), path) + if err != nil { + return nil, err + } } return &Map{ BaseSchema: d.parseBaseSchema(s, path), @@ -148,12 +153,10 @@ func (d *Definitions) parsePrimitive(s *openapi_v2.Schema, path *Path) (Schema, t = s.GetType().GetValue()[0] } switch t { - case String: - case Number: - case Integer: - case Boolean: - case "": // Some models are completely empty, and can be safely ignored. - // Do nothing + case String: // do nothing + case Number: // do nothing + case Integer: // do nothing + case Boolean: // do nothing default: return nil, newSchemaError(path, "Unknown primitive type: %q", t) } @@ -219,27 +222,38 @@ func (d *Definitions) parseArbitrary(s *openapi_v2.Schema, path *Path) (Schema, // ParseSchema creates a walkable Schema from an openapi schema. While // this function is public, it doesn't leak through the interface. func (d *Definitions) ParseSchema(s *openapi_v2.Schema, path *Path) (Schema, error) { - objectTypes := s.GetType().GetValue() - if len(objectTypes) == 1 { - t := objectTypes[0] - switch t { - case object: - return d.parseMap(s, path) - case array: - return d.parseArray(s, path) - } - - } if s.GetXRef() != "" { return d.parseReference(s, path) } - if s.GetProperties() != nil { - return d.parseKind(s, path) + objectTypes := s.GetType().GetValue() + switch len(objectTypes) { + case 0: + // in the OpenAPI schema served by older k8s versions, object definitions created from structs did not include + // the type:object property (they only included the "properties" property), so we need to handle this case + if s.GetProperties() != nil { + return d.parseKind(s, path) + } else { + // Definition has no type and no properties. Treat it as an arbitrary value + // TODO: what if it has additionalProperties or patternProperties? + return d.parseArbitrary(s, path) + } + case 1: + t := objectTypes[0] + switch t { + case object: + if s.GetProperties() != nil { + return d.parseKind(s, path) + } else { + return d.parseMap(s, path) + } + case array: + return d.parseArray(s, path) + } + return d.parsePrimitive(s, path) + default: + // the OpenAPI generator never generates (nor it ever did in the past) OpenAPI type definitions with multiple types + return nil, newSchemaError(path, "definitions with multiple types aren't supported") } - if len(objectTypes) == 0 || (len(objectTypes) == 1 && objectTypes[0] == "") { - return d.parseArbitrary(s, path) - } - return d.parsePrimitive(s, path) } // LookupModel is public through the interface of Models. It diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go index b48e62c3bf9..f26b5ef8810 100644 --- a/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go @@ -59,7 +59,7 @@ type SchemaVisitor interface { } // SchemaVisitorArbitrary is an additional visitor interface which handles -// arbitrary types. For backwards compatability, it's a separate interface +// arbitrary types. For backwards compatibility, it's a separate interface // which is checked for at runtime. type SchemaVisitorArbitrary interface { SchemaVisitor diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/testing/BUILD b/vendor/k8s.io/kube-openapi/pkg/util/proto/testing/BUILD new file mode 100644 index 00000000000..33d54ccd027 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/testing/BUILD @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["openapi.go"], + importpath = "k8s.io/kube-openapi/pkg/util/proto/testing", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", + "//vendor/github.com/googleapis/gnostic/compiler:go_default_library", + "//vendor/gopkg.in/yaml.v2: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/k8s.io/kube-openapi/pkg/util/proto/testing/openapi.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/testing/openapi.go new file mode 100644 index 00000000000..bc280a1982d --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/testing/openapi.go @@ -0,0 +1,68 @@ +/* +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 ( + "io/ioutil" + "os" + "sync" + + yaml "gopkg.in/yaml.v2" + + "github.com/googleapis/gnostic/OpenAPIv2" + "github.com/googleapis/gnostic/compiler" +) + +// Fake opens and returns a openapi swagger from a file Path. It will +// parse only once and then return the same copy everytime. +type Fake struct { + Path string + + once sync.Once + document *openapi_v2.Document + err error +} + +// OpenAPISchema returns the openapi document and a potential error. +func (f *Fake) OpenAPISchema() (*openapi_v2.Document, error) { + f.once.Do(func() { + _, err := os.Stat(f.Path) + if err != nil { + f.err = err + return + } + spec, err := ioutil.ReadFile(f.Path) + if err != nil { + f.err = err + return + } + var info yaml.MapSlice + err = yaml.Unmarshal(spec, &info) + if err != nil { + f.err = err + return + } + f.document, f.err = openapi_v2.NewDocument(info, compiler.NewContext("$root", nil)) + }) + return f.document, f.err +} + +type Empty struct{} + +func (Empty) OpenAPISchema() (*openapi_v2.Document, error) { + return nil, nil +}