Merge remote-tracking branch 'origin/master' into release-1.14

pull/564/head
Hannes Hoerl 2019-03-08 09:03:33 +00:00
commit 2676471cfc
432 changed files with 170251 additions and 1012 deletions

246
Godeps/Godeps.json generated
View File

@ -1,6 +1,6 @@
{
"ImportPath": "k8s.io/kubernetes",
"GoVersion": "go1.11",
"GoVersion": "go1.12",
"GodepVersion": "v80-k8s-r1",
"Packages": [
"github.com/bazelbuild/bazel-gazelle/cmd/gazelle",
@ -2002,188 +2002,188 @@
},
{
"ImportPath": "github.com/google/cadvisor/accelerators",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/cache/memory",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/client/v2",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/collector",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/container",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/container/common",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/container/containerd",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/container/crio",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/container/docker",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/container/libcontainer",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/container/mesos",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/container/raw",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/container/rkt",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/container/systemd",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/devicemapper",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/events",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/fs",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/info/v1",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/info/v2",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/machine",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/manager",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/manager/watcher",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/manager/watcher/raw",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/manager/watcher/rkt",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/metrics",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/storage",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/summary",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/utils",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/utils/cloudinfo",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/utils/cpuload",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/utils/cpuload/netlink",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/utils/docker",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/utils/oomparser",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/utils/sysfs",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/utils/sysinfo",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/version",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/cadvisor/zfs",
"Comment": "v0.33.0",
"Rev": "511ec9ef821b334c3825cebb728208578c2300e8"
"Comment": "v0.33.1",
"Rev": "7e9ea00b05397d43b6539d22ea6ea51bf70fea83"
},
{
"ImportPath": "github.com/google/certificate-transparency-go",
@ -2892,73 +2892,73 @@
},
{
"ImportPath": "github.com/onsi/gomega",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/format",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/gstruct",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/gstruct/errors",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/internal/assertion",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/internal/asyncassertion",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/internal/oraclematcher",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/internal/testingtsupport",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/matchers",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/matchers/support/goraph/bipartitegraph",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/matchers/support/goraph/edge",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/matchers/support/goraph/node",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/matchers/support/goraph/util",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/onsi/gomega/types",
"Comment": "v1.0-122-gd59fa0ac68bb5d",
"Rev": "d59fa0ac68bb5dd932ee8d24eed631cdd519efc3"
"Comment": "v1.4.3-9-g5533ce8a0da374",
"Rev": "5533ce8a0da374da682cd53d70ddcc54adf1a710"
},
{
"ImportPath": "github.com/opencontainers/go-digest",
@ -3636,6 +3636,10 @@
"ImportPath": "golang.org/x/net/html/atom",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
},
{
"ImportPath": "golang.org/x/net/html/charset",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
},
{
"ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
@ -3712,6 +3716,14 @@
"ImportPath": "golang.org/x/text/encoding",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/encoding/charmap",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/encoding/htmlindex",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/encoding/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
@ -3720,6 +3732,22 @@
"ImportPath": "golang.org/x/text/encoding/internal/identifier",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/encoding/japanese",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/encoding/korean",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/encoding/simplifiedchinese",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/encoding/traditionalchinese",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/encoding/unicode",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
@ -3884,6 +3912,10 @@
"ImportPath": "gonum.org/v1/gonum/graph/formats/dot/internal/token",
"Rev": "cebdade430ccb61c1feba4878085f6cf8cb3320e"
},
{
"ImportPath": "gonum.org/v1/gonum/graph/internal/linear",
"Rev": "cebdade430ccb61c1feba4878085f6cf8cb3320e"
},
{
"ImportPath": "gonum.org/v1/gonum/graph/internal/ordered",
"Rev": "cebdade430ccb61c1feba4878085f6cf8cb3320e"
@ -3900,6 +3932,14 @@
"ImportPath": "gonum.org/v1/gonum/graph/simple",
"Rev": "cebdade430ccb61c1feba4878085f6cf8cb3320e"
},
{
"ImportPath": "gonum.org/v1/gonum/graph/topo",
"Rev": "cebdade430ccb61c1feba4878085f6cf8cb3320e"
},
{
"ImportPath": "gonum.org/v1/gonum/graph/traverse",
"Rev": "cebdade430ccb61c1feba4878085f6cf8cb3320e"
},
{
"ImportPath": "gonum.org/v1/gonum/internal/asm/c128",
"Rev": "cebdade430ccb61c1feba4878085f6cf8cb3320e"

335
Godeps/LICENSES generated
View File

@ -101121,6 +101121,41 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
================================================================================
= vendor/golang.org/x/net/html/charset licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/golang.org/x/net/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707
================================================================================
================================================================================
= vendor/golang.org/x/net/http2 licensed under: =
@ -101786,6 +101821,76 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
================================================================================
= vendor/golang.org/x/text/encoding/charmap licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/golang.org/x/text/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707
================================================================================
================================================================================
= vendor/golang.org/x/text/encoding/htmlindex licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/golang.org/x/text/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707
================================================================================
================================================================================
= vendor/golang.org/x/text/encoding/internal licensed under: =
@ -101856,6 +101961,146 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
================================================================================
= vendor/golang.org/x/text/encoding/japanese licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/golang.org/x/text/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707
================================================================================
================================================================================
= vendor/golang.org/x/text/encoding/korean licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/golang.org/x/text/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707
================================================================================
================================================================================
= vendor/golang.org/x/text/encoding/simplifiedchinese licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/golang.org/x/text/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707
================================================================================
================================================================================
= vendor/golang.org/x/text/encoding/traditionalchinese licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/golang.org/x/text/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707
================================================================================
================================================================================
= vendor/golang.org/x/text/encoding/unicode licensed under: =
@ -103221,6 +103466,36 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
================================================================================
= vendor/gonum.org/v1/gonum/graph/internal/linear licensed under: =
Copyright ©2013 The Gonum Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the gonum project nor the names of its authors and
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/gonum.org/v1/gonum/LICENSE 665e67d07d85e236cceb8de602c6255a
================================================================================
================================================================================
= vendor/gonum.org/v1/gonum/graph/internal/ordered licensed under: =
@ -103341,6 +103616,66 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
================================================================================
= vendor/gonum.org/v1/gonum/graph/topo licensed under: =
Copyright ©2013 The Gonum Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the gonum project nor the names of its authors and
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/gonum.org/v1/gonum/LICENSE 665e67d07d85e236cceb8de602c6255a
================================================================================
================================================================================
= vendor/gonum.org/v1/gonum/graph/traverse licensed under: =
Copyright ©2013 The Gonum Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the gonum project nor the names of its authors and
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/gonum.org/v1/gonum/LICENSE 665e67d07d85e236cceb8de602c6255a
================================================================================
================================================================================
= vendor/gonum.org/v1/gonum/internal/asm/c128 licensed under: =

File diff suppressed because it is too large Load Diff

View File

@ -63,6 +63,8 @@ tags_values_pkgs = {"openapi-gen": {
"staging/src/k8s.io/api/imagepolicy/v1alpha1",
"staging/src/k8s.io/api/networking/v1",
"staging/src/k8s.io/api/networking/v1beta1",
"staging/src/k8s.io/api/node/v1alpha1",
"staging/src/k8s.io/api/node/v1beta1",
"staging/src/k8s.io/api/policy/v1beta1",
"staging/src/k8s.io/api/rbac/v1",
"staging/src/k8s.io/api/rbac/v1alpha1",
@ -138,6 +140,8 @@ tags_pkgs_values = {"openapi-gen": {
"staging/src/k8s.io/api/imagepolicy/v1alpha1": ["true"],
"staging/src/k8s.io/api/networking/v1": ["true"],
"staging/src/k8s.io/api/networking/v1beta1": ["true"],
"staging/src/k8s.io/api/node/v1alpha1": ["true"],
"staging/src/k8s.io/api/node/v1beta1": ["true"],
"staging/src/k8s.io/api/policy/v1beta1": ["true"],
"staging/src/k8s.io/api/rbac/v1": ["true"],
"staging/src/k8s.io/api/rbac/v1alpha1": ["true"],

View File

@ -282,8 +282,12 @@ endif
define TEST_CMD_HELP_INFO
# Build and run cmdline tests.
#
# Args:
# WHAT: List of tests to run, check test/cmd/legacy-script.sh for names.
# For example, WHAT=deployment will run run_deployment_tests function.
# Example:
# make test-cmd
# make test-cmd WHAT="deployment impersonation"
endef
.PHONY: test-cmd
ifeq ($(PRINT_HELP),y)

View File

@ -409,8 +409,10 @@ $(CONVERSION_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/conversi
OPENAPI_BASENAME := $(GENERATED_FILE_PREFIX)openapi
OPENAPI_FILENAME := $(OPENAPI_BASENAME).go
OPENAPI_OUTPUT_PKG := pkg/generated/openapi
CRD_OPENAPI_OUTPUT_PKG := staging/src/k8s.io/apiextensions-apiserver/pkg/generated/openapi
BOILERPLATE_FILENAME := vendor/k8s.io/code-generator/hack/boilerplate.go.txt
REPORT_FILENAME := $(OUT_DIR)/violations.report
IGNORED_REPORT_FILENAME := $(OUT_DIR)/ignored_violations.report
KNOWN_VIOLATION_FILENAME := api/api-rules/violation_exceptions.list
# When UPDATE_API_KNOWN_VIOLATIONS is set to be true, let the generator to write
# updated API violations to the known API violation exceptions list.
@ -436,10 +438,11 @@ OPENAPI_DIRS := $(shell \
)
OPENAPI_OUTFILE := $(OPENAPI_OUTPUT_PKG)/$(OPENAPI_FILENAME)
CRD_OPENAPI_OUTFILE := $(CRD_OPENAPI_OUTPUT_PKG)/$(OPENAPI_FILENAME)
# This rule is the user-friendly entrypoint for openapi generation.
.PHONY: gen_openapi
gen_openapi: $(OPENAPI_OUTFILE) $(OPENAPI_GEN)
gen_openapi: $(OPENAPI_OUTFILE) $(OPENAPI_GEN) $(CRD_OPENAPI_OUTFILE)
# For each dir in OPENAPI_DIRS, this establishes a dependency between the
# output file and the input files that should trigger a rebuild.
@ -469,6 +472,17 @@ $(OPENAPI_OUTFILE): $(OPENAPI_GEN) $(KNOWN_VIOLATION_FILENAME)
diff $(REPORT_FILENAME) $(KNOWN_VIOLATION_FILENAME) || \
(echo -e $(API_RULE_CHECK_FAILURE_MESSAGE); exit 1)
# TODO(roycaihw): move the automation to apiextensions-apiserver
$(CRD_OPENAPI_OUTFILE): $(OPENAPI_GEN)
./hack/run-in-gopath.sh $(OPENAPI_GEN) \
--v $(KUBE_VERBOSE) \
--logtostderr \
-i "k8s.io/apimachinery/pkg/apis/meta/v1,k8s.io/api/autoscaling/v1" \
-p $(PRJ_SRC_PATH)/$(CRD_OPENAPI_OUTPUT_PKG) \
-O $(OPENAPI_BASENAME) \
-h $(BOILERPLATE_FILENAME) \
-r $(IGNORED_REPORT_FILENAME) \
"$$@"
# How to build the generator tool. The deps for this are defined in
# the $(GO_PKGDEPS_FILE), above.

View File

@ -773,6 +773,7 @@ function create-master-audit-policy {
- group: "extensions"
- group: "metrics.k8s.io"
- group: "networking.k8s.io"
- group: "node.k8s.io"
- group: "policy"
- group: "rbac.authorization.k8s.io"
- group: "scheduling.k8s.io"
@ -1747,6 +1748,9 @@ function start-kube-apiserver {
if [[ -n "${FEATURE_GATES:-}" ]]; then
params+=" --feature-gates=${FEATURE_GATES}"
fi
if [[ "${FEATURE_GATES:-}" =~ "RuntimeClass=true" ]]; then
params+=" --runtime-config=node.k8s.io/v1alpha1=true"
fi
if [[ -n "${MASTER_ADVERTISE_ADDRESS:-}" ]]; then
params+=" --advertise-address=${MASTER_ADVERTISE_ADDRESS}"
if [[ -n "${PROXY_SSH_USER:-}" ]]; then
@ -2690,9 +2694,6 @@ EOF
setup-addon-manifests "addons" "istio/noauth"
fi
fi
if [[ "${FEATURE_GATES:-}" =~ "RuntimeClass=true" ]]; then
setup-addon-manifests "addons" "runtimeclass"
fi
if [[ -n "${EXTRA_ADDONS_URL:-}" ]]; then
download-extra-addons
setup-addon-manifests "addons" "gce-extras"

View File

@ -600,6 +600,7 @@ function write-linux-node-env {
function write-windows-node-env {
construct-windows-kubelet-flags
construct-windows-kubeproxy-flags
build-windows-kube-env "${KUBE_TEMP}/windows-node-kube-env.yaml"
build-kubelet-config false "windows" "${KUBE_TEMP}/windows-node-kubelet-config.yaml"
}
@ -871,6 +872,37 @@ function construct-windows-kubelet-flags {
KUBELET_ARGS="${flags}"
}
function construct-windows-kubeproxy-flags {
local flags=""
# Use the same log level as the Kubelet during tests.
flags+=" ${KUBELET_TEST_LOG_LEVEL:-"--v=2"}"
# Windows uses kernelspace proxymode
flags+=" --proxy-mode=kernelspace"
# Configure kube-proxy to run as a windows service.
flags+=" --windows-service=true"
# TODO(mtaufen): Configure logging for kube-proxy running as a service.
# I haven't been able to figure out how to direct stdout/stderr into log
# files when configuring it to run via sc.exe, so we just manually
# override logging config here.
flags+=" --log-file=${WINDOWS_LOGS_DIR}\kube-proxy.log"
# klog sets this to true internally, so need to override to false
# so we actually log to the file
flags+=" --logtostderr=false"
# Configure flags with explicit empty string values. We can't escape
# double-quotes, because they still break sc.exe after expansion in the
# binPath parameter, and single-quotes get parsed as characters instead
# of string delimiters.
flags+=" --resource-container="
KUBEPROXY_ARGS="${flags}"
}
# $1: if 'true', we're rendering config for a master, else a node
function build-kubelet-config {
local master="$1"
@ -1438,6 +1470,7 @@ CNI_CONFIG_DIR: $(yaml-quote ${WINDOWS_CNI_CONFIG_DIR})
MANIFESTS_DIR: $(yaml-quote ${WINDOWS_MANIFESTS_DIR})
PKI_DIR: $(yaml-quote ${WINDOWS_PKI_DIR})
KUBELET_CONFIG_FILE: $(yaml-quote ${WINDOWS_KUBELET_CONFIG_FILE})
KUBEPROXY_ARGS: $(yaml-quote ${KUBEPROXY_ARGS})
KUBECONFIG_FILE: $(yaml-quote ${WINDOWS_KUBECONFIG_FILE})
BOOTSTRAP_KUBECONFIG_FILE: $(yaml-quote ${WINDOWS_BOOTSTRAP_KUBECONFIG_FILE})
KUBEPROXY_KUBECONFIG_FILE: $(yaml-quote ${WINDOWS_KUBEPROXY_KUBECONFIG_FILE})

View File

@ -163,6 +163,338 @@ function MustDownload-File {
}
}
# This compiles some C# code that can make syscalls, and pulls the
# result into our powershell environment so we can make syscalls from this script.
# We make syscalls directly, because whatever the powershell cmdlets do under the hood,
# they can't seem to open the log files concurrently with writers.
# See https://docs.microsoft.com/en-us/dotnet/framework/interop/marshaling-data-with-platform-invoke
# for details on which unmanaged types map to managed types.
$SyscallDefinitions = @'
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFileW(
String lpFileName,
UInt32 dwDesiredAccess,
UInt32 dwShareMode,
IntPtr lpSecurityAttributes,
UInt32 dwCreationDisposition,
UInt32 dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetFilePointer(
IntPtr hFile,
Int32 lDistanceToMove,
IntPtr lpDistanceToMoveHigh,
UInt32 dwMoveMethod
);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetEndOfFile(
IntPtr hFile
);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CloseHandle(
IntPtr hObject
);
'@
$Kernel32 = Add-Type -MemberDefinition $SyscallDefinitions -Name 'Kernel32' -Namespace 'Win32' -PassThru
# Close-Handle closes the specified open file handle.
# On failure, throws an exception.
function Close-Handle {
param (
[parameter(Mandatory=$true)] [System.IntPtr]$Handle
)
$ret = $Kernel32::CloseHandle($Handle)
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
if (-not $ret) {
throw "Failed to close open file handle ${Handle}, system error code: ${err}"
}
}
# Open-File tries to open the file at the specified path with ReadWrite access mode and ReadWrite file share mode.
# On success, returns an open file handle.
# On failure, throws an exception.
function Open-File {
param (
[parameter(Mandatory=$true)] [string]$Path
)
$lpFileName = $Path
$dwDesiredAccess = [System.IO.FileAccess]::ReadWrite
$dwShareMode = [System.IO.FileShare]::ReadWrite # Fortunately golang also passes these same flags when it creates the log files, so we can open it concurrently.
$lpSecurityAttributes = [System.IntPtr]::Zero
$dwCreationDisposition = [System.IO.FileMode]::Open
$dwFlagsAndAttributes = [System.IO.FileAttributes]::Normal
$hTemplateFile = [System.IntPtr]::Zero
$handle = $Kernel32::CreateFileW($lpFileName, $dwDesiredAccess, $dwShareMode, $lpSecurityAttributes, $dwCreationDisposition, $dwFlagsAndAttributes, $hTemplateFile)
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
if ($handle -eq -1) {
throw "Failed to open file ${Path}, system error code: ${err}"
}
return $handle
}
# Truncate-File truncates the file in-place by opening it, moving the file pointer to the beginning,
# and setting the end of file to the file pointer's location.
# On failure, throws an exception.
# The file must have been originally created with FILE_SHARE_WRITE for this to be possible.
# Fortunately Go creates files with FILE_SHARE_READ|FILE_SHARE_WRITE by for all os.Open calls,
# so our log writers should be doing the right thing.
function Truncate-File {
param (
[parameter(Mandatory=$true)] [string]$Path
)
$INVALID_SET_FILE_POINTER = 0xffffffff
$NO_ERROR = 0
$FILE_BEGIN = 0
$handle = Open-File -Path $Path
# https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-setfilepointer
# Docs: Because INVALID_SET_FILE_POINTER is a valid value for the low-order DWORD of the new file pointer,
# you must check both the return value of the function and the error code returned by GetLastError to
# determine whether or not an error has occurred. If an error has occurred, the return value of SetFilePointer
# is INVALID_SET_FILE_POINTER and GetLastError returns a value other than NO_ERROR.
$ret = $Kernel32::SetFilePointer($handle, 0, [System.IntPtr]::Zero, $FILE_BEGIN)
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
if ($ret -eq $INVALID_SET_FILE_POINTER -and $err -ne $NO_ERROR) {
Close-Handle -Handle $handle
throw "Failed to set file pointer for handle ${handle}, system error code: ${err}"
}
$ret = $Kernel32::SetEndOfFile($handle)
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
if ($ret -eq 0) {
Close-Handle -Handle $handle
throw "Failed to set end of file for handle ${handle}, system error code: ${err}"
}
Close-Handle -Handle $handle
}
# FileRotationConfig defines the common options for file rotation.
class FileRotationConfig {
# Force rotation, ignoring $MaxBackupInterval and $MaxSize criteria.
[bool]$Force
# Maximum time since last backup, after which file will be rotated.
# When no backups exist, Rotate-File acts as if -MaxBackupInterval has not elapsed,
# instead relying on the other criteria.
[TimeSpan]$MaxBackupInterval
# Maximum file size, after which file will be rotated.
[int]$MaxSize
# Maximum number of backup archives to maintain.
[int]$MaxBackups
}
# New-FileRotationConfig constructs a FileRotationConfig with default options.
function New-FileRotationConfig {
param (
# Force rotation, ignoring $MaxBackupInterval and $MaxSize criteria.
[parameter(Mandatory=$false)] [switch]$Force,
# Maximum time since last backup, after which file will be rotated.
# When no backups exist, Rotate-File acts as if -MaxBackupInterval has not elapsed,
# instead relying on the other criteria.
# Defaults to daily rotations.
[parameter(Mandatory=$false)] [TimeSpan]$MaxBackupInterval = $(New-TimeSpan -Day 1),
# Maximum file size, after which file will be rotated.
[parameter(Mandatory=$false)] [int]$MaxSize = 100mb,
# Maximum number of backup archives to maintain.
[parameter(Mandatory=$false)] [int]$MaxBackups = 5
)
$config = [FileRotationConfig]::new()
$config.Force = $Force
$config.MaxBackupInterval = $MaxBackupInterval
$config.MaxSize = $MaxSize
$config.MaxBackups = $MaxBackups
return $config
}
# Get-Backups returns a list of paths to backup files for the original file path -Path,
# assuming that backup files are in the same directory, with a prefix matching
# the original file name and a .zip suffix.
function Get-Backups {
param (
# Original path of the file for which backups were created (no suffix).
[parameter(Mandatory=$true)] [string]$Path
)
$parent = Split-Path -Parent -Path $Path
$leaf = Split-Path -Leaf -Path $Path
$files = Get-ChildItem -File -Path $parent |
Where-Object Name -like "${leaf}*.zip"
return $files
}
# Trim-Backups deletes old backups for the log file identified by -Path until only -Count remain.
# Deletes backups with the oldest CreationTime first.
function Trim-Backups {
param (
[parameter(Mandatory=$true)] [int]$Count,
[parameter(Mandatory=$true)] [string]$Path
)
if ($Count -lt 0) {
$Count = 0
}
# If creating a new backup will exceed $Count, delete the oldest files
# until we have one less than $Count, leaving room for the new one.
# If the pipe results in zero items, $backups is $null, and if it results
# in only one item, PowerShell doesn't wrap in an array, so we check both cases.
# In the latter case, this actually caused it to often trim all backups, because
# .Length is also a property of FileInfo (size of the file)!
$backups = Get-Backups -Path $Path | Sort-Object -Property CreationTime
if ($backups -and $backups.GetType() -eq @().GetType() -and $backups.Length -gt $Count) {
$num = $backups.Length - $Count
$rmFiles = $backups | Select-Object -First $num
ForEach ($file in $rmFiles) {
Remove-Item $file.FullName
}
}
}
# Backup-File creates a copy of the file at -Path.
# The name of the backup is the same as the file,
# with the suffix "-%Y%m%d-%s" to identify the time of the backup.
# Returns the path to the backup file.
function Backup-File {
param (
[parameter(Mandatory=$true)] [string]$Path
)
$date = Get-Date -UFormat "%Y%m%d-%s"
$dest = "${Path}-${date}"
Copy-Item -Path $Path -Destination $dest
return $dest
}
# Compress-BackupFile creates a compressed archive containing the file
# at -Path and subsequently deletes the file at -Path. We split backup
# and compression steps to minimize time between backup and truncation,
# which helps minimize log loss.
function Compress-BackupFile {
param (
[parameter(Mandatory=$true)] [string]$Path
)
Compress-Archive -Path $Path -DestinationPath "${Path}.zip"
Remove-Item -Path $Path
}
# Rotate-File rotates the log file at -Path by first making a compressed copy of the original
# log file with the suffix "-%Y%m%d-%s" to identify the time of the backup, then truncating
# the original file in-place. Rotation is performed according to the options in -Config.
function Rotate-File {
param (
# Path to the log file to rotate.
[parameter(Mandatory=$true)] [string]$Path,
# Config for file rotation.
[parameter(Mandatory=$true)] [FileRotationConfig]$Config
)
function rotate {
# If creating a new backup will exceed $MaxBackups, delete the oldest files
# until we have one less than $MaxBackups, leaving room for the new one.
Trim-Backups -Count ($Config.MaxBackups - 1) -Path $Path
$backupPath = Backup-File -Path $Path
Truncate-File -Path $Path
Compress-BackupFile -Path $backupPath
}
# Check Force
if ($Config.Force) {
rotate
return
}
# Check MaxSize.
$file = Get-Item $Path
if ($file.Length -gt $Config.MaxSize) {
rotate
return
}
# Check MaxBackupInterval.
$backups = Get-Backups -Path $Path | Sort-Object -Property CreationTime
if ($backups.Length -ge 1) {
$lastBackupTime = $backups[0].CreationTime
$now = Get-Date
if ($now - $lastBackupTime -gt $Config.MaxBackupInterval) {
rotate
return
}
}
}
# Rotate-Files rotates the log files in directory -Path that match -Pattern.
# Rotation is performed by Rotate-File, according to -Config.
function Rotate-Files {
param (
# Pattern that file names must match to be rotated. Does not include parent path.
[parameter(Mandatory=$true)] [string]$Pattern,
# Path to the log directory containing files to rotate.
[parameter(Mandatory=$true)] [string]$Path,
# Config for file rotation.
[parameter(Mandatory=$true)] [FileRotationConfig]$Config
)
$files = Get-ChildItem -File -Path $Path | Where-Object Name -match $Pattern
ForEach ($file in $files) {
try {
Rotate-File -Path $file.FullName -Config $Config
} catch {
Log-Output "Caught exception rotating $($file.FullName): $($_.Exception)"
}
}
}
# Schedule-LogRotation schedules periodic log rotation with the Windows Task Scheduler.
# Rotation is performed by Rotate-Files, according to -Pattern and -Config.
# The system will check whether log files need to be rotated at -RepetitionInterval.
function Schedule-LogRotation {
param (
# Pattern that file names must match to be rotated. Does not include parent path.
[parameter(Mandatory=$true)] [string]$Pattern,
# Path to the log directory containing files to rotate.
[parameter(Mandatory=$true)] [string]$Path,
# Interval at which to check logs against rotation criteria.
# Minimum 1 minute, maximum 31 days (see https://docs.microsoft.com/en-us/windows/desktop/taskschd/taskschedulerschema-interval-repetitiontype-element).
[parameter(Mandatory=$true)] [TimeSpan]$RepetitionInterval,
# Config for file rotation.
[parameter(Mandatory=$true)] [FileRotationConfig]$Config
)
# Write a powershell script to a file that imports this module ($PSCommandPath)
# and calls Rotate-Files with the configured arguments.
$scriptPath = "C:\rotate-kube-logs.ps1"
New-Item -Force -ItemType file -Path $scriptPath | Out-Null
Set-Content -Path $scriptPath @"
`$ErrorActionPreference = 'Stop'
Import-Module -Force ${PSCommandPath}
`$maxBackupInterval = New-Timespan -Days $($Config.MaxBackupInterval.Days) -Hours $($Config.MaxBackupInterval.Hours) -Minutes $($Config.MaxBackupInterval.Minutes) -Seconds $($Config.MaxBackupInterval.Seconds)
`$config = New-FileRotationConfig -Force:`$$($Config.Force) -MaxBackupInterval `$maxBackupInterval -MaxSize $($Config.MaxSize) -MaxBackups $($Config.MaxBackups)
Rotate-Files -Pattern '${Pattern}' -Path '${Path}' -Config `$config
"@
# The task will execute the rotate-kube-logs.ps1 script created above.
# We explicitly set -WorkingDirectory to $Path for safety's sake, otherwise
# it runs in %windir%\system32 by default, which sounds dangerous.
$action = New-ScheduledTaskAction -Execute "powershell" -Argument "-NoLogo -NonInteractive -File ${scriptPath}" -WorkingDirectory $Path
# Start the task immediately, and trigger the task once every $RepetitionInterval.
$trigger = New-ScheduledTaskTrigger -Once -At $(Get-Date) -RepetitionInterval $RepetitionInterval
# Run the task as the same user who is currently running this script.
$principal = New-ScheduledTaskPrincipal $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)
# Just use the default task settings.
$settings = New-ScheduledTaskSettingsSet
# Create the ScheduledTask object from the above parameters.
$task = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Rotate Kubernetes logs"
# Register the new ScheduledTask with the Task Scheduler.
# Always try to unregister and re-register, in case it already exists (e.g. across reboots).
$name = "RotateKubeLogs"
try {
Unregister-ScheduledTask -Confirm:$false -TaskName $name
} catch {} finally {
Register-ScheduledTask -TaskName $name -InputObject $task
}
}
# Returns true if this node is part of a test cluster (see
# cluster/gce/config-test.sh). $KubeEnv is a hash table containing the kube-env
# metadata keys+values.

View File

@ -100,6 +100,7 @@ try {
Dump-DebugInfoToConsole
Set-PrerequisiteOptions
$kube_env = Fetch-KubeEnv
Disable-WindowsDefender
if (Test-IsTestCluster $kube_env) {
Log-Output 'Test cluster detected, installing OpenSSH.'
@ -128,6 +129,9 @@ try {
Log-Output 'Waiting 15 seconds for node to join cluster.'
Start-Sleep 15
Verify-WorkerServices
$config = New-FileRotationConfig
Schedule-LogRotation -Pattern '.*\.log$' -Path ${env:LOGS_DIR} -RepetitionInterval $(New-Timespan -Hour 1) -Config $config
}
catch {
Write-Host 'Exception caught in script:'

View File

@ -564,6 +564,7 @@ users:
clusters:
- name: local
cluster:
server: https://APISERVER_ADDRESS
certificate-authority-data: CA_CERT
contexts:
- context:
@ -572,7 +573,8 @@ contexts:
name: service-account-context
current-context: service-account-context'.`
replace('KUBEPROXY_TOKEN', ${kube_env}['KUBE_PROXY_TOKEN']).`
replace('CA_CERT', ${kube_env}['CA_CERT'])
replace('CA_CERT', ${kube_env}['CA_CERT']).`
replace('APISERVER_ADDRESS', ${kube_env}['KUBERNETES_MASTER_NAME'])
Log-Output ("kubeproxy kubeconfig:`n" +
"$(Get-Content -Raw ${env:KUBEPROXY_KUBECONFIG})")
@ -934,7 +936,7 @@ function Configure-Kubelet {
#
# Required ${kube_env} keys:
# KUBELET_ARGS
# KUBERNETES_MASTER_NAME
# KUBEPROXY_ARGS
# CLUSTER_IP_RANGE
function Start-WorkerServices {
# Compute kubelet args
@ -949,11 +951,7 @@ function Start-WorkerServices {
# Compute kube-proxy args
$kubeproxy_args_str = ${kube_env}['KUBEPROXY_ARGS']
Try {
$kubeproxy_args = $kubeproxy_args_str.Split(" ")
} Catch {
$kubeproxy_args = ""
}
$kubeproxy_args = $kubeproxy_args_str.Split(" ")
Log-Output "kubeproxy_args from metadata: ${kubeproxy_args}"
# kubeproxy is started on Linux nodes using
@ -966,31 +964,9 @@ function Start-WorkerServices {
# --iptables-sync-period=1m --iptables-min-sync-period=10s
# --ipvs-sync-period=1m --ipvs-min-sync-period=10s
# And also with various volumeMounts and "securityContext: privileged: true".
$apiserver_address = ${kube_env}['KUBERNETES_MASTER_NAME']
$default_kubeproxy_args = @(`
"--v=4",
"--master=https://${apiserver_address}",
"--kubeconfig=${env:KUBEPROXY_KUBECONFIG}",
"--proxy-mode=kernelspace",
"--cluster-cidr=$(${kube_env}['CLUSTER_IP_RANGE'])",
# Configure kube-proxy to run as a windows service.
"--windows-service=true",
# TODO(mtaufen): Configure logging for kube-proxy running as a service.
# I haven't been able to figure out how to direct stdout/stderr into log
# files when configuring it to run via sc.exe, so we just manually
# override logging config here.
"--log-file=${env:LOGS_DIR}\kube-proxy.log",
# klog sets this to true intenrally, so need to override to false
# so we actually log to the file
"--logtostderr=false",
# Configure flags with explicit empty string values. We can't escape
# double-quotes, because they still break sc.exe after expansion in the
# binPath parameter, and single-quotes get parsed as characters instead
# of string delimiters.
"--resource-container="
"--cluster-cidr=$(${kube_env}['CLUSTER_IP_RANGE'])"
)
$kubeproxy_args = ${default_kubeproxy_args} + ${kubeproxy_args}
Log-Output "Final kubeproxy_args: ${kubeproxy_args}"

View File

@ -25,6 +25,9 @@ while true; do
if [[ "$STATUS" == "Succeeded" ]]; then
echo "$timestamp Done."
break
elif [[ "$STATUS" == "Failed" ]]; then
echo "$timestamp Failed."
break
else
sleep 5
fi

View File

@ -276,6 +276,8 @@ var apiVersionPriorities = map[schema.GroupVersion]priority{
{Group: "coordination.k8s.io", Version: "v1"}: {group: 16500, version: 15},
{Group: "coordination.k8s.io", Version: "v1beta1"}: {group: 16500, version: 9},
{Group: "auditregistration.k8s.io", Version: "v1alpha1"}: {group: 16400, version: 1},
{Group: "node.k8s.io", Version: "v1alpha1"}: {group: 16300, version: 1},
{Group: "node.k8s.io", Version: "v1beta1"}: {group: 16300, version: 9},
// Append a new group to the end of the list if unsure.
// You can use min(existing group)-100 as the initial value for a group.
// Version can be set to 9 (to have space around) for a new group.

View File

@ -223,6 +223,7 @@ func startAttachDetachController(ctx ControllerContext) (http.Handler, bool, err
ctx.InformerFactory.Core().V1().Nodes(),
ctx.InformerFactory.Core().V1().PersistentVolumeClaims(),
ctx.InformerFactory.Core().V1().PersistentVolumes(),
ctx.InformerFactory.Storage().V1beta1().CSINodes(),
ctx.Cloud,
ProbeAttachableVolumePlugins(),
GetDynamicPluginProber(ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration),

View File

@ -5,6 +5,7 @@ go_library(
srcs = [
"alpha.go",
"certs.go",
"kubeconfig.go",
"kubelet.go",
"selfhosting.go",
],
@ -21,6 +22,7 @@ go_library(
"//cmd/kubeadm/app/features:go_default_library",
"//cmd/kubeadm/app/phases/certs:go_default_library",
"//cmd/kubeadm/app/phases/certs/renewal:go_default_library",
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
"//cmd/kubeadm/app/phases/kubelet:go_default_library",
"//cmd/kubeadm/app/phases/selfhosting:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
@ -52,7 +54,10 @@ filegroup(
go_test(
name = "go_default_test",
srcs = ["certs_test.go"],
srcs = [
"certs_test.go",
"kubeconfig_test.go",
],
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/constants:go_default_library",
@ -61,6 +66,8 @@ go_test(
"//cmd/kubeadm/app/util/pkiutil:go_default_library",
"//cmd/kubeadm/test:go_default_library",
"//cmd/kubeadm/test/cmd:go_default_library",
"//cmd/kubeadm/test/kubeconfig:go_default_library",
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
],
)

View File

@ -32,6 +32,7 @@ func NewCmdAlpha(in io.Reader, out io.Writer) *cobra.Command {
cmd.AddCommand(newCmdCertsUtility())
cmd.AddCommand(newCmdKubeletUtility())
cmd.AddCommand(newCmdKubeConfigUtility(out))
cmd.AddCommand(NewCmdSelfhosting(in))
// TODO: This command should be removed as soon as the kubeadm init phase refactoring is completed.

View File

@ -0,0 +1,106 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package alpha
import (
"io"
"github.com/pkg/errors"
"github.com/spf13/cobra"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
kubeconfigLongDesc = normalizer.LongDesc(`
Kubeconfig file utilities.
` + cmdutil.AlphaDisclaimer)
userKubeconfigLongDesc = normalizer.LongDesc(`
Outputs a kubeconfig file for an additional user.
` + cmdutil.AlphaDisclaimer)
userKubeconfigExample = normalizer.Examples(`
# Outputs a kubeconfig file for an additional user named foo
kubeadm alpha kubeconfig user --client-name=foo
`)
)
// newCmdKubeConfigUtility returns main command for kubeconfig phase
func newCmdKubeConfigUtility(out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "kubeconfig",
Short: "Kubeconfig file utilities",
Long: kubeconfigLongDesc,
}
cmd.AddCommand(newCmdUserKubeConfig(out))
return cmd
}
// newCmdUserKubeConfig returns sub commands for kubeconfig phase
func newCmdUserKubeConfig(out io.Writer) *cobra.Command {
cfg := &kubeadmapiv1beta1.InitConfiguration{}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(cfg)
var token, clientName string
var organizations []string
// Creates the UX Command
cmd := &cobra.Command{
Use: "user",
Short: "Outputs a kubeconfig file for an additional user",
Long: userKubeconfigLongDesc,
Example: userKubeconfigExample,
Run: func(cmd *cobra.Command, args []string) {
if clientName == "" {
kubeadmutil.CheckErr(errors.New("missing required argument --client-name"))
}
// This call returns the ready-to-use configuration based on the default cfg populated by flags
internalcfg, err := configutil.DefaultedInitConfiguration(cfg)
kubeadmutil.CheckErr(err)
// if the kubeconfig file for an additional user has to use a token, use it
if token != "" {
kubeadmutil.CheckErr(kubeconfigphase.WriteKubeConfigWithToken(out, internalcfg, clientName, token))
return
}
// Otherwise, write a kubeconfig file with a generate client cert
kubeadmutil.CheckErr(kubeconfigphase.WriteKubeConfigWithClientCert(out, internalcfg, clientName, organizations))
},
}
// Add flags to the command
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, "The path where certificates are stored")
cmd.Flags().StringVar(&cfg.LocalAPIEndpoint.AdvertiseAddress, "apiserver-advertise-address", cfg.LocalAPIEndpoint.AdvertiseAddress, "The IP address the API server is accessible on")
cmd.Flags().Int32Var(&cfg.LocalAPIEndpoint.BindPort, "apiserver-bind-port", cfg.LocalAPIEndpoint.BindPort, "The port the API server is accessible on")
cmd.Flags().StringVar(&token, "token", token, "The token that should be used as the authentication mechanism for this kubeconfig, instead of client certificates")
cmd.Flags().StringVar(&clientName, "client-name", clientName, "The name of user. It will be used as the CN if client certificates are created")
cmd.Flags().StringSliceVar(&organizations, "org", organizations, "The orgnizations of the client certificate. It will be used as the O if client certificates are created")
return cmd
}

View File

@ -0,0 +1,109 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package alpha
import (
"bytes"
"fmt"
"os"
"testing"
"k8s.io/client-go/tools/clientcmd"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
kubeconfigtestutil "k8s.io/kubernetes/cmd/kubeadm/test/kubeconfig"
)
func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
// Temporary folders for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// Adds a pki folder with a ca cert to the temp folder
pkidir := testutil.SetupPkiDirWithCertificateAuthorithy(t, tmpdir)
// Retrieves ca cert for assertions
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkidir, kubeadmconstants.CACertAndKeyBaseName)
if err != nil {
t.Fatalf("couldn't retrieve ca cert: %v", err)
}
commonFlags := []string{
"--apiserver-advertise-address=1.2.3.4",
"--apiserver-bind-port=1234",
"--client-name=myUser",
fmt.Sprintf("--cert-dir=%s", pkidir),
}
var tests = []struct {
name string
command string
withClientCert bool
withToken bool
additionalFlags []string
}{
{
name: "user subCommand withClientCert",
command: "user",
withClientCert: true,
},
{
name: "user subCommand withToken",
withToken: true,
command: "user",
additionalFlags: []string{"--token=123456"},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
buf := new(bytes.Buffer)
// Get subcommands working in the temporary directory
cmd := newCmdUserKubeConfig(buf)
// Execute the subcommand
allFlags := append(commonFlags, test.additionalFlags...)
cmd.SetArgs(allFlags)
if err := cmd.Execute(); err != nil {
t.Fatal("Could not execute subcommand")
}
// reads kubeconfig written to stdout
config, err := clientcmd.Load(buf.Bytes())
if err != nil {
t.Errorf("couldn't read kubeconfig file from buffer: %v", err)
return
}
// checks that CLI flags are properly propagated
kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
if test.withClientCert {
// checks that kubeconfig files have expected client cert
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, "myUser")
}
if test.withToken {
// checks that kubeconfig files have expected token
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithToken(t, config, "myUser", "123456")
}
})
}
}

View File

@ -38,6 +38,7 @@ import (
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
uploadconfig "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
@ -140,10 +141,15 @@ func NewReset(in io.Reader, ignorePreflightErrors sets.String, forceReset bool,
// Run reverts any changes made to this host by "kubeadm init" or "kubeadm join".
func (r *Reset) Run(out io.Writer, client clientset.Interface, cfg *kubeadmapi.InitConfiguration) error {
var dirsToClean []string
// Only clear etcd data when using local etcd.
etcdManifestPath := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName, "etcd.yaml")
// Reset the ClusterStatus for a given control-plane node.
if isControlPlane() && cfg != nil {
uploadconfig.ResetClusterStatusForNode(cfg.NodeRegistration.Name, client)
}
// Only clear etcd data when using local etcd.
klog.V(1).Infoln("[reset] Checking for etcd config")
etcdManifestPath := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName, "etcd.yaml")
etcdDataDir, err := getEtcdDataDir(etcdManifestPath, cfg)
if err == nil {
dirsToClean = append(dirsToClean, etcdDataDir)
@ -318,3 +324,13 @@ func resetDetectCRISocket(cfg *kubeadmapi.InitConfiguration) (string, error) {
// if this fails, try to detect it
return utilruntime.DetectCRISocket()
}
// isControlPlane checks if a node is a control-plane node by looking up
// the kube-apiserver manifest file
func isControlPlane() bool {
filepath := kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeAPIServer, kubeadmconstants.GetStaticPodDirectory())
if _, err := os.Stat(filepath); os.IsNotExist(err) {
return false
}
return true
}

View File

@ -20,6 +20,8 @@ go_library(
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)

View File

@ -19,10 +19,12 @@ package uploadconfig
import (
"fmt"
"k8s.io/api/core/v1"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
rbac "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/klog"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
@ -37,6 +39,69 @@ const (
NodesKubeadmConfigClusterRoleName = "kubeadm:nodes-kubeadm-config"
)
// ResetClusterStatusForNode removes the APIEndpoint of a given control-plane node
// from the ClusterStatus and updates the kubeadm ConfigMap
func ResetClusterStatusForNode(nodeName string, client clientset.Interface) error {
fmt.Printf("[reset] Removing info for node %q from the ConfigMap %q in the %q Namespace\n",
nodeName, kubeadmconstants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
// Get the kubeadm ConfigMap
configMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(kubeadmconstants.KubeadmConfigConfigMap, metav1.GetOptions{})
if err != nil {
return errors.Wrap(err, "failed to get config map")
}
// Handle missing ClusterConfiguration in the ConfigMap. Should only happen if someone manually
// interacted with the ConfigMap.
clusterConfigurationYaml, ok := configMap.Data[kubeadmconstants.ClusterConfigurationConfigMapKey]
if !ok {
return errors.Errorf("cannot find key %q in ConfigMap %q in the %q Namespace",
kubeadmconstants.ClusterConfigurationConfigMapKey, kubeadmconstants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
}
// Obtain the existing ClusterStatus object
clusterStatus, err := configutil.UnmarshalClusterStatus(configMap.Data)
if err != nil {
return err
}
// Handle a nil APIEndpoints map. Should only happen if someone manually
// interacted with the ConfigMap.
if clusterStatus.APIEndpoints == nil {
return errors.Errorf("APIEndpoints from ConfigMap %q in the %q Namespace is nil",
kubeadmconstants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
}
// Check for existence of the nodeName key in the list of APIEndpoints.
// Return early if it's missing.
apiEndpoint, ok := clusterStatus.APIEndpoints[nodeName]
if !ok {
klog.Warningf("No APIEndpoint registered for node %q", nodeName)
return nil
}
klog.V(2).Infof("Removing APIEndpoint %#v for node %q", apiEndpoint, nodeName)
delete(clusterStatus.APIEndpoints, nodeName)
// Marshal the ClusterStatus back into YAML
clusterStatusYaml, err := configutil.MarshalKubeadmConfigObject(clusterStatus)
if err != nil {
return err
}
// Update the ClusterStatus in the ConfigMap
return apiclient.CreateOrUpdateConfigMap(client, &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: kubeadmconstants.KubeadmConfigConfigMap,
Namespace: metav1.NamespaceSystem,
},
Data: map[string]string{
kubeadmconstants.ClusterConfigurationConfigMapKey: clusterConfigurationYaml,
kubeadmconstants.ClusterStatusConfigMapKey: string(clusterStatusYaml),
},
})
}
// UploadConfiguration saves the InitConfiguration used for later reference (when upgrading for instance)
func UploadConfiguration(cfg *kubeadmapi.InitConfiguration, client clientset.Interface) error {
fmt.Printf("[upload-config] storing the configuration used in ConfigMap %q in the %q Namespace\n", kubeadmconstants.KubeadmConfigConfigMap, metav1.NamespaceSystem)

View File

@ -167,7 +167,7 @@ func getNodeNameFromKubeletConfig(kubeconfigDir string) (string, error) {
// getAPIEndpoint returns the APIEndpoint for the current node
func getAPIEndpoint(data map[string]string, nodeName string, apiEndpoint *kubeadmapi.APIEndpoint) error {
// gets the ClusterStatus from kubeadm-config
clusterStatus, err := unmarshalClusterStatus(data)
clusterStatus, err := UnmarshalClusterStatus(data)
if err != nil {
return err
}
@ -210,7 +210,7 @@ func GetClusterStatus(client clientset.Interface) (*kubeadmapi.ClusterStatus, er
return nil, err
}
clusterStatus, err := unmarshalClusterStatus(configMap.Data)
clusterStatus, err := UnmarshalClusterStatus(configMap.Data)
if err != nil {
return nil, err
}
@ -218,7 +218,8 @@ func GetClusterStatus(client clientset.Interface) (*kubeadmapi.ClusterStatus, er
return clusterStatus, nil
}
func unmarshalClusterStatus(data map[string]string) (*kubeadmapi.ClusterStatus, error) {
// UnmarshalClusterStatus takes raw ConfigMap.Data and converts it to a ClusterStatus object
func UnmarshalClusterStatus(data map[string]string) (*kubeadmapi.ClusterStatus, error) {
clusterStatusData, ok := data[constants.ClusterStatusConfigMapKey]
if !ok {
return nil, errors.Errorf("unexpected error when reading kubeadm-config ConfigMap: %s key value pair missing", constants.ClusterStatusConfigMapKey)

View File

@ -137,7 +137,6 @@ go_library(
"//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/component-base/cli/flag:go_default_library",
"//staging/src/k8s.io/kubelet/config/v1beta1:go_default_library",
"//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:go_default_library",
"//vendor/github.com/coreos/go-systemd/daemon:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",

View File

@ -95,7 +95,6 @@ import (
"k8s.io/kubernetes/pkg/version"
"k8s.io/kubernetes/pkg/version/verflag"
"k8s.io/kubernetes/pkg/volume/util/subpath"
nodeapiclientset "k8s.io/node-api/pkg/client/clientset/versioned"
"k8s.io/utils/exec"
"k8s.io/utils/nsenter"
)
@ -592,15 +591,6 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan
if err != nil {
return fmt.Errorf("failed to initialize kubelet heartbeat client: %v", err)
}
// CRDs are JSON only, and client renegotiation for streaming is not correct as per #67803
crdClientConfig := restclient.CopyConfig(clientConfig)
crdClientConfig.ContentType = "application/json"
kubeDeps.NodeAPIClient, err = nodeapiclientset.NewForConfig(crdClientConfig)
if err != nil {
return fmt.Errorf("failed to initialize kubelet node-api client: %v", err)
}
}
// If the kubelet config controller is available, and dynamic config is enabled, start the config and status sync loops

View File

@ -50,6 +50,7 @@ pkg/apis/extensions/v1beta1
pkg/apis/imagepolicy
pkg/apis/networking
pkg/apis/networking/v1
pkg/apis/node/v1alpha1
pkg/apis/policy
pkg/apis/policy/v1beta1
pkg/apis/policy/validation
@ -279,6 +280,7 @@ pkg/registry/extensions/controller/storage
pkg/registry/extensions/rest
pkg/registry/networking/networkpolicy/storage
pkg/registry/networking/rest
pkg/registry/node/rest
pkg/registry/policy/poddisruptionbudget/storage
pkg/registry/policy/rest
pkg/registry/rbac/clusterrole

View File

@ -80,6 +80,8 @@ events.k8s.io/v1beta1 \
imagepolicy.k8s.io/v1alpha1 \
networking.k8s.io/v1 \
networking.k8s.io/v1beta1 \
node.k8s.io/v1alpha1 \
node.k8s.io/v1beta1 \
policy/v1beta1 \
rbac.authorization.k8s.io/v1 \
rbac.authorization.k8s.io/v1beta1 \

View File

@ -31,7 +31,7 @@ go install k8s.io/kubernetes/vendor/k8s.io/repo-infra/kazel
# Find all of the staging repos.
while IFS='' read -r repo; do staging_repos+=("${repo}"); done <\
<(cd "${KUBE_ROOT}/staging/src" && find k8s.io/ -mindepth 1 -maxdepth 1 -type d | LANG=C sort)
<(cd "${KUBE_ROOT}/staging/src" && find k8s.io -mindepth 1 -maxdepth 1 -type d | LANG=C sort)
# Save the staging repos into a Starlark list that can be used by Bazel rules.
(

View File

@ -41,57 +41,8 @@ fi
gotoprotobuf=$(kube::util::find-binary "go-to-protobuf")
PACKAGES=(
k8s.io/apiserver/pkg/apis/example/v1
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1
k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1
k8s.io/kube-aggregator/pkg/apis/apiregistration/v1
k8s.io/api/core/v1
k8s.io/api/policy/v1beta1
k8s.io/api/extensions/v1beta1
k8s.io/api/autoscaling/v1
k8s.io/api/authorization/v1
k8s.io/api/autoscaling/v2beta1
k8s.io/api/autoscaling/v2beta2
k8s.io/api/authorization/v1beta1
k8s.io/api/batch/v1
k8s.io/api/batch/v1beta1
k8s.io/api/batch/v2alpha1
k8s.io/api/apps/v1beta1
k8s.io/api/apps/v1beta2
k8s.io/api/apps/v1
k8s.io/api/authentication/v1
k8s.io/api/authentication/v1beta1
k8s.io/api/events/v1beta1
k8s.io/api/rbac/v1alpha1
k8s.io/api/rbac/v1beta1
k8s.io/api/rbac/v1
k8s.io/api/certificates/v1beta1
k8s.io/api/coordination/v1beta1
k8s.io/api/coordination/v1
k8s.io/api/imagepolicy/v1alpha1
k8s.io/api/scheduling/v1alpha1
k8s.io/api/scheduling/v1beta1
k8s.io/api/scheduling/v1
k8s.io/api/settings/v1alpha1
k8s.io/api/storage/v1alpha1
k8s.io/api/storage/v1beta1
k8s.io/api/storage/v1
k8s.io/api/admissionregistration/v1beta1
k8s.io/api/admission/v1beta1
k8s.io/api/auditregistration/v1alpha1
k8s.io/api/networking/v1beta1
k8s.io/api/networking/v1
k8s.io/metrics/pkg/apis/metrics/v1alpha1
k8s.io/metrics/pkg/apis/metrics/v1beta1
k8s.io/metrics/pkg/apis/custom_metrics/v1beta1
k8s.io/metrics/pkg/apis/custom_metrics/v1beta2
k8s.io/metrics/pkg/apis/external_metrics/v1beta1
k8s.io/apiserver/pkg/apis/audit/v1alpha1
k8s.io/apiserver/pkg/apis/audit/v1beta1
k8s.io/apiserver/pkg/apis/audit/v1
k8s.io/apiserver/pkg/apis/example2/v1
)
APIROOTS=( ${1} )
shift
# requires the 'proto' tag to build (will remove when ready)
# searches for the protoc-gen-gogo extension in the output directory
@ -101,6 +52,6 @@ PATH="${KUBE_ROOT}/_output/bin:${PATH}" \
"${gotoprotobuf}" \
--proto-import="${KUBE_ROOT}/vendor" \
--proto-import="${KUBE_ROOT}/third_party/protobuf" \
--packages=$(IFS=, ; echo "${PACKAGES[*]}") \
--packages=$(IFS=, ; echo "${APIROOTS[*]}") \
--go-header-file ${KUBE_ROOT}/hack/boilerplate/boilerplate.generatego.txt \
"$@"

View File

@ -24,6 +24,12 @@ KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
# source tree. This is managed in kube::build::copy_output in build/common.sh.
# If the output set is changed update that function.
"${KUBE_ROOT}/build/run.sh" hack/update-generated-protobuf-dockerized.sh "$@"
APIROOTS=${APIROOTS:-$(git grep --files-with-matches -e '// +k8s:protobuf-gen=package' cmd pkg staging | \
xargs -n 1 dirname | \
sed 's,^,k8s.io/kubernetes/,;s,k8s.io/kubernetes/staging/src/,,' | \
sort | uniq
)}
"${KUBE_ROOT}/build/run.sh" hack/update-generated-protobuf-dockerized.sh "${APIROOTS}" "$@"
# ex: ts=2 sw=2 et filetype=sh

View File

@ -23,7 +23,8 @@ source "${KUBE_ROOT}/hack/lib/init.sh"
kube::golang::setup_env
APIROOTS=${APIROOTS:-pkg/api pkg/apis pkg/watch staging/src/k8s.io/apimachinery/pkg/api staging/src/k8s.io/apimachinery/pkg/apis staging/src/k8s.io/apiserver/pkg staging/src/k8s.io/api staging/src/k8s.io/metrics/pkg/apis}
APIROOTS=$(git grep --files-with-matches -e '// +k8s:protobuf-gen=package' cmd pkg staging | xargs -n 1 dirname | sort | uniq)
_tmp="${KUBE_ROOT}/_tmp"
cleanup() {

View File

@ -44,6 +44,7 @@ filegroup(
"//pkg/apis/extensions:all-srcs",
"//pkg/apis/imagepolicy:all-srcs",
"//pkg/apis/networking:all-srcs",
"//pkg/apis/node:all-srcs",
"//pkg/apis/policy:all-srcs",
"//pkg/apis/rbac:all-srcs",
"//pkg/apis/scheduling:all-srcs",

View File

@ -318,10 +318,6 @@ func dropDisabledFields(
podSpec.PriorityClassName = ""
}
if !utilfeature.DefaultFeatureGate.Enabled(features.PodReadinessGates) && !podReadinessGatesInUse(oldPodSpec) {
podSpec.ReadinessGates = nil
}
if !utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) && !sysctlsInUse(oldPodSpec) {
if podSpec.SecurityContext != nil {
podSpec.SecurityContext.Sysctls = nil
@ -534,17 +530,6 @@ func podPriorityInUse(podSpec *api.PodSpec) bool {
return false
}
// podReadinessGatesInUse returns true if the pod spec is non-nil and has ReadinessGates
func podReadinessGatesInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false
}
if podSpec.ReadinessGates != nil {
return true
}
return false
}
func sysctlsInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false

View File

@ -1101,102 +1101,6 @@ func TestDropAppArmor(t *testing.T) {
}
}
func TestDropReadinessGates(t *testing.T) {
podWithoutReadinessGates := func() *api.Pod {
return &api.Pod{
Spec: api.PodSpec{
ReadinessGates: nil,
},
}
}
podWithReadinessGates := func() *api.Pod {
return &api.Pod{
Spec: api.PodSpec{
ReadinessGates: []api.PodReadinessGate{
{
ConditionType: api.PodConditionType("example.com/condition1"),
},
{
ConditionType: api.PodConditionType("example.com/condition2"),
},
},
},
}
}
podInfo := []struct {
description string
hasPodReadinessGates bool
pod func() *api.Pod
}{
{
description: "has ReadinessGates",
hasPodReadinessGates: true,
pod: podWithReadinessGates,
},
{
description: "does not have ReadinessGates",
hasPodReadinessGates: false,
pod: podWithoutReadinessGates,
},
{
description: "is nil",
hasPodReadinessGates: false,
pod: func() *api.Pod { return nil },
},
}
for _, enabled := range []bool{true, false} {
for _, oldPodInfo := range podInfo {
for _, newPodInfo := range podInfo {
oldPodHasReadinessGates, oldPod := oldPodInfo.hasPodReadinessGates, oldPodInfo.pod()
newPodHasReadinessGates, newPod := newPodInfo.hasPodReadinessGates, newPodInfo.pod()
if newPod == nil {
continue
}
t.Run(fmt.Sprintf("featue enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodReadinessGates, enabled)()
var oldPodSpec *api.PodSpec
if oldPod != nil {
oldPodSpec = &oldPod.Spec
}
dropDisabledFields(&newPod.Spec, nil, oldPodSpec, nil)
// old pod should never be changed
if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) {
t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod()))
}
switch {
case enabled || oldPodHasReadinessGates:
// new pod should not be changed if the feature is enabled, or if the old pod had ReadinessGates
if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
}
case newPodHasReadinessGates:
// new pod should be changed
if reflect.DeepEqual(newPod, newPodInfo.pod()) {
t.Errorf("new pod was not changed")
}
// new pod should not have ReadinessGates
if !reflect.DeepEqual(newPod, podWithoutReadinessGates()) {
t.Errorf("new pod had ReadinessGates: %v",
diff.ObjectReflectDiff(newPod, podWithoutReadinessGates()))
}
default:
// new pod should not need to be changed
if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
}
}
})
}
}
}
}
func TestDropTokenRequestProjection(t *testing.T) {
podWithoutTRProjection := func() *api.Pod {
return &api.Pod{

View File

@ -41,6 +41,8 @@ go_library(
"//pkg/apis/imagepolicy/install:go_default_library",
"//pkg/apis/networking:go_default_library",
"//pkg/apis/networking/install:go_default_library",
"//pkg/apis/node:go_default_library",
"//pkg/apis/node/install:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/apis/policy/install:go_default_library",
"//pkg/apis/rbac:go_default_library",

View File

@ -48,6 +48,7 @@ import (
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/imagepolicy"
"k8s.io/kubernetes/pkg/apis/networking"
"k8s.io/kubernetes/pkg/apis/node"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/apis/rbac"
"k8s.io/kubernetes/pkg/apis/scheduling"
@ -70,6 +71,7 @@ import (
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
_ "k8s.io/kubernetes/pkg/apis/networking/install"
_ "k8s.io/kubernetes/pkg/apis/node/install"
_ "k8s.io/kubernetes/pkg/apis/policy/install"
_ "k8s.io/kubernetes/pkg/apis/rbac/install"
_ "k8s.io/kubernetes/pkg/apis/scheduling/install"
@ -257,6 +259,12 @@ func init() {
externalGroupVersion: externalGroupVersion,
}
}
if _, ok := Groups[node.GroupName]; !ok {
externalGroupVersion := schema.GroupVersion{Group: node.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(node.GroupName)[0].Version}
Groups[node.GroupName] = TestGroup{
externalGroupVersion: externalGroupVersion,
}
}
if _, ok := Groups[events.GroupName]; !ok {
externalGroupVersion := schema.GroupVersion{Group: events.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(events.GroupName)[0].Version}
Groups[events.GroupName] = TestGroup{

View File

@ -101,4 +101,10 @@ const (
// This annotation will be used to compute the in-cluster network programming latency SLI, see
// https://github.com/kubernetes/community/blob/master/sig-scalability/slos/network_programming_latency.md
EndpointsLastChangeTriggerTime = "endpoints.kubernetes.io/last-change-trigger-time"
// MigratedPluginsAnnotationKey is the annotation key, set for CSINode objects, that is a comma-separated
// list of in-tree plugins that will be serviced by the CSI backend on the Node represented by CSINode.
// This annotation is used by the Attach Detach Controller to determine whether to use the in-tree or
// CSI Backend for a volume plugin on a specific node.
MigratedPluginsAnnotationKey = "storage.alpha.kubernetes.io/migrated-plugins"
)

38
pkg/apis/node/BUILD Normal file
View File

@ -0,0 +1,38 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"register.go",
"types.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/kubernetes/pkg/apis/node",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//pkg/apis/node/install:all-srcs",
"//pkg/apis/node/v1alpha1:all-srcs",
"//pkg/apis/node/v1beta1:all-srcs",
"//pkg/apis/node/validation:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

20
pkg/apis/node/doc.go Normal file
View File

@ -0,0 +1,20 @@
/*
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.
*/
// +k8s:deepcopy-gen=package
// +groupName=node.k8s.io
package node // import "k8s.io/kubernetes/pkg/apis/node"

View File

@ -0,0 +1,30 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["install.go"],
importpath = "k8s.io/kubernetes/pkg/apis/node/install",
visibility = ["//visibility:public"],
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/node:go_default_library",
"//pkg/apis/node/v1alpha1:go_default_library",
"//pkg/apis/node/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,40 @@
/*
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 install adds the node API group, making it available as
// an option to all of the API encoding/decoding machinery.
package install
import (
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/node"
"k8s.io/kubernetes/pkg/apis/node/v1alpha1"
"k8s.io/kubernetes/pkg/apis/node/v1beta1"
)
func init() {
Install(legacyscheme.Scheme)
}
// Install registers the API group and adds types to a scheme
func Install(scheme *runtime.Scheme) {
utilruntime.Must(node.AddToScheme(scheme))
utilruntime.Must(v1alpha1.AddToScheme(scheme))
utilruntime.Must(v1beta1.AddToScheme(scheme))
utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion))
}

54
pkg/apis/node/register.go Normal file
View File

@ -0,0 +1,54 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package node
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName is the group name use in this package
const GroupName = "node.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
// SchemeBuilder for node api registration.
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
// AddToScheme for node api registration.
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&RuntimeClass{},
&RuntimeClassList{},
)
return nil
}

60
pkg/apis/node/types.go Normal file
View File

@ -0,0 +1,60 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package node
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// RuntimeClass defines a class of container runtime supported in the cluster.
// The RuntimeClass is used to determine which container runtime is used to run
// all containers in a pod. RuntimeClasses are (currently) manually defined by a
// user or cluster provisioner, and referenced in the PodSpec. The Kubelet is
// responsible for resolving the RuntimeClassName reference before running the
// pod. For more details, see
// https://git.k8s.io/enhancements/keps/sig-node/runtime-class.md
type RuntimeClass struct {
metav1.TypeMeta
// +optional
metav1.ObjectMeta
// Handler specifies the underlying runtime and configuration that the CRI
// implementation will use to handle pods of this class. The possible values
// are specific to the node & CRI configuration. It is assumed that all
// handlers are available on every node, and handlers of the same name are
// equivalent on every node.
// For example, a handler called "runc" might specify that the runc OCI
// runtime (using native Linux containers) will be used to run the containers
// in a pod.
// The Handler must conform to the DNS Label (RFC 1123) requirements, and is
// immutable.
Handler string
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// RuntimeClassList is a list of RuntimeClass objects.
type RuntimeClassList struct {
metav1.TypeMeta
// +optional
metav1.ListMeta
// Items is a list of schema objects.
Items []RuntimeClass
}

View File

@ -0,0 +1,47 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"conversion.go",
"doc.go",
"register.go",
"zz_generated.conversion.go",
],
importpath = "k8s.io/kubernetes/pkg/apis/node/v1alpha1",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/node:go_default_library",
"//staging/src/k8s.io/api/node/v1alpha1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["conversion_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/apis/node:go_default_library",
"//staging/src/k8s.io/api/node/v1alpha1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
],
)

View File

@ -0,0 +1,43 @@
/*
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 v1alpha1
import (
v1alpha1 "k8s.io/api/node/v1alpha1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
node "k8s.io/kubernetes/pkg/apis/node"
)
func addConversionFuncs(s *runtime.Scheme) error {
return s.AddConversionFuncs(
Convert_v1alpha1_RuntimeClass_To_node_RuntimeClass,
Convert_node_RuntimeClass_To_v1alpha1_RuntimeClass,
)
}
func Convert_v1alpha1_RuntimeClass_To_node_RuntimeClass(in *v1alpha1.RuntimeClass, out *node.RuntimeClass, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
out.Handler = in.Spec.RuntimeHandler
return nil
}
func Convert_node_RuntimeClass_To_v1alpha1_RuntimeClass(in *node.RuntimeClass, out *v1alpha1.RuntimeClass, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
out.Spec.RuntimeHandler = in.Handler
return nil
}

View File

@ -0,0 +1,54 @@
/*
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 v1alpha1
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1alpha1 "k8s.io/api/node/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
node "k8s.io/kubernetes/pkg/apis/node"
)
func TestRuntimeClassConversion(t *testing.T) {
const (
name = "puppy"
handler = "heidi"
)
internalRC := node.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{Name: name},
Handler: handler,
}
v1alpha1RC := v1alpha1.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{Name: name},
Spec: v1alpha1.RuntimeClassSpec{
RuntimeHandler: handler,
},
}
convertedInternal := node.RuntimeClass{}
require.NoError(t,
Convert_v1alpha1_RuntimeClass_To_node_RuntimeClass(&v1alpha1RC, &convertedInternal, nil))
assert.Equal(t, internalRC, convertedInternal)
convertedV1alpha1 := v1alpha1.RuntimeClass{}
require.NoError(t,
Convert_node_RuntimeClass_To_v1alpha1_RuntimeClass(&internalRC, &convertedV1alpha1, nil))
assert.Equal(t, v1alpha1RC, convertedV1alpha1)
}

View File

@ -0,0 +1,22 @@
/*
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.
*/
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/node
// +k8s:conversion-gen-external-types=k8s.io/api/node/v1alpha1
// +groupName=node.k8s.io
package v1alpha1 // import "k8s.io/kubernetes/pkg/apis/node/v1alpha1"

View File

@ -0,0 +1,46 @@
/*
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 v1alpha1
import (
nodev1alpha1 "k8s.io/api/node/v1alpha1"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName for node API
const GroupName = "node.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
localSchemeBuilder = &nodev1alpha1.SchemeBuilder
// AddToScheme node API registration
AddToScheme = localSchemeBuilder.AddToScheme
)
func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addConversionFuncs)
}

View File

@ -0,0 +1,122 @@
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by conversion-gen. DO NOT EDIT.
package v1alpha1
import (
v1alpha1 "k8s.io/api/node/v1alpha1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
node "k8s.io/kubernetes/pkg/apis/node"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*v1alpha1.RuntimeClass)(nil), (*node.RuntimeClass)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_RuntimeClass_To_node_RuntimeClass(a.(*v1alpha1.RuntimeClass), b.(*node.RuntimeClass), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*node.RuntimeClass)(nil), (*v1alpha1.RuntimeClass)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_node_RuntimeClass_To_v1alpha1_RuntimeClass(a.(*node.RuntimeClass), b.(*v1alpha1.RuntimeClass), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1alpha1.RuntimeClassList)(nil), (*node.RuntimeClassList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_RuntimeClassList_To_node_RuntimeClassList(a.(*v1alpha1.RuntimeClassList), b.(*node.RuntimeClassList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*node.RuntimeClassList)(nil), (*v1alpha1.RuntimeClassList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_node_RuntimeClassList_To_v1alpha1_RuntimeClassList(a.(*node.RuntimeClassList), b.(*v1alpha1.RuntimeClassList), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*node.RuntimeClass)(nil), (*v1alpha1.RuntimeClass)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_node_RuntimeClass_To_v1alpha1_RuntimeClass(a.(*node.RuntimeClass), b.(*v1alpha1.RuntimeClass), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*v1alpha1.RuntimeClass)(nil), (*node.RuntimeClass)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_RuntimeClass_To_node_RuntimeClass(a.(*v1alpha1.RuntimeClass), b.(*node.RuntimeClass), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1alpha1_RuntimeClass_To_node_RuntimeClass(in *v1alpha1.RuntimeClass, out *node.RuntimeClass, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
// WARNING: in.Spec requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_node_RuntimeClass_To_v1alpha1_RuntimeClass(in *node.RuntimeClass, out *v1alpha1.RuntimeClass, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
// WARNING: in.Handler requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_v1alpha1_RuntimeClassList_To_node_RuntimeClassList(in *v1alpha1.RuntimeClassList, out *node.RuntimeClassList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]node.RuntimeClass, len(*in))
for i := range *in {
if err := Convert_v1alpha1_RuntimeClass_To_node_RuntimeClass(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
// Convert_v1alpha1_RuntimeClassList_To_node_RuntimeClassList is an autogenerated conversion function.
func Convert_v1alpha1_RuntimeClassList_To_node_RuntimeClassList(in *v1alpha1.RuntimeClassList, out *node.RuntimeClassList, s conversion.Scope) error {
return autoConvert_v1alpha1_RuntimeClassList_To_node_RuntimeClassList(in, out, s)
}
func autoConvert_node_RuntimeClassList_To_v1alpha1_RuntimeClassList(in *node.RuntimeClassList, out *v1alpha1.RuntimeClassList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]v1alpha1.RuntimeClass, len(*in))
for i := range *in {
if err := Convert_node_RuntimeClass_To_v1alpha1_RuntimeClass(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
// Convert_node_RuntimeClassList_To_v1alpha1_RuntimeClassList is an autogenerated conversion function.
func Convert_node_RuntimeClassList_To_v1alpha1_RuntimeClassList(in *node.RuntimeClassList, out *v1alpha1.RuntimeClassList, s conversion.Scope) error {
return autoConvert_node_RuntimeClassList_To_v1alpha1_RuntimeClassList(in, out, s)
}

View File

@ -0,0 +1,33 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"register.go",
"zz_generated.conversion.go",
],
importpath = "k8s.io/kubernetes/pkg/apis/node/v1beta1",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/node:go_default_library",
"//staging/src/k8s.io/api/node/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,22 @@
/*
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.
*/
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/node
// +k8s:conversion-gen-external-types=k8s.io/api/node/v1beta1
// +groupName=node.k8s.io
package v1beta1 // import "k8s.io/kubernetes/pkg/apis/node/v1beta1"

View File

@ -0,0 +1,39 @@
/*
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 v1beta1
import (
nodev1beta1 "k8s.io/api/node/v1beta1"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName for node API
const GroupName = "node.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
localSchemeBuilder = &nodev1beta1.SchemeBuilder
// AddToScheme node API registration
AddToScheme = localSchemeBuilder.AddToScheme
)

View File

@ -0,0 +1,104 @@
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by conversion-gen. DO NOT EDIT.
package v1beta1
import (
unsafe "unsafe"
v1beta1 "k8s.io/api/node/v1beta1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
node "k8s.io/kubernetes/pkg/apis/node"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*v1beta1.RuntimeClass)(nil), (*node.RuntimeClass)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_RuntimeClass_To_node_RuntimeClass(a.(*v1beta1.RuntimeClass), b.(*node.RuntimeClass), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*node.RuntimeClass)(nil), (*v1beta1.RuntimeClass)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_node_RuntimeClass_To_v1beta1_RuntimeClass(a.(*node.RuntimeClass), b.(*v1beta1.RuntimeClass), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1beta1.RuntimeClassList)(nil), (*node.RuntimeClassList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_RuntimeClassList_To_node_RuntimeClassList(a.(*v1beta1.RuntimeClassList), b.(*node.RuntimeClassList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*node.RuntimeClassList)(nil), (*v1beta1.RuntimeClassList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_node_RuntimeClassList_To_v1beta1_RuntimeClassList(a.(*node.RuntimeClassList), b.(*v1beta1.RuntimeClassList), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1beta1_RuntimeClass_To_node_RuntimeClass(in *v1beta1.RuntimeClass, out *node.RuntimeClass, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
out.Handler = in.Handler
return nil
}
// Convert_v1beta1_RuntimeClass_To_node_RuntimeClass is an autogenerated conversion function.
func Convert_v1beta1_RuntimeClass_To_node_RuntimeClass(in *v1beta1.RuntimeClass, out *node.RuntimeClass, s conversion.Scope) error {
return autoConvert_v1beta1_RuntimeClass_To_node_RuntimeClass(in, out, s)
}
func autoConvert_node_RuntimeClass_To_v1beta1_RuntimeClass(in *node.RuntimeClass, out *v1beta1.RuntimeClass, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
out.Handler = in.Handler
return nil
}
// Convert_node_RuntimeClass_To_v1beta1_RuntimeClass is an autogenerated conversion function.
func Convert_node_RuntimeClass_To_v1beta1_RuntimeClass(in *node.RuntimeClass, out *v1beta1.RuntimeClass, s conversion.Scope) error {
return autoConvert_node_RuntimeClass_To_v1beta1_RuntimeClass(in, out, s)
}
func autoConvert_v1beta1_RuntimeClassList_To_node_RuntimeClassList(in *v1beta1.RuntimeClassList, out *node.RuntimeClassList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]node.RuntimeClass)(unsafe.Pointer(&in.Items))
return nil
}
// Convert_v1beta1_RuntimeClassList_To_node_RuntimeClassList is an autogenerated conversion function.
func Convert_v1beta1_RuntimeClassList_To_node_RuntimeClassList(in *v1beta1.RuntimeClassList, out *node.RuntimeClassList, s conversion.Scope) error {
return autoConvert_v1beta1_RuntimeClassList_To_node_RuntimeClassList(in, out, s)
}
func autoConvert_node_RuntimeClassList_To_v1beta1_RuntimeClassList(in *node.RuntimeClassList, out *v1beta1.RuntimeClassList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]v1beta1.RuntimeClass)(unsafe.Pointer(&in.Items))
return nil
}
// Convert_node_RuntimeClassList_To_v1beta1_RuntimeClassList is an autogenerated conversion function.
func Convert_node_RuntimeClassList_To_v1beta1_RuntimeClassList(in *node.RuntimeClassList, out *v1beta1.RuntimeClassList, s conversion.Scope) error {
return autoConvert_node_RuntimeClassList_To_v1beta1_RuntimeClassList(in, out, s)
}

View File

@ -0,0 +1,38 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["validation.go"],
importpath = "k8s.io/kubernetes/pkg/apis/node/validation",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/node:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["validation_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/apis/node:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/github.com/stretchr/testify/assert: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"],
)

View File

@ -0,0 +1,43 @@
/*
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 validation
import (
apivalidation "k8s.io/apimachinery/pkg/api/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kubernetes/pkg/apis/node"
)
// ValidateRuntimeClass validates the RuntimeClass
func ValidateRuntimeClass(rc *node.RuntimeClass) field.ErrorList {
allErrs := apivalidation.ValidateObjectMeta(&rc.ObjectMeta, false, apivalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
for _, msg := range apivalidation.NameIsDNSLabel(rc.Handler, false) {
allErrs = append(allErrs, field.Invalid(field.NewPath("handler"), rc.Handler, msg))
}
return allErrs
}
// ValidateRuntimeClassUpdate validates an update to the object
func ValidateRuntimeClassUpdate(new, old *node.RuntimeClass) field.ErrorList {
allErrs := apivalidation.ValidateObjectMetaUpdate(&new.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))
allErrs = append(allErrs, apivalidation.ValidateImmutableField(new.Handler, old.Handler, field.NewPath("handler"))...)
return allErrs
}

View File

@ -0,0 +1,128 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/apis/node"
"github.com/stretchr/testify/assert"
)
func TestValidateRuntimeClass(t *testing.T) {
tests := []struct {
name string
rc node.RuntimeClass
expectError bool
}{{
name: "invalid name",
expectError: true,
rc: node.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{Name: "&!@#"},
Handler: "foo",
},
}, {
name: "invalid Handler name",
expectError: true,
rc: node.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Handler: "&@#$",
},
}, {
name: "invalid empty RuntimeClass",
expectError: true,
rc: node.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{Name: "empty"},
},
}, {
name: "valid Handler",
expectError: false,
rc: node.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Handler: "bar-baz",
},
}}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
errs := ValidateRuntimeClass(&test.rc)
if test.expectError {
assert.NotEmpty(t, errs)
} else {
assert.Empty(t, errs)
}
})
}
}
func TestValidateRuntimeUpdate(t *testing.T) {
old := node.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Handler: "bar",
}
tests := []struct {
name string
expectError bool
old, new node.RuntimeClass
}{{
name: "valid metadata update",
old: old,
new: node.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Labels: map[string]string{"foo": "bar"},
},
Handler: "bar",
},
}, {
name: "invalid metadata update",
expectError: true,
old: old,
new: node.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{
Name: "empty",
ClusterName: "somethingelse", // immutable
},
Handler: "bar",
},
}, {
name: "invalid Handler update",
expectError: true,
old: old,
new: node.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Handler: "somethingelse",
},
}}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
// So we don't need to write it in every test case...
test.old.ObjectMeta.ResourceVersion = "1"
test.new.ObjectMeta.ResourceVersion = "1"
errs := ValidateRuntimeClassUpdate(&test.new, &test.old)
if test.expectError {
assert.NotEmpty(t, errs)
} else {
assert.Empty(t, errs)
}
})
}
}

84
pkg/apis/node/zz_generated.deepcopy.go generated Normal file
View File

@ -0,0 +1,84 @@
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package node
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RuntimeClass) DeepCopyInto(out *RuntimeClass) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuntimeClass.
func (in *RuntimeClass) DeepCopy() *RuntimeClass {
if in == nil {
return nil
}
out := new(RuntimeClass)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *RuntimeClass) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RuntimeClassList) DeepCopyInto(out *RuntimeClassList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]RuntimeClass, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuntimeClassList.
func (in *RuntimeClassList) DeepCopy() *RuntimeClassList {
if in == nil {
return nil
}
out := new(RuntimeClassList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *RuntimeClassList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}

View File

@ -26,6 +26,7 @@ go_library(
"//pkg/client/clientset_generated/internalclientset/typed/events/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/networking/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/node/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/policy/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion:go_default_library",
@ -63,6 +64,7 @@ filegroup(
"//pkg/client/clientset_generated/internalclientset/typed/events/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/networking/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/node/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/policy/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion:all-srcs",

View File

@ -35,6 +35,7 @@ import (
eventsinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion"
extensionsinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion"
networkinginternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion"
nodeinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/node/internalversion"
policyinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion"
rbacinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
schedulinginternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion"
@ -57,6 +58,7 @@ type Interface interface {
Events() eventsinternalversion.EventsInterface
Extensions() extensionsinternalversion.ExtensionsInterface
Networking() networkinginternalversion.NetworkingInterface
Node() nodeinternalversion.NodeInterface
Policy() policyinternalversion.PolicyInterface
Rbac() rbacinternalversion.RbacInterface
Scheduling() schedulinginternalversion.SchedulingInterface
@ -81,6 +83,7 @@ type Clientset struct {
events *eventsinternalversion.EventsClient
extensions *extensionsinternalversion.ExtensionsClient
networking *networkinginternalversion.NetworkingClient
node *nodeinternalversion.NodeClient
policy *policyinternalversion.PolicyClient
rbac *rbacinternalversion.RbacClient
scheduling *schedulinginternalversion.SchedulingClient
@ -153,6 +156,11 @@ func (c *Clientset) Networking() networkinginternalversion.NetworkingInterface {
return c.networking
}
// Node retrieves the NodeClient
func (c *Clientset) Node() nodeinternalversion.NodeInterface {
return c.node
}
// Policy retrieves the PolicyClient
func (c *Clientset) Policy() policyinternalversion.PolicyInterface {
return c.policy
@ -246,6 +254,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
if err != nil {
return nil, err
}
cs.node, err = nodeinternalversion.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.policy, err = policyinternalversion.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
@ -291,6 +303,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
cs.events = eventsinternalversion.NewForConfigOrDie(c)
cs.extensions = extensionsinternalversion.NewForConfigOrDie(c)
cs.networking = networkinginternalversion.NewForConfigOrDie(c)
cs.node = nodeinternalversion.NewForConfigOrDie(c)
cs.policy = policyinternalversion.NewForConfigOrDie(c)
cs.rbac = rbacinternalversion.NewForConfigOrDie(c)
cs.scheduling = schedulinginternalversion.NewForConfigOrDie(c)
@ -317,6 +330,7 @@ func New(c rest.Interface) *Clientset {
cs.events = eventsinternalversion.New(c)
cs.extensions = extensionsinternalversion.New(c)
cs.networking = networkinginternalversion.New(c)
cs.node = nodeinternalversion.New(c)
cs.policy = policyinternalversion.New(c)
cs.rbac = rbacinternalversion.New(c)
cs.scheduling = schedulinginternalversion.New(c)

View File

@ -27,6 +27,7 @@ go_library(
"//pkg/apis/events:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/networking:go_default_library",
"//pkg/apis/node:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/scheduling:go_default_library",
@ -59,6 +60,8 @@ go_library(
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/networking/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/node/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/node/internalversion/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/policy/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",

View File

@ -51,6 +51,8 @@ import (
fakeextensionsinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake"
networkinginternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion"
fakenetworkinginternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake"
nodeinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/node/internalversion"
fakenodeinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/node/internalversion/fake"
policyinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion"
fakepolicyinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake"
rbacinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
@ -170,6 +172,11 @@ func (c *Clientset) Networking() networkinginternalversion.NetworkingInterface {
return &fakenetworkinginternalversion.FakeNetworking{Fake: &c.Fake}
}
// Node retrieves the NodeClient
func (c *Clientset) Node() nodeinternalversion.NodeInterface {
return &fakenodeinternalversion.FakeNode{Fake: &c.Fake}
}
// Policy retrieves the PolicyClient
func (c *Clientset) Policy() policyinternalversion.PolicyInterface {
return &fakepolicyinternalversion.FakePolicy{Fake: &c.Fake}

View File

@ -37,6 +37,7 @@ import (
eventsinternalversion "k8s.io/kubernetes/pkg/apis/events"
extensionsinternalversion "k8s.io/kubernetes/pkg/apis/extensions"
networkinginternalversion "k8s.io/kubernetes/pkg/apis/networking"
nodeinternalversion "k8s.io/kubernetes/pkg/apis/node"
policyinternalversion "k8s.io/kubernetes/pkg/apis/policy"
rbacinternalversion "k8s.io/kubernetes/pkg/apis/rbac"
schedulinginternalversion "k8s.io/kubernetes/pkg/apis/scheduling"
@ -61,6 +62,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{
eventsinternalversion.AddToScheme,
extensionsinternalversion.AddToScheme,
networkinginternalversion.AddToScheme,
nodeinternalversion.AddToScheme,
policyinternalversion.AddToScheme,
rbacinternalversion.AddToScheme,
schedulinginternalversion.AddToScheme,

View File

@ -26,6 +26,7 @@ go_library(
"//pkg/apis/events/install:go_default_library",
"//pkg/apis/extensions/install:go_default_library",
"//pkg/apis/networking/install:go_default_library",
"//pkg/apis/node/install:go_default_library",
"//pkg/apis/policy/install:go_default_library",
"//pkg/apis/rbac/install:go_default_library",
"//pkg/apis/scheduling/install:go_default_library",

View File

@ -36,6 +36,7 @@ import (
events "k8s.io/kubernetes/pkg/apis/events/install"
extensions "k8s.io/kubernetes/pkg/apis/extensions/install"
networking "k8s.io/kubernetes/pkg/apis/networking/install"
node "k8s.io/kubernetes/pkg/apis/node/install"
policy "k8s.io/kubernetes/pkg/apis/policy/install"
rbac "k8s.io/kubernetes/pkg/apis/rbac/install"
scheduling "k8s.io/kubernetes/pkg/apis/scheduling/install"
@ -67,6 +68,7 @@ func Install(scheme *runtime.Scheme) {
events.Install(scheme)
extensions.Install(scheme)
networking.Install(scheme)
node.Install(scheme)
policy.Install(scheme)
rbac.Install(scheme)
scheduling.Install(scheme)

View File

@ -0,0 +1,33 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"generated_expansion.go",
"node_client.go",
],
importpath = "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/node/internalversion",
visibility = ["//visibility:public"],
deps = [
"//pkg/client/clientset_generated/internalclientset/scheme:go_default_library",
"//staging/src/k8s.io/client-go/rest:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/node/internalversion/fake:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,20 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
// This package has the automatically generated typed clients.
package internalversion

View File

@ -0,0 +1,29 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"fake_node_client.go",
],
importpath = "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/node/internalversion/fake",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/client-go/rest:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,20 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
// Package fake has the automatically generated clients.
package fake

View File

@ -0,0 +1,35 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakeNode struct {
*testing.Fake
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeNode) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}

View File

@ -0,0 +1,19 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package internalversion

View File

@ -0,0 +1,91 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package internalversion
import (
rest "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme"
)
type NodeInterface interface {
RESTClient() rest.Interface
}
// NodeClient is used to interact with features provided by the node.k8s.io group.
type NodeClient struct {
restClient rest.Interface
}
// NewForConfig creates a new NodeClient for the given config.
func NewForConfig(c *rest.Config) (*NodeClient, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &NodeClient{client}, nil
}
// NewForConfigOrDie creates a new NodeClient for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *NodeClient {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new NodeClient for the given RESTClient.
func New(c rest.Interface) *NodeClient {
return &NodeClient{c}
}
func setConfigDefaults(config *rest.Config) error {
config.APIPath = "/apis"
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("node.k8s.io")[0].Group {
gv := scheme.Scheme.PrioritizedVersionsForGroup("node.k8s.io")[0]
config.GroupVersion = &gv
}
config.NegotiatedSerializer = scheme.Codecs
if config.QPS == 0 {
config.QPS = 5
}
if config.Burst == 0 {
config.Burst = 10
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *NodeClient) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}

View File

@ -1676,7 +1676,8 @@ func validateEmptyConfig(t *testing.T, config string) {
func TestGetZone(t *testing.T) {
cloud := &Cloud{
Config: Config{
Location: "eastus",
Location: "eastus",
UseInstanceMetadata: true,
},
}
testcases := []struct {

View File

@ -19,6 +19,7 @@ package azure
import (
"context"
"fmt"
"os"
"strconv"
"strings"
@ -49,31 +50,39 @@ func (az *Cloud) GetZoneID(zoneLabel string) string {
// GetZone returns the Zone containing the current availability zone and locality region that the program is running in.
// If the node is not running with availability zones, then it will fall back to fault domain.
func (az *Cloud) GetZone(ctx context.Context) (cloudprovider.Zone, error) {
metadata, err := az.metadata.GetMetadata()
if err != nil {
return cloudprovider.Zone{}, err
}
if metadata.Compute == nil {
return cloudprovider.Zone{}, fmt.Errorf("failure of getting compute information from instance metadata")
}
zone := ""
if metadata.Compute.Zone != "" {
zoneID, err := strconv.Atoi(metadata.Compute.Zone)
if az.UseInstanceMetadata {
metadata, err := az.metadata.GetMetadata()
if err != nil {
return cloudprovider.Zone{}, fmt.Errorf("failed to parse zone ID %q: %v", metadata.Compute.Zone, err)
return cloudprovider.Zone{}, err
}
zone = az.makeZone(zoneID)
} else {
klog.V(3).Infof("Availability zone is not enabled for the node, falling back to fault domain")
zone = metadata.Compute.FaultDomain
}
return cloudprovider.Zone{
FailureDomain: zone,
Region: az.Location,
}, nil
if metadata.Compute == nil {
return cloudprovider.Zone{}, fmt.Errorf("failure of getting compute information from instance metadata")
}
zone := ""
if metadata.Compute.Zone != "" {
zoneID, err := strconv.Atoi(metadata.Compute.Zone)
if err != nil {
return cloudprovider.Zone{}, fmt.Errorf("failed to parse zone ID %q: %v", metadata.Compute.Zone, err)
}
zone = az.makeZone(zoneID)
} else {
klog.V(3).Infof("Availability zone is not enabled for the node, falling back to fault domain")
zone = metadata.Compute.FaultDomain
}
return cloudprovider.Zone{
FailureDomain: zone,
Region: az.Location,
}, nil
}
// if UseInstanceMetadata is false, get Zone name by calling ARM
hostname, err := os.Hostname()
if err != nil {
return cloudprovider.Zone{}, fmt.Errorf("failure getting hostname from kernel")
}
return az.vmSet.GetZoneByNodeName(strings.ToLower(hostname))
}
// GetZoneByProviderID implements Zones.GetZoneByProviderID

View File

@ -88,6 +88,12 @@ var UpdateTaintBackoff = wait.Backoff{
Jitter: 1.0,
}
var UpdateLabelBackoff = wait.Backoff{
Steps: 5,
Duration: 100 * time.Millisecond,
Jitter: 1.0,
}
var (
KeyFunc = cache.DeletionHandlingMetaNamespaceKeyFunc
)
@ -1045,3 +1051,48 @@ func ComputeHash(template *v1.PodTemplateSpec, collisionCount *int32) string {
return rand.SafeEncodeString(fmt.Sprint(podTemplateSpecHasher.Sum32()))
}
func AddOrUpdateLabelsOnNode(kubeClient clientset.Interface, nodeName string, labelsToUpdate map[string]string) error {
firstTry := true
return clientretry.RetryOnConflict(UpdateLabelBackoff, func() error {
var err error
var node *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 {
node, err = kubeClient.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{ResourceVersion: "0"})
firstTry = false
} else {
node, err = kubeClient.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{})
}
if err != nil {
return err
}
// Make a copy of the node and update the labels.
newNode := node.DeepCopy()
if newNode.Labels == nil {
newNode.Labels = make(map[string]string)
}
for key, value := range labelsToUpdate {
newNode.Labels[key] = value
}
oldData, err := json.Marshal(node)
if err != nil {
return fmt.Errorf("failed to marshal the existing node %#v: %v", node, err)
}
newData, err := json.Marshal(newNode)
if err != nil {
return fmt.Errorf("failed to marshal the new node %#v: %v", newNode, err)
}
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, &v1.Node{})
if err != nil {
return fmt.Errorf("failed to create a two-way merge patch: %v", err)
}
if _, err := kubeClient.CoreV1().Nodes().Patch(node.Name, types.StrategicMergePatchType, patchBytes); err != nil {
return fmt.Errorf("failed to patch the node: %v", err)
}
return nil
})
}

View File

@ -13,6 +13,7 @@ go_library(
"//pkg/controller/nodelifecycle/scheduler:go_default_library",
"//pkg/controller/util/node:go_default_library",
"//pkg/features:go_default_library",
"//pkg/kubelet/apis:go_default_library",
"//pkg/scheduler/api:go_default_library",
"//pkg/util/metrics:go_default_library",
"//pkg/util/node:go_default_library",
@ -72,6 +73,7 @@ go_test(
"//pkg/controller/testutil:go_default_library",
"//pkg/controller/util/node:go_default_library",
"//pkg/features:go_default_library",
"//pkg/kubelet/apis:go_default_library",
"//pkg/scheduler/api:go_default_library",
"//pkg/util/node:go_default_library",
"//pkg/util/taints:go_default_library",

View File

@ -56,6 +56,7 @@ import (
"k8s.io/kubernetes/pkg/controller/nodelifecycle/scheduler"
nodeutil "k8s.io/kubernetes/pkg/controller/util/node"
"k8s.io/kubernetes/pkg/features"
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
"k8s.io/kubernetes/pkg/util/metrics"
utilnode "k8s.io/kubernetes/pkg/util/node"
@ -130,6 +131,37 @@ const (
retrySleepTime = 20 * time.Millisecond
)
// labelReconcileInfo lists Node labels to reconcile, and how to reconcile them.
// primaryKey and secondaryKey are keys of labels to reconcile.
// - If both keys exist, but their values don't match. Use the value from the
// primaryKey as the source of truth to reconcile.
// - If ensureSecondaryExists is true, and the secondaryKey does not
// exist, secondaryKey will be added with the value of the primaryKey.
var labelReconcileInfo = []struct {
primaryKey string
secondaryKey string
ensureSecondaryExists bool
}{
{
// Reconcile the beta and the stable OS label using the beta label as
// the source of truth.
// TODO(#73084): switch to using the stable label as the source of
// truth in v1.18.
primaryKey: kubeletapis.LabelOS,
secondaryKey: v1.LabelOSStable,
ensureSecondaryExists: true,
},
{
// Reconcile the beta and the stable arch label using the beta label as
// the source of truth.
// TODO(#73084): switch to using the stable label as the source of
// truth in v1.18.
primaryKey: kubeletapis.LabelArch,
secondaryKey: v1.LabelArchStable,
ensureSecondaryExists: true,
},
}
type nodeHealthData struct {
probeTimestamp metav1.Time
readyTransitionTimestamp metav1.Time
@ -355,18 +387,20 @@ func NewNodeLifecycleController(
})
}
klog.Infof("Controller will reconcile labels.")
nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: nodeutil.CreateAddNodeHandler(func(node *v1.Node) error {
nc.nodeUpdateQueue.Add(node.Name)
return nil
}),
UpdateFunc: nodeutil.CreateUpdateNodeHandler(func(_, newNode *v1.Node) error {
nc.nodeUpdateQueue.Add(newNode.Name)
return nil
}),
})
if nc.taintNodeByCondition {
klog.Infof("Controller will taint node by condition.")
nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: nodeutil.CreateAddNodeHandler(func(node *v1.Node) error {
nc.nodeUpdateQueue.Add(node.Name)
return nil
}),
UpdateFunc: nodeutil.CreateUpdateNodeHandler(func(_, newNode *v1.Node) error {
nc.nodeUpdateQueue.Add(newNode.Name)
return nil
}),
})
}
nc.leaseLister = leaseInformer.Lister()
@ -401,18 +435,16 @@ func (nc *Controller) Run(stopCh <-chan struct{}) {
go nc.taintManager.Run(stopCh)
}
if nc.taintNodeByCondition {
// Close node update queue to cleanup go routine.
defer nc.nodeUpdateQueue.ShutDown()
// Close node update queue to cleanup go routine.
defer nc.nodeUpdateQueue.ShutDown()
// Start workers to update NoSchedule taint for nodes.
for i := 0; i < scheduler.UpdateWorkerSize; i++ {
// Thanks to "workqueue", each worker just need to get item from queue, because
// the item is flagged when got from queue: if new event come, the new item will
// be re-queued until "Done", so no more than one worker handle the same item and
// no event missed.
go wait.Until(nc.doNoScheduleTaintingPassWorker, time.Second, stopCh)
}
// Start workers to reconcile labels and/or update NoSchedule taint for nodes.
for i := 0; i < scheduler.UpdateWorkerSize; i++ {
// Thanks to "workqueue", each worker just need to get item from queue, because
// the item is flagged when got from queue: if new event come, the new item will
// be re-queued until "Done", so no more than one worker handle the same item and
// no event missed.
go wait.Until(nc.doNodeProcessingPassWorker, time.Second, stopCh)
}
if nc.useTaintBasedEvictions {
@ -436,7 +468,7 @@ func (nc *Controller) Run(stopCh <-chan struct{}) {
<-stopCh
}
func (nc *Controller) doNoScheduleTaintingPassWorker() {
func (nc *Controller) doNodeProcessingPassWorker() {
for {
obj, shutdown := nc.nodeUpdateQueue.Get()
// "nodeUpdateQueue" will be shutdown when "stopCh" closed;
@ -445,10 +477,17 @@ func (nc *Controller) doNoScheduleTaintingPassWorker() {
return
}
nodeName := obj.(string)
if err := nc.doNoScheduleTaintingPass(nodeName); err != nil {
// TODO (k82cn): Add nodeName back to the queue.
klog.Errorf("Failed to taint NoSchedule on node <%s>, requeue it: %v", nodeName, err)
if nc.taintNodeByCondition {
if err := nc.doNoScheduleTaintingPass(nodeName); err != nil {
klog.Errorf("Failed to taint NoSchedule on node <%s>, requeue it: %v", nodeName, err)
// TODO(k82cn): Add nodeName back to the queue
}
}
// TODO: re-evaluate whether there are any labels that need to be
// reconcile in 1.19. Remove this function if it's no longer necessary.
if err := nc.reconcileNodeLabels(nodeName); err != nil {
klog.Errorf("Failed to reconcile labels for node <%s>, requeue it: %v", nodeName, err)
// TODO(yujuhong): Add nodeName back to the queue
}
nc.nodeUpdateQueue.Done(nodeName)
}
@ -1191,6 +1230,53 @@ func (nc *Controller) ComputeZoneState(nodeReadyConditions []*v1.NodeCondition)
}
}
// reconcileNodeLabels reconciles node labels.
func (nc *Controller) reconcileNodeLabels(nodeName string) error {
node, err := nc.nodeLister.Get(nodeName)
if err != nil {
// If node not found, just ignore it.
if apierrors.IsNotFound(err) {
return nil
}
return err
}
if node.Labels == nil {
// Nothing to reconcile.
return nil
}
labelsToUpdate := map[string]string{}
for _, r := range labelReconcileInfo {
primaryValue, primaryExists := node.Labels[r.primaryKey]
secondaryValue, secondaryExists := node.Labels[r.secondaryKey]
if !primaryExists {
// The primary label key does not exist. This should not happen
// within our supported version skew range, when no external
// components/factors modifying the node object. Ignore this case.
continue
}
if secondaryExists && primaryValue != secondaryValue {
// Secondary label exists, but not consistent with the primary
// label. Need to reconcile.
labelsToUpdate[r.secondaryKey] = primaryValue
} else if !secondaryExists && r.ensureSecondaryExists {
// Apply secondary label based on primary label.
labelsToUpdate[r.secondaryKey] = primaryValue
}
}
if len(labelsToUpdate) == 0 {
return nil
}
if !nodeutil.AddOrUpdateLabelsOnNode(nc.kubeClient, labelsToUpdate, node) {
return fmt.Errorf("failed update labels for node %+v", node)
}
return nil
}
func hash(val string, max int) int {
hasher := fnv.New32a()
io.WriteString(hasher, val)

View File

@ -42,6 +42,7 @@ import (
"k8s.io/kubernetes/pkg/controller/testutil"
nodeutil "k8s.io/kubernetes/pkg/controller/util/node"
"k8s.io/kubernetes/pkg/features"
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
"k8s.io/kubernetes/pkg/util/node"
taintutils "k8s.io/kubernetes/pkg/util/taints"
@ -2910,3 +2911,149 @@ func TestNodeEventGeneration(t *testing.T) {
}
}
}
func TestReconcileNodeLabels(t *testing.T) {
fakeNow := metav1.Date(2017, 1, 1, 12, 0, 0, 0, time.UTC)
evictionTimeout := 10 * time.Minute
fakeNodeHandler := &testutil.FakeNodeHandler{
Existing: []*v1.Node{
{
ObjectMeta: metav1.ObjectMeta{
Name: "node0",
CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
Labels: map[string]string{
v1.LabelZoneRegion: "region1",
v1.LabelZoneFailureDomain: "zone1",
},
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
Type: v1.NodeReady,
Status: v1.ConditionTrue,
LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
},
},
},
},
},
Clientset: fake.NewSimpleClientset(&v1.PodList{Items: []v1.Pod{*testutil.NewPod("pod0", "node0")}}),
}
nodeController, _ := newNodeLifecycleControllerFromClient(
fakeNodeHandler,
evictionTimeout,
testRateLimiterQPS,
testRateLimiterQPS,
testLargeClusterThreshold,
testUnhealthyThreshold,
testNodeMonitorGracePeriod,
testNodeStartupGracePeriod,
testNodeMonitorPeriod,
true)
nodeController.now = func() metav1.Time { return fakeNow }
nodeController.recorder = testutil.NewFakeRecorder()
tests := []struct {
Name string
Node *v1.Node
ExpectedLabels map[string]string
}{
{
Name: "No-op if node has no labels",
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node0",
CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
},
},
ExpectedLabels: nil,
},
{
Name: "No-op if no target labels present",
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node0",
CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
Labels: map[string]string{
v1.LabelZoneRegion: "region1",
},
},
},
ExpectedLabels: map[string]string{
v1.LabelZoneRegion: "region1",
},
},
{
Name: "Create OS/arch stable labels when they don't exist",
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node0",
CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
Labels: map[string]string{
kubeletapis.LabelOS: "linux",
kubeletapis.LabelArch: "amd64",
},
},
},
ExpectedLabels: map[string]string{
kubeletapis.LabelOS: "linux",
kubeletapis.LabelArch: "amd64",
v1.LabelOSStable: "linux",
v1.LabelArchStable: "amd64",
},
},
{
Name: "Reconcile OS/arch stable labels to match beta labels",
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node0",
CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
Labels: map[string]string{
kubeletapis.LabelOS: "linux",
kubeletapis.LabelArch: "amd64",
v1.LabelOSStable: "windows",
v1.LabelArchStable: "arm",
},
},
},
ExpectedLabels: map[string]string{
kubeletapis.LabelOS: "linux",
kubeletapis.LabelArch: "amd64",
v1.LabelOSStable: "linux",
v1.LabelArchStable: "amd64",
},
},
}
for _, test := range tests {
fakeNodeHandler.Update(test.Node)
if err := nodeController.syncNodeStore(fakeNodeHandler); err != nil {
t.Fatalf("unexpected error: %v", err)
}
nodeController.reconcileNodeLabels(test.Node.Name)
if err := nodeController.syncNodeStore(fakeNodeHandler); err != nil {
t.Fatalf("unexpected error: %v", err)
}
node0, err := nodeController.nodeLister.Get("node0")
if err != nil {
t.Fatalf("Can't get current node0...")
}
if len(node0.Labels) != len(test.ExpectedLabels) {
t.Errorf("%s: Unexpected number of taints: expected %d, got %d",
test.Name, len(test.ExpectedLabels), len(node0.Labels))
}
for key, expectedValue := range test.ExpectedLabels {
actualValue, ok := node0.Labels[key]
if !ok {
t.Errorf("%s: Can't find label %v in %v", test.Name, key, node0.Labels)
}
if actualValue != expectedValue {
t.Errorf("%s: label %q: expected value %q, got value %q", test.Name, key, expectedValue, actualValue)
}
}
}
}

View File

@ -214,6 +214,23 @@ func SwapNodeControllerTaint(kubeClient clientset.Interface, taintsToAdd, taints
return true
}
// AddOrUpdateLabelsOnNode updates the labels on the node and returns true on
// success and false on failure.
func AddOrUpdateLabelsOnNode(kubeClient clientset.Interface, labelsToUpdate map[string]string, node *v1.Node) bool {
err := controller.AddOrUpdateLabelsOnNode(kubeClient, node.Name, labelsToUpdate)
if err != nil {
utilruntime.HandleError(
fmt.Errorf(
"unable to update labels %+v for Node %q: %v",
labelsToUpdate,
node.Name,
err))
return false
}
klog.V(4).Infof("Updated labels %+v to Node %v", labelsToUpdate, node.Name)
return true
}
// CreateAddNodeHandler creates an add node handler.
func CreateAddNodeHandler(f func(node *v1.Node) error) func(obj interface{}) {
return func(originalObj interface{}) {

View File

@ -18,6 +18,7 @@ go_library(
"//pkg/controller/volume/attachdetach/reconciler:go_default_library",
"//pkg/controller/volume/attachdetach/statusupdater:go_default_library",
"//pkg/controller/volume/attachdetach/util:go_default_library",
"//pkg/features:go_default_library",
"//pkg/util/mount:go_default_library",
"//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library",
@ -31,11 +32,14 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/informers/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/informers/storage/v1beta1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/listers/storage/v1beta1:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",

View File

@ -30,11 +30,14 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
utilfeature "k8s.io/apiserver/pkg/util/feature"
coreinformers "k8s.io/client-go/informers/core/v1"
storageinformers "k8s.io/client-go/informers/storage/v1beta1"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
corelisters "k8s.io/client-go/listers/core/v1"
storagelisters "k8s.io/client-go/listers/storage/v1beta1"
kcache "k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue"
@ -47,6 +50,7 @@ import (
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/reconciler"
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/statusupdater"
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/util"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
volumeutil "k8s.io/kubernetes/pkg/volume/util"
@ -101,6 +105,7 @@ func NewAttachDetachController(
nodeInformer coreinformers.NodeInformer,
pvcInformer coreinformers.PersistentVolumeClaimInformer,
pvInformer coreinformers.PersistentVolumeInformer,
csiNodeInformer storageinformers.CSINodeInformer,
cloud cloudprovider.Interface,
plugins []volume.VolumePlugin,
prober volume.DynamicPluginProber,
@ -136,6 +141,12 @@ func NewAttachDetachController(
pvcQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "pvcs"),
}
if utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) &&
utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) {
adc.csiNodeLister = csiNodeInformer.Lister()
adc.csiNodeSynced = csiNodeInformer.Informer().HasSynced
}
if err := adc.volumePluginMgr.InitPlugins(plugins, prober, adc); err != nil {
return nil, fmt.Errorf("Could not initialize volume plugins for Attach/Detach Controller: %+v", err)
}
@ -257,6 +268,9 @@ type attachDetachController struct {
nodeLister corelisters.NodeLister
nodesSynced kcache.InformerSynced
csiNodeLister storagelisters.CSINodeLister
csiNodeSynced kcache.InformerSynced
// cloud provider used by volume host
cloud cloudprovider.Interface
@ -309,7 +323,12 @@ func (adc *attachDetachController) Run(stopCh <-chan struct{}) {
klog.Infof("Starting attach detach controller")
defer klog.Infof("Shutting down attach detach controller")
if !controller.WaitForCacheSync("attach detach", stopCh, adc.podsSynced, adc.nodesSynced, adc.pvcsSynced, adc.pvsSynced) {
synced := []kcache.InformerSynced{adc.podsSynced, adc.nodesSynced, adc.pvcsSynced, adc.pvsSynced}
if adc.csiNodeSynced != nil {
synced = append(synced, adc.csiNodeSynced)
}
if !controller.WaitForCacheSync("attach detach", stopCh, synced...) {
return
}
@ -643,6 +662,17 @@ func (adc *attachDetachController) processVolumesInUse(
}
}
var _ volume.VolumeHost = &attachDetachController{}
var _ volume.AttachDetachVolumeHost = &attachDetachController{}
func (adc *attachDetachController) CSINodeLister() storagelisters.CSINodeLister {
return adc.csiNodeLister
}
func (adc *attachDetachController) IsAttachDetachController() bool {
return true
}
// VolumeHost implementation
// This is an unfortunate requirement of the current factoring of volume plugin
// initializing code. It requires kubelet specific methods used by the mounting

View File

@ -44,6 +44,7 @@ func Test_NewAttachDetachController_Positive(t *testing.T) {
informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Core().V1().PersistentVolumes(),
informerFactory.Storage().V1beta1().CSINodes(),
nil, /* cloud */
nil, /* plugins */
nil, /* prober */
@ -218,6 +219,7 @@ func attachDetachRecoveryTestCase(t *testing.T, extraPods1 []*v1.Pod, extraPods2
informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Core().V1().PersistentVolumes(),
informerFactory.Storage().V1beta1().CSINodes(),
nil, /* cloud */
plugins,
prober,

View File

@ -310,9 +310,9 @@ const (
BalanceAttachedNodeVolumes utilfeature.Feature = "BalanceAttachedNodeVolumes"
// owner @freehan
// beta: v1.11
// GA: v1.14
//
// Support Pod Ready++
// Allow user to specify additional conditions to be evaluated for Pod readiness.
PodReadinessGates utilfeature.Feature = "PodReadinessGates"
// owner: @kevtaylor
@ -480,7 +480,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
CSIMigrationOpenStack: {Default: false, PreRelease: utilfeature.Alpha},
VolumeSubpath: {Default: true, PreRelease: utilfeature.GA},
BalanceAttachedNodeVolumes: {Default: false, PreRelease: utilfeature.Alpha},
PodReadinessGates: {Default: true, PreRelease: utilfeature.Beta},
PodReadinessGates: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.16
VolumeSubpathEnvExpansion: {Default: false, PreRelease: utilfeature.Alpha},
KubeletPluginsWatcher: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.16
ResourceQuotaScopeSelectors: {Default: true, PreRelease: utilfeature.Beta},
@ -510,6 +510,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
apiextensionsfeatures.CustomResourceValidation: {Default: true, PreRelease: utilfeature.Beta},
apiextensionsfeatures.CustomResourceSubresources: {Default: true, PreRelease: utilfeature.Beta},
apiextensionsfeatures.CustomResourceWebhookConversion: {Default: false, PreRelease: utilfeature.Alpha},
apiextensionsfeatures.CustomResourcePublishOpenAPI: {Default: false, PreRelease: utilfeature.Alpha},
// features that enable backwards compatibility but are scheduled to be removed
// ...

View File

@ -7,6 +7,7 @@ go_library(
"create_clusterrole.go",
"create_clusterrolebinding.go",
"create_configmap.go",
"create_cronjob.go",
"create_deployment.go",
"create_job.go",
"create_namespace.go",
@ -45,6 +46,7 @@ go_library(
"//staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource:go_default_library",
"//staging/src/k8s.io/client-go/dynamic:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library",
"//staging/src/k8s.io/component-base/cli/flag:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
@ -58,6 +60,7 @@ go_test(
"create_clusterrole_test.go",
"create_clusterrolebinding_test.go",
"create_configmap_test.go",
"create_cronjob_test.go",
"create_deployment_test.go",
"create_job_test.go",
"create_namespace_test.go",

View File

@ -146,6 +146,7 @@ func NewCmdCreate(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cob
cmd.AddCommand(NewCmdCreatePodDisruptionBudget(f, ioStreams))
cmd.AddCommand(NewCmdCreatePriorityClass(f, ioStreams))
cmd.AddCommand(NewCmdCreateJob(f, ioStreams))
cmd.AddCommand(NewCmdCreateCronJob(f, ioStreams))
return cmd
}

View File

@ -0,0 +1,205 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package create
import (
"fmt"
"github.com/spf13/cobra"
batchv1 "k8s.io/api/batch/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/resource"
batchv1beta1client "k8s.io/client-go/kubernetes/typed/batch/v1beta1"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/kubectl/util/templates"
)
var (
cronjobLong = templates.LongDesc(`
Create a cronjob with the specified name.`)
cronjobExample = templates.Examples(`
# Create a cronjob
kubectl create cronjob my-job --image=busybox
# Create a cronjob with command
kubectl create cronjob my-job --image=busybox -- date
# Create a cronjob with schedule
kubectl create cronjob test-job --image=busybox --schedule="*/1 * * * *"`)
)
type CreateCronJobOptions struct {
PrintFlags *genericclioptions.PrintFlags
PrintObj func(obj runtime.Object) error
Name string
Image string
Schedule string
Command []string
Restart string
Namespace string
Client batchv1beta1client.BatchV1beta1Interface
DryRun bool
Builder *resource.Builder
Cmd *cobra.Command
genericclioptions.IOStreams
}
func NewCreateCronJobOptions(ioStreams genericclioptions.IOStreams) *CreateCronJobOptions {
return &CreateCronJobOptions{
PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme),
IOStreams: ioStreams,
}
}
// NewCmdCreateCronJob is a command to to create CronJobs.
func NewCmdCreateCronJob(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
o := NewCreateCronJobOptions(ioStreams)
cmd := &cobra.Command{
Use: "cronjob NAME --image=image --schedule='0/5 * * * ?' -- [COMMAND] [args...]",
Aliases: []string{"cj"},
Short: cronjobLong,
Long: cronjobLong,
Example: cronjobExample,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, cmd, args))
cmdutil.CheckErr(o.Validate())
cmdutil.CheckErr(o.Run())
},
}
o.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddDryRunFlag(cmd)
cmd.Flags().StringVar(&o.Image, "image", o.Image, "Image name to run.")
cmd.Flags().StringVar(&o.Schedule, "schedule", o.Schedule, "A schedule in the Cron format the job should be run with.")
cmd.Flags().StringVar(&o.Restart, "restart", o.Restart, "job's restart policy. supported values: OnFailure, Never")
return cmd
}
func (o *CreateCronJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
o.Name = name
if len(args) > 1 {
o.Command = args[1:]
}
if len(o.Restart) == 0 {
o.Restart = "OnFailure"
}
clientConfig, err := f.ToRESTConfig()
if err != nil {
return err
}
o.Client, err = batchv1beta1client.NewForConfig(clientConfig)
if err != nil {
return err
}
o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}
o.Builder = f.NewBuilder()
o.Cmd = cmd
o.DryRun = cmdutil.GetDryRunFlag(cmd)
if o.DryRun {
o.PrintFlags.Complete("%s (dry run)")
}
printer, err := o.PrintFlags.ToPrinter()
if err != nil {
return err
}
o.PrintObj = func(obj runtime.Object) error {
return printer.PrintObj(obj, o.Out)
}
return nil
}
func (o *CreateCronJobOptions) Validate() error {
if len(o.Image) == 0 {
return fmt.Errorf("--image must be specified")
}
if len(o.Schedule) == 0 {
return fmt.Errorf("--schedule must be specified")
}
return nil
}
func (o *CreateCronJobOptions) Run() error {
var cronjob *batchv1beta1.CronJob
cronjob = o.createCronJob()
if !o.DryRun {
var err error
cronjob, err = o.Client.CronJobs(o.Namespace).Create(cronjob)
if err != nil {
return fmt.Errorf("failed to create cronjob: %v", err)
}
}
return o.PrintObj(cronjob)
}
func (o *CreateCronJobOptions) createCronJob() *batchv1beta1.CronJob {
return &batchv1beta1.CronJob{
TypeMeta: metav1.TypeMeta{APIVersion: batchv1beta1.SchemeGroupVersion.String(), Kind: "CronJob"},
ObjectMeta: metav1.ObjectMeta{
Name: o.Name,
},
Spec: batchv1beta1.CronJobSpec{
Schedule: o.Schedule,
JobTemplate: batchv1beta1.JobTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: o.Name,
},
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: o.Name,
Image: o.Image,
Command: o.Command,
},
},
RestartPolicy: corev1.RestartPolicy(o.Restart),
},
},
},
},
},
}
}

View File

@ -0,0 +1,121 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package create
import (
"testing"
batchv1 "k8s.io/api/batch/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1"
corev1 "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestCreateCronJob(t *testing.T) {
cronjobName := "test-job"
tests := map[string]struct {
image string
command []string
schedule string
restart string
expected *batchv1beta1.CronJob
}{
"just image and OnFailure restart policy": {
image: "busybox",
schedule: "0/5 * * * ?",
restart: "OnFailure",
expected: &batchv1beta1.CronJob{
TypeMeta: metav1.TypeMeta{APIVersion: batchv1beta1.SchemeGroupVersion.String(), Kind: "CronJob"},
ObjectMeta: metav1.ObjectMeta{
Name: cronjobName,
},
Spec: batchv1beta1.CronJobSpec{
Schedule: "0/5 * * * ?",
JobTemplate: batchv1beta1.JobTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: cronjobName,
},
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: cronjobName,
Image: "busybox",
},
},
RestartPolicy: corev1.RestartPolicyOnFailure,
},
},
},
},
},
},
},
"image, command , schedule and Never restart policy": {
image: "busybox",
command: []string{"date"},
schedule: "0/5 * * * ?",
restart: "Never",
expected: &batchv1beta1.CronJob{
TypeMeta: metav1.TypeMeta{APIVersion: batchv1beta1.SchemeGroupVersion.String(), Kind: "CronJob"},
ObjectMeta: metav1.ObjectMeta{
Name: cronjobName,
},
Spec: batchv1beta1.CronJobSpec{
Schedule: "0/5 * * * ?",
JobTemplate: batchv1beta1.JobTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: cronjobName,
},
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: cronjobName,
Image: "busybox",
Command: []string{"date"},
},
},
RestartPolicy: corev1.RestartPolicyNever,
},
},
},
},
},
},
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
o := &CreateCronJobOptions{
Name: cronjobName,
Image: tc.image,
Command: tc.command,
Schedule: tc.schedule,
Restart: tc.restart,
}
cronjob := o.createCronJob()
if !apiequality.Semantic.DeepEqual(cronjob, tc.expected) {
t.Errorf("expected:\n%#v\ngot:\n%#v", tc.expected, cronjob)
}
})
}
}

View File

@ -23,6 +23,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
@ -31,6 +32,7 @@ go_library(
"//staging/src/k8s.io/client-go/dynamic:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
"//staging/src/k8s.io/client-go/tools/watch:go_default_library",
"//vendor/github.com/docker/distribution/reference:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",

View File

@ -29,6 +29,7 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/watch"
@ -37,6 +38,7 @@ import (
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/tools/cache"
watchtools "k8s.io/client-go/tools/watch"
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/attach"
@ -490,18 +492,41 @@ func (o *RunOptions) removeCreatedObjects(f cmdutil.Factory, createdObjects []*R
// waitForPod watches the given pod until the exitCondition is true
func waitForPod(podClient corev1client.PodsGetter, ns, name string, exitCondition watchtools.ConditionFunc) (*corev1.Pod, error) {
w, err := podClient.Pods(ns).Watch(metav1.SingleObject(metav1.ObjectMeta{Name: name}))
if err != nil {
return nil, err
}
// TODO: expose the timeout
ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), 0*time.Second)
defer cancel()
preconditionFunc := func(store cache.Store) (bool, error) {
_, exists, err := store.Get(&metav1.ObjectMeta{Namespace: ns, Name: name})
if err != nil {
return true, err
}
if !exists {
// We need to make sure we see the object in the cache before we start waiting for events
// or we would be waiting for the timeout if such object didn't exist.
// (e.g. it was deleted before we started informers so they wouldn't even see the delete event)
return true, errors.NewNotFound(corev1.Resource("pods"), name)
}
return false, nil
}
fieldSelector := fields.OneTermEqualSelector("metadata.name", name).String()
lw := &cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
options.FieldSelector = fieldSelector
return podClient.Pods(ns).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
options.FieldSelector = fieldSelector
return podClient.Pods(ns).Watch(options)
},
}
intr := interrupt.New(nil, cancel)
var result *corev1.Pod
err = intr.Run(func() error {
ev, err := watchtools.UntilWithoutRetry(ctx, w, func(ev watch.Event) (bool, error) {
err := intr.Run(func() error {
ev, err := watchtools.UntilWithSync(ctx, lw, &corev1.Pod{}, preconditionFunc, func(ev watch.Event) (bool, error) {
return exitCondition(ev)
})
if ev != nil {
@ -510,11 +535,6 @@ func waitForPod(podClient corev1client.PodsGetter, ns, name string, exitConditio
return err
})
// Fix generic not found error.
if err != nil && errors.IsNotFound(err) {
err = errors.NewNotFound(corev1.Resource("pods"), name)
}
return result, err
}

View File

@ -140,7 +140,6 @@ go_library(
"//staging/src/k8s.io/client-go/util/certificate:go_default_library",
"//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:go_default_library",
"//third_party/forked/golang/expansion:go_default_library",
"//vendor/github.com/golang/groupcache/lru:go_default_library",
"//vendor/github.com/google/cadvisor/events:go_default_library",

View File

@ -44,6 +44,7 @@ filegroup(
"//pkg/kubelet/apis/pluginregistration/v1alpha1:all-srcs",
"//pkg/kubelet/apis/pluginregistration/v1beta1:all-srcs",
"//pkg/kubelet/apis/podresources:all-srcs",
"//pkg/kubelet/apis/resourcemetrics/v1alpha1:all-srcs",
"//pkg/kubelet/apis/stats/v1alpha1:all-srcs",
],
tags = ["automanaged"],

View File

@ -0,0 +1,26 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["config.go"],
importpath = "k8s.io/kubernetes/pkg/kubelet/apis/resourcemetrics/v1alpha1",
visibility = ["//visibility:public"],
deps = [
"//pkg/kubelet/apis/stats/v1alpha1:go_default_library",
"//pkg/kubelet/server/stats: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"],
)

View File

@ -0,0 +1,81 @@
/*
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 v1alpha1
import (
"time"
summary "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
"k8s.io/kubernetes/pkg/kubelet/server/stats"
)
// Version is the string representation of the version of this configuration
const Version = "v1alpha1"
// Config is the v1alpha1 resource metrics definition
func Config() stats.ResourceMetricsConfig {
return stats.ResourceMetricsConfig{
NodeMetrics: []stats.NodeResourceMetric{
{
Name: "node_cpu_usage_seconds_total",
Description: "Cumulative cpu time consumed by the node in core-seconds",
ValueFn: func(s summary.NodeStats) (*float64, time.Time) {
if s.CPU == nil {
return nil, time.Time{}
}
v := float64(*s.CPU.UsageCoreNanoSeconds) / float64(time.Second)
return &v, s.CPU.Time.Time
},
},
{
Name: "node_memory_working_set_bytes",
Description: "Current working set of the node in bytes",
ValueFn: func(s summary.NodeStats) (*float64, time.Time) {
if s.Memory == nil {
return nil, time.Time{}
}
v := float64(*s.Memory.WorkingSetBytes)
return &v, s.Memory.Time.Time
},
},
},
ContainerMetrics: []stats.ContainerResourceMetric{
{
Name: "container_cpu_usage_seconds_total",
Description: "Cumulative cpu time consumed by the container in core-seconds",
ValueFn: func(s summary.ContainerStats) (*float64, time.Time) {
if s.CPU == nil {
return nil, time.Time{}
}
v := float64(*s.CPU.UsageCoreNanoSeconds) / float64(time.Second)
return &v, s.CPU.Time.Time
},
},
{
Name: "container_memory_working_set_bytes",
Description: "Current working set of the container in bytes",
ValueFn: func(s summary.ContainerStats) (*float64, time.Time) {
if s.Memory == nil {
return nil, time.Time{}
}
v := float64(*s.Memory.WorkingSetBytes)
return &v, s.Memory.Time.Time
},
},
},
}
}

View File

@ -137,6 +137,9 @@ func (ds *dockerService) CreateContainer(_ context.Context, r *runtimeapi.Create
},
HostConfig: &dockercontainer.HostConfig{
Binds: generateMountBindings(config.GetMounts()),
RestartPolicy: dockercontainer.RestartPolicy{
Name: "no",
},
},
}

View File

@ -113,7 +113,6 @@ import (
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/csi"
"k8s.io/kubernetes/pkg/volume/util/subpath"
nodeapiclientset "k8s.io/node-api/pkg/client/clientset/versioned"
utilexec "k8s.io/utils/exec"
"k8s.io/utils/integer"
)
@ -248,7 +247,6 @@ type Dependencies struct {
HeartbeatClient clientset.Interface
OnHeartbeatFailure func()
KubeClient clientset.Interface
NodeAPIClient nodeapiclientset.Interface
Mounter mount.Interface
OOMAdjuster *oom.OOMAdjuster
OSInterface kubecontainer.OSInterface
@ -658,8 +656,8 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
}
klet.runtimeService = runtimeService
if utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) && kubeDeps.NodeAPIClient != nil {
klet.runtimeClassManager = runtimeclass.NewManager(kubeDeps.NodeAPIClient)
if utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) {
klet.runtimeClassManager = runtimeclass.NewManager(kubeDeps.KubeClient)
}
runtime, err := kuberuntime.NewKubeGenericRuntimeManager(
@ -776,6 +774,9 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
tokenManager := token.NewManager(kubeDeps.KubeClient)
// NewInitializedVolumePluginMgr intializes some storageErrors on the Kubelet runtimeState (in csi_plugin.go init)
// which affects node ready status. This function must be called before Kubelet is initialized so that the Node
// ReadyState is accurate with the storage state.
klet.volumePluginMgr, err =
NewInitializedVolumePluginMgr(klet, secretManager, configMapManager, tokenManager, kubeDeps.VolumePlugins, kubeDeps.DynamicPluginProber)
if err != nil {

View File

@ -544,7 +544,7 @@ func (kl *Kubelet) defaultNodeStatusFuncs() []func(*v1.Node) error {
nodestatus.MemoryPressureCondition(kl.clock.Now, kl.evictionManager.IsUnderMemoryPressure, kl.recordNodeStatusEvent),
nodestatus.DiskPressureCondition(kl.clock.Now, kl.evictionManager.IsUnderDiskPressure, kl.recordNodeStatusEvent),
nodestatus.PIDPressureCondition(kl.clock.Now, kl.evictionManager.IsUnderPIDPressure, kl.recordNodeStatusEvent),
nodestatus.ReadyCondition(kl.clock.Now, kl.runtimeState.runtimeErrors, kl.runtimeState.networkErrors, validateHostFunc, kl.containerManager.Status, kl.recordNodeStatusEvent),
nodestatus.ReadyCondition(kl.clock.Now, kl.runtimeState.runtimeErrors, kl.runtimeState.networkErrors, kl.runtimeState.storageErrors, validateHostFunc, kl.containerManager.Status, kl.recordNodeStatusEvent),
nodestatus.VolumesInUse(kl.volumeManager.ReconcilerStatesHasBeenSynced, kl.volumeManager.GetVolumesInUse),
nodestatus.RemoveOutOfDiskCondition(),
// TODO(mtaufen): I decided not to move this setter for now, since all it does is send an event

View File

@ -440,6 +440,7 @@ func ReadyCondition(
nowFunc func() time.Time, // typically Kubelet.clock.Now
runtimeErrorsFunc func() error, // typically Kubelet.runtimeState.runtimeErrors
networkErrorsFunc func() error, // typically Kubelet.runtimeState.networkErrors
storageErrorsFunc func() error, // typically Kubelet.runtimeState.storageErrors
appArmorValidateHostFunc func() error, // typically Kubelet.appArmorValidator.ValidateHost, might be nil depending on whether there was an appArmorValidator
cmStatusFunc func() cm.Status, // typically Kubelet.containerManager.Status
recordEventFunc func(eventType, event string), // typically Kubelet.recordNodeStatusEvent
@ -456,7 +457,7 @@ func ReadyCondition(
Message: "kubelet is posting ready status",
LastHeartbeatTime: currentTime,
}
errs := []error{runtimeErrorsFunc(), networkErrorsFunc()}
errs := []error{runtimeErrorsFunc(), networkErrorsFunc(), storageErrorsFunc()}
requiredCapacities := []v1.ResourceName{v1.ResourceCPU, v1.ResourceMemory, v1.ResourcePods}
if utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
requiredCapacities = append(requiredCapacities, v1.ResourceEphemeralStorage)

View File

@ -895,6 +895,7 @@ func TestReadyCondition(t *testing.T) {
node *v1.Node
runtimeErrors error
networkErrors error
storageErrors error
appArmorValidateHostFunc func() error
cmStatus cm.Status
expectConditions []v1.NodeCondition
@ -929,6 +930,12 @@ func TestReadyCondition(t *testing.T) {
},
expectConditions: []v1.NodeCondition{*makeReadyCondition(true, "kubelet is posting ready status. WARNING: foo", now, now)},
},
{
desc: "new, not ready: storage errors",
node: withCapacity.DeepCopy(),
storageErrors: errors.New("some storage error"),
expectConditions: []v1.NodeCondition{*makeReadyCondition(false, "some storage error", now, now)},
},
{
desc: "new, not ready: runtime and network errors",
node: withCapacity.DeepCopy(),
@ -1003,6 +1010,9 @@ func TestReadyCondition(t *testing.T) {
networkErrorsFunc := func() error {
return tc.networkErrors
}
storageErrorsFunc := func() error {
return tc.storageErrors
}
cmStatusFunc := func() cm.Status {
return tc.cmStatus
}
@ -1014,7 +1024,7 @@ func TestReadyCondition(t *testing.T) {
})
}
// construct setter
setter := ReadyCondition(nowFunc, runtimeErrorsFunc, networkErrorsFunc, tc.appArmorValidateHostFunc, cmStatusFunc, recordEventFunc)
setter := ReadyCondition(nowFunc, runtimeErrorsFunc, networkErrorsFunc, storageErrorsFunc, tc.appArmorValidateHostFunc, cmStatusFunc, recordEventFunc)
// call setter on node
if err := setter(tc.node); err != nil {
t.Fatalf("unexpected error: %v", err)

View File

@ -30,6 +30,7 @@ type runtimeState struct {
lastBaseRuntimeSync time.Time
baseRuntimeSyncThreshold time.Duration
networkError error
storageError error
cidr string
healthChecks []*healthCheck
}
@ -61,6 +62,12 @@ func (s *runtimeState) setNetworkState(err error) {
s.networkError = err
}
func (s *runtimeState) setStorageState(err error) {
s.Lock()
defer s.Unlock()
s.storageError = err
}
func (s *runtimeState) setPodCIDR(cidr string) {
s.Lock()
defer s.Unlock()
@ -101,6 +108,16 @@ func (s *runtimeState) networkErrors() error {
return utilerrors.NewAggregate(errs)
}
func (s *runtimeState) storageErrors() error {
s.RLock()
defer s.RUnlock()
errs := []error{}
if s.storageError != nil {
errs = append(errs, s.storageError)
}
return utilerrors.NewAggregate(errs)
}
func newRuntimeState(
runtimeSyncThreshold time.Duration,
) *runtimeState {

View File

@ -7,10 +7,9 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:go_default_library",
"//staging/src/k8s.io/node-api/pkg/client/informers/externalversions:go_default_library",
"//staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/listers/node/v1beta1:go_default_library",
],
)

View File

@ -20,31 +20,23 @@ import (
"fmt"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
nodeapiclient "k8s.io/node-api/pkg/client/clientset/versioned"
nodeapiinformer "k8s.io/node-api/pkg/client/informers/externalversions"
nodev1alpha1 "k8s.io/node-api/pkg/client/listers/node/v1alpha1"
)
var (
runtimeClassGVR = schema.GroupVersionResource{
Group: "node.k8s.io",
Version: "v1alpha1",
Resource: "runtimeclasses",
}
"k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes"
nodev1beta1 "k8s.io/client-go/listers/node/v1beta1"
)
// Manager caches RuntimeClass API objects, and provides accessors to the Kubelet.
type Manager struct {
informerFactory nodeapiinformer.SharedInformerFactory
lister nodev1alpha1.RuntimeClassLister
informerFactory informers.SharedInformerFactory
lister nodev1beta1.RuntimeClassLister
}
// NewManager returns a new RuntimeClass Manager. Run must be called before the manager can be used.
func NewManager(client nodeapiclient.Interface) *Manager {
func NewManager(client clientset.Interface) *Manager {
const resyncPeriod = 0
factory := nodeapiinformer.NewSharedInformerFactory(client, resyncPeriod)
lister := factory.Node().V1alpha1().RuntimeClasses().Lister()
factory := informers.NewSharedInformerFactory(client, resyncPeriod)
lister := factory.Node().V1beta1().RuntimeClasses().Lister()
return &Manager{
informerFactory: factory,
@ -82,9 +74,5 @@ func (m *Manager) LookupRuntimeHandler(runtimeClassName *string) (string, error)
return "", fmt.Errorf("Failed to lookup RuntimeClass %s: %v", name, err)
}
handler := rc.Spec.RuntimeHandler
if handler == nil {
return "", nil
}
return *handler, nil
return rc.Handler, nil
}

View File

@ -33,7 +33,6 @@ func TestLookupRuntimeHandler(t *testing.T) {
expected string
expectError bool
}{
{rcn: nil, expected: ""},
{rcn: pointer.StringPtr(""), expected: ""},
{rcn: pointer.StringPtr(rctest.EmptyRuntimeClass), expected: ""},
{rcn: pointer.StringPtr(rctest.SandboxRuntimeClass), expected: "kata-containers"},

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