Commit 28e8b5ab authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #36263 from apprenda/kubeadm-unit-tests-pkg-master

Automatic merge from submit-queue Kubeadm unit tests for kubeadm/app/master package Added unit tests for the kubeadm/app/master package testing functionality of tokens.go, kubeconfig.go, manifests.go, pki.go, discovery.go, addons.go, and apiclient.go. This PR is part of the ongoing effort to add tests (#35025) /cc @pires @jbeda
parents d71154b9 b3a56abe
...@@ -44,3 +44,24 @@ go_library( ...@@ -44,3 +44,24 @@ go_library(
"//pkg/util/wait:go_default_library", "//pkg/util/wait:go_default_library",
], ],
) )
go_test(
name = "go_default_test",
srcs = [
"addons_test.go",
"apiclient_test.go",
"discovery_test.go",
"kubeconfig_test.go",
"manifests_test.go",
"pki_test.go",
"tokens_test.go",
],
library = "go_default_library",
tags = ["automanaged"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/util/cert:go_default_library",
"//pkg/util/intstr:go_default_library",
],
)
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package master
import (
"testing"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
)
func TestCreateKubeProxyPodSpec(t *testing.T) {
var tests = []struct {
cfg *kubeadmapi.MasterConfiguration
expected bool
}{
{
cfg: &kubeadmapi.MasterConfiguration{},
expected: true,
},
}
for _, rt := range tests {
actual := createKubeProxyPodSpec(rt.cfg)
if (actual.Containers[0].Name != "") != rt.expected {
t.Errorf(
"failed createKubeProxyPodSpec:\n\texpected: %t\n\t actual: %t",
rt.expected,
(actual.Containers[0].Name != ""),
)
}
}
}
func TestCreateKubeDNSPodSpec(t *testing.T) {
var tests = []struct {
cfg *kubeadmapi.MasterConfiguration
expected string
}{
{
cfg: &kubeadmapi.MasterConfiguration{
Networking: kubeadm.Networking{DNSDomain: "localhost"},
},
expected: "--domain=localhost",
},
{
cfg: &kubeadmapi.MasterConfiguration{
Networking: kubeadm.Networking{DNSDomain: "foo"},
},
expected: "--domain=foo",
},
}
for _, rt := range tests {
actual := createKubeDNSPodSpec(rt.cfg)
if actual.Containers[0].Args[0] != rt.expected {
t.Errorf(
"failed createKubeDNSPodSpec:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual.Containers[0].Args[0],
)
}
}
}
func TestCreateKubeDNSServiceSpec(t *testing.T) {
var tests = []struct {
cfg *kubeadmapi.MasterConfiguration
expected bool
}{
{
cfg: &kubeadmapi.MasterConfiguration{
Networking: kubeadm.Networking{ServiceSubnet: "foo"},
},
expected: false,
},
{
cfg: &kubeadmapi.MasterConfiguration{
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/1"},
},
expected: false,
},
{
cfg: &kubeadmapi.MasterConfiguration{
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/24"},
},
expected: true,
},
}
for _, rt := range tests {
_, actual := createKubeDNSServiceSpec(rt.cfg)
if (actual == nil) != rt.expected {
t.Errorf(
"failed createKubeDNSServiceSpec:\n\texpected: %t\n\t actual: %t",
rt.expected,
(actual == nil),
)
}
}
}
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package master
import (
"fmt"
"testing"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
apiv1 "k8s.io/kubernetes/pkg/api/v1"
)
func TestCreateClientAndWaitForAPI(t *testing.T) {
cfg := &kubeadmapi.MasterConfiguration{
Networking: kubeadm.Networking{DNSDomain: "localhost"},
}
fmt.Println(cfg)
}
func TestStandardLabels(t *testing.T) {
var tests = []struct {
n string
expected string
}{
{
n: "foo",
expected: "foo",
},
{
n: "bar",
expected: "bar",
},
}
for _, rt := range tests {
actual := standardLabels(rt.n)
if actual["component"] != rt.expected {
t.Errorf(
"failed standardLabels:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual["component"],
)
}
if actual["name"] != rt.expected {
t.Errorf(
"failed standardLabels:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual["name"],
)
}
if actual["k8s-app"] != rt.expected {
t.Errorf(
"failed standardLabels:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual["k8s-app"],
)
}
}
}
func TestNewDaemonSet(t *testing.T) {
var tests = []struct {
dn string
expected string
}{
{
dn: "foo",
expected: "foo",
},
{
dn: "bar",
expected: "bar",
},
}
for _, rt := range tests {
p := apiv1.PodSpec{}
actual := NewDaemonSet(rt.dn, p)
if actual.Spec.Selector.MatchLabels["k8s-app"] != rt.expected {
t.Errorf(
"failed NewDaemonSet:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual.Spec.Selector.MatchLabels["k8s-app"],
)
}
if actual.Spec.Selector.MatchLabels["component"] != rt.expected {
t.Errorf(
"failed NewDaemonSet:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual.Spec.Selector.MatchLabels["component"],
)
}
if actual.Spec.Selector.MatchLabels["name"] != rt.expected {
t.Errorf(
"failed NewDaemonSet:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual.Spec.Selector.MatchLabels["name"],
)
}
}
}
func TestNewService(t *testing.T) {
var tests = []struct {
dn string
expected string
}{
{
dn: "foo",
expected: "foo",
},
{
dn: "bar",
expected: "bar",
},
}
for _, rt := range tests {
p := apiv1.ServiceSpec{}
actual := NewService(rt.dn, p)
if actual.ObjectMeta.Labels["k8s-app"] != rt.expected {
t.Errorf(
"failed NewService:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual.ObjectMeta.Labels["k8s-app"],
)
}
if actual.ObjectMeta.Labels["component"] != rt.expected {
t.Errorf(
"failed NewService:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual.ObjectMeta.Labels["component"],
)
}
if actual.ObjectMeta.Labels["name"] != rt.expected {
t.Errorf(
"failed NewService:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual.ObjectMeta.Labels["name"],
)
}
}
}
func TestNewDeployment(t *testing.T) {
var tests = []struct {
dn string
expected string
}{
{
dn: "foo",
expected: "foo",
},
{
dn: "bar",
expected: "bar",
},
}
for _, rt := range tests {
p := apiv1.PodSpec{}
actual := NewDeployment(rt.dn, 1, p)
if actual.Spec.Selector.MatchLabels["k8s-app"] != rt.expected {
t.Errorf(
"failed NewDeployment:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual.Spec.Selector.MatchLabels["k8s-app"],
)
}
if actual.Spec.Selector.MatchLabels["component"] != rt.expected {
t.Errorf(
"failed NewDeployment:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual.Spec.Selector.MatchLabels["component"],
)
}
if actual.Spec.Selector.MatchLabels["name"] != rt.expected {
t.Errorf(
"failed NewDeployment:\n\texpected: %s\n\t actual: %s",
rt.expected,
actual.Spec.Selector.MatchLabels["name"],
)
}
}
}
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package master
import (
"crypto/x509"
"testing"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
)
func TestEncodeKubeDiscoverySecretData(t *testing.T) {
var tests = []struct {
cfg *kubeadmapi.MasterConfiguration
expected bool
}{
{
cfg: &kubeadmapi.MasterConfiguration{
API: kubeadmapi.API{BindPort: 123, AdvertiseAddresses: []string{"10.0.0.1"}},
Networking: kubeadmapi.Networking{ServiceSubnet: "10.0.0.1/1"},
},
expected: true,
},
}
for _, rt := range tests {
caCert := &x509.Certificate{}
actual := encodeKubeDiscoverySecretData(rt.cfg, caCert)
if (actual != nil) != rt.expected {
t.Errorf(
"failed encodeKubeDiscoverySecretData, return map[string][]byte was nil",
)
}
}
}
func TestNewKubeDiscoveryPodSpec(t *testing.T) {
var tests = []struct {
cfg *kubeadmapi.MasterConfiguration
p int32
expected bool
}{
{
cfg: &kubeadmapi.MasterConfiguration{
Discovery: kubeadmapi.Discovery{BindPort: 123},
},
p: 123,
},
{
cfg: &kubeadmapi.MasterConfiguration{
Discovery: kubeadmapi.Discovery{BindPort: 456},
},
p: 456,
},
}
for _, rt := range tests {
actual := newKubeDiscoveryPodSpec(rt.cfg)
if actual.Containers[0].Ports[0].HostPort != rt.p {
t.Errorf(
"failed newKubeDiscoveryPodSpec:\n\texpected: %d\n\t actual: %d",
rt.p,
actual.Containers[0].Ports[0].HostPort,
)
}
}
}
func TestNewKubeDiscovery(t *testing.T) {
var tests = []struct {
cfg *kubeadmapi.MasterConfiguration
caCert *x509.Certificate
expected bool
}{
{
cfg: &kubeadmapi.MasterConfiguration{
API: kubeadmapi.API{BindPort: 123, AdvertiseAddresses: []string{"10.0.0.1"}},
Networking: kubeadmapi.Networking{ServiceSubnet: "10.0.0.1/1"},
},
caCert: &x509.Certificate{},
},
}
for _, rt := range tests {
actual := newKubeDiscovery(rt.cfg, rt.caCert)
if actual.Deployment == nil || actual.Secret == nil {
t.Errorf(
"failed newKubeDiscovery, kubeDiscovery was nil",
)
}
}
}
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package master
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"testing"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
)
func TestCreateCertsAndConfigForClients(t *testing.T) {
var tests = []struct {
a kubeadmapi.API
cn []string
caKeySize int
expected bool
}{
{
a: kubeadmapi.API{AdvertiseAddresses: []string{"foo"}},
cn: []string{"localhost"},
caKeySize: 128,
expected: false,
},
{
a: kubeadmapi.API{AdvertiseAddresses: []string{"foo"}},
cn: []string{},
caKeySize: 128,
expected: true,
},
{
a: kubeadmapi.API{AdvertiseAddresses: []string{"foo"}},
cn: []string{"localhost"},
caKeySize: 2048,
expected: true,
},
}
for _, rt := range tests {
caKey, err := rsa.GenerateKey(rand.Reader, rt.caKeySize)
if err != nil {
t.Fatalf("Couldn't create rsa Private Key")
}
caCert := &x509.Certificate{}
_, actual := CreateCertsAndConfigForClients(rt.a, rt.cn, caKey, caCert)
if (actual == nil) != rt.expected {
t.Errorf(
"failed CreateCertsAndConfigForClients:\n\texpected: %t\n\t actual: %t",
rt.expected,
(actual == nil),
)
}
}
}
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package master
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"fmt"
"io/ioutil"
"os"
"testing"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
certutil "k8s.io/kubernetes/pkg/util/cert"
)
func TestNewCertificateAuthority(t *testing.T) {
r, x, err := newCertificateAuthority()
if r == nil {
t.Errorf(
"failed newCertificateAuthority, rsa key == nil",
)
}
if x == nil {
t.Errorf(
"failed newCertificateAuthority, x509 cert == nil",
)
}
if err != nil {
t.Errorf(
"failed newCertificateAuthority with an error: %v",
err,
)
}
}
func TestNewServerKeyAndCert(t *testing.T) {
var tests = []struct {
cfg *kubeadmapi.MasterConfiguration
caKeySize int
expected bool
}{
{
// given CIDR too small
cfg: &kubeadmapi.MasterConfiguration{
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/1"},
},
caKeySize: 2048,
expected: false,
},
{
// bad CIDR
cfg: &kubeadmapi.MasterConfiguration{
Networking: kubeadm.Networking{ServiceSubnet: "foo"},
},
caKeySize: 2048,
expected: false,
},
{
// RSA key too small
cfg: &kubeadmapi.MasterConfiguration{
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/24"},
},
caKeySize: 128,
expected: false,
},
{
cfg: &kubeadmapi.MasterConfiguration{
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/24"},
},
caKeySize: 2048,
expected: true,
},
}
for _, rt := range tests {
caKey, err := rsa.GenerateKey(rand.Reader, rt.caKeySize)
if err != nil {
t.Fatalf("Couldn't create rsa Private Key")
}
caCert := &x509.Certificate{}
altNames := certutil.AltNames{}
_, _, actual := newServerKeyAndCert(rt.cfg, caCert, caKey, altNames)
if (actual == nil) != rt.expected {
t.Errorf(
"failed newServerKeyAndCert:\n\texpected: %t\n\t actual: %t",
rt.expected,
(actual == nil),
)
}
}
}
func TestNewClientKeyAndCert(t *testing.T) {
var tests = []struct {
caKeySize int
expected bool
}{
{
// RSA key too small
caKeySize: 128,
expected: false,
},
{
caKeySize: 2048,
expected: true,
},
}
for _, rt := range tests {
caKey, err := rsa.GenerateKey(rand.Reader, rt.caKeySize)
if err != nil {
t.Fatalf("Couldn't create rsa Private Key")
}
caCert := &x509.Certificate{}
_, _, actual := newClientKeyAndCert(caCert, caKey)
if (actual == nil) != rt.expected {
t.Errorf(
"failed newClientKeyAndCert:\n\texpected: %t\n\t actual: %t",
rt.expected,
(actual == nil),
)
}
}
}
func TestWriteKeysAndCert(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatalf("Couldn't create tmpdir")
}
defer os.Remove(tmpdir)
caKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
t.Fatalf("Couldn't create rsa Private Key")
}
caCert := &x509.Certificate{}
actual := writeKeysAndCert(tmpdir, "foo", caKey, caCert)
if actual != nil {
t.Errorf(
"failed writeKeysAndCert with an error: %v",
actual,
)
}
}
func TestPathsKeysCerts(t *testing.T) {
var tests = []struct {
pkiPath string
name string
expected []string
}{
{
pkiPath: "foo",
name: "bar",
expected: []string{"foo/bar-pub.pem", "foo/bar-key.pem", "foo/bar.pem"},
},
{
pkiPath: "bar",
name: "foo",
expected: []string{"bar/foo-pub.pem", "bar/foo-key.pem", "bar/foo.pem"},
},
}
for _, rt := range tests {
a, b, c := pathsKeysCerts(rt.pkiPath, rt.name)
all := []string{a, b, c}
for i := range all {
if all[i] != rt.expected[i] {
t.Errorf(
"failed pathsKeysCerts:\n\texpected: %s\n\t actual: %s",
rt.expected[i],
all[i],
)
}
}
}
}
func TestNewServiceAccountKey(t *testing.T) {
r, err := newServiceAccountKey()
if r == nil {
t.Errorf(
"failed newServiceAccountKey, rsa key == nil",
)
}
if err != nil {
t.Errorf(
"failed newServiceAccountKey with an error: %v",
err,
)
}
}
func TestCreatePKIAssets(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatalf("Couldn't create tmpdir")
}
defer os.Remove(tmpdir)
// set up tmp GlobalEnvParams values for testing
oldEnv := kubeadmapi.GlobalEnvParams
kubeadmapi.GlobalEnvParams.HostPKIPath = fmt.Sprintf("%s/etc/kubernetes/pki", tmpdir)
defer func() { kubeadmapi.GlobalEnvParams = oldEnv }()
var tests = []struct {
cfg *kubeadmapi.MasterConfiguration
expected bool
}{
{
cfg: &kubeadmapi.MasterConfiguration{},
expected: false,
},
{
cfg: &kubeadmapi.MasterConfiguration{
API: kubeadm.API{AdvertiseAddresses: []string{"10.0.0.1"}},
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/1"},
},
expected: false,
},
{
cfg: &kubeadmapi.MasterConfiguration{
API: kubeadm.API{AdvertiseAddresses: []string{"10.0.0.1"}},
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/24"},
},
expected: true,
},
}
for _, rt := range tests {
_, _, actual := CreatePKIAssets(rt.cfg)
if (actual == nil) != rt.expected {
t.Errorf(
"failed CreatePKIAssets with an error:\n\texpected: %t\n\t actual: %t",
rt.expected,
(actual == nil),
)
}
}
}
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package master
import (
"fmt"
"io/ioutil"
"os"
"testing"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
)
func TestGenerateTokenIfNeeded(t *testing.T) {
var tests = []struct {
s kubeadmapi.Secrets
expected bool
}{
{kubeadmapi.Secrets{GivenToken: "noperiod"}, false}, // not 2-part '.' format
{kubeadmapi.Secrets{GivenToken: "abcd.a"}, false}, // len(tokenID) != 6
{kubeadmapi.Secrets{GivenToken: "abcdef.a"}, true},
{kubeadmapi.Secrets{GivenToken: ""}, true},
}
for _, rt := range tests {
actual := generateTokenIfNeeded(&rt.s)
if (actual == nil) != rt.expected {
t.Errorf(
"failed UseGivenTokenIfValid:\n\texpected: %t\n\t actual: %t\n\t token:%s",
rt.expected,
(actual == nil),
rt.s.GivenToken,
)
}
}
}
func TestCreateTokenAuthFile(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatalf("Couldn't create tmpdir")
}
defer os.Remove(tmpdir)
// set up tmp GlobalEnvParams values for testing
oldEnv := kubeadmapi.GlobalEnvParams
kubeadmapi.GlobalEnvParams.HostPKIPath = fmt.Sprintf("%s/etc/kubernetes/pki", tmpdir)
defer func() { kubeadmapi.GlobalEnvParams = oldEnv }()
var tests = []struct {
s kubeadmapi.Secrets
expected bool
}{
{kubeadmapi.Secrets{GivenToken: "noperiod"}, false}, // not 2-part '.' format
{kubeadmapi.Secrets{GivenToken: "abcd.a"}, false}, // len(tokenID) != 6
{kubeadmapi.Secrets{GivenToken: "abcdef.a"}, true},
{kubeadmapi.Secrets{GivenToken: ""}, true},
}
for _, rt := range tests {
actual := CreateTokenAuthFile(&rt.s)
if (actual == nil) != rt.expected {
t.Errorf(
"failed WriteKubeconfigIfNotExists with an error:\n\texpected: %t\n\t actual: %t",
rt.expected,
(actual == nil),
)
}
}
}
...@@ -506,6 +506,7 @@ k8s.io/kubernetes/cmd/kube-proxy/app,luxas,1 ...@@ -506,6 +506,7 @@ k8s.io/kubernetes/cmd/kube-proxy/app,luxas,1
k8s.io/kubernetes/cmd/kubeadm/app/cmd,caesarxuchao,1 k8s.io/kubernetes/cmd/kubeadm/app/cmd,caesarxuchao,1
k8s.io/kubernetes/cmd/kubeadm/app/images,davidopp,1 k8s.io/kubernetes/cmd/kubeadm/app/images,davidopp,1
k8s.io/kubernetes/cmd/kubeadm/app/node,apprenda,0 k8s.io/kubernetes/cmd/kubeadm/app/node,apprenda,0
k8s.io/kubernetes/cmd/kubeadm/app/master,apprenda,0
k8s.io/kubernetes/cmd/kubeadm/app/preflight,apprenda,0 k8s.io/kubernetes/cmd/kubeadm/app/preflight,apprenda,0
k8s.io/kubernetes/cmd/kubeadm/app/util,krousey,1 k8s.io/kubernetes/cmd/kubeadm/app/util,krousey,1
k8s.io/kubernetes/cmd/kubeadm/test,pipejakob,0 k8s.io/kubernetes/cmd/kubeadm/test,pipejakob,0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment