mirror of https://github.com/k3s-io/k3s
Merge pull request #35144 from pipejakob/generate-token
Automatic merge from submit-queue New command: "kubeadm token generate" As part of #33930, this PR adds a new top-level command to kubeadm to just generate a token for use with the init/join commands. Otherwise, users are left to either figure out how to generate a token on their own, or let `kubeadm init` generate a token, capture and parse the output, and then use that token for `kubeadm join`. At this point, I was hoping for feedback on the CLI experience, and then I can add tests. I spoke with @mikedanese and he didn't like the original propose of `kubeadm util generate-token`, so here are the runners up: ``` $ kubeadm generate-token # <--- current implementation $ kubeadm generate token # in case kubeadm might generate other things in the future? $ kubeadm init --generate-token # possibly as a subcommand of an existing one ``` Currently, the output is simply the token on one line without any padding/formatting: ``` $ kubeadm generate-token 1087fd.722b60cdd39b1a5f ``` CC: @kubernetes/sig-cluster-lifecycle **Release note**: <!-- Steps to write your release note: 1. Use the release-note-* labels to set the release note state (if you have access) 2. Enter your extended release note in the below block; leaving it blank means using the PR title as the release note. If no release note is required, just write `NONE`. --> ``` release-note New kubeadm command: generate-token ```pull/6/head
commit
afa99c68b8
1
Makefile
1
Makefile
|
@ -193,6 +193,7 @@ test-e2e-node: ginkgo generated_files
|
||||||
# make test-cmd
|
# make test-cmd
|
||||||
.PHONY: test-cmd
|
.PHONY: test-cmd
|
||||||
test-cmd: generated_files
|
test-cmd: generated_files
|
||||||
|
hack/make-rules/test-kubeadm-cmd.sh
|
||||||
hack/make-rules/test-cmd.sh
|
hack/make-rules/test-cmd.sh
|
||||||
|
|
||||||
# Remove all build artifacts.
|
# Remove all build artifacts.
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
KUBE_ROOT=${KUBE_ROOT:-$(dirname "${BASH_SOURCE}")/..}
|
||||||
|
source "${KUBE_ROOT}/cluster/kube-util.sh"
|
||||||
|
|
||||||
|
# Get the absolute path of the directory component of a file, i.e. the
|
||||||
|
# absolute path of the dirname of $1.
|
||||||
|
get_absolute_dirname() {
|
||||||
|
echo "$(cd "$(dirname "$1")" && pwd)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Detect the OS name/arch so that we can find our binary
|
||||||
|
case "$(uname -s)" in
|
||||||
|
Darwin)
|
||||||
|
host_os=darwin
|
||||||
|
;;
|
||||||
|
Linux)
|
||||||
|
host_os=linux
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported host OS. Must be Linux or Mac OS X." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$(uname -m)" in
|
||||||
|
x86_64*)
|
||||||
|
host_arch=amd64
|
||||||
|
;;
|
||||||
|
i?86_64*)
|
||||||
|
host_arch=amd64
|
||||||
|
;;
|
||||||
|
amd64*)
|
||||||
|
host_arch=amd64
|
||||||
|
;;
|
||||||
|
arm*)
|
||||||
|
host_arch=arm
|
||||||
|
;;
|
||||||
|
i?86*)
|
||||||
|
host_arch=386
|
||||||
|
;;
|
||||||
|
s390x*)
|
||||||
|
host_arch=s390x
|
||||||
|
;;
|
||||||
|
ppc64le*)
|
||||||
|
host_arch=ppc64le
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported host arch. Must be x86_64, 386, arm, s390x or ppc64le." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# If KUBEADM_PATH isn't set, gather up the list of likely places and use ls
|
||||||
|
# to find the latest one.
|
||||||
|
if [[ -z "${KUBEADM_PATH:-}" ]]; then
|
||||||
|
locations=(
|
||||||
|
"${KUBE_ROOT}/_output/bin/kubeadm"
|
||||||
|
"${KUBE_ROOT}/_output/dockerized/bin/${host_os}/${host_arch}/kubeadm"
|
||||||
|
"${KUBE_ROOT}/_output/local/bin/${host_os}/${host_arch}/kubeadm"
|
||||||
|
"${KUBE_ROOT}/platforms/${host_os}/${host_arch}/kubeadm"
|
||||||
|
)
|
||||||
|
kubeadm=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
|
||||||
|
|
||||||
|
if [[ ! -x "$kubeadm" ]]; then
|
||||||
|
{
|
||||||
|
echo "It looks as if you don't have a compiled kubeadm binary"
|
||||||
|
echo
|
||||||
|
echo "If you are running from a clone of the git repo, please run"
|
||||||
|
echo "'./build/run.sh make cross'. Note that this requires having"
|
||||||
|
echo "Docker installed."
|
||||||
|
echo
|
||||||
|
echo "If you are running from a binary release tarball, something is wrong. "
|
||||||
|
echo "Look at http://kubernetes.io/ for information on how to contact the "
|
||||||
|
echo "development team for help."
|
||||||
|
} >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
elif [[ ! -x "${KUBEADM_PATH}" ]]; then
|
||||||
|
{
|
||||||
|
echo "KUBEADM_PATH environment variable set to '${KUBEADM_PATH}', but "
|
||||||
|
echo "this doesn't seem to be a valid executable."
|
||||||
|
} >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
kubeadm="${KUBEADM_PATH:-${kubeadm}}"
|
||||||
|
|
||||||
|
"${kubeadm}" "${@+$@}"
|
|
@ -17,6 +17,7 @@ go_library(
|
||||||
"init.go",
|
"init.go",
|
||||||
"join.go",
|
"join.go",
|
||||||
"reset.go",
|
"reset.go",
|
||||||
|
"token.go",
|
||||||
"version.go",
|
"version.go",
|
||||||
],
|
],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
|
@ -43,7 +44,10 @@ go_library(
|
||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "go_default_test",
|
name = "go_default_test",
|
||||||
srcs = ["reset_test.go"],
|
srcs = [
|
||||||
|
"reset_test.go",
|
||||||
|
"token_test.go",
|
||||||
|
],
|
||||||
library = "go_default_library",
|
library = "go_default_library",
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = ["//cmd/kubeadm/app/preflight:go_default_library"],
|
deps = ["//cmd/kubeadm/app/preflight:go_default_library"],
|
||||||
|
|
|
@ -81,6 +81,7 @@ func NewKubeadmCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob
|
||||||
cmds.AddCommand(NewCmdInit(out))
|
cmds.AddCommand(NewCmdInit(out))
|
||||||
cmds.AddCommand(NewCmdJoin(out))
|
cmds.AddCommand(NewCmdJoin(out))
|
||||||
cmds.AddCommand(NewCmdReset(out))
|
cmds.AddCommand(NewCmdReset(out))
|
||||||
|
cmds.AddCommand(NewCmdToken(out))
|
||||||
cmds.AddCommand(NewCmdVersion(out))
|
cmds.AddCommand(NewCmdVersion(out))
|
||||||
|
|
||||||
return cmds
|
return cmds
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
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 cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/renstrom/dedent"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewCmdToken(out io.Writer) *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "token",
|
||||||
|
Short: "Manage tokens used by init/join",
|
||||||
|
|
||||||
|
// Without this callback, if a user runs just the "token"
|
||||||
|
// command without a subcommand, or with an invalid subcommand,
|
||||||
|
// cobra will print usage information, but still exit cleanly.
|
||||||
|
// We want to return an error code in these cases so that the
|
||||||
|
// user knows that their command was invalid.
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if len(args) < 1 {
|
||||||
|
return errors.New("missing subcommand; 'token' is not meant to be run on its own")
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("invalid subcommand: %s", args[0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.AddCommand(NewCmdTokenGenerate(out))
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCmdTokenGenerate(out io.Writer) *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: "generate",
|
||||||
|
Short: "Generate and print a token suitable for use with init/join",
|
||||||
|
Long: dedent.Dedent(`
|
||||||
|
This command will print out a randomly-generated token that you can use with
|
||||||
|
the "init" and "join" commands.
|
||||||
|
|
||||||
|
You don't have to use this command in order to generate a token, you can do so
|
||||||
|
yourself as long as it's in the format "<6 characters>.<16 characters>". This
|
||||||
|
command is provided for convenience to generate tokens in that format.
|
||||||
|
|
||||||
|
You can also use "kubeadm init" without specifying a token, and it will
|
||||||
|
generate and print one for you.
|
||||||
|
`),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
err := RunGenerateToken(out)
|
||||||
|
kubeadmutil.CheckErr(err)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunGenerateToken(out io.Writer) error {
|
||||||
|
s := &kubeadmapi.Secrets{}
|
||||||
|
err := util.GenerateToken(s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(out, s.GivenToken)
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
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 cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TokenExpectedRegex = "^\\S{6}\\.\\S{16}\n$"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRunGenerateToken(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
err := RunGenerateToken(&buf)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("RunGenerateToken returned an error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := buf.String()
|
||||||
|
|
||||||
|
matched, err := regexp.MatchString(TokenExpectedRegex, output)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("encountered an error while trying to match RunGenerateToken's output: %v", err)
|
||||||
|
}
|
||||||
|
if !matched {
|
||||||
|
t.Errorf("RunGenerateToken's output did not match expected regex; wanted: [%s], got: [%s]", TokenExpectedRegex, output)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@io_bazel_rules_go//go:def.bzl",
|
||||||
|
"go_binary",
|
||||||
|
"go_library",
|
||||||
|
"go_test",
|
||||||
|
"cgo_library",
|
||||||
|
)
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["util.go"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "go_default_test",
|
||||||
|
srcs = ["token_test.go"],
|
||||||
|
library = "go_default_library",
|
||||||
|
tags = ["automanaged"],
|
||||||
|
deps = [],
|
||||||
|
)
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
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 kubeadm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TokenExpectedRegex = "^\\S{6}\\.\\S{16}\n$"
|
||||||
|
)
|
||||||
|
|
||||||
|
var kubeadmPath string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.StringVar(&kubeadmPath, "kubeadm-path", "cluster/kubeadm.sh", "Location of kubeadm")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCmdTokenGenerate(t *testing.T) {
|
||||||
|
stdout, _, err := RunCmd(kubeadmPath, "token", "generate")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("'kubeadm token generate' exited uncleanly: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
matched, err := regexp.MatchString(TokenExpectedRegex, stdout)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("encountered an error while trying to match 'kubeadm token generate' stdout: %v", err)
|
||||||
|
}
|
||||||
|
if !matched {
|
||||||
|
t.Errorf("'kubeadm token generate' stdout did not match expected regex; wanted: [%s], got: [%s]", TokenExpectedRegex, stdout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCmdTokenGenerateTypoError(t *testing.T) {
|
||||||
|
/*
|
||||||
|
Since we expect users to do things like this:
|
||||||
|
|
||||||
|
$ TOKEN=$(kubeadm token generate)
|
||||||
|
|
||||||
|
we want to make sure that if they have a typo in their command, we exit
|
||||||
|
with a non-zero status code after showing the command's usage, so that
|
||||||
|
the usage itself isn't captured as a token without the user noticing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_, _, err := RunCmd(kubeadmPath, "token", "genorate") // subtle typo
|
||||||
|
if err == nil {
|
||||||
|
t.Error("'kubeadm token genorate' (a deliberate typo) exited without an error when we expected non-zero exit status")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
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 kubeadm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Forked from test/e2e/framework because the e2e framework is quite bloated
|
||||||
|
// for our purposes here, and modified to remove undesired logging.
|
||||||
|
func RunCmd(command string, args ...string) (string, string, error) {
|
||||||
|
var bout, berr bytes.Buffer
|
||||||
|
cmd := exec.Command(command, args...)
|
||||||
|
cmd.Stdout = io.MultiWriter(os.Stdout, &bout)
|
||||||
|
cmd.Stderr = io.MultiWriter(os.Stderr, &berr)
|
||||||
|
err := cmd.Run()
|
||||||
|
stdout, stderr := bout.String(), berr.String()
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf("error running %s %v; got error %v, stdout %q, stderr %q",
|
||||||
|
command, args, err, stdout, stderr)
|
||||||
|
}
|
||||||
|
return stdout, stderr, nil
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
||||||
|
source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||||
|
|
||||||
|
KUBEADM_PATH="${KUBEADM_PATH:=$(kube::realpath "${KUBE_ROOT}")/cluster/kubeadm.sh}"
|
||||||
|
|
||||||
|
# If testing a different version of kubeadm than the current build, you can
|
||||||
|
# comment this out to save yourself from needlessly building here.
|
||||||
|
make -C "${KUBE_ROOT}" WHAT=cmd/kubeadm
|
||||||
|
|
||||||
|
make -C "${KUBE_ROOT}" test \
|
||||||
|
WHAT=cmd/kubeadm/test \
|
||||||
|
KUBE_TEST_ARGS="--kubeadm-path '${KUBEADM_PATH}'"
|
|
@ -35,6 +35,7 @@ kube::test::find_dirs() {
|
||||||
-path './_artifacts/*' \
|
-path './_artifacts/*' \
|
||||||
-o -path './_output/*' \
|
-o -path './_output/*' \
|
||||||
-o -path './_gopath/*' \
|
-o -path './_gopath/*' \
|
||||||
|
-o -path './cmd/kubeadm/test/*' \
|
||||||
-o -path './contrib/podex/*' \
|
-o -path './contrib/podex/*' \
|
||||||
-o -path './output/*' \
|
-o -path './output/*' \
|
||||||
-o -path './release/*' \
|
-o -path './release/*' \
|
||||||
|
|
|
@ -302,6 +302,7 @@ kube-master
|
||||||
kube-master
|
kube-master
|
||||||
kube-master-url
|
kube-master-url
|
||||||
kube-reserved
|
kube-reserved
|
||||||
|
kubeadm-path
|
||||||
kubecfg-file
|
kubecfg-file
|
||||||
kubectl-path
|
kubectl-path
|
||||||
kubelet-address
|
kubelet-address
|
||||||
|
|
|
@ -468,6 +468,7 @@ 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/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/kubelet/app,hurf,1
|
k8s.io/kubernetes/cmd/kubelet/app,hurf,1
|
||||||
k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types,caesarxuchao,0
|
k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types,caesarxuchao,0
|
||||||
k8s.io/kubernetes/cmd/libs/go2idl/go-to-protobuf/protobuf,smarterclayton,0
|
k8s.io/kubernetes/cmd/libs/go2idl/go-to-protobuf/protobuf,smarterclayton,0
|
||||||
|
|
|
Loading…
Reference in New Issue