mirror of https://github.com/k3s-io/k3s
Merge branch 'master' into keymutex
commit
e72b32558c
|
@ -1555,8 +1555,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Comment": "v4.0.0-3-g36442dbdb58521",
|
"Comment": "v4.1.0-11-gd4020504c68b6b",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/exponent-io/jsonpath",
|
"ImportPath": "github.com/exponent-io/jsonpath",
|
||||||
|
@ -4120,6 +4120,10 @@
|
||||||
"ImportPath": "k8s.io/utils/nsenter",
|
"ImportPath": "k8s.io/utils/nsenter",
|
||||||
"Rev": "ed37f7428a91fc2a81070808937195dcd46d320e"
|
"Rev": "ed37f7428a91fc2a81070808937195dcd46d320e"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "k8s.io/utils/path",
|
||||||
|
"Rev": "ed37f7428a91fc2a81070808937195dcd46d320e"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/utils/pointer",
|
"ImportPath": "k8s.io/utils/pointer",
|
||||||
"Rev": "ed37f7428a91fc2a81070808937195dcd46d320e"
|
"Rev": "ed37f7428a91fc2a81070808937195dcd46d320e"
|
||||||
|
|
|
@ -116633,6 +116633,216 @@ third-party archives.
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/k8s.io/utils/path 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/utils/LICENSE 3b83ef96387f14655fc854ddc3c6bd57
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
= vendor/k8s.io/utils/pointer licensed under: =
|
= vendor/k8s.io/utils/pointer licensed under: =
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ REGISTRY ?= staging-k8s.gcr.io
|
||||||
IMAGE ?= $(REGISTRY)/debian-base
|
IMAGE ?= $(REGISTRY)/debian-base
|
||||||
BUILD_IMAGE ?= debian-build
|
BUILD_IMAGE ?= debian-build
|
||||||
|
|
||||||
TAG ?= 0.4.0
|
TAG ?= 0.4.1
|
||||||
|
|
||||||
TAR_FILE ?= rootfs.tar
|
TAR_FILE ?= rootfs.tar
|
||||||
ARCH?=amd64
|
ARCH?=amd64
|
||||||
|
|
|
@ -19,12 +19,12 @@
|
||||||
|
|
||||||
REGISTRY?=staging-k8s.gcr.io
|
REGISTRY?=staging-k8s.gcr.io
|
||||||
IMAGE?=$(REGISTRY)/debian-hyperkube-base
|
IMAGE?=$(REGISTRY)/debian-hyperkube-base
|
||||||
TAG=0.12.0
|
TAG=0.12.1
|
||||||
ARCH?=amd64
|
ARCH?=amd64
|
||||||
ALL_ARCH = amd64 arm arm64 ppc64le s390x
|
ALL_ARCH = amd64 arm arm64 ppc64le s390x
|
||||||
CACHEBUST?=1
|
CACHEBUST?=1
|
||||||
|
|
||||||
BASEIMAGE=k8s.gcr.io/debian-base-$(ARCH):0.4.0
|
BASEIMAGE=k8s.gcr.io/debian-base-$(ARCH):0.4.1
|
||||||
CNI_VERSION=v0.6.0
|
CNI_VERSION=v0.6.0
|
||||||
|
|
||||||
TEMP_DIR:=$(shell mktemp -d)
|
TEMP_DIR:=$(shell mktemp -d)
|
||||||
|
|
|
@ -16,12 +16,12 @@
|
||||||
|
|
||||||
REGISTRY?="staging-k8s.gcr.io"
|
REGISTRY?="staging-k8s.gcr.io"
|
||||||
IMAGE=$(REGISTRY)/debian-iptables
|
IMAGE=$(REGISTRY)/debian-iptables
|
||||||
TAG?=v11.0
|
TAG?=v11.0.1
|
||||||
ARCH?=amd64
|
ARCH?=amd64
|
||||||
ALL_ARCH = amd64 arm arm64 ppc64le s390x
|
ALL_ARCH = amd64 arm arm64 ppc64le s390x
|
||||||
TEMP_DIR:=$(shell mktemp -d)
|
TEMP_DIR:=$(shell mktemp -d)
|
||||||
|
|
||||||
BASEIMAGE?=k8s.gcr.io/debian-base-$(ARCH):0.4.0
|
BASEIMAGE?=k8s.gcr.io/debian-base-$(ARCH):0.4.1
|
||||||
|
|
||||||
# This option is for running docker manifest command
|
# This option is for running docker manifest command
|
||||||
export DOCKER_CLI_EXPERIMENTAL := enabled
|
export DOCKER_CLI_EXPERIMENTAL := enabled
|
||||||
|
|
|
@ -33,7 +33,7 @@ rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["replicationcontrollers/scale"]
|
resources: ["replicationcontrollers/scale"]
|
||||||
verbs: ["get", "update"]
|
verbs: ["get", "update"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions","apps"]
|
||||||
resources: ["deployments/scale", "replicasets/scale"]
|
resources: ["deployments/scale", "replicasets/scale"]
|
||||||
verbs: ["get", "update"]
|
verbs: ["get", "update"]
|
||||||
# Remove the configmaps rule once below issue is fixed:
|
# Remove the configmaps rule once below issue is fixed:
|
||||||
|
@ -85,7 +85,7 @@ spec:
|
||||||
fsGroup: 65534
|
fsGroup: 65534
|
||||||
containers:
|
containers:
|
||||||
- name: autoscaler
|
- name: autoscaler
|
||||||
image: k8s.gcr.io/cluster-proportional-autoscaler-amd64:1.3.0
|
image: k8s.gcr.io/cluster-proportional-autoscaler-amd64:1.4.0
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: "20m"
|
cpu: "20m"
|
||||||
|
|
|
@ -22,6 +22,7 @@ go_library(
|
||||||
"//pkg/kubelet/qos:go_default_library",
|
"//pkg/kubelet/qos:go_default_library",
|
||||||
"//pkg/master/ports:go_default_library",
|
"//pkg/master/ports:go_default_library",
|
||||||
"//pkg/proxy:go_default_library",
|
"//pkg/proxy:go_default_library",
|
||||||
|
"//pkg/proxy/apis:go_default_library",
|
||||||
"//pkg/proxy/apis/config:go_default_library",
|
"//pkg/proxy/apis/config:go_default_library",
|
||||||
"//pkg/proxy/apis/config/scheme:go_default_library",
|
"//pkg/proxy/apis/config/scheme:go_default_library",
|
||||||
"//pkg/proxy/apis/config/validation:go_default_library",
|
"//pkg/proxy/apis/config/validation:go_default_library",
|
||||||
|
|
|
@ -53,6 +53,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/kubelet/qos"
|
"k8s.io/kubernetes/pkg/kubelet/qos"
|
||||||
"k8s.io/kubernetes/pkg/master/ports"
|
"k8s.io/kubernetes/pkg/master/ports"
|
||||||
"k8s.io/kubernetes/pkg/proxy"
|
"k8s.io/kubernetes/pkg/proxy"
|
||||||
|
"k8s.io/kubernetes/pkg/proxy/apis"
|
||||||
kubeproxyconfig "k8s.io/kubernetes/pkg/proxy/apis/config"
|
kubeproxyconfig "k8s.io/kubernetes/pkg/proxy/apis/config"
|
||||||
"k8s.io/kubernetes/pkg/proxy/apis/config/scheme"
|
"k8s.io/kubernetes/pkg/proxy/apis/config/scheme"
|
||||||
"k8s.io/kubernetes/pkg/proxy/apis/config/validation"
|
"k8s.io/kubernetes/pkg/proxy/apis/config/validation"
|
||||||
|
@ -583,7 +584,7 @@ func (s *ProxyServer) Run() error {
|
||||||
|
|
||||||
informerFactory := informers.NewSharedInformerFactoryWithOptions(s.Client, s.ConfigSyncPeriod,
|
informerFactory := informers.NewSharedInformerFactoryWithOptions(s.Client, s.ConfigSyncPeriod,
|
||||||
informers.WithTweakListOptions(func(options *v1meta.ListOptions) {
|
informers.WithTweakListOptions(func(options *v1meta.ListOptions) {
|
||||||
options.LabelSelector = "!service.kubernetes.io/service-proxy-name"
|
options.LabelSelector = "!" + apis.LabelServiceProxyName
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Create configs (i.e. Watches for Services and Endpoints)
|
// Create configs (i.e. Watches for Services and Endpoints)
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
"AllowedPrefixes": [
|
"AllowedPrefixes": [
|
||||||
"k8s.io/utils/exec",
|
"k8s.io/utils/exec",
|
||||||
"k8s.io/utils/integer",
|
"k8s.io/utils/integer",
|
||||||
|
"k8s.io/utils/path",
|
||||||
"k8s.io/utils/pointer"
|
"k8s.io/utils/pointer"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -77,7 +78,6 @@
|
||||||
"k8s.io/kubernetes/pkg/scheduler/util",
|
"k8s.io/kubernetes/pkg/scheduler/util",
|
||||||
"k8s.io/kubernetes/pkg/security/apparmor",
|
"k8s.io/kubernetes/pkg/security/apparmor",
|
||||||
"k8s.io/kubernetes/pkg/serviceaccount",
|
"k8s.io/kubernetes/pkg/serviceaccount",
|
||||||
"k8s.io/kubernetes/pkg/util/file",
|
|
||||||
"k8s.io/kubernetes/pkg/util/hash",
|
"k8s.io/kubernetes/pkg/util/hash",
|
||||||
"k8s.io/kubernetes/pkg/util/initsystem",
|
"k8s.io/kubernetes/pkg/util/initsystem",
|
||||||
"k8s.io/kubernetes/pkg/util/ipvs",
|
"k8s.io/kubernetes/pkg/util/ipvs",
|
||||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
@ -38,6 +37,7 @@ import (
|
||||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
|
@ -68,17 +68,6 @@ var (
|
||||||
|
|
||||||
`)
|
`)
|
||||||
|
|
||||||
notReadyToJoinControPlaneTemp = template.Must(template.New("join").Parse(dedent.Dedent(`
|
|
||||||
One or more conditions for hosting a new control plane instance is not satisfied.
|
|
||||||
|
|
||||||
{{.Error}}
|
|
||||||
|
|
||||||
Please ensure that:
|
|
||||||
* The cluster has a stable controlPlaneEndpoint address.
|
|
||||||
* The certificates that must be shared among control plane instances are provided.
|
|
||||||
|
|
||||||
`)))
|
|
||||||
|
|
||||||
joinControPlaneDoneTemp = template.Must(template.New("join").Parse(dedent.Dedent(`
|
joinControPlaneDoneTemp = template.Must(template.New("join").Parse(dedent.Dedent(`
|
||||||
This node has joined the cluster and a new control plane instance was created:
|
This node has joined the cluster and a new control plane instance was created:
|
||||||
|
|
||||||
|
@ -210,9 +199,7 @@ func NewCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command {
|
||||||
AddJoinConfigFlags(cmd.Flags(), joinOptions.externalcfg)
|
AddJoinConfigFlags(cmd.Flags(), joinOptions.externalcfg)
|
||||||
AddJoinOtherFlags(cmd.Flags(), &joinOptions.cfgPath, &joinOptions.ignorePreflightErrors, &joinOptions.controlPlane, &joinOptions.token)
|
AddJoinOtherFlags(cmd.Flags(), &joinOptions.cfgPath, &joinOptions.ignorePreflightErrors, &joinOptions.controlPlane, &joinOptions.token)
|
||||||
|
|
||||||
// initialize the workflow runner with the list of phases
|
joinRunner.AppendPhase(phases.NewPreflightJoinPhase())
|
||||||
// TODO: append phases here like so:
|
|
||||||
// joinRunner.AppendPhase(phases.NewPreflightMasterPhase())
|
|
||||||
|
|
||||||
// sets the data builder function, that will be used by the runner
|
// sets the data builder function, that will be used by the runner
|
||||||
// both when running the entire workflow or single phases
|
// both when running the entire workflow or single phases
|
||||||
|
@ -445,14 +432,6 @@ func (j *joinData) OutputWriter() io.Writer {
|
||||||
|
|
||||||
// Run executes worker node provisioning and tries to join an existing cluster.
|
// Run executes worker node provisioning and tries to join an existing cluster.
|
||||||
func (j *joinData) Run() error {
|
func (j *joinData) Run() error {
|
||||||
fmt.Println("[preflight] Running pre-flight checks")
|
|
||||||
|
|
||||||
// Start with general checks
|
|
||||||
klog.V(1).Infoln("[preflight] Running general checks")
|
|
||||||
if err := preflight.RunJoinNodeChecks(utilsexec.New(), j.cfg, j.ignorePreflightErrors); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the init configuration based on the join configuration.
|
// Fetch the init configuration based on the join configuration.
|
||||||
// TODO: individual phases should call these:
|
// TODO: individual phases should call these:
|
||||||
// - phases that need initCfg should call joinData.InitCfg().
|
// - phases that need initCfg should call joinData.InitCfg().
|
||||||
|
@ -465,35 +444,7 @@ func (j *joinData) Run() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue with more specific checks based on the init configuration
|
|
||||||
klog.V(1).Infoln("[preflight] Running configuration dependant checks")
|
|
||||||
if err := preflight.RunOptionalJoinNodeChecks(utilsexec.New(), &initCfg.ClusterConfiguration, j.ignorePreflightErrors); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if j.cfg.ControlPlane != nil {
|
if j.cfg.ControlPlane != nil {
|
||||||
// Checks if the cluster configuration supports
|
|
||||||
// joining a new control plane instance and if all the necessary certificates are provided
|
|
||||||
if err := j.CheckIfReadyForAdditionalControlPlane(&initCfg.ClusterConfiguration); err != nil {
|
|
||||||
// outputs the not ready for hosting a new control plane instance message
|
|
||||||
ctx := map[string]string{
|
|
||||||
"Error": err.Error(),
|
|
||||||
}
|
|
||||||
|
|
||||||
var msg bytes.Buffer
|
|
||||||
notReadyToJoinControPlaneTemp.Execute(&msg, ctx)
|
|
||||||
return errors.New(msg.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// run kubeadm init preflight checks for checking all the prequisites
|
|
||||||
fmt.Println("[join] Running pre-flight checks before initializing the new control plane instance")
|
|
||||||
preflight.RunInitMasterChecks(utilsexec.New(), initCfg, j.ignorePreflightErrors)
|
|
||||||
|
|
||||||
fmt.Println("[join] Pulling control-plane images")
|
|
||||||
if err := preflight.RunPullImagesCheck(utilsexec.New(), initCfg, j.ignorePreflightErrors); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Prepares the node for hosting a new control plane instance by writing necessary
|
// Prepares the node for hosting a new control plane instance by writing necessary
|
||||||
// kubeconfig files, and static pod manifests
|
// kubeconfig files, and static pod manifests
|
||||||
if err := j.PrepareForHostingControlPlane(initCfg); err != nil {
|
if err := j.PrepareForHostingControlPlane(initCfg); err != nil {
|
||||||
|
@ -539,22 +490,6 @@ func (j *joinData) Run() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckIfReadyForAdditionalControlPlane ensures that the cluster is in a state that supports
|
|
||||||
// joining an additional control plane instance and if the node is ready to join
|
|
||||||
func (j *joinData) CheckIfReadyForAdditionalControlPlane(cfg *kubeadmapi.ClusterConfiguration) error {
|
|
||||||
// blocks if the cluster was created without a stable control plane endpoint
|
|
||||||
if cfg.ControlPlaneEndpoint == "" {
|
|
||||||
return errors.New("unable to add a new control plane instance a cluster that doesn't have a stable controlPlaneEndpoint address")
|
|
||||||
}
|
|
||||||
|
|
||||||
// checks if the certificates that must be equal across contolplane instances are provided
|
|
||||||
if ret, err := certsphase.SharedCertificateExists(cfg); !ret {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrepareForHostingControlPlane makes all preparation activities require for a node hosting a new control plane instance
|
// PrepareForHostingControlPlane makes all preparation activities require for a node hosting a new control plane instance
|
||||||
func (j *joinData) PrepareForHostingControlPlane(initConfiguration *kubeadmapi.InitConfiguration) error {
|
func (j *joinData) PrepareForHostingControlPlane(initConfiguration *kubeadmapi.InitConfiguration) error {
|
||||||
|
|
||||||
|
|
|
@ -17,23 +17,43 @@ limitations under the License.
|
||||||
package phases
|
package phases
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/lithammer/dedent"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/klog"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||||
utilsexec "k8s.io/utils/exec"
|
utilsexec "k8s.io/utils/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
masterPreflightExample = normalizer.Examples(`
|
initPreflightExample = normalizer.Examples(`
|
||||||
# Run master pre-flight checks using a config file.
|
# Run master pre-flight checks using a config file.
|
||||||
kubeadm init phase preflight --config kubeadm-config.yml
|
kubeadm init phase preflight --config kubeadm-config.yml
|
||||||
`)
|
`)
|
||||||
|
joinPreflightExample = normalizer.Examples(`
|
||||||
|
# Run join pre-flight checks using a config file.
|
||||||
|
kubeadm join phase preflight --config kubeadm-config.yml
|
||||||
|
`)
|
||||||
|
|
||||||
|
notReadyToJoinControPlaneTemp = template.Must(template.New("join").Parse(dedent.Dedent(`
|
||||||
|
One or more conditions for hosting a new control plane instance is not satisfied.
|
||||||
|
|
||||||
|
{{.Error}}
|
||||||
|
|
||||||
|
Please ensure that:
|
||||||
|
* The cluster has a stable controlPlaneEndpoint address.
|
||||||
|
* The certificates that must be shared among control plane instances are provided.
|
||||||
|
|
||||||
|
`)))
|
||||||
)
|
)
|
||||||
|
|
||||||
// preflightMasterData defines the behavior that a runtime data struct passed to the PreflightMaster master phase
|
// preflightMasterData defines the behavior that a runtime data struct passed to the PreflightMaster master phase
|
||||||
|
@ -45,13 +65,19 @@ type preflightMasterData interface {
|
||||||
IgnorePreflightErrors() sets.String
|
IgnorePreflightErrors() sets.String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type preflightJoinData interface {
|
||||||
|
Cfg() *kubeadmapi.JoinConfiguration
|
||||||
|
InitCfg() (*kubeadmapi.InitConfiguration, error)
|
||||||
|
IgnorePreflightErrors() sets.String
|
||||||
|
}
|
||||||
|
|
||||||
// NewPreflightMasterPhase creates a kubeadm workflow phase that implements preflight checks for a new master node.
|
// NewPreflightMasterPhase creates a kubeadm workflow phase that implements preflight checks for a new master node.
|
||||||
func NewPreflightMasterPhase() workflow.Phase {
|
func NewPreflightMasterPhase() workflow.Phase {
|
||||||
return workflow.Phase{
|
return workflow.Phase{
|
||||||
Name: "preflight",
|
Name: "preflight",
|
||||||
Short: "Run master pre-flight checks",
|
Short: "Run master pre-flight checks",
|
||||||
Long: "Run master pre-flight checks, functionally equivalent to what implemented by kubeadm init.",
|
Long: "Run master pre-flight checks, functionally equivalent to what implemented by kubeadm init.",
|
||||||
Example: masterPreflightExample,
|
Example: initPreflightExample,
|
||||||
Run: runPreflightMaster,
|
Run: runPreflightMaster,
|
||||||
InheritFlags: []string{
|
InheritFlags: []string{
|
||||||
options.CfgPath,
|
options.CfgPath,
|
||||||
|
@ -60,6 +86,7 @@ func NewPreflightMasterPhase() workflow.Phase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(dmaiocchi): rename all instances of master to controlPlane in this file.
|
||||||
// runPreflightMaster executes preflight checks logic.
|
// runPreflightMaster executes preflight checks logic.
|
||||||
func runPreflightMaster(c workflow.RunData) error {
|
func runPreflightMaster(c workflow.RunData) error {
|
||||||
data, ok := c.(preflightMasterData)
|
data, ok := c.(preflightMasterData)
|
||||||
|
@ -85,3 +112,96 @@ func runPreflightMaster(c workflow.RunData) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewPreflightJoinPhase creates a kubeadm workflow phase that implements preflight checks for a new node join
|
||||||
|
func NewPreflightJoinPhase() workflow.Phase {
|
||||||
|
return workflow.Phase{
|
||||||
|
Name: "preflight",
|
||||||
|
Short: "Run join pre-flight checks",
|
||||||
|
Long: "Run join pre-flight checks, functionally equivalent to what is implemented by kubeadm join.",
|
||||||
|
Example: joinPreflightExample,
|
||||||
|
Run: runPreflightJoin,
|
||||||
|
InheritFlags: []string{
|
||||||
|
options.CfgPath,
|
||||||
|
options.IgnorePreflightErrors,
|
||||||
|
options.TLSBootstrapToken,
|
||||||
|
options.TokenStr,
|
||||||
|
options.ControlPlane,
|
||||||
|
options.APIServerAdvertiseAddress,
|
||||||
|
options.APIServerBindPort,
|
||||||
|
options.NodeCRISocket,
|
||||||
|
options.NodeName,
|
||||||
|
options.FileDiscovery,
|
||||||
|
options.TokenDiscovery,
|
||||||
|
options.TokenDiscoveryCAHash,
|
||||||
|
options.TokenDiscoverySkipCAHash,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// runPreflightJoin executes preflight checks logic.
|
||||||
|
func runPreflightJoin(c workflow.RunData) error {
|
||||||
|
j, ok := c.(preflightJoinData)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("preflight phase invoked with an invalid data struct")
|
||||||
|
}
|
||||||
|
// Start with general checks
|
||||||
|
klog.V(1).Infoln("[preflight] Running general checks")
|
||||||
|
if err := preflight.RunJoinNodeChecks(utilsexec.New(), j.Cfg(), j.IgnorePreflightErrors()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
initCfg, err := j.InitCfg()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue with more specific checks based on the init configuration
|
||||||
|
klog.V(1).Infoln("[preflight] Running configuration dependant checks")
|
||||||
|
if err := preflight.RunOptionalJoinNodeChecks(utilsexec.New(), &initCfg.ClusterConfiguration, j.IgnorePreflightErrors()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if j.Cfg().ControlPlane != nil {
|
||||||
|
// Checks if the cluster configuration supports
|
||||||
|
// joining a new control plane instance and if all the necessary certificates are provided
|
||||||
|
if err := checkIfReadyForAdditionalControlPlane(&initCfg.ClusterConfiguration); err != nil {
|
||||||
|
// outputs the not ready for hosting a new control plane instance message
|
||||||
|
ctx := map[string]string{
|
||||||
|
"Error": err.Error(),
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg bytes.Buffer
|
||||||
|
notReadyToJoinControPlaneTemp.Execute(&msg, ctx)
|
||||||
|
return errors.New(msg.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// run kubeadm init preflight checks for checking all the prequisites
|
||||||
|
fmt.Println("[preflight] Running pre-flight checks before initializing the new control plane instance")
|
||||||
|
if err := preflight.RunInitMasterChecks(utilsexec.New(), initCfg, j.IgnorePreflightErrors()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("[preflight] Pulling control-plane images")
|
||||||
|
if err := preflight.RunPullImagesCheck(utilsexec.New(), initCfg, j.IgnorePreflightErrors()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkIfReadyForAdditionalControlPlane ensures that the cluster is in a state that supports
|
||||||
|
// joining an additional control plane instance and if the node is ready to preflight
|
||||||
|
func checkIfReadyForAdditionalControlPlane(initConfiguration *kubeadmapi.ClusterConfiguration) error {
|
||||||
|
// blocks if the cluster was created without a stable control plane endpoint
|
||||||
|
if initConfiguration.ControlPlaneEndpoint == "" {
|
||||||
|
return errors.New("unable to add a new control plane instance a cluster that doesn't have a stable controlPlaneEndpoint address")
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks if the certificates that must be equal across contolplane instances are provided
|
||||||
|
if ret, err := certs.SharedCertificateExists(initConfiguration); !ret {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ func GetKubeletVersion(execer utilsexec.Interface) (*version.Version, error) {
|
||||||
command := execer.Command("kubelet", "--version")
|
command := execer.Command("kubelet", "--version")
|
||||||
out, err := command.CombinedOutput()
|
out, err := command.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "cannot execute 'kubelet --version'")
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanOutput := strings.TrimSpace(string(out))
|
cleanOutput := strings.TrimSpace(string(out))
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestValidateDockerInfo(t *testing.T) {
|
||||||
Reporter: DefaultReporter,
|
Reporter: DefaultReporter,
|
||||||
}
|
}
|
||||||
spec := &DockerSpec{
|
spec := &DockerSpec{
|
||||||
Version: []string{`1\.1[1-3]\..*`, `17\.0[3,6,9]\..*`, `18\.06\..*`},
|
Version: []string{`1\.1[1-3]\..*`, `17\.0[3,6,9]\..*`, `18\.0[6,9]\..*`},
|
||||||
GraphDriver: []string{"driver_1", "driver_2"},
|
GraphDriver: []string{"driver_1", "driver_2"},
|
||||||
}
|
}
|
||||||
for _, test := range []struct {
|
for _, test := range []struct {
|
||||||
|
|
|
@ -62,7 +62,7 @@ var DefaultSysSpec = SysSpec{
|
||||||
Cgroups: []string{"cpu", "cpuacct", "cpuset", "devices", "freezer", "memory"},
|
Cgroups: []string{"cpu", "cpuacct", "cpuset", "devices", "freezer", "memory"},
|
||||||
RuntimeSpec: RuntimeSpec{
|
RuntimeSpec: RuntimeSpec{
|
||||||
DockerSpec: &DockerSpec{
|
DockerSpec: &DockerSpec{
|
||||||
Version: []string{`1\.1[1-3]\..*`, `17\.0[3,6,9]\..*`, `18\.06\..*`},
|
Version: []string{`1\.1[1-3]\..*`, `17\.0[3,6,9]\..*`, `18\.0[6,9]\..*`},
|
||||||
GraphDriver: []string{"aufs", "overlay", "overlay2", "devicemapper", "zfs"},
|
GraphDriver: []string{"aufs", "overlay", "overlay2", "devicemapper", "zfs"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -38,7 +38,7 @@ var DefaultSysSpec = SysSpec{
|
||||||
Cgroups: []string{},
|
Cgroups: []string{},
|
||||||
RuntimeSpec: RuntimeSpec{
|
RuntimeSpec: RuntimeSpec{
|
||||||
DockerSpec: &DockerSpec{
|
DockerSpec: &DockerSpec{
|
||||||
Version: []string{`18\.06\..*`}, //Requires [18.06] or later
|
Version: []string{`18\.0[6,9]\..*`},
|
||||||
GraphDriver: []string{"windowsfilter"},
|
GraphDriver: []string{"windowsfilter"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -355,7 +355,6 @@ pkg/util/bandwidth
|
||||||
pkg/util/config
|
pkg/util/config
|
||||||
pkg/util/ebtables
|
pkg/util/ebtables
|
||||||
pkg/util/env
|
pkg/util/env
|
||||||
pkg/util/file
|
|
||||||
pkg/util/goroutinemap/exponentialbackoff
|
pkg/util/goroutinemap/exponentialbackoff
|
||||||
pkg/util/initsystem
|
pkg/util/initsystem
|
||||||
pkg/util/iptables
|
pkg/util/iptables
|
||||||
|
|
|
@ -158,11 +158,6 @@
|
||||||
./pkg/kubectl/cmd/edit/testdata/record_testcase.sh
|
./pkg/kubectl/cmd/edit/testdata/record_testcase.sh
|
||||||
./pkg/util/verify-util-pkg.sh
|
./pkg/util/verify-util-pkg.sh
|
||||||
./plugin/pkg/admission/imagepolicy/gencerts.sh
|
./plugin/pkg/admission/imagepolicy/gencerts.sh
|
||||||
./staging/src/k8s.io/apiextensions-apiserver/examples/client-go/hack/update-codegen.sh
|
|
||||||
./staging/src/k8s.io/apiextensions-apiserver/examples/client-go/hack/verify-codegen.sh
|
|
||||||
./staging/src/k8s.io/apiextensions-apiserver/hack/build-image.sh
|
|
||||||
./staging/src/k8s.io/apiextensions-apiserver/hack/update-codegen.sh
|
|
||||||
./staging/src/k8s.io/apiextensions-apiserver/hack/verify-codegen.sh
|
|
||||||
./staging/src/k8s.io/code-generator/generate-groups.sh
|
./staging/src/k8s.io/code-generator/generate-groups.sh
|
||||||
./staging/src/k8s.io/code-generator/generate-internal-groups.sh
|
./staging/src/k8s.io/code-generator/generate-internal-groups.sh
|
||||||
./staging/src/k8s.io/code-generator/hack/update-codegen.sh
|
./staging/src/k8s.io/code-generator/hack/update-codegen.sh
|
||||||
|
@ -178,9 +173,6 @@
|
||||||
./staging/src/k8s.io/metrics/hack/verify-codegen.sh
|
./staging/src/k8s.io/metrics/hack/verify-codegen.sh
|
||||||
./staging/src/k8s.io/node-api/hack/update-codegen.sh
|
./staging/src/k8s.io/node-api/hack/update-codegen.sh
|
||||||
./staging/src/k8s.io/node-api/hack/verify-codegen.sh
|
./staging/src/k8s.io/node-api/hack/verify-codegen.sh
|
||||||
./staging/src/k8s.io/sample-apiserver/hack/build-image.sh
|
|
||||||
./staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh
|
|
||||||
./staging/src/k8s.io/sample-apiserver/hack/verify-codegen.sh
|
|
||||||
./test/cmd/apply.sh
|
./test/cmd/apply.sh
|
||||||
./test/cmd/apps.sh
|
./test/cmd/apps.sh
|
||||||
./test/cmd/authorization.sh
|
./test/cmd/authorization.sh
|
||||||
|
|
|
@ -697,6 +697,15 @@ function kube::util::ensure-cfssl {
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
host_arch=$(kube::util::host_arch)
|
||||||
|
|
||||||
|
if [[ "${host_arch}" != "amd64" ]]; then
|
||||||
|
echo "Cannot download cfssl on non-amd64 hosts and cfssl does not appear to be installed."
|
||||||
|
echo "Please install cfssl and cfssljson and verify they are in \$PATH."
|
||||||
|
echo "Hint: export PATH=\$PATH:\$GOPATH/bin; go get -u github.com/cloudflare/cfssl/cmd/..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Create a temp dir for cfssl if no directory was given
|
# Create a temp dir for cfssl if no directory was given
|
||||||
local cfssldir=${1:-}
|
local cfssldir=${1:-}
|
||||||
if [[ -z "${cfssldir}" ]]; then
|
if [[ -z "${cfssldir}" ]]; then
|
||||||
|
|
|
@ -78,6 +78,7 @@ CLOUD_PROVIDER=${CLOUD_PROVIDER:-""}
|
||||||
CLOUD_CONFIG=${CLOUD_CONFIG:-""}
|
CLOUD_CONFIG=${CLOUD_CONFIG:-""}
|
||||||
FEATURE_GATES=${FEATURE_GATES:-"AllAlpha=false"}
|
FEATURE_GATES=${FEATURE_GATES:-"AllAlpha=false"}
|
||||||
STORAGE_BACKEND=${STORAGE_BACKEND:-"etcd3"}
|
STORAGE_BACKEND=${STORAGE_BACKEND:-"etcd3"}
|
||||||
|
STORAGE_MEDIA_TYPE=${STORAGE_MEDIA_TYPE:-""}
|
||||||
# preserve etcd data. you also need to set ETCD_DIR.
|
# preserve etcd data. you also need to set ETCD_DIR.
|
||||||
PRESERVE_ETCD="${PRESERVE_ETCD:-false}"
|
PRESERVE_ETCD="${PRESERVE_ETCD:-false}"
|
||||||
# enable Pod priority and preemption
|
# enable Pod priority and preemption
|
||||||
|
@ -574,6 +575,7 @@ function start_apiserver {
|
||||||
--insecure-bind-address="${API_HOST_IP}" \
|
--insecure-bind-address="${API_HOST_IP}" \
|
||||||
--insecure-port="${API_PORT}" \
|
--insecure-port="${API_PORT}" \
|
||||||
--storage-backend=${STORAGE_BACKEND} \
|
--storage-backend=${STORAGE_BACKEND} \
|
||||||
|
--storage-media-type=${STORAGE_MEDIA_TYPE} \
|
||||||
--etcd-servers="http://${ETCD_HOST}:${ETCD_PORT}" \
|
--etcd-servers="http://${ETCD_HOST}:${ETCD_PORT}" \
|
||||||
--service-cluster-ip-range="${SERVICE_CLUSTER_IP_RANGE}" \
|
--service-cluster-ip-range="${SERVICE_CLUSTER_IP_RANGE}" \
|
||||||
--feature-gates="${FEATURE_GATES}" \
|
--feature-gates="${FEATURE_GATES}" \
|
||||||
|
|
|
@ -5,31 +5,18 @@
|
||||||
"AllowedPrefixes": [
|
"AllowedPrefixes": [
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme",
|
"k8s.io/kubernetes/pkg/api/legacyscheme",
|
||||||
"k8s.io/kubernetes/pkg/api/service",
|
"k8s.io/kubernetes/pkg/api/service",
|
||||||
"k8s.io/kubernetes/pkg/api/v1/pod",
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1/service",
|
"k8s.io/kubernetes/pkg/api/v1/service",
|
||||||
"k8s.io/kubernetes/pkg/apis/apps",
|
|
||||||
"k8s.io/kubernetes/pkg/apis/autoscaling",
|
|
||||||
"k8s.io/kubernetes/pkg/apis/core",
|
"k8s.io/kubernetes/pkg/apis/core",
|
||||||
"k8s.io/kubernetes/pkg/apis/scheduling",
|
|
||||||
"k8s.io/kubernetes/pkg/capabilities",
|
|
||||||
"k8s.io/kubernetes/pkg/cloudprovider",
|
"k8s.io/kubernetes/pkg/cloudprovider",
|
||||||
"k8s.io/kubernetes/pkg/controller",
|
|
||||||
"k8s.io/kubernetes/pkg/credentialprovider",
|
"k8s.io/kubernetes/pkg/credentialprovider",
|
||||||
"k8s.io/kubernetes/pkg/features",
|
"k8s.io/kubernetes/pkg/features",
|
||||||
"k8s.io/kubernetes/pkg/fieldpath",
|
|
||||||
"k8s.io/kubernetes/pkg/kubelet/apis",
|
"k8s.io/kubernetes/pkg/kubelet/apis",
|
||||||
"k8s.io/kubernetes/pkg/kubelet/types",
|
|
||||||
"k8s.io/kubernetes/pkg/master/ports",
|
"k8s.io/kubernetes/pkg/master/ports",
|
||||||
"k8s.io/kubernetes/pkg/security/apparmor",
|
|
||||||
"k8s.io/kubernetes/pkg/serviceaccount",
|
|
||||||
"k8s.io/kubernetes/pkg/util/file",
|
|
||||||
"k8s.io/kubernetes/pkg/util/hash",
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount",
|
"k8s.io/kubernetes/pkg/util/mount",
|
||||||
|
"k8s.io/kubernetes/pkg/util/file",
|
||||||
"k8s.io/kubernetes/pkg/util/net/sets",
|
"k8s.io/kubernetes/pkg/util/net/sets",
|
||||||
"k8s.io/kubernetes/pkg/util/parsers",
|
|
||||||
"k8s.io/kubernetes/pkg/util/resizefs",
|
"k8s.io/kubernetes/pkg/util/resizefs",
|
||||||
"k8s.io/kubernetes/pkg/util/strings",
|
"k8s.io/kubernetes/pkg/util/strings",
|
||||||
"k8s.io/kubernetes/pkg/util/taints",
|
|
||||||
"k8s.io/kubernetes/pkg/version",
|
"k8s.io/kubernetes/pkg/version",
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
],
|
],
|
||||||
|
|
|
@ -28,7 +28,6 @@ go_library(
|
||||||
importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/aws",
|
importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/aws",
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/v1/service:go_default_library",
|
"//pkg/api/v1/service:go_default_library",
|
||||||
"//pkg/controller:go_default_library",
|
|
||||||
"//pkg/credentialprovider/aws:go_default_library",
|
"//pkg/credentialprovider/aws:go_default_library",
|
||||||
"//pkg/kubelet/apis:go_default_library",
|
"//pkg/kubelet/apis:go_default_library",
|
||||||
"//pkg/version:go_default_library",
|
"//pkg/version:go_default_library",
|
||||||
|
@ -45,6 +44,7 @@ go_library(
|
||||||
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
||||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||||
|
"//staging/src/k8s.io/cloud-provider/node/helpers:go_default_library",
|
||||||
"//vendor/github.com/aws/aws-sdk-go/aws:go_default_library",
|
"//vendor/github.com/aws/aws-sdk-go/aws:go_default_library",
|
||||||
"//vendor/github.com/aws/aws-sdk-go/aws/awserr:go_default_library",
|
"//vendor/github.com/aws/aws-sdk-go/aws/awserr:go_default_library",
|
||||||
"//vendor/github.com/aws/aws-sdk-go/aws/credentials:go_default_library",
|
"//vendor/github.com/aws/aws-sdk-go/aws/credentials:go_default_library",
|
||||||
|
|
|
@ -56,9 +56,9 @@ import (
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
|
nodehelpers "k8s.io/cloud-provider/node/helpers"
|
||||||
"k8s.io/kubernetes/pkg/api/v1/service"
|
"k8s.io/kubernetes/pkg/api/v1/service"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
|
||||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||||
"k8s.io/kubernetes/pkg/version"
|
"k8s.io/kubernetes/pkg/version"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
|
@ -1938,7 +1938,7 @@ func (c *Cloud) applyUnSchedulableTaint(nodeName types.NodeName, reason string)
|
||||||
Value: "true",
|
Value: "true",
|
||||||
Effect: v1.TaintEffectNoSchedule,
|
Effect: v1.TaintEffectNoSchedule,
|
||||||
}
|
}
|
||||||
err := controller.AddOrUpdateTaintOnNode(c.kubeClient, string(nodeName), taint)
|
err := nodehelpers.AddOrUpdateTaintOnNode(c.kubeClient, string(nodeName), taint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Error applying taint to node %s with error %v", nodeName, err)
|
klog.Errorf("Error applying taint to node %s with error %v", nodeName, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -306,7 +306,6 @@
|
||||||
"k8s.io/kubernetes/pkg/scheduler/api",
|
"k8s.io/kubernetes/pkg/scheduler/api",
|
||||||
"k8s.io/kubernetes/pkg/scheduler/util",
|
"k8s.io/kubernetes/pkg/scheduler/util",
|
||||||
"k8s.io/kubernetes/pkg/security/apparmor",
|
"k8s.io/kubernetes/pkg/security/apparmor",
|
||||||
"k8s.io/kubernetes/pkg/util/file",
|
|
||||||
"k8s.io/kubernetes/pkg/util/net/sets",
|
"k8s.io/kubernetes/pkg/util/net/sets",
|
||||||
"k8s.io/kubernetes/pkg/util/parsers",
|
"k8s.io/kubernetes/pkg/util/parsers",
|
||||||
"k8s.io/kubernetes/pkg/fieldpath",
|
"k8s.io/kubernetes/pkg/fieldpath",
|
||||||
|
@ -339,6 +338,7 @@
|
||||||
"k8s.io/utils/nsenter",
|
"k8s.io/utils/nsenter",
|
||||||
"k8s.io/utils/integer",
|
"k8s.io/utils/integer",
|
||||||
"k8s.io/utils/io",
|
"k8s.io/utils/io",
|
||||||
|
"k8s.io/utils/path",
|
||||||
"k8s.io/utils/pointer",
|
"k8s.io/utils/pointer",
|
||||||
"k8s.io/utils/exec",
|
"k8s.io/utils/exec",
|
||||||
"k8s.io/utils/strings"
|
"k8s.io/utils/strings"
|
||||||
|
|
|
@ -964,6 +964,9 @@ func (dsc *DaemonSetsController) manage(ds *apps.DaemonSet, hash string) error {
|
||||||
failedPodsObserved += failedPodsObservedOnNode
|
failedPodsObserved += failedPodsObservedOnNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove pods assigned to not existing nodes.
|
||||||
|
podsToDelete = append(podsToDelete, getPodsWithoutNode(nodeList, nodeToDaemonPods)...)
|
||||||
|
|
||||||
// Label new pods using the hash label value of the current history when creating them
|
// Label new pods using the hash label value of the current history when creating them
|
||||||
if err = dsc.syncNodes(ds, podsToDelete, nodesNeedingDaemonPods, hash); err != nil {
|
if err = dsc.syncNodes(ds, podsToDelete, nodesNeedingDaemonPods, hash); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1524,3 +1527,21 @@ func (o podByCreationTimestampAndPhase) Less(i, j int) bool {
|
||||||
func failedPodsBackoffKey(ds *apps.DaemonSet, nodeName string) string {
|
func failedPodsBackoffKey(ds *apps.DaemonSet, nodeName string) string {
|
||||||
return fmt.Sprintf("%s/%d/%s", ds.UID, ds.Status.ObservedGeneration, nodeName)
|
return fmt.Sprintf("%s/%d/%s", ds.UID, ds.Status.ObservedGeneration, nodeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPodsWithoutNode returns list of pods assigned to not existing nodes.
|
||||||
|
func getPodsWithoutNode(
|
||||||
|
runningNodesList []*v1.Node, nodeToDaemonPods map[string][]*v1.Pod) []string {
|
||||||
|
var results []string
|
||||||
|
isNodeRunning := make(map[string]bool)
|
||||||
|
for _, node := range runningNodesList {
|
||||||
|
isNodeRunning[node.Name] = true
|
||||||
|
}
|
||||||
|
for n, pods := range nodeToDaemonPods {
|
||||||
|
if !isNodeRunning[n] {
|
||||||
|
for _, pod := range pods {
|
||||||
|
results = append(results, pod.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
|
@ -2447,6 +2447,25 @@ func TestDeleteNoDaemonPod(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeletePodForNotExistingNode(t *testing.T) {
|
||||||
|
for _, f := range []bool{true, false} {
|
||||||
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ScheduleDaemonSetPods, f)()
|
||||||
|
for _, strategy := range updateStrategies() {
|
||||||
|
ds := newDaemonSet("foo")
|
||||||
|
ds.Spec.UpdateStrategy = *strategy
|
||||||
|
manager, podControl, _, err := newTestController(ds)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error creating DaemonSets controller: %v", err)
|
||||||
|
}
|
||||||
|
manager.dsStore.Add(ds)
|
||||||
|
addNodes(manager.nodeStore, 0, 1, nil)
|
||||||
|
addPods(manager.podStore, "node-0", simpleDaemonSetLabel, ds, 1)
|
||||||
|
addPods(manager.podStore, "node-1", simpleDaemonSetLabel, ds, 1)
|
||||||
|
syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 1, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetNodesToDaemonPods(t *testing.T) {
|
func TestGetNodesToDaemonPods(t *testing.T) {
|
||||||
for _, f := range []bool{true, false} {
|
for _, f := range []bool{true, false} {
|
||||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ScheduleDaemonSetPods, f)()
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ScheduleDaemonSetPods, f)()
|
||||||
|
|
|
@ -121,6 +121,7 @@ const (
|
||||||
// owner: @bsalamat
|
// owner: @bsalamat
|
||||||
// alpha: v1.8
|
// alpha: v1.8
|
||||||
// beta: v1.11
|
// beta: v1.11
|
||||||
|
// GA: v1.14
|
||||||
//
|
//
|
||||||
// Add priority to pods. Priority affects scheduling and preemption of pods.
|
// Add priority to pods. Priority affects scheduling and preemption of pods.
|
||||||
PodPriority utilfeature.Feature = "PodPriority"
|
PodPriority utilfeature.Feature = "PodPriority"
|
||||||
|
@ -432,7 +433,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
|
||||||
Sysctls: {Default: true, PreRelease: utilfeature.Beta},
|
Sysctls: {Default: true, PreRelease: utilfeature.Beta},
|
||||||
DebugContainers: {Default: false, PreRelease: utilfeature.Alpha},
|
DebugContainers: {Default: false, PreRelease: utilfeature.Alpha},
|
||||||
PodShareProcessNamespace: {Default: true, PreRelease: utilfeature.Beta},
|
PodShareProcessNamespace: {Default: true, PreRelease: utilfeature.Beta},
|
||||||
PodPriority: {Default: true, PreRelease: utilfeature.Beta},
|
PodPriority: {Default: true, PreRelease: utilfeature.GA},
|
||||||
TaintNodesByCondition: {Default: true, PreRelease: utilfeature.Beta},
|
TaintNodesByCondition: {Default: true, PreRelease: utilfeature.Beta},
|
||||||
MountPropagation: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.14
|
MountPropagation: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.14
|
||||||
QOSReserved: {Default: false, PreRelease: utilfeature.Alpha},
|
QOSReserved: {Default: false, PreRelease: utilfeature.Alpha},
|
||||||
|
|
|
@ -126,7 +126,6 @@
|
||||||
"k8s.io/kubernetes/pkg/scheduler/volumebinder",
|
"k8s.io/kubernetes/pkg/scheduler/volumebinder",
|
||||||
"k8s.io/kubernetes/pkg/security/apparmor",
|
"k8s.io/kubernetes/pkg/security/apparmor",
|
||||||
"k8s.io/kubernetes/pkg/serviceaccount",
|
"k8s.io/kubernetes/pkg/serviceaccount",
|
||||||
"k8s.io/kubernetes/pkg/util/file",
|
|
||||||
"k8s.io/kubernetes/pkg/util/goroutinemap",
|
"k8s.io/kubernetes/pkg/util/goroutinemap",
|
||||||
"k8s.io/kubernetes/pkg/util/hash",
|
"k8s.io/kubernetes/pkg/util/hash",
|
||||||
"k8s.io/kubernetes/pkg/util/interrupt",
|
"k8s.io/kubernetes/pkg/util/interrupt",
|
||||||
|
@ -144,6 +143,7 @@
|
||||||
"k8s.io/kubernetes/pkg/volume/util",
|
"k8s.io/kubernetes/pkg/volume/util",
|
||||||
"k8s.io/utils/nsenter",
|
"k8s.io/utils/nsenter",
|
||||||
"k8s.io/utils/io",
|
"k8s.io/utils/io",
|
||||||
|
"k8s.io/utils/path",
|
||||||
"k8s.io/utils/pointer"
|
"k8s.io/utils/pointer"
|
||||||
],
|
],
|
||||||
"ForbiddenPrefixes": []
|
"ForbiddenPrefixes": []
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
@ -339,12 +338,6 @@ type defaultPluginHandler struct{}
|
||||||
|
|
||||||
// Lookup implements PluginHandler
|
// Lookup implements PluginHandler
|
||||||
func (h *defaultPluginHandler) Lookup(filename string) (string, error) {
|
func (h *defaultPluginHandler) Lookup(filename string) (string, error) {
|
||||||
// if on Windows, append the "exe" extension
|
|
||||||
// to the filename that we are looking up.
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
filename = filename + ".exe"
|
|
||||||
}
|
|
||||||
|
|
||||||
return exec.LookPath(filename)
|
return exec.LookPath(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ func NewCustomColumnsPrinterFromSpec(spec string, decoder runtime.Decoder, noHea
|
||||||
parts := strings.Split(spec, ",")
|
parts := strings.Split(spec, ",")
|
||||||
columns := make([]Column, len(parts))
|
columns := make([]Column, len(parts))
|
||||||
for ix := range parts {
|
for ix := range parts {
|
||||||
colSpec := strings.Split(parts[ix], ":")
|
colSpec := strings.SplitN(parts[ix], ":", 2)
|
||||||
if len(colSpec) != 2 {
|
if len(colSpec) != 2 {
|
||||||
return nil, fmt.Errorf("unexpected custom-columns spec: %s, expected <header>:<json-path-expr>", parts[ix])
|
return nil, fmt.Errorf("unexpected custom-columns spec: %s, expected <header>:<json-path-expr>", parts[ix])
|
||||||
}
|
}
|
||||||
|
|
|
@ -373,3 +373,198 @@ bar bar bar
|
||||||
t.Errorf("\nexpected:\n'%s'\nsaw\n'%s'\n", expectedOutput, buffer.String())
|
t.Errorf("\nexpected:\n'%s'\nsaw\n'%s'\n", expectedOutput, buffer.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSliceColumnPrint(t *testing.T) {
|
||||||
|
pod := &corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fake-name",
|
||||||
|
Namespace: "fake-namespace",
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "fake0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "fake1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "fake2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "fake3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
spec string
|
||||||
|
expectedOutput string
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "containers[0]",
|
||||||
|
spec: "CONTAINER:.spec.containers[0].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
fake0
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[3]",
|
||||||
|
spec: "CONTAINER:.spec.containers[3].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
fake3
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[5], illegal expression because it is out of bounds",
|
||||||
|
spec: "CONTAINER:.spec.containers[5].name",
|
||||||
|
expectedOutput: "",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[-1], it equals containers[3]",
|
||||||
|
spec: "CONTAINER:.spec.containers[-1].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
fake3
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[-2], it equals containers[2]",
|
||||||
|
spec: "CONTAINER:.spec.containers[-2].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
fake2
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[-4], it equals containers[0]",
|
||||||
|
spec: "CONTAINER:.spec.containers[-4].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
fake0
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[-5], illegal expression because it is out of bounds",
|
||||||
|
spec: "CONTAINER:.spec.containers[-5].name",
|
||||||
|
expectedOutput: "",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[0:0], it equals empty set",
|
||||||
|
spec: "CONTAINER:.spec.containers[0:0].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
<none>
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[0:3]",
|
||||||
|
spec: "CONTAINER:.spec.containers[0:3].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
fake0,fake1,fake2
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[1:]",
|
||||||
|
spec: "CONTAINER:.spec.containers[1:].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
fake1,fake2,fake3
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[3:1], illegal expression because start index is greater than end index",
|
||||||
|
spec: "CONTAINER:.spec.containers[3:1].name",
|
||||||
|
expectedOutput: "",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "containers[0:-1], it equals containers[0:3]",
|
||||||
|
spec: "CONTAINER:.spec.containers[0:-1].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
fake0,fake1,fake2
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[-1:], it equals containers[3:]",
|
||||||
|
spec: "CONTAINER:.spec.containers[-1:].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
fake3
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[-4:], it equals containers[0:]",
|
||||||
|
spec: "CONTAINER:.spec.containers[-4:].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
fake0,fake1,fake2,fake3
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "containers[-3:-1], it equasl containers[1:3]",
|
||||||
|
spec: "CONTAINER:.spec.containers[-3:-1].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
fake1,fake2
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[-2:-3], it equals containers[2:1], illegal expression because start index is greater than end index",
|
||||||
|
spec: "CONTAINER:.spec.containers[-2:-3].name",
|
||||||
|
expectedOutput: "",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[4:4], it equals empty set",
|
||||||
|
spec: "CONTAINER:.spec.containers[4:4].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
<none>
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "containers[-5:-5], it equals empty set",
|
||||||
|
spec: "CONTAINER:.spec.containers[-5:-5].name",
|
||||||
|
expectedOutput: `CONTAINER
|
||||||
|
<none>
|
||||||
|
`,
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
printer, err := NewCustomColumnsPrinterFromSpec(test.spec, decoder, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("test %s has unexpected error: %v", test.name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := &bytes.Buffer{}
|
||||||
|
err = printer.PrintObj(pod, buffer)
|
||||||
|
if test.expectErr {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("test %s has unexpected error: %v", test.name, err)
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("test %s has unexpected error: %v", test.name, err)
|
||||||
|
} else if buffer.String() != test.expectedOutput {
|
||||||
|
t.Errorf("test %s has unexpected output:\nexpected: %s\nsaw: %s", test.name, test.expectedOutput, buffer.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -100,11 +100,7 @@ func (o *PluginListOptions) Complete(cmd *cobra.Command) error {
|
||||||
seenPlugins: make(map[string]string, 0),
|
seenPlugins: make(map[string]string, 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
path := "PATH"
|
o.PluginPaths = filepath.SplitList(os.Getenv("PATH"))
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
path = "path"
|
|
||||||
}
|
|
||||||
o.PluginPaths = filepath.SplitList(os.Getenv(path))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +226,10 @@ func isExecutable(fullPath string) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
if strings.HasSuffix(info.Name(), ".exe") {
|
fileExt := strings.ToLower(filepath.Ext(fullPath))
|
||||||
|
|
||||||
|
switch fileExt {
|
||||||
|
case ".bat", ".cmd", ".com", ".exe":
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
|
|
|
@ -103,7 +103,6 @@ go_library(
|
||||||
"//pkg/security/podsecuritypolicy/sysctl:go_default_library",
|
"//pkg/security/podsecuritypolicy/sysctl:go_default_library",
|
||||||
"//pkg/securitycontext:go_default_library",
|
"//pkg/securitycontext:go_default_library",
|
||||||
"//pkg/util/dbus:go_default_library",
|
"//pkg/util/dbus:go_default_library",
|
||||||
"//pkg/util/file:go_default_library",
|
|
||||||
"//pkg/util/iptables:go_default_library",
|
"//pkg/util/iptables:go_default_library",
|
||||||
"//pkg/util/mount:go_default_library",
|
"//pkg/util/mount:go_default_library",
|
||||||
"//pkg/util/node:go_default_library",
|
"//pkg/util/node:go_default_library",
|
||||||
|
@ -150,6 +149,7 @@ go_library(
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
"//vendor/k8s.io/utils/integer:go_default_library",
|
"//vendor/k8s.io/utils/integer:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/path:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,6 @@ go_library(
|
||||||
"//pkg/kubelet/metrics:go_default_library",
|
"//pkg/kubelet/metrics:go_default_library",
|
||||||
"//pkg/kubelet/qos:go_default_library",
|
"//pkg/kubelet/qos:go_default_library",
|
||||||
"//pkg/kubelet/types:go_default_library",
|
"//pkg/kubelet/types:go_default_library",
|
||||||
"//pkg/util/file:go_default_library",
|
|
||||||
"//pkg/util/mount:go_default_library",
|
"//pkg/util/mount:go_default_library",
|
||||||
"//pkg/util/oom:go_default_library",
|
"//pkg/util/oom:go_default_library",
|
||||||
"//pkg/util/procfs:go_default_library",
|
"//pkg/util/procfs:go_default_library",
|
||||||
|
@ -88,6 +87,7 @@ go_library(
|
||||||
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
|
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
|
||||||
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd:go_default_library",
|
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd:go_default_library",
|
||||||
"//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
|
"//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/path:go_default_library",
|
||||||
],
|
],
|
||||||
"@io_bazel_rules_go//go/platform:nacl": [
|
"@io_bazel_rules_go//go/platform:nacl": [
|
||||||
"//pkg/kubelet/cadvisor:go_default_library",
|
"//pkg/kubelet/cadvisor:go_default_library",
|
||||||
|
|
|
@ -56,11 +56,11 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/kubelet/status"
|
"k8s.io/kubernetes/pkg/kubelet/status"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher"
|
"k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher"
|
||||||
schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"
|
schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"
|
||||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/util/oom"
|
"k8s.io/kubernetes/pkg/util/oom"
|
||||||
"k8s.io/kubernetes/pkg/util/procfs"
|
"k8s.io/kubernetes/pkg/util/procfs"
|
||||||
utilsysctl "k8s.io/kubernetes/pkg/util/sysctl"
|
utilsysctl "k8s.io/kubernetes/pkg/util/sysctl"
|
||||||
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -179,11 +179,11 @@ func validateSystemRequirements(mountUtil mount.Interface) (features, error) {
|
||||||
|
|
||||||
// Check if cpu quota is available.
|
// Check if cpu quota is available.
|
||||||
// CPU cgroup is required and so it expected to be mounted at this point.
|
// CPU cgroup is required and so it expected to be mounted at this point.
|
||||||
periodExists, err := utilfile.FileExists(path.Join(cpuMountPoint, "cpu.cfs_period_us"))
|
periodExists, err := utilpath.Exists(utilpath.CheckFollowSymlink, path.Join(cpuMountPoint, "cpu.cfs_period_us"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("failed to detect if CPU cgroup cpu.cfs_period_us is available - %v", err)
|
klog.Errorf("failed to detect if CPU cgroup cpu.cfs_period_us is available - %v", err)
|
||||||
}
|
}
|
||||||
quotaExists, err := utilfile.FileExists(path.Join(cpuMountPoint, "cpu.cfs_quota_us"))
|
quotaExists, err := utilpath.Exists(utilpath.CheckFollowSymlink, path.Join(cpuMountPoint, "cpu.cfs_quota_us"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("failed to detect if CPU cgroup cpu.cfs_quota_us is available - %v", err)
|
klog.Errorf("failed to detect if CPU cgroup cpu.cfs_quota_us is available - %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,9 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/kubelet/cm"
|
"k8s.io/kubernetes/pkg/kubelet/cm"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/config"
|
"k8s.io/kubernetes/pkg/kubelet/config"
|
||||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
utilnode "k8s.io/kubernetes/pkg/util/node"
|
utilnode "k8s.io/kubernetes/pkg/util/node"
|
||||||
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getRootDir returns the full path to the directory under which kubelet can
|
// getRootDir returns the full path to the directory under which kubelet can
|
||||||
|
@ -293,7 +293,7 @@ func (kl *Kubelet) getPodVolumePathListFromDisk(podUID types.UID) ([]string, err
|
||||||
for _, volumePluginDir := range volumePluginDirs {
|
for _, volumePluginDir := range volumePluginDirs {
|
||||||
volumePluginName := volumePluginDir.Name()
|
volumePluginName := volumePluginDir.Name()
|
||||||
volumePluginPath := filepath.Join(podVolDir, volumePluginName)
|
volumePluginPath := filepath.Join(podVolDir, volumePluginName)
|
||||||
volumeDirs, err := utilfile.ReadDirNoStat(volumePluginPath)
|
volumeDirs, err := utilpath.ReadDirNoStat(volumePluginPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumes, fmt.Errorf("Could not read directory %s: %v", volumePluginPath, err)
|
return volumes, fmt.Errorf("Could not read directory %s: %v", volumePluginPath, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ go_library(
|
||||||
"//pkg/features:go_default_library",
|
"//pkg/features:go_default_library",
|
||||||
"//pkg/kubelet/config:go_default_library",
|
"//pkg/kubelet/config:go_default_library",
|
||||||
"//pkg/kubelet/volumemanager/cache:go_default_library",
|
"//pkg/kubelet/volumemanager/cache:go_default_library",
|
||||||
"//pkg/util/file:go_default_library",
|
|
||||||
"//pkg/util/goroutinemap/exponentialbackoff:go_default_library",
|
"//pkg/util/goroutinemap/exponentialbackoff:go_default_library",
|
||||||
"//pkg/util/mount:go_default_library",
|
"//pkg/util/mount:go_default_library",
|
||||||
"//pkg/volume:go_default_library",
|
"//pkg/volume:go_default_library",
|
||||||
|
@ -30,6 +29,7 @@ go_library(
|
||||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
"//vendor/k8s.io/utils/strings:go_default_library",
|
"//vendor/k8s.io/utils/strings:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/path:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/config"
|
"k8s.io/kubernetes/pkg/kubelet/config"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/volumemanager/cache"
|
"k8s.io/kubernetes/pkg/kubelet/volumemanager/cache"
|
||||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
|
||||||
"k8s.io/kubernetes/pkg/util/goroutinemap/exponentialbackoff"
|
"k8s.io/kubernetes/pkg/util/goroutinemap/exponentialbackoff"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
volumepkg "k8s.io/kubernetes/pkg/volume"
|
volumepkg "k8s.io/kubernetes/pkg/volume"
|
||||||
|
@ -45,6 +44,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/volume/util/operationexecutor"
|
"k8s.io/kubernetes/pkg/volume/util/operationexecutor"
|
||||||
volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
|
volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
|
||||||
utilstrings "k8s.io/utils/strings"
|
utilstrings "k8s.io/utils/strings"
|
||||||
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reconciler runs a periodic loop to reconcile the desired state of the world
|
// Reconciler runs a periodic loop to reconcile the desired state of the world
|
||||||
|
@ -673,7 +673,7 @@ func getVolumesFromPodDir(podDir string) ([]podVolume, error) {
|
||||||
for _, volumeDir := range volumesDirInfo {
|
for _, volumeDir := range volumesDirInfo {
|
||||||
pluginName := volumeDir.Name()
|
pluginName := volumeDir.Name()
|
||||||
volumePluginPath := path.Join(volumesDir, pluginName)
|
volumePluginPath := path.Join(volumesDir, pluginName)
|
||||||
volumePluginDirs, err := utilfile.ReadDirNoStat(volumePluginPath)
|
volumePluginDirs, err := utilpath.ReadDirNoStat(volumePluginPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Could not read volume plugin directory %q: %v", volumePluginPath, err)
|
klog.Errorf("Could not read volume plugin directory %q: %v", volumePluginPath, err)
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -68,7 +68,7 @@ func NewAutoRegistrationController(crdinformer crdinformers.CustomResourceDefini
|
||||||
crdSynced: crdinformer.Informer().HasSynced,
|
crdSynced: crdinformer.Informer().HasSynced,
|
||||||
apiServiceRegistration: apiServiceRegistration,
|
apiServiceRegistration: apiServiceRegistration,
|
||||||
syncedInitialSet: make(chan struct{}),
|
syncedInitialSet: make(chan struct{}),
|
||||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "crd-autoregister"),
|
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "crd_autoregistration_controller"),
|
||||||
}
|
}
|
||||||
c.syncHandler = c.handleVersionUpdate
|
c.syncHandler = c.handleVersionUpdate
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,10 @@ go_library(
|
||||||
importpath = "k8s.io/kubernetes/pkg/master/tunneler",
|
importpath = "k8s.io/kubernetes/pkg/master/tunneler",
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/ssh:go_default_library",
|
"//pkg/ssh:go_default_library",
|
||||||
"//pkg/util/file:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/path:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"k8s.io/kubernetes/pkg/ssh"
|
"k8s.io/kubernetes/pkg/ssh"
|
||||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InstallSSHKey func(ctx context.Context, user string, data []byte) error
|
type InstallSSHKey func(ctx context.Context, user string, data []byte) error
|
||||||
|
@ -119,7 +119,7 @@ func (c *SSHTunneler) Run(getAddresses AddressFunc) {
|
||||||
|
|
||||||
// public keyfile is written last, so check for that.
|
// public keyfile is written last, so check for that.
|
||||||
publicKeyFile := c.SSHKeyfile + ".pub"
|
publicKeyFile := c.SSHKeyfile + ".pub"
|
||||||
exists, err := utilfile.FileExists(publicKeyFile)
|
exists, err := utilpath.Exists(utilpath.CheckFollowSymlink, publicKeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Error detecting if key exists: %v", err)
|
klog.Errorf("Error detecting if key exists: %v", err)
|
||||||
} else if !exists {
|
} else if !exists {
|
||||||
|
@ -208,7 +208,7 @@ func generateSSHKey(privateKeyfile, publicKeyfile string) error {
|
||||||
}
|
}
|
||||||
// If private keyfile already exists, we must have only made it halfway
|
// If private keyfile already exists, we must have only made it halfway
|
||||||
// through last time, so delete it.
|
// through last time, so delete it.
|
||||||
exists, err := utilfile.FileExists(privateKeyfile)
|
exists, err := utilpath.Exists(utilpath.CheckFollowSymlink, privateKeyfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Error detecting if private key exists: %v", err)
|
klog.Errorf("Error detecting if private key exists: %v", err)
|
||||||
} else if exists {
|
} else if exists {
|
||||||
|
|
|
@ -38,7 +38,7 @@ filegroup(
|
||||||
name = "all-srcs",
|
name = "all-srcs",
|
||||||
srcs = [
|
srcs = [
|
||||||
":package-srcs",
|
":package-srcs",
|
||||||
"//pkg/proxy/apis/config:all-srcs",
|
"//pkg/proxy/apis:all-srcs",
|
||||||
"//pkg/proxy/config:all-srcs",
|
"//pkg/proxy/config:all-srcs",
|
||||||
"//pkg/proxy/healthcheck:all-srcs",
|
"//pkg/proxy/healthcheck:all-srcs",
|
||||||
"//pkg/proxy/iptables:all-srcs",
|
"//pkg/proxy/iptables:all-srcs",
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@io_bazel_rules_go//go:def.bzl",
|
||||||
|
"go_library",
|
||||||
|
)
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["well_known_labels.go"],
|
||||||
|
importpath = "k8s.io/kubernetes/pkg/proxy/apis",
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [
|
||||||
|
":package-srcs",
|
||||||
|
"//pkg/proxy/apis/config:all-srcs",
|
||||||
|
],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package apis
|
||||||
|
|
||||||
|
const (
|
||||||
|
// LabelServiceProxyName indicates that an alternative service
|
||||||
|
// proxy will implement this Service.
|
||||||
|
LabelServiceProxyName = "service.kubernetes.io/service-proxy-name"
|
||||||
|
)
|
|
@ -1085,6 +1085,7 @@ func MakeDefaultErrorFunc(client clientset.Interface, backoff *util.PodBackoff,
|
||||||
}
|
}
|
||||||
|
|
||||||
backoff.Gc()
|
backoff.Gc()
|
||||||
|
podSchedulingCycle := podQueue.SchedulingCycle()
|
||||||
// Retry asynchronously.
|
// Retry asynchronously.
|
||||||
// Note that this is extremely rudimentary and we need a more real error handling path.
|
// Note that this is extremely rudimentary and we need a more real error handling path.
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -1110,7 +1111,7 @@ func MakeDefaultErrorFunc(client clientset.Interface, backoff *util.PodBackoff,
|
||||||
pod, err := client.CoreV1().Pods(podID.Namespace).Get(podID.Name, metav1.GetOptions{})
|
pod, err := client.CoreV1().Pods(podID.Namespace).Get(podID.Name, metav1.GetOptions{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if len(pod.Spec.NodeName) == 0 {
|
if len(pod.Spec.NodeName) == 0 {
|
||||||
podQueue.AddUnschedulableIfNotPresent(pod)
|
podQueue.AddUnschedulableIfNotPresent(pod, podSchedulingCycle)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,14 @@ const unschedulableQTimeInterval = 60 * time.Second
|
||||||
type SchedulingQueue interface {
|
type SchedulingQueue interface {
|
||||||
Add(pod *v1.Pod) error
|
Add(pod *v1.Pod) error
|
||||||
AddIfNotPresent(pod *v1.Pod) error
|
AddIfNotPresent(pod *v1.Pod) error
|
||||||
AddUnschedulableIfNotPresent(pod *v1.Pod) error
|
// AddUnschedulableIfNotPresent adds an unschedulable pod back to scheduling queue.
|
||||||
|
// The podSchedulingCycle represents the current scheduling cycle number which can be
|
||||||
|
// returned by calling SchedulingCycle().
|
||||||
|
AddUnschedulableIfNotPresent(pod *v1.Pod, podSchedulingCycle int64) error
|
||||||
|
// SchedulingCycle returns the current number of scheduling cycle which is
|
||||||
|
// cached by scheduling queue. Normally, incrementing this number whenever
|
||||||
|
// a pod is popped (e.g. called Pop()) is enough.
|
||||||
|
SchedulingCycle() int64
|
||||||
// Pop removes the head of the queue and returns it. It blocks if the
|
// Pop removes the head of the queue and returns it. It blocks if the
|
||||||
// queue is empty and waits until a new item is added to the queue.
|
// queue is empty and waits until a new item is added to the queue.
|
||||||
Pop() (*v1.Pod, error)
|
Pop() (*v1.Pod, error)
|
||||||
|
@ -111,10 +118,15 @@ func (f *FIFO) AddIfNotPresent(pod *v1.Pod) error {
|
||||||
|
|
||||||
// AddUnschedulableIfNotPresent adds an unschedulable pod back to the queue. In
|
// AddUnschedulableIfNotPresent adds an unschedulable pod back to the queue. In
|
||||||
// FIFO it is added to the end of the queue.
|
// FIFO it is added to the end of the queue.
|
||||||
func (f *FIFO) AddUnschedulableIfNotPresent(pod *v1.Pod) error {
|
func (f *FIFO) AddUnschedulableIfNotPresent(pod *v1.Pod, podSchedulingCycle int64) error {
|
||||||
return f.FIFO.AddIfNotPresent(pod)
|
return f.FIFO.AddIfNotPresent(pod)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SchedulingCycle implements SchedulingQueue.SchedulingCycle interface.
|
||||||
|
func (f *FIFO) SchedulingCycle() int64 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
// Update updates a pod in the FIFO.
|
// Update updates a pod in the FIFO.
|
||||||
func (f *FIFO) Update(oldPod, newPod *v1.Pod) error {
|
func (f *FIFO) Update(oldPod, newPod *v1.Pod) error {
|
||||||
return f.FIFO.Update(newPod)
|
return f.FIFO.Update(newPod)
|
||||||
|
@ -218,12 +230,14 @@ type PriorityQueue struct {
|
||||||
// nominatedPods is a structures that stores pods which are nominated to run
|
// nominatedPods is a structures that stores pods which are nominated to run
|
||||||
// on nodes.
|
// on nodes.
|
||||||
nominatedPods *nominatedPodMap
|
nominatedPods *nominatedPodMap
|
||||||
// receivedMoveRequest is set to true whenever we receive a request to move a
|
// schedulingCycle represents sequence number of scheduling cycle and is incremented
|
||||||
// pod from the unschedulableQ to the activeQ, and is set to false, when we pop
|
// when a pod is popped.
|
||||||
// a pod from the activeQ. It indicates if we received a move request when a
|
schedulingCycle int64
|
||||||
// pod was in flight (we were trying to schedule it). In such a case, we put
|
// moveRequestCycle caches the sequence number of scheduling cycle when we
|
||||||
// the pod back into the activeQ if it is determined unschedulable.
|
// received a move request. Unscheduable pods in and before this scheduling
|
||||||
receivedMoveRequest bool
|
// cycle will be put back to activeQueue if we were trying to schedule them
|
||||||
|
// when we received move request.
|
||||||
|
moveRequestCycle int64
|
||||||
|
|
||||||
// closed indicates that the queue is closed.
|
// closed indicates that the queue is closed.
|
||||||
// It is mainly used to let Pop() exit its control loop while waiting for an item.
|
// It is mainly used to let Pop() exit its control loop while waiting for an item.
|
||||||
|
@ -265,12 +279,13 @@ func NewPriorityQueue(stop <-chan struct{}) *PriorityQueue {
|
||||||
// NewPriorityQueueWithClock creates a PriorityQueue which uses the passed clock for time.
|
// NewPriorityQueueWithClock creates a PriorityQueue which uses the passed clock for time.
|
||||||
func NewPriorityQueueWithClock(stop <-chan struct{}, clock util.Clock) *PriorityQueue {
|
func NewPriorityQueueWithClock(stop <-chan struct{}, clock util.Clock) *PriorityQueue {
|
||||||
pq := &PriorityQueue{
|
pq := &PriorityQueue{
|
||||||
clock: clock,
|
clock: clock,
|
||||||
stop: stop,
|
stop: stop,
|
||||||
podBackoff: util.CreatePodBackoffWithClock(1*time.Second, 10*time.Second, clock),
|
podBackoff: util.CreatePodBackoffWithClock(1*time.Second, 10*time.Second, clock),
|
||||||
activeQ: util.NewHeap(cache.MetaNamespaceKeyFunc, activeQComp),
|
activeQ: util.NewHeap(cache.MetaNamespaceKeyFunc, activeQComp),
|
||||||
unschedulableQ: newUnschedulablePodsMap(),
|
unschedulableQ: newUnschedulablePodsMap(),
|
||||||
nominatedPods: newNominatedPodMap(),
|
nominatedPods: newNominatedPodMap(),
|
||||||
|
moveRequestCycle: -1,
|
||||||
}
|
}
|
||||||
pq.cond.L = &pq.lock
|
pq.cond.L = &pq.lock
|
||||||
pq.podBackoffQ = util.NewHeap(cache.MetaNamespaceKeyFunc, pq.podsCompareBackoffCompleted)
|
pq.podBackoffQ = util.NewHeap(cache.MetaNamespaceKeyFunc, pq.podsCompareBackoffCompleted)
|
||||||
|
@ -372,12 +387,19 @@ func (p *PriorityQueue) backoffPod(pod *v1.Pod) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SchedulingCycle returns current scheduling cycle.
|
||||||
|
func (p *PriorityQueue) SchedulingCycle() int64 {
|
||||||
|
p.lock.RLock()
|
||||||
|
defer p.lock.RUnlock()
|
||||||
|
return p.schedulingCycle
|
||||||
|
}
|
||||||
|
|
||||||
// AddUnschedulableIfNotPresent does nothing if the pod is present in any
|
// AddUnschedulableIfNotPresent does nothing if the pod is present in any
|
||||||
// queue. If pod is unschedulable, it adds pod to unschedulable queue if
|
// queue. If pod is unschedulable, it adds pod to unschedulable queue if
|
||||||
// p.receivedMoveRequest is false or to backoff queue if p.receivedMoveRequest
|
// p.moveRequestCycle > podSchedulingCycle or to backoff queue if p.moveRequestCycle
|
||||||
// is true but pod is subject to backoff. In other cases, it adds pod to active
|
// <= podSchedulingCycle but pod is subject to backoff. In other cases, it adds pod to
|
||||||
// queue and clears p.receivedMoveRequest.
|
// active queue.
|
||||||
func (p *PriorityQueue) AddUnschedulableIfNotPresent(pod *v1.Pod) error {
|
func (p *PriorityQueue) AddUnschedulableIfNotPresent(pod *v1.Pod, podSchedulingCycle int64) error {
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
if p.unschedulableQ.get(pod) != nil {
|
if p.unschedulableQ.get(pod) != nil {
|
||||||
|
@ -389,7 +411,7 @@ func (p *PriorityQueue) AddUnschedulableIfNotPresent(pod *v1.Pod) error {
|
||||||
if _, exists, _ := p.podBackoffQ.Get(pod); exists {
|
if _, exists, _ := p.podBackoffQ.Get(pod); exists {
|
||||||
return fmt.Errorf("pod is already present in the backoffQ")
|
return fmt.Errorf("pod is already present in the backoffQ")
|
||||||
}
|
}
|
||||||
if !p.receivedMoveRequest && isPodUnschedulable(pod) {
|
if podSchedulingCycle > p.moveRequestCycle && isPodUnschedulable(pod) {
|
||||||
p.backoffPod(pod)
|
p.backoffPod(pod)
|
||||||
p.unschedulableQ.addOrUpdate(pod)
|
p.unschedulableQ.addOrUpdate(pod)
|
||||||
p.nominatedPods.add(pod, "")
|
p.nominatedPods.add(pod, "")
|
||||||
|
@ -412,7 +434,6 @@ func (p *PriorityQueue) AddUnschedulableIfNotPresent(pod *v1.Pod) error {
|
||||||
p.nominatedPods.add(pod, "")
|
p.nominatedPods.add(pod, "")
|
||||||
p.cond.Broadcast()
|
p.cond.Broadcast()
|
||||||
}
|
}
|
||||||
p.receivedMoveRequest = false
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +491,8 @@ func (p *PriorityQueue) flushUnschedulableQLeftover() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop removes the head of the active queue and returns it. It blocks if the
|
// Pop removes the head of the active queue and returns it. It blocks if the
|
||||||
// activeQ is empty and waits until a new item is added to the queue.
|
// activeQ is empty and waits until a new item is added to the queue. It
|
||||||
|
// increments scheduling cycle when a pod is popped.
|
||||||
func (p *PriorityQueue) Pop() (*v1.Pod, error) {
|
func (p *PriorityQueue) Pop() (*v1.Pod, error) {
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
|
@ -488,6 +510,7 @@ func (p *PriorityQueue) Pop() (*v1.Pod, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pod := obj.(*v1.Pod)
|
pod := obj.(*v1.Pod)
|
||||||
|
p.schedulingCycle++
|
||||||
return pod, err
|
return pod, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,7 +631,7 @@ func (p *PriorityQueue) MoveAllToActiveQueue() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.unschedulableQ.clear()
|
p.unschedulableQ.clear()
|
||||||
p.receivedMoveRequest = true
|
p.moveRequestCycle = p.schedulingCycle
|
||||||
p.cond.Broadcast()
|
p.cond.Broadcast()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,7 +649,7 @@ func (p *PriorityQueue) movePodsToActiveQueue(pods []*v1.Pod) {
|
||||||
}
|
}
|
||||||
p.unschedulableQ.delete(pod)
|
p.unschedulableQ.delete(pod)
|
||||||
}
|
}
|
||||||
p.receivedMoveRequest = true
|
p.moveRequestCycle = p.schedulingCycle
|
||||||
p.cond.Broadcast()
|
p.cond.Broadcast()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,9 +179,9 @@ func TestPriorityQueue_AddIfNotPresent(t *testing.T) {
|
||||||
func TestPriorityQueue_AddUnschedulableIfNotPresent(t *testing.T) {
|
func TestPriorityQueue_AddUnschedulableIfNotPresent(t *testing.T) {
|
||||||
q := NewPriorityQueue(nil)
|
q := NewPriorityQueue(nil)
|
||||||
q.Add(&highPriNominatedPod)
|
q.Add(&highPriNominatedPod)
|
||||||
q.AddUnschedulableIfNotPresent(&highPriNominatedPod) // Must not add anything.
|
q.AddUnschedulableIfNotPresent(&highPriNominatedPod, q.SchedulingCycle()) // Must not add anything.
|
||||||
q.AddUnschedulableIfNotPresent(&medPriorityPod) // This should go to activeQ.
|
q.AddUnschedulableIfNotPresent(&medPriorityPod, q.SchedulingCycle()) // This should go to activeQ.
|
||||||
q.AddUnschedulableIfNotPresent(&unschedulablePod)
|
q.AddUnschedulableIfNotPresent(&unschedulablePod, q.SchedulingCycle())
|
||||||
expectedNominatedPods := &nominatedPodMap{
|
expectedNominatedPods := &nominatedPodMap{
|
||||||
nominatedPodToNode: map[types.UID]string{
|
nominatedPodToNode: map[types.UID]string{
|
||||||
medPriorityPod.UID: "node1",
|
medPriorityPod.UID: "node1",
|
||||||
|
@ -209,6 +209,78 @@ func TestPriorityQueue_AddUnschedulableIfNotPresent(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestPriorityQueue_AddUnschedulableIfNotPresent_Async tests scenario when
|
||||||
|
// AddUnschedulableIfNotPresent is called asynchronously pods in and before
|
||||||
|
// current scheduling cycle will be put back to activeQueue if we were trying
|
||||||
|
// to schedule them when we received move request.
|
||||||
|
func TestPriorityQueue_AddUnschedulableIfNotPresent_Async(t *testing.T) {
|
||||||
|
q := NewPriorityQueue(nil)
|
||||||
|
totalNum := 10
|
||||||
|
expectedPods := make([]v1.Pod, 0, totalNum)
|
||||||
|
for i := 0; i < totalNum; i++ {
|
||||||
|
priority := int32(i)
|
||||||
|
p := v1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: fmt.Sprintf("pod%d", i),
|
||||||
|
Namespace: fmt.Sprintf("ns%d", i),
|
||||||
|
UID: types.UID(fmt.Sprintf("upns%d", i)),
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Priority: &priority,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedPods = append(expectedPods, p)
|
||||||
|
// priority is to make pods ordered in the PriorityQueue
|
||||||
|
q.Add(&p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop all pods except for the first one
|
||||||
|
for i := totalNum - 1; i > 0; i-- {
|
||||||
|
p, _ := q.Pop()
|
||||||
|
if !reflect.DeepEqual(&expectedPods[i], p) {
|
||||||
|
t.Errorf("Unexpected pod. Expected: %v, got: %v", &expectedPods[i], p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move all pods to active queue when we were trying to schedule them
|
||||||
|
q.MoveAllToActiveQueue()
|
||||||
|
moveReqChan := make(chan struct{})
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(totalNum - 1)
|
||||||
|
// mark pods[1] ~ pods[totalNum-1] as unschedulable, fire goroutines to add them back later
|
||||||
|
for i := 1; i < totalNum; i++ {
|
||||||
|
unschedulablePod := expectedPods[i].DeepCopy()
|
||||||
|
unschedulablePod.Status = v1.PodStatus{
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodScheduled,
|
||||||
|
Status: v1.ConditionFalse,
|
||||||
|
Reason: v1.PodReasonUnschedulable,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cycle := q.SchedulingCycle()
|
||||||
|
go func() {
|
||||||
|
<-moveReqChan
|
||||||
|
q.AddUnschedulableIfNotPresent(unschedulablePod, cycle)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
firstPod, _ := q.Pop()
|
||||||
|
if !reflect.DeepEqual(&expectedPods[0], firstPod) {
|
||||||
|
t.Errorf("Unexpected pod. Expected: %v, got: %v", &expectedPods[0], firstPod)
|
||||||
|
}
|
||||||
|
// close moveReqChan here to make sure q.AddUnschedulableIfNotPresent is called after another pod is popped
|
||||||
|
close(moveReqChan)
|
||||||
|
wg.Wait()
|
||||||
|
// all other pods should be in active queue again
|
||||||
|
for i := 1; i < totalNum; i++ {
|
||||||
|
if _, exists, _ := q.activeQ.Get(&expectedPods[i]); !exists {
|
||||||
|
t.Errorf("Expected %v to be added to activeQ.", expectedPods[i].Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPriorityQueue_Pop(t *testing.T) {
|
func TestPriorityQueue_Pop(t *testing.T) {
|
||||||
q := NewPriorityQueue(nil)
|
q := NewPriorityQueue(nil)
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
|
@ -680,7 +752,7 @@ func TestRecentlyTriedPodsGoBack(t *testing.T) {
|
||||||
LastProbeTime: metav1.Now(),
|
LastProbeTime: metav1.Now(),
|
||||||
})
|
})
|
||||||
// Put in the unschedulable queue.
|
// Put in the unschedulable queue.
|
||||||
q.AddUnschedulableIfNotPresent(p1)
|
q.AddUnschedulableIfNotPresent(p1, q.SchedulingCycle())
|
||||||
// Move all unschedulable pods to the active queue.
|
// Move all unschedulable pods to the active queue.
|
||||||
q.MoveAllToActiveQueue()
|
q.MoveAllToActiveQueue()
|
||||||
// Simulation is over. Now let's pop all pods. The pod popped first should be
|
// Simulation is over. Now let's pop all pods. The pod popped first should be
|
||||||
|
@ -728,7 +800,7 @@ func TestPodFailedSchedulingMultipleTimesDoesNotBlockNewerPod(t *testing.T) {
|
||||||
LastProbeTime: metav1.Now(),
|
LastProbeTime: metav1.Now(),
|
||||||
})
|
})
|
||||||
// Put in the unschedulable queue
|
// Put in the unschedulable queue
|
||||||
q.AddUnschedulableIfNotPresent(&unschedulablePod)
|
q.AddUnschedulableIfNotPresent(&unschedulablePod, q.SchedulingCycle())
|
||||||
// Clear its backoff to simulate backoff its expiration
|
// Clear its backoff to simulate backoff its expiration
|
||||||
q.clearPodBackoff(&unschedulablePod)
|
q.clearPodBackoff(&unschedulablePod)
|
||||||
// Move all unschedulable pods to the active queue.
|
// Move all unschedulable pods to the active queue.
|
||||||
|
@ -771,7 +843,7 @@ func TestPodFailedSchedulingMultipleTimesDoesNotBlockNewerPod(t *testing.T) {
|
||||||
LastProbeTime: metav1.Now(),
|
LastProbeTime: metav1.Now(),
|
||||||
})
|
})
|
||||||
// And then, put unschedulable pod to the unschedulable queue
|
// And then, put unschedulable pod to the unschedulable queue
|
||||||
q.AddUnschedulableIfNotPresent(&unschedulablePod)
|
q.AddUnschedulableIfNotPresent(&unschedulablePod, q.SchedulingCycle())
|
||||||
// Clear its backoff to simulate its backoff expiration
|
// Clear its backoff to simulate its backoff expiration
|
||||||
q.clearPodBackoff(&unschedulablePod)
|
q.clearPodBackoff(&unschedulablePod)
|
||||||
// Move all unschedulable pods to the active queue.
|
// Move all unschedulable pods to the active queue.
|
||||||
|
@ -838,7 +910,7 @@ func TestHighProirotyBackoff(t *testing.T) {
|
||||||
Message: "fake scheduling failure",
|
Message: "fake scheduling failure",
|
||||||
})
|
})
|
||||||
// Put in the unschedulable queue.
|
// Put in the unschedulable queue.
|
||||||
q.AddUnschedulableIfNotPresent(p)
|
q.AddUnschedulableIfNotPresent(p, q.SchedulingCycle())
|
||||||
// Move all unschedulable pods to the active queue.
|
// Move all unschedulable pods to the active queue.
|
||||||
q.MoveAllToActiveQueue()
|
q.MoveAllToActiveQueue()
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,9 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/features:go_default_library",
|
"//pkg/features:go_default_library",
|
||||||
"//pkg/kubelet/types:go_default_library",
|
"//pkg/kubelet/types:go_default_library",
|
||||||
"//pkg/util/file:go_default_library",
|
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/path:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ import (
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
|
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
|
||||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Whether AppArmor should be disabled by default.
|
// Whether AppArmor should be disabled by default.
|
||||||
|
@ -195,7 +195,7 @@ func getAppArmorFS() (string, error) {
|
||||||
}
|
}
|
||||||
if fields[2] == "securityfs" {
|
if fields[2] == "securityfs" {
|
||||||
appArmorFS := path.Join(fields[1], "apparmor")
|
appArmorFS := path.Join(fields[1], "apparmor")
|
||||||
if ok, err := utilfile.FileExists(appArmorFS); !ok {
|
if ok, err := utilpath.Exists(utilpath.CheckFollowSymlink, appArmorFS); !ok {
|
||||||
msg := fmt.Sprintf("path %s does not exist", appArmorFS)
|
msg := fmt.Sprintf("path %s does not exist", appArmorFS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("%s: %v", msg, err)
|
return "", fmt.Errorf("%s: %v", msg, err)
|
||||||
|
|
|
@ -20,7 +20,6 @@ filegroup(
|
||||||
"//pkg/util/dbus:all-srcs",
|
"//pkg/util/dbus:all-srcs",
|
||||||
"//pkg/util/ebtables:all-srcs",
|
"//pkg/util/ebtables:all-srcs",
|
||||||
"//pkg/util/env:all-srcs",
|
"//pkg/util/env:all-srcs",
|
||||||
"//pkg/util/file:all-srcs",
|
|
||||||
"//pkg/util/filesystem:all-srcs",
|
"//pkg/util/filesystem:all-srcs",
|
||||||
"//pkg/util/flag:all-srcs",
|
"//pkg/util/flag:all-srcs",
|
||||||
"//pkg/util/flock:all-srcs",
|
"//pkg/util/flock:all-srcs",
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
package(default_visibility = ["//visibility:public"])
|
|
||||||
|
|
||||||
load(
|
|
||||||
"@io_bazel_rules_go//go:def.bzl",
|
|
||||||
"go_library",
|
|
||||||
"go_test",
|
|
||||||
)
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = ["file.go"],
|
|
||||||
importpath = "k8s.io/kubernetes/pkg/util/file",
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_test(
|
|
||||||
name = "go_default_test",
|
|
||||||
srcs = ["file_test.go"],
|
|
||||||
embed = [":go_default_library"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/github.com/spf13/afero:go_default_library",
|
|
||||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
|
@ -1,57 +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 file
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileExists checks if specified file exists.
|
|
||||||
func FileExists(filename string) (bool, error) {
|
|
||||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
|
||||||
return false, nil
|
|
||||||
} else if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileOrSymlinkExists checks if specified file or symlink exists.
|
|
||||||
func FileOrSymlinkExists(filename string) (bool, error) {
|
|
||||||
if _, err := os.Lstat(filename); os.IsNotExist(err) {
|
|
||||||
return false, nil
|
|
||||||
} else if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadDirNoStat returns a string of files/directories contained
|
|
||||||
// in dirname without calling lstat on them.
|
|
||||||
func ReadDirNoStat(dirname string) ([]string, error) {
|
|
||||||
if dirname == "" {
|
|
||||||
dirname = "."
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Open(dirname)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
return f.Readdirnames(-1)
|
|
||||||
}
|
|
|
@ -1,149 +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 file
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/spf13/afero"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func RecoverEnv(wd, tmpDir string) {
|
|
||||||
os.Chdir(wd)
|
|
||||||
os.RemoveAll(tmpDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileUtils(t *testing.T) {
|
|
||||||
fs := &afero.Afero{Fs: afero.NewOsFs()}
|
|
||||||
// Create tmp dir
|
|
||||||
tmpDir, err := fs.TempDir(os.TempDir(), "util_file_test_")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Failed to test: failed to create temp dir.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// create tmp file
|
|
||||||
tmpFile, err := fs.TempFile(tmpDir, "test_file_exists_")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Failed to test: failed to create temp file.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// create tmp sym link
|
|
||||||
tmpSymlinkName := filepath.Join(tmpDir, "test_file_exists_sym_link")
|
|
||||||
err = os.Symlink(tmpFile.Name(), tmpSymlinkName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Failed to test: failed to create sym link.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// create tmp sub dir
|
|
||||||
tmpSubDir, err := fs.TempDir(tmpDir, "sub_")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Failed to test: failed to create temp sub dir.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// record the current dir
|
|
||||||
currentDir, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Failed to test: failed to get current dir.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// change the work dir to temp dir
|
|
||||||
err = os.Chdir(tmpDir)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Failed to test: failed to change work dir.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// recover test environment
|
|
||||||
defer RecoverEnv(currentDir, tmpDir)
|
|
||||||
|
|
||||||
t.Run("TestFileExists", func(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
fileName string
|
|
||||||
expectedError bool
|
|
||||||
expectedValue bool
|
|
||||||
}{
|
|
||||||
{"file_not_exists", filepath.Join(tmpDir, "file_not_exist_case"), false, false},
|
|
||||||
{"file_exists", tmpFile.Name(), false, true},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
realValued, realError := FileExists(test.fileName)
|
|
||||||
if test.expectedError {
|
|
||||||
assert.Errorf(t, realError, "Failed to test with '%s': %s", test.fileName, test.name)
|
|
||||||
} else {
|
|
||||||
assert.EqualValuesf(t, test.expectedValue, realValued, "Failed to test with '%s': %s", test.fileName, test.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("TestFileOrSymlinkExists", func(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
fileName string
|
|
||||||
expectedError bool
|
|
||||||
expectedValue bool
|
|
||||||
}{
|
|
||||||
{"file_not_exists", filepath.Join(tmpDir, "file_not_exist_case"), false, false},
|
|
||||||
{"file_exists", tmpFile.Name(), false, true},
|
|
||||||
{"symlink_exists", tmpSymlinkName, false, true},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
realValued, realError := FileOrSymlinkExists(test.fileName)
|
|
||||||
if test.expectedError {
|
|
||||||
assert.Errorf(t, realError, "Failed to test with '%s': %s", test.fileName, test.name)
|
|
||||||
} else {
|
|
||||||
assert.EqualValuesf(t, test.expectedValue, realValued, "Failed to test with '%s': %s", test.fileName, test.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("TestReadDirNoStat", func(t *testing.T) {
|
|
||||||
_, tmpFileSimpleName := filepath.Split(tmpFile.Name())
|
|
||||||
_, tmpSymlinkSimpleName := filepath.Split(tmpSymlinkName)
|
|
||||||
_, tmpSubDirSimpleName := filepath.Split(tmpSubDir)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
dirName string
|
|
||||||
expectedError bool
|
|
||||||
expectedValue []string
|
|
||||||
}{
|
|
||||||
{"dir_not_exists", filepath.Join(tmpDir, "file_not_exist_case"), true, []string{}},
|
|
||||||
{"dir_is_empty", "", false, []string{tmpFileSimpleName, tmpSymlinkSimpleName, tmpSubDirSimpleName}},
|
|
||||||
{"dir_exists", tmpDir, false, []string{tmpFileSimpleName, tmpSymlinkSimpleName, tmpSubDirSimpleName}},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
realValued, realError := ReadDirNoStat(test.dirName)
|
|
||||||
|
|
||||||
// execute sort action before compare
|
|
||||||
sort.Strings(realValued)
|
|
||||||
sort.Strings(test.expectedValue)
|
|
||||||
|
|
||||||
if test.expectedError {
|
|
||||||
assert.Errorf(t, realError, "Failed to test with '%s': %s", test.dirName, test.name)
|
|
||||||
} else {
|
|
||||||
assert.EqualValuesf(t, test.expectedValue, realValued, "Failed to test with '%s': %s", test.dirName, test.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -35,11 +35,11 @@ go_library(
|
||||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||||
],
|
],
|
||||||
"@io_bazel_rules_go//go/platform:linux": [
|
"@io_bazel_rules_go//go/platform:linux": [
|
||||||
"//pkg/util/file:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||||
"//vendor/k8s.io/utils/io:go_default_library",
|
"//vendor/k8s.io/utils/io:go_default_library",
|
||||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/path:go_default_library",
|
||||||
],
|
],
|
||||||
"@io_bazel_rules_go//go/platform:nacl": [
|
"@io_bazel_rules_go//go/platform:nacl": [
|
||||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||||
|
@ -57,8 +57,8 @@ go_library(
|
||||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||||
],
|
],
|
||||||
"@io_bazel_rules_go//go/platform:windows": [
|
"@io_bazel_rules_go//go/platform:windows": [
|
||||||
"//pkg/util/file:go_default_library",
|
|
||||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/path:go_default_library",
|
||||||
],
|
],
|
||||||
"//conditions:default": [],
|
"//conditions:default": [],
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -33,9 +33,9 @@ import (
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
|
||||||
utilexec "k8s.io/utils/exec"
|
utilexec "k8s.io/utils/exec"
|
||||||
utilio "k8s.io/utils/io"
|
utilio "k8s.io/utils/io"
|
||||||
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -417,7 +417,7 @@ func (mounter *Mounter) MakeFile(pathname string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
||||||
return utilfile.FileExists(pathname)
|
return utilpath.Exists(utilpath.CheckFollowSymlink, pathname)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mounter *Mounter) EvalHostSymlinks(pathname string) (string, error) {
|
func (mounter *Mounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ import (
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
|
||||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mounter provides the default implementation of mount.Interface
|
// Mounter provides the default implementation of mount.Interface
|
||||||
|
@ -235,7 +235,7 @@ func (mounter *Mounter) MakeFile(pathname string) error {
|
||||||
|
|
||||||
// ExistsPath checks whether the path exists
|
// ExistsPath checks whether the path exists
|
||||||
func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
||||||
return utilfile.FileExists(pathname)
|
return utilpath.Exists(utilpath.CheckFollowSymlink, pathname)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EvalHostSymlinks returns the path name after evaluating symlinks
|
// EvalHostSymlinks returns the path name after evaluating symlinks
|
||||||
|
|
|
@ -27,8 +27,8 @@ import (
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
|
||||||
"k8s.io/utils/nsenter"
|
"k8s.io/utils/nsenter"
|
||||||
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -291,7 +291,7 @@ func (mounter *NsenterMounter) ExistsPath(pathname string) (bool, error) {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
kubeletpath := mounter.ne.KubeletPath(hostPath)
|
kubeletpath := mounter.ne.KubeletPath(hostPath)
|
||||||
return utilfile.FileExists(kubeletpath)
|
return utilpath.Exists(utilpath.CheckFollowSymlink, kubeletpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mounter *NsenterMounter) EvalHostSymlinks(pathname string) (string, error) {
|
func (mounter *NsenterMounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
||||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||||
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package prometheus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
|
"k8s.io/klog"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
@ -133,7 +134,9 @@ func (prometheusMetricsProvider) NewDeprecatedDepthMetric(name string) workqueue
|
||||||
Name: "depth",
|
Name: "depth",
|
||||||
Help: "(Deprecated) Current depth of workqueue: " + name,
|
Help: "(Deprecated) Current depth of workqueue: " + name,
|
||||||
})
|
})
|
||||||
prometheus.Register(depth)
|
if err := prometheus.Register(depth); err != nil {
|
||||||
|
klog.Errorf("failed to register depth metric %v: %v", name, err)
|
||||||
|
}
|
||||||
return depth
|
return depth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +146,9 @@ func (prometheusMetricsProvider) NewDeprecatedAddsMetric(name string) workqueue.
|
||||||
Name: "adds",
|
Name: "adds",
|
||||||
Help: "(Deprecated) Total number of adds handled by workqueue: " + name,
|
Help: "(Deprecated) Total number of adds handled by workqueue: " + name,
|
||||||
})
|
})
|
||||||
prometheus.Register(adds)
|
if err := prometheus.Register(adds); err != nil {
|
||||||
|
klog.Errorf("failed to register adds metric %v: %v", name, err)
|
||||||
|
}
|
||||||
return adds
|
return adds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +158,9 @@ func (prometheusMetricsProvider) NewDeprecatedLatencyMetric(name string) workque
|
||||||
Name: "queue_latency",
|
Name: "queue_latency",
|
||||||
Help: "(Deprecated) How long an item stays in workqueue" + name + " before being requested.",
|
Help: "(Deprecated) How long an item stays in workqueue" + name + " before being requested.",
|
||||||
})
|
})
|
||||||
prometheus.Register(latency)
|
if err := prometheus.Register(latency); err != nil {
|
||||||
|
klog.Errorf("failed to register latency metric %v: %v", name, err)
|
||||||
|
}
|
||||||
return latency
|
return latency
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +170,9 @@ func (prometheusMetricsProvider) NewDeprecatedWorkDurationMetric(name string) wo
|
||||||
Name: "work_duration",
|
Name: "work_duration",
|
||||||
Help: "(Deprecated) How long processing an item from workqueue" + name + " takes.",
|
Help: "(Deprecated) How long processing an item from workqueue" + name + " takes.",
|
||||||
})
|
})
|
||||||
prometheus.Register(workDuration)
|
if err := prometheus.Register(workDuration); err != nil {
|
||||||
|
klog.Errorf("failed to register work_duration metric %v: %v", name, err)
|
||||||
|
}
|
||||||
return workDuration
|
return workDuration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +185,9 @@ func (prometheusMetricsProvider) NewDeprecatedUnfinishedWorkSecondsMetric(name s
|
||||||
"values indicate stuck threads. One can deduce the number of stuck " +
|
"values indicate stuck threads. One can deduce the number of stuck " +
|
||||||
"threads by observing the rate at which this increases.",
|
"threads by observing the rate at which this increases.",
|
||||||
})
|
})
|
||||||
prometheus.Register(unfinished)
|
if err := prometheus.Register(unfinished); err != nil {
|
||||||
|
klog.Errorf("failed to register unfinished_work_seconds metric %v: %v", name, err)
|
||||||
|
}
|
||||||
return unfinished
|
return unfinished
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +198,9 @@ func (prometheusMetricsProvider) NewDeprecatedLongestRunningProcessorMicrosecond
|
||||||
Help: "(Deprecated) How many microseconds has the longest running " +
|
Help: "(Deprecated) How many microseconds has the longest running " +
|
||||||
"processor for " + name + " been running.",
|
"processor for " + name + " been running.",
|
||||||
})
|
})
|
||||||
prometheus.Register(unfinished)
|
if err := prometheus.Register(unfinished); err != nil {
|
||||||
|
klog.Errorf("failed to register longest_running_processor_microseconds metric %v: %v", name, err)
|
||||||
|
}
|
||||||
return unfinished
|
return unfinished
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +210,8 @@ func (prometheusMetricsProvider) NewDeprecatedRetriesMetric(name string) workque
|
||||||
Name: "retries",
|
Name: "retries",
|
||||||
Help: "(Deprecated) Total number of retries handled by workqueue: " + name,
|
Help: "(Deprecated) Total number of retries handled by workqueue: " + name,
|
||||||
})
|
})
|
||||||
prometheus.Register(retries)
|
if err := prometheus.Register(retries); err != nil {
|
||||||
|
klog.Errorf("failed to register retries metric %v: %v", name, err)
|
||||||
|
}
|
||||||
return retries
|
return retries
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ go_library(
|
||||||
"//pkg/cloudprovider/providers/gce:go_default_library",
|
"//pkg/cloudprovider/providers/gce:go_default_library",
|
||||||
"//pkg/features:go_default_library",
|
"//pkg/features:go_default_library",
|
||||||
"//pkg/kubelet/apis:go_default_library",
|
"//pkg/kubelet/apis:go_default_library",
|
||||||
"//pkg/util/file:go_default_library",
|
|
||||||
"//pkg/util/mount:go_default_library",
|
"//pkg/util/mount:go_default_library",
|
||||||
"//pkg/volume:go_default_library",
|
"//pkg/volume:go_default_library",
|
||||||
"//pkg/volume/util:go_default_library",
|
"//pkg/volume/util:go_default_library",
|
||||||
|
@ -35,6 +34,7 @@ go_library(
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
"//vendor/k8s.io/utils/strings:go_default_library",
|
"//vendor/k8s.io/utils/strings:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/path:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,11 @@ import (
|
||||||
gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
|
gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
"k8s.io/utils/exec"
|
"k8s.io/utils/exec"
|
||||||
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -236,7 +236,7 @@ func verifyDevicePath(devicePaths []string, sdBeforeSet sets.String, diskName st
|
||||||
|
|
||||||
// Calls scsi_id on the given devicePath to get the serial number reported by that device.
|
// Calls scsi_id on the given devicePath to get the serial number reported by that device.
|
||||||
func getScsiSerial(devicePath, diskName string) (string, error) {
|
func getScsiSerial(devicePath, diskName string) (string, error) {
|
||||||
exists, err := utilfile.FileExists("/lib/udev/scsi_id")
|
exists, err := utilpath.Exists(utilpath.CheckFollowSymlink, "/lib/udev/scsi_id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to check scsi_id existence: %v", err)
|
return "", fmt.Errorf("failed to check scsi_id existence: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ go_test(
|
||||||
srcs = ["host_path_test.go"],
|
srcs = ["host_path_test.go"],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/util/file:go_default_library",
|
|
||||||
"//pkg/util/mount:go_default_library",
|
"//pkg/util/mount:go_default_library",
|
||||||
"//pkg/volume:go_default_library",
|
"//pkg/volume:go_default_library",
|
||||||
"//pkg/volume/testing:go_default_library",
|
"//pkg/volume/testing:go_default_library",
|
||||||
|
@ -41,6 +40,7 @@ go_test(
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/path:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,10 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
|
||||||
utilmount "k8s.io/kubernetes/pkg/util/mount"
|
utilmount "k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newHostPathType(pathType string) *v1.HostPathType {
|
func newHostPathType(pathType string) *v1.HostPathType {
|
||||||
|
@ -122,7 +122,7 @@ func TestDeleter(t *testing.T) {
|
||||||
if err := deleter.Delete(); err != nil {
|
if err := deleter.Delete(); err != nil {
|
||||||
t.Errorf("Mock Recycler expected to return nil but got %s", err)
|
t.Errorf("Mock Recycler expected to return nil but got %s", err)
|
||||||
}
|
}
|
||||||
if exists, _ := utilfile.FileExists(tempPath); exists {
|
if exists, _ := utilpath.Exists(utilpath.CheckFollowSymlink, tempPath); exists {
|
||||||
t.Errorf("Temp path expected to be deleted, but was found at %s", tempPath)
|
t.Errorf("Temp path expected to be deleted, but was found at %s", tempPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ go_library(
|
||||||
importpath = "k8s.io/kubernetes/pkg/volume/rbd",
|
importpath = "k8s.io/kubernetes/pkg/volume/rbd",
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/features:go_default_library",
|
"//pkg/features:go_default_library",
|
||||||
"//pkg/util/file:go_default_library",
|
|
||||||
"//pkg/util/mount:go_default_library",
|
"//pkg/util/mount:go_default_library",
|
||||||
"//pkg/util/node:go_default_library",
|
"//pkg/util/node:go_default_library",
|
||||||
"//pkg/volume:go_default_library",
|
"//pkg/volume:go_default_library",
|
||||||
|
@ -36,6 +35,7 @@ go_library(
|
||||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
"//vendor/k8s.io/utils/strings:go_default_library",
|
"//vendor/k8s.io/utils/strings:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/path:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,11 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/util/errors"
|
"k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
fileutil "k8s.io/kubernetes/pkg/util/file"
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/util/node"
|
"k8s.io/kubernetes/pkg/util/node"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volutil "k8s.io/kubernetes/pkg/volume/util"
|
volutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -486,7 +486,7 @@ func (util *RBDUtil) DetachDisk(plugin *rbdPlugin, deviceMountPath string, devic
|
||||||
// Currently, we don't persist rbd info on the disk, but for backward
|
// Currently, we don't persist rbd info on the disk, but for backward
|
||||||
// compatbility, we need to clean it if found.
|
// compatbility, we need to clean it if found.
|
||||||
rbdFile := path.Join(deviceMountPath, "rbd.json")
|
rbdFile := path.Join(deviceMountPath, "rbd.json")
|
||||||
exists, err := fileutil.FileExists(rbdFile)
|
exists, err := utilpath.Exists(utilpath.CheckFollowSymlink, rbdFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,19 @@
|
||||||
This repo is still in the experimental stage. Shortly it will contain the schema of the API that are served by the Kubernetes apiserver.
|
# api
|
||||||
|
|
||||||
|
Schema of the external API types that are served by the Kubernetes API server.
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
This library is the canonical location of the Kubernetes API definition. Most likely interaction with this repository is as a dependency of client-go.
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
Branches track Kubernetes branches and are compatible with that repo.
|
||||||
|
|
||||||
|
## Where does it come from?
|
||||||
|
|
||||||
|
`api` is synced from https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/api. Code changes are made in that location, merged into `k8s.io/kubernetes` and later synced here.
|
||||||
|
|
||||||
|
## Things you should *NOT* do
|
||||||
|
|
||||||
|
1. https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/api is synced to k8s.io/api. All changes must be made in the former. The latter is read-only.
|
||||||
|
|
|
@ -372,7 +372,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/ghodss/yaml",
|
"ImportPath": "github.com/ghodss/yaml",
|
||||||
|
|
|
@ -18,17 +18,17 @@ set -o errexit
|
||||||
set -o nounset
|
set -o nounset
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/..
|
SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
|
||||||
CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
|
CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
|
||||||
|
|
||||||
# generate the code with:
|
# generate the code with:
|
||||||
# --output-base because this script should also be able to run inside the vendor dir of
|
# --output-base because this script should also be able to run inside the vendor dir of
|
||||||
# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
|
# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
|
||||||
# instead of the $GOPATH directly. For normal projects this can be dropped.
|
# instead of the $GOPATH directly. For normal projects this can be dropped.
|
||||||
${CODEGEN_PKG}/generate-groups.sh all \
|
"${CODEGEN_PKG}/generate-groups.sh" all \
|
||||||
k8s.io/apiextensions-apiserver/examples/client-go/pkg/client k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis \
|
k8s.io/apiextensions-apiserver/examples/client-go/pkg/client k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis \
|
||||||
cr:v1 \
|
cr:v1 \
|
||||||
--output-base "$(dirname ${BASH_SOURCE})/../../../../.."
|
--output-base "$(dirname "${BASH_SOURCE[0]}")/../../../../.."
|
||||||
|
|
||||||
# To use your own boilerplate text append:
|
# To use your own boilerplate text append:
|
||||||
# --go-header-file ${SCRIPT_ROOT}/hack/custom-boilerplate.go.txt
|
# --go-header-file ${SCRIPT_ROOT}/hack/custom-boilerplate.go.txt
|
||||||
|
|
|
@ -18,7 +18,7 @@ set -o errexit
|
||||||
set -o nounset
|
set -o nounset
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/..
|
SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
|
||||||
|
|
||||||
DIFFROOT="${SCRIPT_ROOT}/pkg"
|
DIFFROOT="${SCRIPT_ROOT}/pkg"
|
||||||
TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg"
|
TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg"
|
||||||
|
|
|
@ -14,8 +14,11 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../../../../..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/../../../../..
|
||||||
source "${KUBE_ROOT}/hack/lib/util.sh"
|
source "${KUBE_ROOT}/hack/lib/util.sh"
|
||||||
|
|
||||||
# Register function to be called on EXIT to remove generated binary.
|
# Register function to be called on EXIT to remove generated binary.
|
||||||
|
|
|
@ -18,8 +18,8 @@ set -o errexit
|
||||||
set -o nounset
|
set -o nounset
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/..
|
SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
|
||||||
CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
|
CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
|
||||||
|
|
||||||
# generate the code with:
|
# generate the code with:
|
||||||
# --output-base because this script should also be able to run inside the vendor dir of
|
# --output-base because this script should also be able to run inside the vendor dir of
|
||||||
|
@ -27,8 +27,8 @@ CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-ge
|
||||||
# instead of the $GOPATH directly. For normal projects this can be dropped.
|
# instead of the $GOPATH directly. For normal projects this can be dropped.
|
||||||
CLIENTSET_NAME_VERSIONED=clientset \
|
CLIENTSET_NAME_VERSIONED=clientset \
|
||||||
CLIENTSET_NAME_INTERNAL=internalclientset \
|
CLIENTSET_NAME_INTERNAL=internalclientset \
|
||||||
${CODEGEN_PKG}/generate-internal-groups.sh all \
|
"${CODEGEN_PKG}/generate-internal-groups.sh" all \
|
||||||
k8s.io/apiextensions-apiserver/pkg/client k8s.io/apiextensions-apiserver/pkg/apis k8s.io/apiextensions-apiserver/pkg/apis \
|
k8s.io/apiextensions-apiserver/pkg/client k8s.io/apiextensions-apiserver/pkg/apis k8s.io/apiextensions-apiserver/pkg/apis \
|
||||||
"apiextensions:v1beta1" \
|
"apiextensions:v1beta1" \
|
||||||
--output-base "$(dirname ${BASH_SOURCE})/../../.." \
|
--output-base "$(dirname "${BASH_SOURCE[0]}")/../../.." \
|
||||||
--go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt
|
--go-header-file "${SCRIPT_ROOT}/hack/boilerplate.go.txt"
|
||||||
|
|
|
@ -18,8 +18,7 @@ set -o errexit
|
||||||
set -o nounset
|
set -o nounset
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/..
|
SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
|
||||||
SCRIPT_BASE=${SCRIPT_ROOT}/../..
|
|
||||||
|
|
||||||
DIFFROOT="${SCRIPT_ROOT}/pkg"
|
DIFFROOT="${SCRIPT_ROOT}/pkg"
|
||||||
TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg"
|
TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg"
|
||||||
|
|
|
@ -79,7 +79,7 @@ func NewCRDFinalizer(
|
||||||
crdLister: crdInformer.Lister(),
|
crdLister: crdInformer.Lister(),
|
||||||
crdSynced: crdInformer.Informer().HasSynced,
|
crdSynced: crdInformer.Informer().HasSynced,
|
||||||
crClientGetter: crClientGetter,
|
crClientGetter: crClientGetter,
|
||||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "CustomResourceDefinition-CRDFinalizer"),
|
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "crd_finalizer"),
|
||||||
}
|
}
|
||||||
|
|
||||||
crdInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
crdInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||||
|
|
|
@ -66,7 +66,7 @@ func NewNamingConditionController(
|
||||||
crdClient: crdClient,
|
crdClient: crdClient,
|
||||||
crdLister: crdInformer.Lister(),
|
crdLister: crdInformer.Lister(),
|
||||||
crdSynced: crdInformer.Informer().HasSynced,
|
crdSynced: crdInformer.Informer().HasSynced,
|
||||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "CustomResourceDefinition-NamingConditionController"),
|
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "crd_naming_condition_controller"),
|
||||||
}
|
}
|
||||||
|
|
||||||
informerIndexer := crdInformer.Informer().GetIndexer()
|
informerIndexer := crdInformer.Informer().GetIndexer()
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/gogo/protobuf/proto",
|
"ImportPath": "github.com/gogo/protobuf/proto",
|
||||||
|
|
|
@ -9,6 +9,7 @@ load(
|
||||||
go_test(
|
go_test(
|
||||||
name = "go_default_test",
|
name = "go_default_test",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"codec_test.go",
|
||||||
"conversion_test.go",
|
"conversion_test.go",
|
||||||
"converter_test.go",
|
"converter_test.go",
|
||||||
"embedded_test.go",
|
"embedded_test.go",
|
||||||
|
|
|
@ -283,6 +283,7 @@ var _ GroupVersioner = multiGroupVersioner{}
|
||||||
type multiGroupVersioner struct {
|
type multiGroupVersioner struct {
|
||||||
target schema.GroupVersion
|
target schema.GroupVersion
|
||||||
acceptedGroupKinds []schema.GroupKind
|
acceptedGroupKinds []schema.GroupKind
|
||||||
|
coerce bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMultiGroupVersioner returns the provided group version for any kind that matches one of the provided group kinds.
|
// NewMultiGroupVersioner returns the provided group version for any kind that matches one of the provided group kinds.
|
||||||
|
@ -294,6 +295,22 @@ func NewMultiGroupVersioner(gv schema.GroupVersion, groupKinds ...schema.GroupKi
|
||||||
return multiGroupVersioner{target: gv, acceptedGroupKinds: groupKinds}
|
return multiGroupVersioner{target: gv, acceptedGroupKinds: groupKinds}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewCoercingMultiGroupVersioner returns the provided group version for any incoming kind.
|
||||||
|
// Incoming kinds that match the provided groupKinds are preferred.
|
||||||
|
// Kind may be empty in the provided group kind, in which case any kind will match.
|
||||||
|
// Examples:
|
||||||
|
// gv=mygroup/__internal, groupKinds=mygroup/Foo, anothergroup/Bar
|
||||||
|
// KindForGroupVersionKinds(yetanother/v1/Baz, anothergroup/v1/Bar) -> mygroup/__internal/Bar (matched preferred group/kind)
|
||||||
|
//
|
||||||
|
// gv=mygroup/__internal, groupKinds=mygroup, anothergroup
|
||||||
|
// KindForGroupVersionKinds(yetanother/v1/Baz, anothergroup/v1/Bar) -> mygroup/__internal/Bar (matched preferred group)
|
||||||
|
//
|
||||||
|
// gv=mygroup/__internal, groupKinds=mygroup, anothergroup
|
||||||
|
// KindForGroupVersionKinds(yetanother/v1/Baz, yetanother/v1/Bar) -> mygroup/__internal/Baz (no preferred group/kind match, uses first kind in list)
|
||||||
|
func NewCoercingMultiGroupVersioner(gv schema.GroupVersion, groupKinds ...schema.GroupKind) GroupVersioner {
|
||||||
|
return multiGroupVersioner{target: gv, acceptedGroupKinds: groupKinds, coerce: true}
|
||||||
|
}
|
||||||
|
|
||||||
// KindForGroupVersionKinds returns the target group version if any kind matches any of the original group kinds. It will
|
// KindForGroupVersionKinds returns the target group version if any kind matches any of the original group kinds. It will
|
||||||
// use the originating kind where possible.
|
// use the originating kind where possible.
|
||||||
func (v multiGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (schema.GroupVersionKind, bool) {
|
func (v multiGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (schema.GroupVersionKind, bool) {
|
||||||
|
@ -308,5 +325,8 @@ func (v multiGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersio
|
||||||
return v.target.WithKind(src.Kind), true
|
return v.target.WithKind(src.Kind), true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if v.coerce && len(kinds) > 0 {
|
||||||
|
return v.target.WithKind(kinds[0].Kind), true
|
||||||
|
}
|
||||||
return schema.GroupVersionKind{}, false
|
return schema.GroupVersionKind{}, false
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func gv(group, version string) schema.GroupVersion {
|
||||||
|
return schema.GroupVersion{Group: group, Version: version}
|
||||||
|
}
|
||||||
|
func gvk(group, version, kind string) schema.GroupVersionKind {
|
||||||
|
return schema.GroupVersionKind{Group: group, Version: version, Kind: kind}
|
||||||
|
}
|
||||||
|
func gk(group, kind string) schema.GroupKind {
|
||||||
|
return schema.GroupKind{Group: group, Kind: kind}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCoercingMultiGroupVersioner(t *testing.T) {
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
target schema.GroupVersion
|
||||||
|
preferredKinds []schema.GroupKind
|
||||||
|
kinds []schema.GroupVersionKind
|
||||||
|
expectKind schema.GroupVersionKind
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "matched preferred group/kind",
|
||||||
|
target: gv("mygroup", "__internal"),
|
||||||
|
preferredKinds: []schema.GroupKind{gk("mygroup", "Foo"), gk("anothergroup", "Bar")},
|
||||||
|
kinds: []schema.GroupVersionKind{gvk("yetanother", "v1", "Baz"), gvk("anothergroup", "v1", "Bar")},
|
||||||
|
expectKind: gvk("mygroup", "__internal", "Bar"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "matched preferred group",
|
||||||
|
target: gv("mygroup", "__internal"),
|
||||||
|
preferredKinds: []schema.GroupKind{gk("mygroup", ""), gk("anothergroup", "")},
|
||||||
|
kinds: []schema.GroupVersionKind{gvk("yetanother", "v1", "Baz"), gvk("anothergroup", "v1", "Bar")},
|
||||||
|
expectKind: gvk("mygroup", "__internal", "Bar"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no preferred group/kind match, uses first kind in list",
|
||||||
|
target: gv("mygroup", "__internal"),
|
||||||
|
preferredKinds: []schema.GroupKind{gk("mygroup", ""), gk("anothergroup", "")},
|
||||||
|
kinds: []schema.GroupVersionKind{gvk("yetanother", "v1", "Baz"), gvk("yetanother", "v1", "Bar")},
|
||||||
|
expectKind: gvk("mygroup", "__internal", "Baz"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testcases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
v := NewCoercingMultiGroupVersioner(tc.target, tc.preferredKinds...)
|
||||||
|
kind, ok := v.KindForGroupVersionKinds(tc.kinds)
|
||||||
|
if !ok {
|
||||||
|
t.Error("got no kind")
|
||||||
|
}
|
||||||
|
if kind != tc.expectKind {
|
||||||
|
t.Errorf("expected %#v, got %#v", tc.expectKind, kind)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -372,7 +372,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/ghodss/yaml",
|
"ImportPath": "github.com/ghodss/yaml",
|
||||||
|
|
|
@ -85,7 +85,7 @@ func NewStorageCodec(opts StorageCodecConfig) (runtime.Codec, error) {
|
||||||
)
|
)
|
||||||
decoder := opts.StorageSerializer.DecoderToVersion(
|
decoder := opts.StorageSerializer.DecoderToVersion(
|
||||||
recognizer.NewDecoder(decoders...),
|
recognizer.NewDecoder(decoders...),
|
||||||
runtime.NewMultiGroupVersioner(
|
runtime.NewCoercingMultiGroupVersioner(
|
||||||
opts.MemoryVersion,
|
opts.MemoryVersion,
|
||||||
schema.GroupKind{Group: opts.MemoryVersion.Group},
|
schema.GroupKind{Group: opts.MemoryVersion.Group},
|
||||||
schema.GroupKind{Group: opts.StorageVersion.Group},
|
schema.GroupKind{Group: opts.StorageVersion.Group},
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/gogo/protobuf/proto",
|
"ImportPath": "github.com/gogo/protobuf/proto",
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/gogo/protobuf/proto",
|
"ImportPath": "github.com/gogo/protobuf/proto",
|
||||||
|
|
|
@ -148,12 +148,19 @@ func (c *threadSafeMap) Index(indexName string, obj interface{}) ([]interface{},
|
||||||
}
|
}
|
||||||
index := c.indices[indexName]
|
index := c.indices[indexName]
|
||||||
|
|
||||||
// need to de-dupe the return list. Since multiple keys are allowed, this can happen.
|
var returnKeySet sets.String
|
||||||
returnKeySet := sets.String{}
|
if len(indexKeys) == 1 {
|
||||||
for _, indexKey := range indexKeys {
|
// In majority of cases, there is exactly one value matching.
|
||||||
set := index[indexKey]
|
// Optimize the most common path - deduping is not needed here.
|
||||||
for _, key := range set.UnsortedList() {
|
returnKeySet = index[indexKeys[0]]
|
||||||
returnKeySet.Insert(key)
|
} else {
|
||||||
|
// Need to de-dupe the return list.
|
||||||
|
// Since multiple keys are allowed, this can happen.
|
||||||
|
returnKeySet = sets.String{}
|
||||||
|
for _, indexKey := range indexKeys {
|
||||||
|
for key := range index[indexKey] {
|
||||||
|
returnKeySet.Insert(key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,9 @@ filegroup(
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "all-srcs",
|
name = "all-srcs",
|
||||||
srcs = [":package-srcs"],
|
srcs = [
|
||||||
|
":package-srcs",
|
||||||
|
"//staging/src/k8s.io/cloud-provider/node:all-srcs",
|
||||||
|
],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
)
|
)
|
||||||
|
|
|
@ -286,6 +286,10 @@
|
||||||
"ImportPath": "k8s.io/api/storage/v1beta1",
|
"ImportPath": "k8s.io/api/storage/v1beta1",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
|
||||||
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/api/errors",
|
"ImportPath": "k8s.io/apimachinery/pkg/api/errors",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
@ -398,6 +402,10 @@
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/json",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/json",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
|
||||||
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/naming",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/naming",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
@ -414,6 +422,10 @@
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
|
||||||
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
@ -438,6 +450,10 @@
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/watch",
|
"ImportPath": "k8s.io/apimachinery/pkg/watch",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
|
||||||
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
|
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
@ -950,6 +966,10 @@
|
||||||
"ImportPath": "k8s.io/klog",
|
"ImportPath": "k8s.io/klog",
|
||||||
"Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f"
|
"Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
||||||
|
"Rev": "ced9eb3070a5f1c548ef46e8dfe2a97c208d9f03"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/utils/buffer",
|
"ImportPath": "k8s.io/utils/buffer",
|
||||||
"Rev": "ed37f7428a91fc2a81070808937195dcd46d320e"
|
"Rev": "ed37f7428a91fc2a81070808937195dcd46d320e"
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [
|
||||||
|
":package-srcs",
|
||||||
|
"//staging/src/k8s.io/cloud-provider/node/helpers:all-srcs",
|
||||||
|
],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
|
@ -0,0 +1,33 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["taints.go"],
|
||||||
|
importmap = "k8s.io/kubernetes/vendor/k8s.io/cloud-provider/node/helpers",
|
||||||
|
importpath = "k8s.io/cloud-provider/node/helpers",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
|
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
|
"//staging/src/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"],
|
||||||
|
)
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
NOTE: the contents of this file has been copied from k8s.io/kubernetes/pkg/controller
|
||||||
|
and k8s.io/kubernetes/pkg/util/taints. The reason for duplicating this code is to remove
|
||||||
|
dependencies to k8s.io/kubernetes in all the cloud providers. Once k8s.io/kubernetes/pkg/util/taints
|
||||||
|
is moved to an external repository, this file should be removed and replaced with that one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helpers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/equality"
|
||||||
|
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"
|
||||||
|
clientretry "k8s.io/client-go/util/retry"
|
||||||
|
)
|
||||||
|
|
||||||
|
var updateTaintBackoff = wait.Backoff{
|
||||||
|
Steps: 5,
|
||||||
|
Duration: 100 * time.Millisecond,
|
||||||
|
Jitter: 1.0,
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddOrUpdateTaintOnNode add taints to the node. If taint was added into node, it'll issue API calls
|
||||||
|
// to update nodes; otherwise, no API calls. Return error if any.
|
||||||
|
func AddOrUpdateTaintOnNode(c clientset.Interface, nodeName string, taints ...*v1.Taint) error {
|
||||||
|
if len(taints) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
firstTry := true
|
||||||
|
return clientretry.RetryOnConflict(updateTaintBackoff, func() error {
|
||||||
|
var err error
|
||||||
|
var oldNode *v1.Node
|
||||||
|
// First we try getting node from the API server cache, as it's cheaper. If it fails
|
||||||
|
// we get it from etcd to be sure to have fresh data.
|
||||||
|
if firstTry {
|
||||||
|
oldNode, err = c.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{ResourceVersion: "0"})
|
||||||
|
firstTry = false
|
||||||
|
} else {
|
||||||
|
oldNode, err = c.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{})
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var newNode *v1.Node
|
||||||
|
oldNodeCopy := oldNode
|
||||||
|
updated := false
|
||||||
|
for _, taint := range taints {
|
||||||
|
curNewNode, ok, err := addOrUpdateTaint(oldNodeCopy, taint)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to update taint of node")
|
||||||
|
}
|
||||||
|
updated = updated || ok
|
||||||
|
newNode = curNewNode
|
||||||
|
oldNodeCopy = curNewNode
|
||||||
|
}
|
||||||
|
if !updated {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return PatchNodeTaints(c, nodeName, oldNode, newNode)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// PatchNodeTaints patches node's taints.
|
||||||
|
func PatchNodeTaints(c clientset.Interface, nodeName string, oldNode *v1.Node, newNode *v1.Node) error {
|
||||||
|
oldData, err := json.Marshal(oldNode)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to marshal old node %#v for node %q: %v", oldNode, nodeName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
newTaints := newNode.Spec.Taints
|
||||||
|
newNodeClone := oldNode.DeepCopy()
|
||||||
|
newNodeClone.Spec.Taints = newTaints
|
||||||
|
newData, err := json.Marshal(newNodeClone)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to marshal new node %#v for node %q: %v", newNodeClone, nodeName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create patch for node %q: %v", nodeName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.CoreV1().Nodes().Patch(nodeName, types.StrategicMergePatchType, patchBytes)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// addOrUpdateTaint tries to add a taint to annotations list. Returns a new copy of updated Node and true if something was updated
|
||||||
|
// false otherwise.
|
||||||
|
func addOrUpdateTaint(node *v1.Node, taint *v1.Taint) (*v1.Node, bool, error) {
|
||||||
|
newNode := node.DeepCopy()
|
||||||
|
nodeTaints := newNode.Spec.Taints
|
||||||
|
|
||||||
|
var newTaints []v1.Taint
|
||||||
|
updated := false
|
||||||
|
for i := range nodeTaints {
|
||||||
|
if taint.MatchTaint(&nodeTaints[i]) {
|
||||||
|
if equality.Semantic.DeepEqual(*taint, nodeTaints[i]) {
|
||||||
|
return newNode, false, nil
|
||||||
|
}
|
||||||
|
newTaints = append(newTaints, *taint)
|
||||||
|
updated = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newTaints = append(newTaints, nodeTaints[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
if !updated {
|
||||||
|
newTaints = append(newTaints, *taint)
|
||||||
|
}
|
||||||
|
|
||||||
|
newNode.Spec.Taints = newTaints
|
||||||
|
return newNode, true, nil
|
||||||
|
}
|
|
@ -12,7 +12,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/gogo/protobuf/proto",
|
"ImportPath": "github.com/gogo/protobuf/proto",
|
||||||
|
|
|
@ -96,7 +96,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/go-openapi/jsonpointer",
|
"ImportPath": "github.com/go-openapi/jsonpointer",
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/gogo/protobuf/proto",
|
"ImportPath": "github.com/gogo/protobuf/proto",
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/gogo/protobuf/proto",
|
"ImportPath": "github.com/gogo/protobuf/proto",
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/go-openapi/jsonpointer",
|
"ImportPath": "github.com/go-openapi/jsonpointer",
|
||||||
|
|
|
@ -14,8 +14,11 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../../../../..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/../../../../..
|
||||||
source "${KUBE_ROOT}/hack/lib/util.sh"
|
source "${KUBE_ROOT}/hack/lib/util.sh"
|
||||||
|
|
||||||
# Register function to be called on EXIT to remove generated binary.
|
# Register function to be called on EXIT to remove generated binary.
|
||||||
|
|
|
@ -18,24 +18,24 @@ set -o errexit
|
||||||
set -o nounset
|
set -o nounset
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/..
|
SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
|
||||||
CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
|
CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
|
||||||
|
|
||||||
# generate the code with:
|
# generate the code with:
|
||||||
# --output-base because this script should also be able to run inside the vendor dir of
|
# --output-base because this script should also be able to run inside the vendor dir of
|
||||||
# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
|
# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
|
||||||
# instead of the $GOPATH directly. For normal projects this can be dropped.
|
# instead of the $GOPATH directly. For normal projects this can be dropped.
|
||||||
${CODEGEN_PKG}/generate-groups.sh all \
|
"${CODEGEN_PKG}/generate-groups.sh" all \
|
||||||
k8s.io/sample-apiserver/pkg/client k8s.io/sample-apiserver/pkg/apis \
|
k8s.io/sample-apiserver/pkg/client k8s.io/sample-apiserver/pkg/apis \
|
||||||
"wardle:v1alpha1,v1beta1" \
|
"wardle:v1alpha1,v1beta1" \
|
||||||
--output-base "$(dirname ${BASH_SOURCE})/../../.." \
|
--output-base "$(dirname "${BASH_SOURCE[0]}")/../../.." \
|
||||||
--go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt
|
--go-header-file "${SCRIPT_ROOT}"/hack/boilerplate.go.txt
|
||||||
|
|
||||||
${CODEGEN_PKG}/generate-internal-groups.sh "deepcopy,defaulter,conversion" \
|
"${CODEGEN_PKG}/generate-internal-groups.sh" "deepcopy,defaulter,conversion" \
|
||||||
k8s.io/sample-apiserver/pkg/client k8s.io/sample-apiserver/pkg/apis k8s.io/sample-apiserver/pkg/apis \
|
k8s.io/sample-apiserver/pkg/client k8s.io/sample-apiserver/pkg/apis k8s.io/sample-apiserver/pkg/apis \
|
||||||
"wardle:v1alpha1,v1beta1" \
|
"wardle:v1alpha1,v1beta1" \
|
||||||
--output-base "$(dirname ${BASH_SOURCE})/../../.." \
|
--output-base "$(dirname "${BASH_SOURCE[0]}")/../../.." \
|
||||||
--go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt
|
--go-header-file "${SCRIPT_ROOT}/hack/boilerplate.go.txt"
|
||||||
|
|
||||||
# To use your own boilerplate text use:
|
# To use your own boilerplate text use:
|
||||||
# --go-header-file ${SCRIPT_ROOT}/hack/custom-boilerplate.go.txt
|
# --go-header-file "${SCRIPT_ROOT}/hack/custom-boilerplate.go.txt"
|
||||||
|
|
|
@ -18,8 +18,7 @@ set -o errexit
|
||||||
set -o nounset
|
set -o nounset
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/..
|
SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
|
||||||
SCRIPT_BASE=${SCRIPT_ROOT}/../..
|
|
||||||
|
|
||||||
DIFFROOT="${SCRIPT_ROOT}/pkg"
|
DIFFROOT="${SCRIPT_ROOT}/pkg"
|
||||||
TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg"
|
TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/gogo/protobuf/proto",
|
"ImportPath": "github.com/gogo/protobuf/proto",
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/evanphx/json-patch",
|
"ImportPath": "github.com/evanphx/json-patch",
|
||||||
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
|
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/gogo/protobuf/proto",
|
"ImportPath": "github.com/gogo/protobuf/proto",
|
||||||
|
|
|
@ -17,7 +17,9 @@ limitations under the License.
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
|
@ -63,6 +65,51 @@ var CommonImageWhiteList = sets.NewString(
|
||||||
imageutils.GetE2EImage(imageutils.Net),
|
imageutils.GetE2EImage(imageutils.Net),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type testImagesStruct struct {
|
||||||
|
BusyBoxImage string
|
||||||
|
GBFrontendImage string
|
||||||
|
GBRedisSlaveImage string
|
||||||
|
KittenImage string
|
||||||
|
LivenessImage string
|
||||||
|
MounttestImage string
|
||||||
|
NautilusImage string
|
||||||
|
NginxImage string
|
||||||
|
NginxNewImage string
|
||||||
|
PauseImage string
|
||||||
|
RedisImage string
|
||||||
|
}
|
||||||
|
|
||||||
|
var testImages testImagesStruct
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
testImages = testImagesStruct{
|
||||||
|
imageutils.GetE2EImage(imageutils.BusyBox),
|
||||||
|
imageutils.GetE2EImage(imageutils.GBFrontend),
|
||||||
|
imageutils.GetE2EImage(imageutils.GBRedisSlave),
|
||||||
|
imageutils.GetE2EImage(imageutils.Kitten),
|
||||||
|
imageutils.GetE2EImage(imageutils.Liveness),
|
||||||
|
imageutils.GetE2EImage(imageutils.Mounttest),
|
||||||
|
imageutils.GetE2EImage(imageutils.Nautilus),
|
||||||
|
imageutils.GetE2EImage(imageutils.Nginx),
|
||||||
|
imageutils.GetE2EImage(imageutils.NginxNew),
|
||||||
|
imageutils.GetE2EImage(imageutils.Pause),
|
||||||
|
imageutils.GetE2EImage(imageutils.Redis),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SubstituteImageName(content string) string {
|
||||||
|
contentWithImageName := new(bytes.Buffer)
|
||||||
|
tmpl, err := template.New("imagemanifest").Parse(content)
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("Failed Parse the template: %v", err)
|
||||||
|
}
|
||||||
|
err = tmpl.Execute(contentWithImageName, testImages)
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("Failed executing template: %v", err)
|
||||||
|
}
|
||||||
|
return contentWithImageName.String()
|
||||||
|
}
|
||||||
|
|
||||||
func svcByName(name string, port int) *v1.Service {
|
func svcByName(name string, port int) *v1.Service {
|
||||||
return &v1.Service{
|
return &v1.Service{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"k8s.io/apiserver/pkg/authentication/serviceaccount"
|
"k8s.io/apiserver/pkg/authentication/serviceaccount"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||||
|
commonutils "k8s.io/kubernetes/test/e2e/common"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
"k8s.io/kubernetes/test/e2e/framework/testfiles"
|
"k8s.io/kubernetes/test/e2e/framework/testfiles"
|
||||||
|
|
||||||
|
@ -62,8 +63,8 @@ var _ = framework.KubeDescribe("[Feature:Example]", func() {
|
||||||
framework.KubeDescribe("Liveness", func() {
|
framework.KubeDescribe("Liveness", func() {
|
||||||
It("liveness pods should be automatically restarted", func() {
|
It("liveness pods should be automatically restarted", func() {
|
||||||
test := "test/fixtures/doc-yaml/user-guide/liveness"
|
test := "test/fixtures/doc-yaml/user-guide/liveness"
|
||||||
execYaml := readFile(test, "exec-liveness.yaml")
|
execYaml := readFile(test, "exec-liveness.yaml.in")
|
||||||
httpYaml := readFile(test, "http-liveness.yaml")
|
httpYaml := readFile(test, "http-liveness.yaml.in")
|
||||||
nsFlag := fmt.Sprintf("--namespace=%v", ns)
|
nsFlag := fmt.Sprintf("--namespace=%v", ns)
|
||||||
|
|
||||||
framework.RunKubectlOrDieInput(execYaml, "create", "-f", "-", nsFlag)
|
framework.RunKubectlOrDieInput(execYaml, "create", "-f", "-", nsFlag)
|
||||||
|
@ -111,7 +112,7 @@ var _ = framework.KubeDescribe("[Feature:Example]", func() {
|
||||||
It("should create a pod that reads a secret", func() {
|
It("should create a pod that reads a secret", func() {
|
||||||
test := "test/fixtures/doc-yaml/user-guide/secrets"
|
test := "test/fixtures/doc-yaml/user-guide/secrets"
|
||||||
secretYaml := readFile(test, "secret.yaml")
|
secretYaml := readFile(test, "secret.yaml")
|
||||||
podYaml := readFile(test, "secret-pod.yaml")
|
podYaml := readFile(test, "secret-pod.yaml.in")
|
||||||
|
|
||||||
nsFlag := fmt.Sprintf("--namespace=%v", ns)
|
nsFlag := fmt.Sprintf("--namespace=%v", ns)
|
||||||
podName := "secret-test-pod"
|
podName := "secret-test-pod"
|
||||||
|
@ -131,7 +132,7 @@ var _ = framework.KubeDescribe("[Feature:Example]", func() {
|
||||||
framework.KubeDescribe("Downward API", func() {
|
framework.KubeDescribe("Downward API", func() {
|
||||||
It("should create a pod that prints his name and namespace", func() {
|
It("should create a pod that prints his name and namespace", func() {
|
||||||
test := "test/fixtures/doc-yaml/user-guide/downward-api"
|
test := "test/fixtures/doc-yaml/user-guide/downward-api"
|
||||||
podYaml := readFile(test, "dapi-pod.yaml")
|
podYaml := readFile(test, "dapi-pod.yaml.in")
|
||||||
nsFlag := fmt.Sprintf("--namespace=%v", ns)
|
nsFlag := fmt.Sprintf("--namespace=%v", ns)
|
||||||
podName := "dapi-test-pod"
|
podName := "dapi-test-pod"
|
||||||
|
|
||||||
|
@ -151,5 +152,5 @@ var _ = framework.KubeDescribe("[Feature:Example]", func() {
|
||||||
|
|
||||||
func readFile(test, file string) string {
|
func readFile(test, file string) string {
|
||||||
from := filepath.Join(test, file)
|
from := filepath.Join(test, file)
|
||||||
return string(testfiles.ReadOrDie(from, Fail))
|
return commonutils.SubstituteImageName(string(testfiles.ReadOrDie(from, Fail)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,9 @@ var SchedulingLatencyMetricName = model.LabelValue(schedulermetric.SchedulerSubs
|
||||||
|
|
||||||
var InterestingApiServerMetrics = []string{
|
var InterestingApiServerMetrics = []string{
|
||||||
"apiserver_request_total",
|
"apiserver_request_total",
|
||||||
"apiserver_request_latency_seconds_summary",
|
// TODO(krzysied): apiserver_request_latencies_summary is a deprecated metric.
|
||||||
|
// It should be replaced with new metric.
|
||||||
|
"apiserver_request_latencies_summary",
|
||||||
"etcd_helper_cache_entry_total",
|
"etcd_helper_cache_entry_total",
|
||||||
"etcd_helper_cache_hit_total",
|
"etcd_helper_cache_hit_total",
|
||||||
"etcd_helper_cache_miss_total",
|
"etcd_helper_cache_miss_total",
|
||||||
|
@ -475,9 +477,9 @@ func readLatencyMetrics(c clientset.Interface) (*APIResponsiveness, error) {
|
||||||
|
|
||||||
for _, sample := range samples {
|
for _, sample := range samples {
|
||||||
// Example line:
|
// Example line:
|
||||||
// apiserver_request_latency_seconds_summary{resource="namespaces",verb="LIST",quantile="0.99"} 0.000908
|
// apiserver_request_latencies_summary{resource="namespaces",verb="LIST",quantile="0.99"} 908
|
||||||
// apiserver_request_total{resource="pods",verb="LIST",client="kubectl",code="200",contentType="json"} 233
|
// apiserver_request_total{resource="pods",verb="LIST",client="kubectl",code="200",contentType="json"} 233
|
||||||
if sample.Metric[model.MetricNameLabel] != "apiserver_request_latency_seconds_summary" &&
|
if sample.Metric[model.MetricNameLabel] != "apiserver_request_latencies_summary" &&
|
||||||
sample.Metric[model.MetricNameLabel] != "apiserver_request_total" {
|
sample.Metric[model.MetricNameLabel] != "apiserver_request_total" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -491,13 +493,13 @@ func readLatencyMetrics(c clientset.Interface) (*APIResponsiveness, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch sample.Metric[model.MetricNameLabel] {
|
switch sample.Metric[model.MetricNameLabel] {
|
||||||
case "apiserver_request_latency_seconds_summary":
|
case "apiserver_request_latencies_summary":
|
||||||
latency := sample.Value
|
latency := sample.Value
|
||||||
quantile, err := strconv.ParseFloat(string(sample.Metric[model.QuantileLabel]), 64)
|
quantile, err := strconv.ParseFloat(string(sample.Metric[model.QuantileLabel]), 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
a.addMetricRequestLatency(resource, subresource, verb, scope, quantile, time.Duration(int64(latency))*time.Second)
|
a.addMetricRequestLatency(resource, subresource, verb, scope, quantile, time.Duration(int64(latency))*time.Microsecond)
|
||||||
case "apiserver_request_total":
|
case "apiserver_request_total":
|
||||||
count := sample.Value
|
count := sample.Value
|
||||||
a.addMetricRequestCount(resource, subresource, verb, scope, int(count))
|
a.addMetricRequestCount(resource, subresource, verb, scope, int(count))
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue