mirror of https://github.com/k3s-io/k3s
Delete additional commands
parent
9f8e12f753
commit
b450d184a4
|
@ -1,35 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "clicheck",
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["check_cli_conventions.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/clicheck",
|
||||
deps = [
|
||||
"//pkg/kubectl/cmd:go_default_library",
|
||||
"//pkg/kubectl/cmd/util/sanity:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -1,6 +0,0 @@
|
|||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- sig-cli-maintainers
|
||||
reviewers:
|
||||
- sig-cli
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd"
|
||||
cmdsanity "k8s.io/kubernetes/pkg/kubectl/cmd/util/sanity"
|
||||
)
|
||||
|
||||
var (
|
||||
skip = []string{}
|
||||
)
|
||||
|
||||
func main() {
|
||||
var errorCount int
|
||||
|
||||
kubectl := cmd.NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
errors := cmdsanity.RunCmdChecks(kubectl, cmdsanity.AllCmdChecks, []string{})
|
||||
for _, err := range errors {
|
||||
errorCount++
|
||||
fmt.Fprintf(os.Stderr, " %d. %s\n", errorCount, err)
|
||||
}
|
||||
|
||||
errors = cmdsanity.RunGlobalChecks(cmdsanity.AllGlobalChecks)
|
||||
for _, err := range errors {
|
||||
errorCount++
|
||||
fmt.Fprintf(os.Stderr, " %d. %s\n", errorCount, err)
|
||||
}
|
||||
|
||||
if errorCount > 0 {
|
||||
fmt.Fprintf(os.Stdout, "Found %d errors.\n", errorCount)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, "Congrats, CLI looks good!")
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"//build:go.bzl",
|
||||
go_binary = "go_binary_conditional_pure",
|
||||
)
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_binary(
|
||||
name = "gendocs",
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["gen_kubectl_docs.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/gendocs",
|
||||
deps = [
|
||||
"//cmd/genutils:go_default_library",
|
||||
"//pkg/kubectl/cmd:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra/doc:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra/doc"
|
||||
"k8s.io/kubernetes/cmd/genutils"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// use os.Args instead of "flags" because "flags" will mess up the man pages!
|
||||
path := "docs/"
|
||||
if len(os.Args) == 2 {
|
||||
path = os.Args[1]
|
||||
} else if len(os.Args) > 2 {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s [output directory]\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
outDir, err := genutils.OutDir(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Set environment variables used by kubectl so the output is consistent,
|
||||
// regardless of where we run.
|
||||
os.Setenv("HOME", "/home/username")
|
||||
// TODO os.Stdin should really be something like ioutil.Discard, but a Reader
|
||||
kubectl := cmd.NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
doc.GenMarkdownTree(kubectl, outDir)
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"//build:go.bzl",
|
||||
go_binary = "go_binary_conditional_pure",
|
||||
)
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "genkubedocs",
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"gen_kube_docs.go",
|
||||
"postprocessing.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/genkubedocs",
|
||||
deps = [
|
||||
"//cmd/cloud-controller-manager/app:go_default_library",
|
||||
"//cmd/genutils:go_default_library",
|
||||
"//cmd/kube-apiserver/app:go_default_library",
|
||||
"//cmd/kube-controller-manager/app:go_default_library",
|
||||
"//cmd/kube-proxy/app:go_default_library",
|
||||
"//cmd/kube-scheduler/app:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd:go_default_library",
|
||||
"//cmd/kubelet/app:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/server:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra/doc:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["postprocessing_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
)
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra/doc"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
ccmapp "k8s.io/kubernetes/cmd/cloud-controller-manager/app"
|
||||
"k8s.io/kubernetes/cmd/genutils"
|
||||
apiservapp "k8s.io/kubernetes/cmd/kube-apiserver/app"
|
||||
cmapp "k8s.io/kubernetes/cmd/kube-controller-manager/app"
|
||||
proxyapp "k8s.io/kubernetes/cmd/kube-proxy/app"
|
||||
schapp "k8s.io/kubernetes/cmd/kube-scheduler/app"
|
||||
kubeadmapp "k8s.io/kubernetes/cmd/kubeadm/app/cmd"
|
||||
kubeletapp "k8s.io/kubernetes/cmd/kubelet/app"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// use os.Args instead of "flags" because "flags" will mess up the man pages!
|
||||
path := ""
|
||||
module := ""
|
||||
if len(os.Args) == 3 {
|
||||
path = os.Args[1]
|
||||
module = os.Args[2]
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s [output directory] [module] \n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
outDir, err := genutils.OutDir(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
switch module {
|
||||
case "kube-apiserver":
|
||||
// generate docs for kube-apiserver
|
||||
apiserver := apiservapp.NewAPIServerCommand(server.SetupSignalHandler())
|
||||
doc.GenMarkdownTree(apiserver, outDir)
|
||||
case "kube-controller-manager":
|
||||
// generate docs for kube-controller-manager
|
||||
controllermanager := cmapp.NewControllerManagerCommand()
|
||||
doc.GenMarkdownTree(controllermanager, outDir)
|
||||
case "cloud-controller-manager":
|
||||
// generate docs for cloud-controller-manager
|
||||
cloudcontrollermanager := ccmapp.NewCloudControllerManagerCommand()
|
||||
doc.GenMarkdownTree(cloudcontrollermanager, outDir)
|
||||
case "kube-proxy":
|
||||
// generate docs for kube-proxy
|
||||
proxy := proxyapp.NewProxyCommand()
|
||||
doc.GenMarkdownTree(proxy, outDir)
|
||||
case "kube-scheduler":
|
||||
// generate docs for kube-scheduler
|
||||
scheduler := schapp.NewSchedulerCommand()
|
||||
doc.GenMarkdownTree(scheduler, outDir)
|
||||
case "kubelet":
|
||||
// generate docs for kubelet
|
||||
kubelet := kubeletapp.NewKubeletCommand(server.SetupSignalHandler())
|
||||
doc.GenMarkdownTree(kubelet, outDir)
|
||||
case "kubeadm":
|
||||
// resets global flags created by kubelet or other commands e.g.
|
||||
// --azure-container-registry-config from pkg/credentialprovider/azure
|
||||
// --version pkg/version/verflag
|
||||
pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
|
||||
|
||||
// generate docs for kubeadm
|
||||
kubeadm := kubeadmapp.NewKubeadmCommand(os.Stdin, os.Stdout, os.Stderr)
|
||||
doc.GenMarkdownTree(kubeadm, outDir)
|
||||
|
||||
// cleanup generated code for usage as include in the website
|
||||
MarkdownPostProcessing(kubeadm, outDir, cleanupForInclude)
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Module %s is not supported", module)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// MarkdownPostProcessing goes though the generated files
|
||||
func MarkdownPostProcessing(cmd *cobra.Command, dir string, processor func(string) string) error {
|
||||
for _, c := range cmd.Commands() {
|
||||
if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
|
||||
continue
|
||||
}
|
||||
if err := MarkdownPostProcessing(c, dir, processor); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".md"
|
||||
filename := filepath.Join(dir, basename)
|
||||
|
||||
markdownBytes, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
processedMarkDown := processor(string(markdownBytes))
|
||||
|
||||
return ioutil.WriteFile(filename, []byte(processedMarkDown), 0644)
|
||||
}
|
||||
|
||||
// cleanupForInclude parts of markdown that will make difficult to use it as include in the website:
|
||||
// - The title of the document (this allow more flexibility for include, e.g. include in tabs)
|
||||
// - The sections see also, that assumes file will be used as a main page
|
||||
func cleanupForInclude(md string) string {
|
||||
lines := strings.Split(md, "\n")
|
||||
|
||||
cleanMd := ""
|
||||
for i, line := range lines {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
if line == "### SEE ALSO" {
|
||||
break
|
||||
}
|
||||
|
||||
cleanMd += line
|
||||
if i < len(lines)-1 {
|
||||
cleanMd += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
return cleanMd
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCleanupForInclude(t *testing.T) {
|
||||
|
||||
var tests = []struct {
|
||||
markdown, expectedMarkdown string
|
||||
}{
|
||||
{ // first line is removed
|
||||
// Nb. first line is the title of the document, and by removing it you get
|
||||
// more flexibility for include, e.g. include in tabs
|
||||
markdown: "line 1\n" +
|
||||
"line 2\n" +
|
||||
"line 3",
|
||||
expectedMarkdown: "line 2\n" +
|
||||
"line 3",
|
||||
},
|
||||
{ // everything after ###SEE ALSO is removed
|
||||
// Nb. see also, that assumes file will be used as a main page (does not apply to includes)
|
||||
markdown: "line 1\n" +
|
||||
"line 2\n" +
|
||||
"### SEE ALSO\n" +
|
||||
"line 3",
|
||||
expectedMarkdown: "line 2\n",
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := cleanupForInclude(rt.markdown)
|
||||
if actual != rt.expectedMarkdown {
|
||||
t.Errorf(
|
||||
"failed cleanupForInclude:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expectedMarkdown,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"//build:go.bzl",
|
||||
go_binary = "go_binary_conditional_pure",
|
||||
)
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_binary(
|
||||
name = "genman",
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["gen_kube_man.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/genman",
|
||||
deps = [
|
||||
"//cmd/cloud-controller-manager/app:go_default_library",
|
||||
"//cmd/genutils:go_default_library",
|
||||
"//cmd/kube-apiserver/app:go_default_library",
|
||||
"//cmd/kube-controller-manager/app:go_default_library",
|
||||
"//cmd/kube-proxy/app:go_default_library",
|
||||
"//cmd/kube-scheduler/app:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd:go_default_library",
|
||||
"//cmd/kubelet/app:go_default_library",
|
||||
"//pkg/kubectl/cmd:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/server:go_default_library",
|
||||
"//vendor/github.com/cpuguy83/go-md2man/md2man:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -1,231 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
mangen "github.com/cpuguy83/go-md2man/md2man"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
ccmapp "k8s.io/kubernetes/cmd/cloud-controller-manager/app"
|
||||
"k8s.io/kubernetes/cmd/genutils"
|
||||
apiservapp "k8s.io/kubernetes/cmd/kube-apiserver/app"
|
||||
cmapp "k8s.io/kubernetes/cmd/kube-controller-manager/app"
|
||||
proxyapp "k8s.io/kubernetes/cmd/kube-proxy/app"
|
||||
schapp "k8s.io/kubernetes/cmd/kube-scheduler/app"
|
||||
kubeadmapp "k8s.io/kubernetes/cmd/kubeadm/app/cmd"
|
||||
kubeletapp "k8s.io/kubernetes/cmd/kubelet/app"
|
||||
kubectlcmd "k8s.io/kubernetes/pkg/kubectl/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// use os.Args instead of "flags" because "flags" will mess up the man pages!
|
||||
path := "docs/man/man1"
|
||||
module := ""
|
||||
if len(os.Args) == 3 {
|
||||
path = os.Args[1]
|
||||
module = os.Args[2]
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s [output directory] [module] \n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
outDir, err := genutils.OutDir(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Set environment variables used by command so the output is consistent,
|
||||
// regardless of where we run.
|
||||
os.Setenv("HOME", "/home/username")
|
||||
|
||||
switch module {
|
||||
case "kube-apiserver":
|
||||
// generate manpage for kube-apiserver
|
||||
apiserver := apiservapp.NewAPIServerCommand(server.SetupSignalHandler())
|
||||
genMarkdown(apiserver, "", outDir)
|
||||
for _, c := range apiserver.Commands() {
|
||||
genMarkdown(c, "kube-apiserver", outDir)
|
||||
}
|
||||
case "kube-controller-manager":
|
||||
// generate manpage for kube-controller-manager
|
||||
controllermanager := cmapp.NewControllerManagerCommand()
|
||||
genMarkdown(controllermanager, "", outDir)
|
||||
for _, c := range controllermanager.Commands() {
|
||||
genMarkdown(c, "kube-controller-manager", outDir)
|
||||
}
|
||||
case "cloud-controller-manager":
|
||||
//generate manpage for cloud-controller-manager
|
||||
controllermanager := ccmapp.NewCloudControllerManagerCommand()
|
||||
genMarkdown(controllermanager, "", outDir)
|
||||
for _, c := range controllermanager.Commands() {
|
||||
genMarkdown(c, "cloud-controller-manager", outDir)
|
||||
}
|
||||
case "kube-proxy":
|
||||
// generate manpage for kube-proxy
|
||||
proxy := proxyapp.NewProxyCommand()
|
||||
genMarkdown(proxy, "", outDir)
|
||||
for _, c := range proxy.Commands() {
|
||||
genMarkdown(c, "kube-proxy", outDir)
|
||||
}
|
||||
case "kube-scheduler":
|
||||
// generate manpage for kube-scheduler
|
||||
scheduler := schapp.NewSchedulerCommand()
|
||||
genMarkdown(scheduler, "", outDir)
|
||||
for _, c := range scheduler.Commands() {
|
||||
genMarkdown(c, "kube-scheduler", outDir)
|
||||
}
|
||||
case "kubelet":
|
||||
// generate manpage for kubelet
|
||||
kubelet := kubeletapp.NewKubeletCommand(server.SetupSignalHandler())
|
||||
genMarkdown(kubelet, "", outDir)
|
||||
for _, c := range kubelet.Commands() {
|
||||
genMarkdown(c, "kubelet", outDir)
|
||||
}
|
||||
case "kubectl":
|
||||
// generate manpage for kubectl
|
||||
// TODO os.Stdin should really be something like ioutil.Discard, but a Reader
|
||||
kubectl := kubectlcmd.NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
genMarkdown(kubectl, "", outDir)
|
||||
for _, c := range kubectl.Commands() {
|
||||
genMarkdown(c, "kubectl", outDir)
|
||||
}
|
||||
case "kubeadm":
|
||||
// generate manpage for kubelet
|
||||
kubeadm := kubeadmapp.NewKubeadmCommand(os.Stdin, os.Stdout, os.Stderr)
|
||||
genMarkdown(kubeadm, "", outDir)
|
||||
for _, c := range kubeadm.Commands() {
|
||||
genMarkdown(c, "kubeadm", outDir)
|
||||
}
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Module %s is not supported", module)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func preamble(out *bytes.Buffer, name, short, long string) {
|
||||
out.WriteString(`% KUBERNETES(1) kubernetes User Manuals
|
||||
% Eric Paris
|
||||
% Jan 2015
|
||||
# NAME
|
||||
`)
|
||||
fmt.Fprintf(out, "%s \\- %s\n\n", name, short)
|
||||
fmt.Fprintf(out, "# SYNOPSIS\n")
|
||||
fmt.Fprintf(out, "**%s** [OPTIONS]\n\n", name)
|
||||
fmt.Fprintf(out, "# DESCRIPTION\n")
|
||||
fmt.Fprintf(out, "%s\n\n", long)
|
||||
}
|
||||
|
||||
func printFlags(out *bytes.Buffer, flags *pflag.FlagSet) {
|
||||
flags.VisitAll(func(flag *pflag.Flag) {
|
||||
format := "**--%s**=%s\n\t%s\n\n"
|
||||
if flag.Value.Type() == "string" {
|
||||
// put quotes on the value
|
||||
format = "**--%s**=%q\n\t%s\n\n"
|
||||
}
|
||||
|
||||
// Todo, when we mark a shorthand is deprecated, but specify an empty message.
|
||||
// The flag.ShorthandDeprecated is empty as the shorthand is deprecated.
|
||||
// Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok.
|
||||
if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 {
|
||||
format = "**-%s**, " + format
|
||||
fmt.Fprintf(out, format, flag.Shorthand, flag.Name, flag.DefValue, flag.Usage)
|
||||
} else {
|
||||
fmt.Fprintf(out, format, flag.Name, flag.DefValue, flag.Usage)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func printOptions(out *bytes.Buffer, command *cobra.Command) {
|
||||
flags := command.NonInheritedFlags()
|
||||
if flags.HasFlags() {
|
||||
fmt.Fprintf(out, "# OPTIONS\n")
|
||||
printFlags(out, flags)
|
||||
fmt.Fprintf(out, "\n")
|
||||
}
|
||||
flags = command.InheritedFlags()
|
||||
if flags.HasFlags() {
|
||||
fmt.Fprintf(out, "# OPTIONS INHERITED FROM PARENT COMMANDS\n")
|
||||
printFlags(out, flags)
|
||||
fmt.Fprintf(out, "\n")
|
||||
}
|
||||
}
|
||||
|
||||
func genMarkdown(command *cobra.Command, parent, docsDir string) {
|
||||
dparent := strings.Replace(parent, " ", "-", -1)
|
||||
name := command.Name()
|
||||
dname := name
|
||||
if len(parent) > 0 {
|
||||
dname = dparent + "-" + name
|
||||
name = parent + " " + name
|
||||
}
|
||||
|
||||
out := new(bytes.Buffer)
|
||||
short := command.Short
|
||||
long := command.Long
|
||||
if len(long) == 0 {
|
||||
long = short
|
||||
}
|
||||
|
||||
preamble(out, name, short, long)
|
||||
printOptions(out, command)
|
||||
|
||||
if len(command.Example) > 0 {
|
||||
fmt.Fprintf(out, "# EXAMPLE\n")
|
||||
fmt.Fprintf(out, "```\n%s\n```\n", command.Example)
|
||||
}
|
||||
|
||||
if len(command.Commands()) > 0 || len(parent) > 0 {
|
||||
fmt.Fprintf(out, "# SEE ALSO\n")
|
||||
if len(parent) > 0 {
|
||||
fmt.Fprintf(out, "**%s(1)**, ", dparent)
|
||||
}
|
||||
for _, c := range command.Commands() {
|
||||
fmt.Fprintf(out, "**%s-%s(1)**, ", dname, c.Name())
|
||||
genMarkdown(c, name, docsDir)
|
||||
}
|
||||
fmt.Fprintf(out, "\n")
|
||||
}
|
||||
|
||||
out.WriteString(`
|
||||
# HISTORY
|
||||
January 2015, Originally compiled by Eric Paris (eparis at redhat dot com) based on the kubernetes source material, but hopefully they have been automatically generated since!
|
||||
`)
|
||||
|
||||
final := mangen.Render(out.Bytes())
|
||||
|
||||
filename := docsDir + dname + ".1"
|
||||
outFile, err := os.Create(filename)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer outFile.Close()
|
||||
_, err = outFile.Write(final)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"//build:go.bzl",
|
||||
go_binary = "go_binary_conditional_pure",
|
||||
)
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_binary(
|
||||
name = "genswaggertypedocs",
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["swagger_type_docs.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/genswaggertypedocs",
|
||||
deps = [
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
kruntime "k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
var (
|
||||
functionDest = flag.StringP("func-dest", "f", "-", "Output for swagger functions; '-' means stdout (default)")
|
||||
typeSrc = flag.StringP("type-src", "s", "", "From where we are going to read the types")
|
||||
verify = flag.BoolP("verify", "v", false, "Verifies if the given type-src file has documentation for every type")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if *typeSrc == "" {
|
||||
klog.Fatalf("Please define -s flag as it is the source file")
|
||||
}
|
||||
|
||||
var funcOut io.Writer
|
||||
if *functionDest == "-" {
|
||||
funcOut = os.Stdout
|
||||
} else {
|
||||
file, err := os.Create(*functionDest)
|
||||
if err != nil {
|
||||
klog.Fatalf("Couldn't open %v: %v", *functionDest, err)
|
||||
}
|
||||
defer file.Close()
|
||||
funcOut = file
|
||||
}
|
||||
|
||||
docsForTypes := kruntime.ParseDocumentationFrom(*typeSrc)
|
||||
|
||||
if *verify == true {
|
||||
rc, err := kruntime.VerifySwaggerDocsExist(docsForTypes, funcOut)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error in verification process: %s\n", err)
|
||||
}
|
||||
os.Exit(rc)
|
||||
}
|
||||
|
||||
if docsForTypes != nil && len(docsForTypes) > 0 {
|
||||
if err := kruntime.WriteSwaggerDocFunc(docsForTypes, funcOut); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error when writing swagger documentation functions: %s\n", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["genutils.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/genutils",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["genutils_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package genutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// OutDir creates the absolute path name from path and checks path exists.
|
||||
// Returns absolute path including trailing '/' or error if path does not exist.
|
||||
func OutDir(path string) (string, error) {
|
||||
outDir, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
stat, err := os.Stat(outDir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if !stat.IsDir() {
|
||||
return "", fmt.Errorf("output directory %s is not a directory", outDir)
|
||||
}
|
||||
outDir = outDir + "/"
|
||||
return outDir, nil
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package genutils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidDir(t *testing.T) {
|
||||
_, err := OutDir("./")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidDir(t *testing.T) {
|
||||
_, err := OutDir("./nondir")
|
||||
if err == nil {
|
||||
t.Fatal("expected an error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotDir(t *testing.T) {
|
||||
_, err := OutDir("./genutils_test.go")
|
||||
if err == nil {
|
||||
t.Fatal("expected an error")
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"//build:go.bzl",
|
||||
go_binary = "go_binary_conditional_pure",
|
||||
)
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_binary(
|
||||
name = "genyaml",
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["gen_kubectl_yaml.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/genyaml",
|
||||
deps = [
|
||||
"//cmd/genutils:go_default_library",
|
||||
"//pkg/kubectl/cmd:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/gopkg.in/yaml.v2:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -1,168 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"gopkg.in/yaml.v2"
|
||||
"k8s.io/kubernetes/cmd/genutils"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd"
|
||||
)
|
||||
|
||||
type cmdOption struct {
|
||||
Name string
|
||||
Shorthand string `yaml:",omitempty"`
|
||||
DefaultValue string `yaml:"default_value,omitempty"`
|
||||
Usage string `yaml:",omitempty"`
|
||||
}
|
||||
|
||||
type cmdDoc struct {
|
||||
Name string
|
||||
Synopsis string `yaml:",omitempty"`
|
||||
Description string `yaml:",omitempty"`
|
||||
Options []cmdOption `yaml:",omitempty"`
|
||||
InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"`
|
||||
Example string `yaml:",omitempty"`
|
||||
SeeAlso []string `yaml:"see_also,omitempty"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
path := "docs/yaml/kubectl"
|
||||
if len(os.Args) == 2 {
|
||||
path = os.Args[1]
|
||||
} else if len(os.Args) > 2 {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s [output directory]\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
outDir, err := genutils.OutDir(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Set environment variables used by kubectl so the output is consistent,
|
||||
// regardless of where we run.
|
||||
os.Setenv("HOME", "/home/username")
|
||||
// TODO os.Stdin should really be something like ioutil.Discard, but a Reader
|
||||
kubectl := cmd.NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
genYaml(kubectl, "", outDir)
|
||||
for _, c := range kubectl.Commands() {
|
||||
genYaml(c, "kubectl", outDir)
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary workaround for yaml lib generating incorrect yaml with long strings
|
||||
// that do not contain \n.
|
||||
func forceMultiLine(s string) string {
|
||||
if len(s) > 60 && !strings.Contains(s, "\n") {
|
||||
s = s + "\n"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func genFlagResult(flags *pflag.FlagSet) []cmdOption {
|
||||
result := []cmdOption{}
|
||||
|
||||
flags.VisitAll(func(flag *pflag.Flag) {
|
||||
// Todo, when we mark a shorthand is deprecated, but specify an empty message.
|
||||
// The flag.ShorthandDeprecated is empty as the shorthand is deprecated.
|
||||
// Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok.
|
||||
if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 {
|
||||
opt := cmdOption{
|
||||
flag.Name,
|
||||
flag.Shorthand,
|
||||
flag.DefValue,
|
||||
forceMultiLine(flag.Usage),
|
||||
}
|
||||
result = append(result, opt)
|
||||
} else {
|
||||
opt := cmdOption{
|
||||
Name: flag.Name,
|
||||
DefaultValue: forceMultiLine(flag.DefValue),
|
||||
Usage: forceMultiLine(flag.Usage),
|
||||
}
|
||||
result = append(result, opt)
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func genYaml(command *cobra.Command, parent, docsDir string) {
|
||||
doc := cmdDoc{}
|
||||
|
||||
doc.Name = command.Name()
|
||||
doc.Synopsis = forceMultiLine(command.Short)
|
||||
doc.Description = forceMultiLine(command.Long)
|
||||
|
||||
flags := command.NonInheritedFlags()
|
||||
if flags.HasFlags() {
|
||||
doc.Options = genFlagResult(flags)
|
||||
}
|
||||
flags = command.InheritedFlags()
|
||||
if flags.HasFlags() {
|
||||
doc.InheritedOptions = genFlagResult(flags)
|
||||
}
|
||||
|
||||
if len(command.Example) > 0 {
|
||||
doc.Example = command.Example
|
||||
}
|
||||
|
||||
if len(command.Commands()) > 0 || len(parent) > 0 {
|
||||
result := []string{}
|
||||
if len(parent) > 0 {
|
||||
result = append(result, parent)
|
||||
}
|
||||
for _, c := range command.Commands() {
|
||||
result = append(result, c.Name())
|
||||
}
|
||||
doc.SeeAlso = result
|
||||
}
|
||||
|
||||
final, err := yaml.Marshal(&doc)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var filename string
|
||||
|
||||
if parent == "" {
|
||||
filename = docsDir + doc.Name + ".yaml"
|
||||
} else {
|
||||
filename = docsDir + parent + "_" + doc.Name + ".yaml"
|
||||
}
|
||||
|
||||
outFile, err := os.Create(filename)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer outFile.Close()
|
||||
_, err = outFile.Write(final)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "importverifier",
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["importverifier.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/importverifier",
|
||||
deps = ["//vendor/gopkg.in/yaml.v2:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -1,10 +0,0 @@
|
|||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
reviewers:
|
||||
- stevekuznetsov
|
||||
- deads2k
|
||||
- sttts
|
||||
approvers:
|
||||
- stevekuznetsov
|
||||
- deads2k
|
||||
- sttts
|
|
@ -1,278 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Package is a subset of cmd/go.Package
|
||||
type Package struct {
|
||||
Dir string `yaml:",omitempty"` // directory containing package sources
|
||||
ImportPath string `yaml:",omitempty"` // import path of package in dir
|
||||
Imports []string `yaml:",omitempty"` // import paths used by this package
|
||||
TestImports []string `yaml:",omitempty"` // imports from TestGoFiles
|
||||
XTestImports []string `yaml:",omitempty"` // imports from XTestGoFiles
|
||||
}
|
||||
|
||||
// ImportRestriction describes a set of allowable import
|
||||
// trees for a tree of source code
|
||||
type ImportRestriction struct {
|
||||
// BaseDir is the root of the package tree that is
|
||||
// restricted by this configuration, given as a
|
||||
// relative path from the root of the repository
|
||||
BaseDir string `yaml:"baseImportPath"`
|
||||
// IgnoredSubTrees are roots of sub-trees of the
|
||||
// BaseDir for which we do not want to enforce
|
||||
// any import restrictions whatsoever, given as
|
||||
// relative paths from the root of the repository
|
||||
IgnoredSubTrees []string `yaml:"ignoredSubTrees,omitempty"`
|
||||
// AllowedImports are roots of package trees that
|
||||
// are allowed to be imported from the BaseDir,
|
||||
// given as paths that would be used in a Go
|
||||
// import statement
|
||||
AllowedImports []string `yaml:"allowedImports"`
|
||||
// ExcludeTests will skip checking test dependencies.
|
||||
ExcludeTests bool `yaml:"excludeTests"`
|
||||
}
|
||||
|
||||
// ForbiddenImportsFor determines all of the forbidden
|
||||
// imports for a package given the import restrictions
|
||||
func (i *ImportRestriction) ForbiddenImportsFor(pkg Package) ([]string, error) {
|
||||
if restricted, err := i.isRestrictedDir(pkg.Dir); err != nil {
|
||||
return []string{}, err
|
||||
} else if !restricted {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
return i.forbiddenImportsFor(pkg), nil
|
||||
}
|
||||
|
||||
// isRestrictedDir determines if the source directory has
|
||||
// any restrictions placed on it by this configuration.
|
||||
// A path will be restricted if:
|
||||
// - it falls under the base import path
|
||||
// - it does not fall under any of the ignored sub-trees
|
||||
func (i *ImportRestriction) isRestrictedDir(dir string) (bool, error) {
|
||||
if under, err := isPathUnder(i.BaseDir, dir); err != nil {
|
||||
return false, err
|
||||
} else if !under {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for _, ignored := range i.IgnoredSubTrees {
|
||||
if under, err := isPathUnder(ignored, dir); err != nil {
|
||||
return false, err
|
||||
} else if under {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// isPathUnder determines if path is under base
|
||||
func isPathUnder(base, path string) (bool, error) {
|
||||
absBase, err := filepath.Abs(base)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
absPath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
relPath, err := filepath.Rel(absBase, absPath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// if path is below base, the relative path
|
||||
// from base to path will not start with `../`
|
||||
return !strings.HasPrefix(relPath, ".."), nil
|
||||
}
|
||||
|
||||
// forbiddenImportsFor determines all of the forbidden
|
||||
// imports for a package given the import restrictions
|
||||
// and returns a deduplicated list of them
|
||||
func (i *ImportRestriction) forbiddenImportsFor(pkg Package) []string {
|
||||
forbiddenImportSet := map[string]struct{}{}
|
||||
imports := pkg.Imports
|
||||
if !i.ExcludeTests {
|
||||
imports = append(imports, append(pkg.TestImports, pkg.XTestImports...)...)
|
||||
}
|
||||
for _, imp := range imports {
|
||||
path := extractVendorPath(imp)
|
||||
if i.isForbidden(path) {
|
||||
forbiddenImportSet[path] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
var forbiddenImports []string
|
||||
for imp := range forbiddenImportSet {
|
||||
forbiddenImports = append(forbiddenImports, imp)
|
||||
}
|
||||
return forbiddenImports
|
||||
}
|
||||
|
||||
// extractVendorPath removes a vendor prefix if one exists
|
||||
func extractVendorPath(path string) string {
|
||||
vendorPath := "/vendor/"
|
||||
if !strings.Contains(path, vendorPath) {
|
||||
return path
|
||||
}
|
||||
|
||||
return path[strings.Index(path, vendorPath)+len(vendorPath):]
|
||||
}
|
||||
|
||||
// isForbidden determines if an import is forbidden,
|
||||
// which is true when the import is:
|
||||
// - of a package under the rootPackage
|
||||
// - is not of the base import path or a sub-package of it
|
||||
// - is not of an allowed path or a sub-package of one
|
||||
func (i *ImportRestriction) isForbidden(imp string) bool {
|
||||
importsBelowRoot := strings.HasPrefix(imp, rootPackage)
|
||||
importsBelowBase := strings.HasPrefix(imp, i.BaseDir)
|
||||
importsAllowed := false
|
||||
for _, allowed := range i.AllowedImports {
|
||||
exactlyImportsAllowed := imp == allowed
|
||||
importsBelowAllowed := strings.HasPrefix(imp, fmt.Sprintf("%s/", allowed))
|
||||
importsAllowed = importsAllowed || (importsBelowAllowed || exactlyImportsAllowed)
|
||||
}
|
||||
|
||||
return importsBelowRoot && !importsBelowBase && !importsAllowed
|
||||
}
|
||||
|
||||
var rootPackage string
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 3 {
|
||||
log.Fatalf("Usage: %s ROOT RESTRICTIONS.yaml", os.Args[0])
|
||||
}
|
||||
|
||||
rootPackage = os.Args[1]
|
||||
configFile := os.Args[2]
|
||||
importRestrictions, err := loadImportRestrictions(configFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load import restrictions: %v", err)
|
||||
}
|
||||
|
||||
foundForbiddenImports := false
|
||||
for _, restriction := range importRestrictions {
|
||||
log.Printf("Inspecting imports under %s...\n", restriction.BaseDir)
|
||||
packages, err := resolvePackageTree(restriction.BaseDir)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to resolve package tree: %v", err)
|
||||
} else if len(packages) == 0 {
|
||||
log.Fatalf("Found no packages under tree %s", restriction.BaseDir)
|
||||
}
|
||||
|
||||
log.Printf("- validating imports for %d packages in the tree", len(packages))
|
||||
restrictionViolated := false
|
||||
for _, pkg := range packages {
|
||||
if forbidden, err := restriction.ForbiddenImportsFor(pkg); err != nil {
|
||||
log.Fatalf("-- failed to validate imports: %v", err)
|
||||
} else if len(forbidden) != 0 {
|
||||
logForbiddenPackages(pkg.ImportPath, forbidden)
|
||||
restrictionViolated = true
|
||||
}
|
||||
}
|
||||
if restrictionViolated {
|
||||
foundForbiddenImports = true
|
||||
log.Println("- FAIL")
|
||||
} else {
|
||||
log.Println("- OK")
|
||||
}
|
||||
}
|
||||
|
||||
if foundForbiddenImports {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func loadImportRestrictions(configFile string) ([]ImportRestriction, error) {
|
||||
config, err := ioutil.ReadFile(configFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load configuration from %s: %v", configFile, err)
|
||||
}
|
||||
|
||||
var importRestrictions []ImportRestriction
|
||||
if err := yaml.Unmarshal(config, &importRestrictions); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal from %s: %v", configFile, err)
|
||||
}
|
||||
|
||||
return importRestrictions, nil
|
||||
}
|
||||
|
||||
func resolvePackageTree(treeBase string) ([]Package, error) {
|
||||
cmd := "go"
|
||||
args := []string{"list", "-json", fmt.Sprintf("%s...", treeBase)}
|
||||
stdout, err := exec.Command(cmd, args...).Output()
|
||||
if err != nil {
|
||||
var message string
|
||||
if ee, ok := err.(*exec.ExitError); ok {
|
||||
message = fmt.Sprintf("%v\n%v", ee, string(ee.Stderr))
|
||||
} else {
|
||||
message = fmt.Sprintf("%v", err)
|
||||
}
|
||||
return nil, fmt.Errorf("failed to run `%s %s`: %v", cmd, strings.Join(args, " "), message)
|
||||
}
|
||||
|
||||
packages, err := decodePackages(bytes.NewReader(stdout))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode packages: %v", err)
|
||||
}
|
||||
|
||||
return packages, nil
|
||||
}
|
||||
|
||||
func decodePackages(r io.Reader) ([]Package, error) {
|
||||
// `go list -json` concatenates package definitions
|
||||
// instead of emitting a single valid JSON, so we
|
||||
// need to stream the output to decode it into the
|
||||
// data we are looking for instead of just using a
|
||||
// simple JSON decoder on stdout
|
||||
var packages []Package
|
||||
decoder := json.NewDecoder(r)
|
||||
for decoder.More() {
|
||||
var pkg Package
|
||||
if err := decoder.Decode(&pkg); err != nil {
|
||||
return nil, fmt.Errorf("invalid package: %v", err)
|
||||
}
|
||||
packages = append(packages, pkg)
|
||||
}
|
||||
|
||||
return packages, nil
|
||||
}
|
||||
|
||||
func logForbiddenPackages(base string, forbidden []string) {
|
||||
log.Printf("-- found forbidden imports for %s:\n", base)
|
||||
for _, forbiddenPackage := range forbidden {
|
||||
log.Printf("--- %s\n", forbiddenPackage)
|
||||
}
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
{
|
||||
"Rules": [
|
||||
{
|
||||
"SelectorRegexp": "k8s[.]io/(api/|apimachinery/|apiextensions-apiserver/|apiserver/)",
|
||||
"AllowedPrefixes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"SelectorRegexp": "k8s[.]io/client-go/",
|
||||
"AllowedPrefixes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"SelectorRegexp": "k8s[.]io/kubelet/",
|
||||
"AllowedPrefixes": [
|
||||
"k8s.io/kubelet/config/v1beta1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SelectorRegexp": "k8s[.]io/kube-openapi/",
|
||||
"AllowedPrefixes": [
|
||||
"k8s.io/kube-openapi/pkg/util/proto"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SelectorRegexp": "k8s[.]io/kube-proxy/",
|
||||
"AllowedPrefixes": [
|
||||
"k8s.io/kube-proxy/config/v1alpha1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SelectorRegexp": "k8s[.]io/kubernetes/cmd",
|
||||
"AllowedPrefixes": [
|
||||
"k8s.io/kubernetes/cmd/kubeadm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SelectorRegexp": "k8s[.]io/utils",
|
||||
"AllowedPrefixes": [
|
||||
"k8s.io/utils/exec",
|
||||
"k8s.io/utils/integer",
|
||||
"k8s.io/utils/path",
|
||||
"k8s.io/utils/pointer",
|
||||
"k8s.io/utils/net"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SelectorRegexp": "k8s[.]io/kubernetes/pkg",
|
||||
"AllowedPrefixes": [
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme",
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling",
|
||||
"k8s.io/kubernetes/pkg/apis/core",
|
||||
"k8s.io/kubernetes/pkg/api/service",
|
||||
"k8s.io/kubernetes/pkg/apis/apps",
|
||||
"k8s.io/kubernetes/pkg/apis/rbac",
|
||||
"k8s.io/kubernetes/pkg/apis/scheduling",
|
||||
"k8s.io/kubernetes/pkg/api/v1/pod",
|
||||
"k8s.io/kubernetes/pkg/capabilities",
|
||||
"k8s.io/kubernetes/pkg/controller",
|
||||
"k8s.io/kubernetes/pkg/features",
|
||||
"k8s.io/kubernetes/pkg/fieldpath",
|
||||
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes",
|
||||
"k8s.io/kubernetes/pkg/kubelet/apis",
|
||||
"k8s.io/kubernetes/pkg/kubelet/qos",
|
||||
"k8s.io/kubernetes/pkg/kubelet/types",
|
||||
"k8s.io/kubernetes/pkg/master/ports",
|
||||
"k8s.io/kubernetes/pkg/proxy/apis/config",
|
||||
"k8s.io/kubernetes/pkg/registry/core/service/allocator",
|
||||
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator",
|
||||
"k8s.io/kubernetes/pkg/security/apparmor",
|
||||
"k8s.io/kubernetes/pkg/serviceaccount",
|
||||
"k8s.io/kubernetes/pkg/util/hash",
|
||||
"k8s.io/kubernetes/pkg/util/initsystem",
|
||||
"k8s.io/kubernetes/pkg/util/ipvs",
|
||||
"k8s.io/kubernetes/pkg/util/metrics",
|
||||
"k8s.io/kubernetes/pkg/util/node",
|
||||
"k8s.io/kubernetes/pkg/util/normalizer",
|
||||
"k8s.io/kubernetes/pkg/util/parsers",
|
||||
"k8s.io/kubernetes/pkg/util/procfs",
|
||||
"k8s.io/kubernetes/pkg/util/taints",
|
||||
"k8s.io/kubernetes/pkg/util/ipvs",
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
],
|
||||
"ForbiddenPrefixes": [
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers",
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/aws",
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/azure",
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/cloudstack",
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/fake",
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce",
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/openstack",
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt",
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/photon",
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere",
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SelectorRegexp": "github[.]com",
|
||||
"AllowedPrefixes": [
|
||||
"github.com/beorn7/perks/quantile",
|
||||
"github.com/blang/semver",
|
||||
"github.com/coreos/etcd/auth/authpb",
|
||||
"github.com/coreos/etcd/clientv3",
|
||||
"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
||||
"github.com/coreos/etcd/etcdserver/etcdserverpb",
|
||||
"github.com/coreos/etcd/mvcc/mvccpb",
|
||||
"github.com/coreos/etcd/pkg/tlsutil",
|
||||
"github.com/coreos/etcd/pkg/transport",
|
||||
"github.com/davecgh/go-spew/spew",
|
||||
"github.com/docker/distribution/digestset",
|
||||
"github.com/docker/distribution/reference",
|
||||
"github.com/docker/docker/api",
|
||||
"github.com/docker/docker/client",
|
||||
"github.com/docker/docker/pkg/term",
|
||||
"github.com/docker/go-connections/nat",
|
||||
"github.com/docker/go-connections/sockets",
|
||||
"github.com/docker/go-connections/tlsconfig",
|
||||
"github.com/docker/go-units",
|
||||
"github.com/docker/libnetwork/ipvs",
|
||||
"github.com/gogo/protobuf/proto",
|
||||
"github.com/gogo/protobuf/sortkeys",
|
||||
"github.com/golang/groupcache/lru",
|
||||
"github.com/golang/protobuf/proto",
|
||||
"github.com/golang/protobuf/ptypes",
|
||||
"github.com/googleapis/gnostic/compiler",
|
||||
"github.com/googleapis/gnostic/extensions",
|
||||
"github.com/googleapis/gnostic/OpenAPIv2",
|
||||
"github.com/google/btree",
|
||||
"github.com/google/gofuzz",
|
||||
"github.com/gregjones/httpcache",
|
||||
"github.com/hashicorp/golang-lru",
|
||||
"github.com/imdario/mergo",
|
||||
"github.com/json-iterator/go",
|
||||
"github.com/MakeNowJust/heredoc",
|
||||
"github.com/matttproud/golang_protobuf_extensions/pbutil",
|
||||
"github.com/mholt/caddy/caddyfile",
|
||||
"github.com/modern-go/concurrent",
|
||||
"github.com/modern-go/reflect2",
|
||||
"github.com/opencontainers/go-digest",
|
||||
"github.com/opencontainers/image-spec/specs-go",
|
||||
"github.com/peterbourgon/diskv",
|
||||
"github.com/pkg/errors",
|
||||
"github.com/pmezard/go-difflib/difflib",
|
||||
"github.com/prometheus/client_golang/prometheus",
|
||||
"github.com/prometheus/client_model/go",
|
||||
"github.com/prometheus/common/expfmt",
|
||||
"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg",
|
||||
"github.com/prometheus/common/model",
|
||||
"github.com/prometheus/procfs",
|
||||
"github.com/PuerkitoBio/purell",
|
||||
"github.com/PuerkitoBio/urlesc",
|
||||
"github.com/lithammer/dedent",
|
||||
"github.com/russross/blackfriday",
|
||||
"github.com/shurcooL/sanitized_anchor_name",
|
||||
"github.com/spf13/cobra",
|
||||
"github.com/spf13/pflag"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SelectorRegexp": "golang[.]org",
|
||||
"AllowedPrefixes": [
|
||||
"golang.org/x/crypto/ed25519",
|
||||
"golang.org/x/crypto/ssh/terminal",
|
||||
"golang.org/x/net/context",
|
||||
"golang.org/x/net/http2",
|
||||
"golang.org/x/net/idna",
|
||||
"golang.org/x/net/internal/timeseries",
|
||||
"golang.org/x/net/lex/httplex",
|
||||
"golang.org/x/net/proxy",
|
||||
"golang.org/x/net/trace",
|
||||
"golang.org/x/oauth2",
|
||||
"golang.org/x/sys/unix",
|
||||
"golang.org/x/text/cases",
|
||||
"golang.org/x/text/internal",
|
||||
"golang.org/x/text/language",
|
||||
"golang.org/x/text/runes",
|
||||
"golang.org/x/text/secure/bidirule",
|
||||
"golang.org/x/text/secure/precis",
|
||||
"golang.org/x/text/transform",
|
||||
"golang.org/x/text/unicode/bidi",
|
||||
"golang.org/x/text/unicode/norm",
|
||||
"golang.org/x/text/width",
|
||||
"golang.org/x/time/rate"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SelectorRegexp": "google[.]golang[.]org",
|
||||
"AllowedPrefixes": [
|
||||
"google.golang.org/genproto/googleapis/rpc/status",
|
||||
"google.golang.org/grpc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SelectorRegexp": "gopkg[.]in",
|
||||
"AllowedPrefixes": [
|
||||
"gopkg.in/inf.v0",
|
||||
"gopkg.in/square/go-jose.v2",
|
||||
"gopkg.in/yaml.v2"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
)
|
||||
load("//pkg/version:def.bzl", "version_x_defs")
|
||||
|
||||
go_binary(
|
||||
name = "kubeadm",
|
||||
embed = [":go_default_library"],
|
||||
pure = "on",
|
||||
x_defs = version_x_defs(),
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["kubeadm.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//cmd/kubeadm/app:all-srcs",
|
||||
"//cmd/kubeadm/test:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -1,23 +0,0 @@
|
|||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- luxas
|
||||
- timothysc
|
||||
- fabriziopandini
|
||||
- neolit123
|
||||
reviewers:
|
||||
- luxas
|
||||
- timothysc
|
||||
- fabriziopandini
|
||||
- neolit123
|
||||
- kad
|
||||
- liztio
|
||||
- chuckha
|
||||
- detiber
|
||||
- dixudx
|
||||
- rosti
|
||||
- yagonobre
|
||||
# Might want to add @xiangpengzhao and @stealthybox back in the future
|
||||
labels:
|
||||
- area/kubeadm
|
||||
- sig/cluster-lifecycle
|
|
@ -1,57 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["kubeadm.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/cmd:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/cli/flag:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//cmd/kubeadm/app/apis/kubeadm:all-srcs",
|
||||
"//cmd/kubeadm/app/cmd:all-srcs",
|
||||
"//cmd/kubeadm/app/componentconfigs:all-srcs",
|
||||
"//cmd/kubeadm/app/constants:all-srcs",
|
||||
"//cmd/kubeadm/app/discovery:all-srcs",
|
||||
"//cmd/kubeadm/app/features:all-srcs",
|
||||
"//cmd/kubeadm/app/images:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/addons/dns:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/addons/proxy:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/bootstraptoken/clusterinfo:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/bootstraptoken/node:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/certs:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/controlplane:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/copycerts:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/etcd:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/kubeconfig:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/kubelet:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/markcontrolplane:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/patchnode:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/selfhosting:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/upgrade:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/uploadconfig:all-srcs",
|
||||
"//cmd/kubeadm/app/preflight:all-srcs",
|
||||
"//cmd/kubeadm/app/util:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -1,65 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bootstraptokenhelpers.go",
|
||||
"bootstraptokenstring.go",
|
||||
"doc.go",
|
||||
"register.go",
|
||||
"types.go",
|
||||
"zz_generated.deepcopy.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm",
|
||||
deps = [
|
||||
"//pkg/kubelet/apis/config:go_default_library",
|
||||
"//pkg/proxy/apis/config:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//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",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/fuzzer:all-srcs",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/scheme:all-srcs",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha3:all-srcs",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:all-srcs",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/validation:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"bootstraptokenhelpers_test.go",
|
||||
"bootstraptokenstring_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
],
|
||||
)
|
|
@ -1,169 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package kubeadm
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
||||
)
|
||||
|
||||
// ToSecret converts the given BootstrapToken object to its Secret representation that
|
||||
// may be submitted to the API Server in order to be stored.
|
||||
func (bt *BootstrapToken) ToSecret() *v1.Secret {
|
||||
return &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: bootstraputil.BootstrapTokenSecretName(bt.Token.ID),
|
||||
Namespace: metav1.NamespaceSystem,
|
||||
},
|
||||
Type: v1.SecretType(bootstrapapi.SecretTypeBootstrapToken),
|
||||
Data: encodeTokenSecretData(bt, time.Now()),
|
||||
}
|
||||
}
|
||||
|
||||
// encodeTokenSecretData takes the token discovery object and an optional duration and returns the .Data for the Secret
|
||||
// now is passed in order to be able to used in unit testing
|
||||
func encodeTokenSecretData(token *BootstrapToken, now time.Time) map[string][]byte {
|
||||
data := map[string][]byte{
|
||||
bootstrapapi.BootstrapTokenIDKey: []byte(token.Token.ID),
|
||||
bootstrapapi.BootstrapTokenSecretKey: []byte(token.Token.Secret),
|
||||
}
|
||||
|
||||
if len(token.Description) > 0 {
|
||||
data[bootstrapapi.BootstrapTokenDescriptionKey] = []byte(token.Description)
|
||||
}
|
||||
|
||||
// If for some strange reason both token.TTL and token.Expires would be set
|
||||
// (they are mutually exlusive in validation so this shouldn't be the case),
|
||||
// token.Expires has higher priority, as can be seen in the logic here.
|
||||
if token.Expires != nil {
|
||||
// Format the expiration date accordingly
|
||||
// TODO: This maybe should be a helper function in bootstraputil?
|
||||
expirationString := token.Expires.Time.Format(time.RFC3339)
|
||||
data[bootstrapapi.BootstrapTokenExpirationKey] = []byte(expirationString)
|
||||
|
||||
} else if token.TTL != nil && token.TTL.Duration > 0 {
|
||||
// Only if .Expires is unset, TTL might have an effect
|
||||
// Get the current time, add the specified duration, and format it accordingly
|
||||
expirationString := now.Add(token.TTL.Duration).Format(time.RFC3339)
|
||||
data[bootstrapapi.BootstrapTokenExpirationKey] = []byte(expirationString)
|
||||
}
|
||||
|
||||
for _, usage := range token.Usages {
|
||||
data[bootstrapapi.BootstrapTokenUsagePrefix+usage] = []byte("true")
|
||||
}
|
||||
|
||||
if len(token.Groups) > 0 {
|
||||
data[bootstrapapi.BootstrapTokenExtraGroupsKey] = []byte(strings.Join(token.Groups, ","))
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// BootstrapTokenFromSecret returns a BootstrapToken object from the given Secret
|
||||
func BootstrapTokenFromSecret(secret *v1.Secret) (*BootstrapToken, error) {
|
||||
// Get the Token ID field from the Secret data
|
||||
tokenID := getSecretString(secret, bootstrapapi.BootstrapTokenIDKey)
|
||||
if len(tokenID) == 0 {
|
||||
return nil, errors.Errorf("bootstrap Token Secret has no token-id data: %s", secret.Name)
|
||||
}
|
||||
|
||||
// Enforce the right naming convention
|
||||
if secret.Name != bootstraputil.BootstrapTokenSecretName(tokenID) {
|
||||
return nil, errors.Errorf("bootstrap token name is not of the form '%s(token-id)'. Actual: %q. Expected: %q",
|
||||
bootstrapapi.BootstrapTokenSecretPrefix, secret.Name, bootstraputil.BootstrapTokenSecretName(tokenID))
|
||||
}
|
||||
|
||||
tokenSecret := getSecretString(secret, bootstrapapi.BootstrapTokenSecretKey)
|
||||
if len(tokenSecret) == 0 {
|
||||
return nil, errors.Errorf("bootstrap Token Secret has no token-secret data: %s", secret.Name)
|
||||
}
|
||||
|
||||
// Create the BootstrapTokenString object based on the ID and Secret
|
||||
bts, err := NewBootstrapTokenStringFromIDAndSecret(tokenID, tokenSecret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "bootstrap Token Secret is invalid and couldn't be parsed")
|
||||
}
|
||||
|
||||
// Get the description (if any) from the Secret
|
||||
description := getSecretString(secret, bootstrapapi.BootstrapTokenDescriptionKey)
|
||||
|
||||
// Expiration time is optional, if not specified this implies the token
|
||||
// never expires.
|
||||
secretExpiration := getSecretString(secret, bootstrapapi.BootstrapTokenExpirationKey)
|
||||
var expires *metav1.Time
|
||||
if len(secretExpiration) > 0 {
|
||||
expTime, err := time.Parse(time.RFC3339, secretExpiration)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "can't parse expiration time of bootstrap token %q", secret.Name)
|
||||
}
|
||||
expires = &metav1.Time{Time: expTime}
|
||||
}
|
||||
|
||||
// Build an usages string slice from the Secret data
|
||||
var usages []string
|
||||
for k, v := range secret.Data {
|
||||
// Skip all fields that don't include this prefix
|
||||
if !strings.HasPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix) {
|
||||
continue
|
||||
}
|
||||
// Skip those that don't have this usage set to true
|
||||
if string(v) != "true" {
|
||||
continue
|
||||
}
|
||||
usages = append(usages, strings.TrimPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix))
|
||||
}
|
||||
// Only sort the slice if defined
|
||||
if usages != nil {
|
||||
sort.Strings(usages)
|
||||
}
|
||||
|
||||
// Get the extra groups information from the Secret
|
||||
// It's done this way to make .Groups be nil in case there is no items, rather than an
|
||||
// empty slice or an empty slice with a "" string only
|
||||
var groups []string
|
||||
groupsString := getSecretString(secret, bootstrapapi.BootstrapTokenExtraGroupsKey)
|
||||
g := strings.Split(groupsString, ",")
|
||||
if len(g) > 0 && len(g[0]) > 0 {
|
||||
groups = g
|
||||
}
|
||||
|
||||
return &BootstrapToken{
|
||||
Token: bts,
|
||||
Description: description,
|
||||
Expires: expires,
|
||||
Usages: usages,
|
||||
Groups: groups,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getSecretString returns the string value for the given key in the specified Secret
|
||||
func getSecretString(secret *v1.Secret, key string) string {
|
||||
if secret.Data == nil {
|
||||
return ""
|
||||
}
|
||||
if val, ok := secret.Data[key]; ok {
|
||||
return string(val)
|
||||
}
|
||||
return ""
|
||||
}
|
|
@ -1,508 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package kubeadm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// This timestamp is used as the reference value when computing expiration dates based on TTLs in these unit tests
|
||||
var refTime = time.Date(1970, time.January, 1, 1, 1, 1, 0, time.UTC)
|
||||
|
||||
func TestToSecret(t *testing.T) {
|
||||
|
||||
var tests = []struct {
|
||||
bt *BootstrapToken
|
||||
secret *v1.Secret
|
||||
}{
|
||||
{
|
||||
&BootstrapToken{ // all together
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
Usages: []string{"signing", "authentication"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
&v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bootstrap-token-abcdef",
|
||||
Namespace: "kube-system",
|
||||
},
|
||||
Type: v1.SecretType("bootstrap.kubernetes.io/token"),
|
||||
Data: map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"description": []byte("foo"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
"auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.bt.Token.ID, func(t *testing.T) {
|
||||
actual := rt.bt.ToSecret()
|
||||
if !reflect.DeepEqual(actual, rt.secret) {
|
||||
t.Errorf(
|
||||
"failed BootstrapToken.ToSecret():\n\texpected: %v\n\t actual: %v",
|
||||
rt.secret,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrapTokenToSecretRoundtrip(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bt *BootstrapToken
|
||||
}{
|
||||
{
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.bt.Token.ID, func(t *testing.T) {
|
||||
actual, err := BootstrapTokenFromSecret(rt.bt.ToSecret())
|
||||
if err != nil {
|
||||
t.Errorf("failed BootstrapToken to Secret roundtrip with error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, rt.bt) {
|
||||
t.Errorf(
|
||||
"failed BootstrapToken to Secret roundtrip:\n\texpected: %v\n\t actual: %v",
|
||||
rt.bt,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeTokenSecretData(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
bt *BootstrapToken
|
||||
data map[string][]byte
|
||||
}{
|
||||
{
|
||||
"the minimum amount of information needed to be specified",
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
},
|
||||
},
|
||||
{
|
||||
"adds description",
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"description": []byte("foo"),
|
||||
},
|
||||
},
|
||||
{
|
||||
"adds ttl",
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
TTL: &metav1.Duration{
|
||||
Duration: mustParseDuration("2h", t),
|
||||
},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"expiration": []byte(refTime.Add(mustParseDuration("2h", t)).Format(time.RFC3339)),
|
||||
},
|
||||
},
|
||||
{
|
||||
"adds expiration",
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
},
|
||||
},
|
||||
{
|
||||
"adds ttl and expiration, should favor expiration",
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
TTL: &metav1.Duration{
|
||||
Duration: mustParseDuration("2h", t),
|
||||
},
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
},
|
||||
},
|
||||
{
|
||||
"adds usages",
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
},
|
||||
},
|
||||
{
|
||||
"adds groups",
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"),
|
||||
},
|
||||
},
|
||||
{
|
||||
"all together",
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
TTL: &metav1.Duration{
|
||||
Duration: mustParseDuration("2h", t),
|
||||
},
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"description": []byte("foo"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
"auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t *testing.T) {
|
||||
actual := encodeTokenSecretData(rt.bt, refTime)
|
||||
if !reflect.DeepEqual(actual, rt.data) {
|
||||
t.Errorf(
|
||||
"failed encodeTokenSecretData:\n\texpected: %v\n\t actual: %v",
|
||||
rt.data,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func mustParseDuration(durationStr string, t *testing.T) time.Duration {
|
||||
d, err := time.ParseDuration(durationStr)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't parse duration %q: %v", durationStr, err)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func TestBootstrapTokenFromSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
desc string
|
||||
name string
|
||||
data map[string][]byte
|
||||
bt *BootstrapToken
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
"minimum information",
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid token id",
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdeF"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid secret naming",
|
||||
"foo",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid token secret",
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("ABCDEF0123456789"),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"adds description",
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"description": []byte("foo"),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"adds expiration",
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid expiration",
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"expiration": []byte("invalid date"),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"adds usages",
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"should ignore usages that aren't set to true",
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
"usage-bootstrap-foo": []byte("false"),
|
||||
"usage-bootstrap-bar": []byte(""),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"adds groups",
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"all fields set",
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"description": []byte("foo"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
"auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.desc, func(t *testing.T) {
|
||||
actual, err := BootstrapTokenFromSecret(&v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: rt.name,
|
||||
Namespace: "kube-system",
|
||||
},
|
||||
Type: v1.SecretType("bootstrap.kubernetes.io/token"),
|
||||
Data: rt.data,
|
||||
})
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenFromSecret\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else {
|
||||
if actual == nil && rt.bt == nil {
|
||||
// if both pointers are nil, it's okay, just continue
|
||||
return
|
||||
}
|
||||
// If one of the pointers is defined but the other isn't, throw error. If both pointers are defined but unequal, throw error
|
||||
if (actual == nil && rt.bt != nil) || (actual != nil && rt.bt == nil) || !reflect.DeepEqual(*actual, *rt.bt) {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenFromSecret\n\texpected: %s\n\t actual: %s",
|
||||
jsonMarshal(rt.bt),
|
||||
jsonMarshal(actual),
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func jsonMarshal(bt *BootstrapToken) string {
|
||||
b, _ := json.Marshal(*bt)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func TestGetSecretString(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
secret *v1.Secret
|
||||
key string
|
||||
expectedVal string
|
||||
}{
|
||||
{
|
||||
name: "existing key",
|
||||
secret: &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Data: map[string][]byte{
|
||||
"foo": []byte("bar"),
|
||||
},
|
||||
},
|
||||
key: "foo",
|
||||
expectedVal: "bar",
|
||||
},
|
||||
{
|
||||
name: "non-existing key",
|
||||
secret: &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Data: map[string][]byte{
|
||||
"foo": []byte("bar"),
|
||||
},
|
||||
},
|
||||
key: "baz",
|
||||
expectedVal: "",
|
||||
},
|
||||
{
|
||||
name: "no data",
|
||||
secret: &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
},
|
||||
key: "foo",
|
||||
expectedVal: "",
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t *testing.T) {
|
||||
actual := getSecretString(rt.secret, rt.key)
|
||||
if actual != rt.expectedVal {
|
||||
t.Errorf(
|
||||
"failed getSecretString:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expectedVal,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package kubeadm holds the internal kubeadm API types
|
||||
// Note: This file should be kept in sync with the similar one for the external API
|
||||
// TODO: The BootstrapTokenString object should move out to either k8s.io/client-go or k8s.io/api in the future
|
||||
// (probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now.
|
||||
package kubeadm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
||||
)
|
||||
|
||||
// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used
|
||||
// for both validation of the practically of the API server from a joining node's point
|
||||
// of view and as an authentication method for the node in the bootstrap phase of
|
||||
// "kubeadm join". This token is and should be short-lived
|
||||
type BootstrapTokenString struct {
|
||||
ID string
|
||||
Secret string
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (bts BootstrapTokenString) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf(`"%s"`, bts.String())), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaller interface.
|
||||
func (bts *BootstrapTokenString) UnmarshalJSON(b []byte) error {
|
||||
// If the token is represented as "", just return quickly without an error
|
||||
if len(b) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove unnecessary " characters coming from the JSON parser
|
||||
token := strings.Replace(string(b), `"`, ``, -1)
|
||||
// Convert the string Token to a BootstrapTokenString object
|
||||
newbts, err := NewBootstrapTokenString(token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bts.ID = newbts.ID
|
||||
bts.Secret = newbts.Secret
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the string representation of the BootstrapTokenString
|
||||
func (bts BootstrapTokenString) String() string {
|
||||
if len(bts.ID) > 0 && len(bts.Secret) > 0 {
|
||||
return bootstraputil.TokenFromIDAndSecret(bts.ID, bts.Secret)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewBootstrapTokenString converts the given Bootstrap Token as a string
|
||||
// to the BootstrapTokenString object used for serialization/deserialization
|
||||
// and internal usage. It also automatically validates that the given token
|
||||
// is of the right format
|
||||
func NewBootstrapTokenString(token string) (*BootstrapTokenString, error) {
|
||||
substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(token)
|
||||
// TODO: Add a constant for the 3 value here, and explain better why it's needed (other than because how the regexp parsin works)
|
||||
if len(substrs) != 3 {
|
||||
return nil, errors.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern)
|
||||
}
|
||||
|
||||
return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil
|
||||
}
|
||||
|
||||
// NewBootstrapTokenStringFromIDAndSecret is a wrapper around NewBootstrapTokenString
|
||||
// that allows the caller to specify the ID and Secret separately
|
||||
func NewBootstrapTokenStringFromIDAndSecret(id, secret string) (*BootstrapTokenString, error) {
|
||||
return NewBootstrapTokenString(bootstraputil.TokenFromIDAndSecret(id, secret))
|
||||
}
|
|
@ -1,249 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package kubeadm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func TestMarshalJSON(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bts BootstrapTokenString
|
||||
expected string
|
||||
}{
|
||||
{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`},
|
||||
{BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`},
|
||||
{BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.bts.ID, func(t *testing.T) {
|
||||
b, err := json.Marshal(rt.bts)
|
||||
if err != nil {
|
||||
t.Fatalf("json.Marshal returned an unexpected error: %v", err)
|
||||
}
|
||||
if string(b) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
string(b),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalJSON(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
bts *BootstrapTokenString
|
||||
expectedError bool
|
||||
}{
|
||||
{`"f.s"`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef."`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true},
|
||||
{`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false},
|
||||
{`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.input, func(t *testing.T) {
|
||||
newbts := &BootstrapTokenString{}
|
||||
err := json.Unmarshal([]byte(rt.input), newbts)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err)
|
||||
} else if !reflect.DeepEqual(rt.bts, newbts) {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v",
|
||||
rt.bts,
|
||||
newbts,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONRoundtrip(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{`"abcdef.abcdef0123456789"`, nil},
|
||||
{"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.input, func(t *testing.T) {
|
||||
if err := roundtrip(rt.input, rt.bts); err != nil {
|
||||
t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func roundtrip(input string, bts *BootstrapTokenString) error {
|
||||
var b []byte
|
||||
var err error
|
||||
newbts := &BootstrapTokenString{}
|
||||
// If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string
|
||||
if len(input) > 0 {
|
||||
if err := json.Unmarshal([]byte(input), newbts); err != nil {
|
||||
return errors.Wrap(err, "expected no unmarshal error, got error")
|
||||
}
|
||||
if b, err = json.Marshal(newbts); err != nil {
|
||||
return errors.Wrap(err, "expected no marshal error, got error")
|
||||
}
|
||||
if input != string(b) {
|
||||
return errors.Errorf(
|
||||
"expected token: %s\n\t actual: %s",
|
||||
input,
|
||||
string(b),
|
||||
)
|
||||
}
|
||||
} else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object
|
||||
if b, err = json.Marshal(bts); err != nil {
|
||||
return errors.Wrap(err, "expected no marshal error, got error")
|
||||
}
|
||||
if err := json.Unmarshal(b, newbts); err != nil {
|
||||
return errors.Wrap(err, "expected no unmarshal error, got error")
|
||||
}
|
||||
if !reflect.DeepEqual(bts, newbts) {
|
||||
return errors.Errorf(
|
||||
"expected object: %v\n\t actual: %v",
|
||||
bts,
|
||||
newbts,
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestTokenFromIDAndSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bts BootstrapTokenString
|
||||
expected string
|
||||
}{
|
||||
{BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"},
|
||||
{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"},
|
||||
{BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.bts.ID, func(t *testing.T) {
|
||||
actual := rt.bts.String()
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBootstrapTokenString(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token string
|
||||
expectedError bool
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{token: "", expectedError: true, bts: nil},
|
||||
{token: ".", expectedError: true, bts: nil},
|
||||
{token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "123456.", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation
|
||||
{token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation
|
||||
{token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id
|
||||
{token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
|
||||
{token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
|
||||
{token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character
|
||||
{token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
|
||||
{token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
|
||||
{token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
{token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.token, func(t *testing.T) {
|
||||
actual, err := NewBootstrapTokenString(rt.token)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.token,
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else if !reflect.DeepEqual(actual, rt.bts) {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v",
|
||||
rt.token,
|
||||
rt.bts,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
id, secret string
|
||||
expectedError bool
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{id: "", secret: "", expectedError: true, bts: nil},
|
||||
{id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id
|
||||
{id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
|
||||
{id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
|
||||
{id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character
|
||||
{id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
|
||||
{id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
|
||||
{id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
{id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.id, func(t *testing.T) {
|
||||
actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.id,
|
||||
rt.secret,
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else if !reflect.DeepEqual(actual, rt.bts) {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v",
|
||||
rt.id,
|
||||
rt.secret,
|
||||
rt.bts,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +groupName=kubeadm.k8s.io
|
||||
|
||||
// Package kubeadm is the package that contains the libraries that drive the kubeadm binary.
|
||||
// kubeadm is responsible for handling a Kubernetes cluster's lifecycle.
|
||||
package kubeadm // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
|
@ -1,44 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["fuzzer.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["fuzzer_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/apitesting/roundtrip:go_default_library",
|
||||
],
|
||||
)
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fuzzer
|
||||
|
||||
import (
|
||||
fuzz "github.com/google/gofuzz"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
)
|
||||
|
||||
// Funcs returns the fuzzer functions for the kubeadm apis.
|
||||
func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
return []interface{}{
|
||||
fuzzInitConfiguration,
|
||||
fuzzClusterConfiguration,
|
||||
fuzzComponentConfigs,
|
||||
fuzzNodeRegistration,
|
||||
fuzzDNS,
|
||||
fuzzLocalEtcd,
|
||||
fuzzNetworking,
|
||||
fuzzJoinConfiguration,
|
||||
}
|
||||
}
|
||||
|
||||
func fuzzInitConfiguration(obj *kubeadm.InitConfiguration, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
|
||||
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
|
||||
|
||||
// Since ClusterConfiguration never get serialized in the external variant of InitConfiguration,
|
||||
// it is necessary to apply external api defaults here to get the round trip internal->external->internal working.
|
||||
// More specifically:
|
||||
// internal with manually applied defaults -> external object : loosing ClusterConfiguration) -> internal object with automatically applied defaults
|
||||
obj.ClusterConfiguration = kubeadm.ClusterConfiguration{
|
||||
APIServer: kubeadm.APIServer{
|
||||
TimeoutForControlPlane: &metav1.Duration{
|
||||
Duration: constants.DefaultControlPlaneTimeout,
|
||||
},
|
||||
},
|
||||
DNS: kubeadm.DNS{
|
||||
Type: kubeadm.CoreDNS,
|
||||
},
|
||||
CertificatesDir: v1beta1.DefaultCertificatesDir,
|
||||
ClusterName: v1beta1.DefaultClusterName,
|
||||
Etcd: kubeadm.Etcd{
|
||||
Local: &kubeadm.LocalEtcd{
|
||||
DataDir: v1beta1.DefaultEtcdDataDir,
|
||||
},
|
||||
},
|
||||
ImageRepository: v1beta1.DefaultImageRepository,
|
||||
KubernetesVersion: v1beta1.DefaultKubernetesVersion,
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: v1beta1.DefaultServicesSubnet,
|
||||
DNSDomain: v1beta1.DefaultServiceDNSDomain,
|
||||
},
|
||||
}
|
||||
// Adds the default bootstrap token to get the round working
|
||||
obj.BootstrapTokens = []kubeadm.BootstrapToken{
|
||||
{
|
||||
// Description
|
||||
// Expires
|
||||
Groups: []string{"foo"},
|
||||
// Token
|
||||
TTL: &metav1.Duration{Duration: 1234},
|
||||
Usages: []string{"foo"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func fuzzNodeRegistration(obj *kubeadm.NodeRegistrationOptions, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
|
||||
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
|
||||
obj.CRISocket = "foo"
|
||||
}
|
||||
|
||||
func fuzzClusterConfiguration(obj *kubeadm.ClusterConfiguration, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
|
||||
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
|
||||
obj.CertificatesDir = "foo"
|
||||
obj.CIImageRepository = "" //This fields doesn't exists in public API >> using default to get the roundtrip test pass
|
||||
obj.ClusterName = "bar"
|
||||
obj.ImageRepository = "baz"
|
||||
obj.KubernetesVersion = "qux"
|
||||
obj.APIServer.TimeoutForControlPlane = &metav1.Duration{
|
||||
Duration: constants.DefaultControlPlaneTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
func fuzzDNS(obj *kubeadm.DNS, c fuzz.Continue) {
|
||||
// This is intentionally not calling c.FuzzNoCustom because DNS struct does not exists in v1alpha3 api
|
||||
// (so no random value will be applied, and this is necessary for getting roundtrip passing)
|
||||
|
||||
// Pinning values for fields that get defaults if fuzz value is empty string or nil
|
||||
obj.Type = kubeadm.CoreDNS
|
||||
}
|
||||
|
||||
func fuzzComponentConfigs(obj *kubeadm.ComponentConfigs, c fuzz.Continue) {
|
||||
// This is intentionally empty because component config does not exists in the public api
|
||||
// (empty mean all ComponentConfigs fields nil, and this is necessary for getting roundtrip passing)
|
||||
}
|
||||
|
||||
func fuzzLocalEtcd(obj *kubeadm.LocalEtcd, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
|
||||
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
|
||||
obj.DataDir = "foo"
|
||||
|
||||
// Pinning values for fields that does not exists in v1alpha3 api
|
||||
obj.ImageRepository = ""
|
||||
obj.ImageTag = ""
|
||||
}
|
||||
|
||||
func fuzzNetworking(obj *kubeadm.Networking, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
|
||||
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
|
||||
obj.DNSDomain = "foo"
|
||||
obj.ServiceSubnet = "bar"
|
||||
}
|
||||
|
||||
func fuzzJoinConfiguration(obj *kubeadm.JoinConfiguration, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
|
||||
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
|
||||
obj.CACertPath = "foo"
|
||||
obj.Discovery = kubeadm.Discovery{
|
||||
BootstrapToken: &kubeadm.BootstrapTokenDiscovery{Token: "baz"},
|
||||
TLSBootstrapToken: "qux",
|
||||
Timeout: &metav1.Duration{Duration: 1234},
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fuzzer
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/apitesting/roundtrip"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
)
|
||||
|
||||
func TestRoundTripTypes(t *testing.T) {
|
||||
roundtrip.RoundTripTestForAPIGroup(t, scheme.AddToScheme, Funcs)
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package kubeadm
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "kubeadm.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
|
||||
|
||||
var (
|
||||
// SchemeBuilder points to a list of functions added to Scheme.
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
// AddToScheme applies all the stored functions to the scheme.
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&InitConfiguration{},
|
||||
&ClusterConfiguration{},
|
||||
&ClusterStatus{},
|
||||
&JoinConfiguration{},
|
||||
)
|
||||
return nil
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["scheme.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha3:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//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",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer: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"],
|
||||
)
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package scheme
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
)
|
||||
|
||||
// Scheme is the runtime.Scheme to which all kubeadm api types are registered.
|
||||
var Scheme = runtime.NewScheme()
|
||||
|
||||
// Codecs provides access to encoding and decoding for the scheme.
|
||||
var Codecs = serializer.NewCodecFactory(Scheme)
|
||||
|
||||
func init() {
|
||||
metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||
AddToScheme(Scheme)
|
||||
}
|
||||
|
||||
// AddToScheme builds the kubeadm scheme using all known versions of the kubeadm api.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
utilruntime.Must(kubeadm.AddToScheme(scheme))
|
||||
utilruntime.Must(v1alpha3.AddToScheme(scheme))
|
||||
utilruntime.Must(v1beta1.AddToScheme(scheme))
|
||||
utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion))
|
||||
}
|
|
@ -1,460 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package kubeadm
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
|
||||
kubeproxyconfig "k8s.io/kubernetes/pkg/proxy/apis/config"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// InitConfiguration contains a list of fields that are specifically "kubeadm init"-only runtime
|
||||
// information. The cluster-wide config is stored in ClusterConfiguration. The InitConfiguration
|
||||
// object IS NOT uploaded to the kubeadm-config ConfigMap in the cluster, only the
|
||||
// ClusterConfiguration is.
|
||||
type InitConfiguration struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
// ClusterConfiguration holds the cluster-wide information, and embeds that struct (which can be (un)marshalled separately as well)
|
||||
// When InitConfiguration is marshalled to bytes in the external version, this information IS NOT preserved (which can be seen from
|
||||
// the `json:"-"` tag in the external variant of these API types.
|
||||
ClusterConfiguration `json:"-"`
|
||||
|
||||
// BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create.
|
||||
BootstrapTokens []BootstrapToken
|
||||
|
||||
// NodeRegistration holds fields that relate to registering the new control-plane node to the cluster
|
||||
NodeRegistration NodeRegistrationOptions
|
||||
|
||||
// LocalAPIEndpoint represents the endpoint of the API server instance that's deployed on this control plane node
|
||||
// In HA setups, this differs from ClusterConfiguration.ControlPlaneEndpoint in the sense that ControlPlaneEndpoint
|
||||
// is the global endpoint for the cluster, which then loadbalances the requests to each individual API server. This
|
||||
// configuration object lets you customize what IP/DNS name and port the local API server advertises it's accessible
|
||||
// on. By default, kubeadm tries to auto-detect the IP of the default interface and use that, but in case that process
|
||||
// fails you may set the desired value here.
|
||||
LocalAPIEndpoint APIEndpoint
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// ClusterConfiguration contains cluster-wide configuration for a kubeadm cluster
|
||||
type ClusterConfiguration struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
// ComponentConfigs holds internal ComponentConfig struct types known to kubeadm, should long-term only exist in the internal kubeadm API
|
||||
// +k8s:conversion-gen=false
|
||||
ComponentConfigs ComponentConfigs
|
||||
|
||||
// Etcd holds configuration for etcd.
|
||||
Etcd Etcd
|
||||
|
||||
// Networking holds configuration for the networking topology of the cluster.
|
||||
Networking Networking
|
||||
// KubernetesVersion is the target version of the control plane.
|
||||
KubernetesVersion string
|
||||
|
||||
// ControlPlaneEndpoint sets a stable IP address or DNS name for the control plane; it
|
||||
// can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port.
|
||||
// In case the ControlPlaneEndpoint is not specified, the AdvertiseAddress + BindPort
|
||||
// are used; in case the ControlPlaneEndpoint is specified but without a TCP port,
|
||||
// the BindPort is used.
|
||||
// Possible usages are:
|
||||
// e.g. In a cluster with more than one control plane instances, this field should be
|
||||
// assigned the address of the external load balancer in front of the
|
||||
// control plane instances.
|
||||
// e.g. in environments with enforced node recycling, the ControlPlaneEndpoint
|
||||
// could be used for assigning a stable DNS to the control plane.
|
||||
ControlPlaneEndpoint string
|
||||
|
||||
// APIServer contains extra settings for the API server control plane component
|
||||
APIServer APIServer
|
||||
|
||||
// ControllerManager contains extra settings for the controller manager control plane component
|
||||
ControllerManager ControlPlaneComponent
|
||||
|
||||
// Scheduler contains extra settings for the scheduler control plane component
|
||||
Scheduler ControlPlaneComponent
|
||||
|
||||
// DNS defines the options for the DNS add-on installed in the cluster.
|
||||
DNS DNS
|
||||
|
||||
// CertificatesDir specifies where to store or look for all required certificates.
|
||||
CertificatesDir string
|
||||
|
||||
// ImageRepository sets the container registry to pull images from.
|
||||
// If empty, `k8s.gcr.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`)
|
||||
// `gcr.io/kubernetes-ci-images` will be used as a default for control plane components and for kube-proxy, while `k8s.gcr.io`
|
||||
// will be used for all the other images.
|
||||
ImageRepository string
|
||||
|
||||
// CIImageRepository is the container registry for core images generated by CI.
|
||||
// Useful for running kubeadm with images from CI builds.
|
||||
// +k8s:conversion-gen=false
|
||||
CIImageRepository string
|
||||
|
||||
// UseHyperKubeImage controls if hyperkube should be used for Kubernetes components instead of their respective separate images
|
||||
UseHyperKubeImage bool
|
||||
|
||||
// FeatureGates enabled by the user.
|
||||
FeatureGates map[string]bool
|
||||
|
||||
// The cluster name
|
||||
ClusterName string
|
||||
}
|
||||
|
||||
// ControlPlaneComponent holds settings common to control plane component of the cluster
|
||||
type ControlPlaneComponent struct {
|
||||
// ExtraArgs is an extra set of flags to pass to the control plane component.
|
||||
// TODO: This is temporary and ideally we would like to switch all components to
|
||||
// use ComponentConfig + ConfigMaps.
|
||||
ExtraArgs map[string]string
|
||||
|
||||
// ExtraVolumes is an extra set of host volumes, mounted to the control plane component.
|
||||
ExtraVolumes []HostPathMount
|
||||
}
|
||||
|
||||
// APIServer holds settings necessary for API server deployments in the cluster
|
||||
type APIServer struct {
|
||||
ControlPlaneComponent
|
||||
|
||||
// CertSANs sets extra Subject Alternative Names for the API Server signing cert.
|
||||
CertSANs []string
|
||||
|
||||
// TimeoutForControlPlane controls the timeout that we use for API server to appear
|
||||
TimeoutForControlPlane *metav1.Duration
|
||||
}
|
||||
|
||||
// DNSAddOnType defines string identifying DNS add-on types
|
||||
type DNSAddOnType string
|
||||
|
||||
const (
|
||||
// CoreDNS add-on type
|
||||
CoreDNS DNSAddOnType = "CoreDNS"
|
||||
|
||||
// KubeDNS add-on type
|
||||
KubeDNS DNSAddOnType = "kube-dns"
|
||||
)
|
||||
|
||||
// DNS defines the DNS addon that should be used in the cluster
|
||||
type DNS struct {
|
||||
// Type defines the DNS add-on to be used
|
||||
Type DNSAddOnType
|
||||
|
||||
// ImageMeta allows to customize the image used for the DNS component
|
||||
ImageMeta `json:",inline"`
|
||||
}
|
||||
|
||||
// ImageMeta allows to customize the image used for components that are not
|
||||
// originated from the Kubernetes/Kubernetes release process
|
||||
type ImageMeta struct {
|
||||
// ImageRepository sets the container registry to pull images from.
|
||||
// if not set, the ImageRepository defined in ClusterConfiguration will be used instead.
|
||||
ImageRepository string
|
||||
|
||||
// ImageTag allows to specify a tag for the image.
|
||||
// In case this value is set, kubeadm does not change automatically the version of the above components during upgrades.
|
||||
ImageTag string
|
||||
|
||||
//TODO: evaluate if we need also a ImageName based on user feedbacks
|
||||
}
|
||||
|
||||
// ComponentConfigs holds known internal ComponentConfig types for other components
|
||||
type ComponentConfigs struct {
|
||||
// Kubelet holds the ComponentConfiguration for the kubelet
|
||||
Kubelet *kubeletconfig.KubeletConfiguration
|
||||
// KubeProxy holds the ComponentConfiguration for the kube-proxy
|
||||
KubeProxy *kubeproxyconfig.KubeProxyConfiguration
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// ClusterStatus contains the cluster status. The ClusterStatus will be stored in the kubeadm-config
|
||||
// ConfigMap in the cluster, and then updated by kubeadm when additional control plane instance joins or leaves the cluster.
|
||||
type ClusterStatus struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
// APIEndpoints currently available in the cluster, one for each control plane/api server instance.
|
||||
// The key of the map is the IP of the host's default interface
|
||||
APIEndpoints map[string]APIEndpoint
|
||||
}
|
||||
|
||||
// APIEndpoint struct contains elements of API server instance deployed on a node.
|
||||
type APIEndpoint struct {
|
||||
// AdvertiseAddress sets the IP address for the API server to advertise.
|
||||
AdvertiseAddress string
|
||||
|
||||
// BindPort sets the secure port for the API Server to bind to.
|
||||
// Defaults to 6443.
|
||||
BindPort int32
|
||||
}
|
||||
|
||||
// NodeRegistrationOptions holds fields that relate to registering a new control-plane or node to the cluster, either via "kubeadm init" or "kubeadm join"
|
||||
type NodeRegistrationOptions struct {
|
||||
|
||||
// Name is the `.Metadata.Name` field of the Node API object that will be created in this `kubeadm init` or `kubeadm join` operation.
|
||||
// This field is also used in the CommonName field of the kubelet's client certificate to the API server.
|
||||
// Defaults to the hostname of the node if not provided.
|
||||
Name string
|
||||
|
||||
// CRISocket is used to retrieve container runtime info. This information will be annotated to the Node API object, for later re-use
|
||||
CRISocket string
|
||||
|
||||
// Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the `kubeadm init` process
|
||||
// it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your control-plane node, set this field to an
|
||||
// empty slice, i.e. `taints: {}` in the YAML file. This field is solely used for Node registration.
|
||||
Taints []v1.Taint
|
||||
|
||||
// KubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file
|
||||
// kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap
|
||||
// Flags have higher priority when parsing. These values are local and specific to the node kubeadm is executing on.
|
||||
KubeletExtraArgs map[string]string
|
||||
}
|
||||
|
||||
// Networking contains elements describing cluster's networking configuration.
|
||||
type Networking struct {
|
||||
// ServiceSubnet is the subnet used by k8s services. Defaults to "10.96.0.0/12".
|
||||
ServiceSubnet string
|
||||
// PodSubnet is the subnet used by pods.
|
||||
PodSubnet string
|
||||
// DNSDomain is the dns domain used by k8s services. Defaults to "cluster.local".
|
||||
DNSDomain string
|
||||
}
|
||||
|
||||
// BootstrapToken describes one bootstrap token, stored as a Secret in the cluster
|
||||
// TODO: The BootstrapToken object should move out to either k8s.io/client-go or k8s.io/api in the future
|
||||
// (probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now.
|
||||
type BootstrapToken struct {
|
||||
// Token is used for establishing bidirectional trust between nodes and control-planes.
|
||||
// Used for joining nodes in the cluster.
|
||||
Token *BootstrapTokenString
|
||||
// Description sets a human-friendly message why this token exists and what it's used
|
||||
// for, so other administrators can know its purpose.
|
||||
Description string
|
||||
// TTL defines the time to live for this token. Defaults to 24h.
|
||||
// Expires and TTL are mutually exclusive.
|
||||
TTL *metav1.Duration
|
||||
// Expires specifies the timestamp when this token expires. Defaults to being set
|
||||
// dynamically at runtime based on the TTL. Expires and TTL are mutually exclusive.
|
||||
Expires *metav1.Time
|
||||
// Usages describes the ways in which this token can be used. Can by default be used
|
||||
// for establishing bidirectional trust, but that can be changed here.
|
||||
Usages []string
|
||||
// Groups specifies the extra groups that this token will authenticate as when/if
|
||||
// used for authentication
|
||||
Groups []string
|
||||
}
|
||||
|
||||
// Etcd contains elements describing Etcd configuration.
|
||||
type Etcd struct {
|
||||
|
||||
// Local provides configuration knobs for configuring the local etcd instance
|
||||
// Local and External are mutually exclusive
|
||||
Local *LocalEtcd
|
||||
|
||||
// External describes how to connect to an external etcd cluster
|
||||
// Local and External are mutually exclusive
|
||||
External *ExternalEtcd
|
||||
}
|
||||
|
||||
// LocalEtcd describes that kubeadm should run an etcd cluster locally
|
||||
type LocalEtcd struct {
|
||||
// ImageMeta allows to customize the container used for etcd
|
||||
ImageMeta `json:",inline"`
|
||||
|
||||
// DataDir is the directory etcd will place its data.
|
||||
// Defaults to "/var/lib/etcd".
|
||||
DataDir string
|
||||
|
||||
// ExtraArgs are extra arguments provided to the etcd binary
|
||||
// when run inside a static pod.
|
||||
ExtraArgs map[string]string
|
||||
|
||||
// ServerCertSANs sets extra Subject Alternative Names for the etcd server signing cert.
|
||||
ServerCertSANs []string
|
||||
// PeerCertSANs sets extra Subject Alternative Names for the etcd peer signing cert.
|
||||
PeerCertSANs []string
|
||||
}
|
||||
|
||||
// ExternalEtcd describes an external etcd cluster
|
||||
type ExternalEtcd struct {
|
||||
|
||||
// Endpoints of etcd members. Useful for using external etcd.
|
||||
// If not provided, kubeadm will run etcd in a static pod.
|
||||
Endpoints []string
|
||||
// CAFile is an SSL Certificate Authority file used to secure etcd communication.
|
||||
CAFile string
|
||||
// CertFile is an SSL certification file used to secure etcd communication.
|
||||
CertFile string
|
||||
// KeyFile is an SSL key file used to secure etcd communication.
|
||||
KeyFile string
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// JoinConfiguration contains elements describing a particular node.
|
||||
type JoinConfiguration struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
// NodeRegistration holds fields that relate to registering the new control-plane node to the cluster
|
||||
NodeRegistration NodeRegistrationOptions
|
||||
|
||||
// CACertPath is the path to the SSL certificate authority used to
|
||||
// secure comunications between node and control-plane.
|
||||
// Defaults to "/etc/kubernetes/pki/ca.crt".
|
||||
CACertPath string
|
||||
|
||||
// Discovery specifies the options for the kubelet to use during the TLS Bootstrap process
|
||||
Discovery Discovery
|
||||
|
||||
// ControlPlane defines the additional control plane instance to be deployed on the joining node.
|
||||
// If nil, no additional control plane instance will be deployed.
|
||||
ControlPlane *JoinControlPlane
|
||||
}
|
||||
|
||||
// JoinControlPlane contains elements describing an additional control plane instance to be deployed on the joining node.
|
||||
type JoinControlPlane struct {
|
||||
// LocalAPIEndpoint represents the endpoint of the API server instance to be deployed on this node.
|
||||
LocalAPIEndpoint APIEndpoint
|
||||
}
|
||||
|
||||
// Discovery specifies the options for the kubelet to use during the TLS Bootstrap process
|
||||
type Discovery struct {
|
||||
// BootstrapToken is used to set the options for bootstrap token based discovery
|
||||
// BootstrapToken and File are mutually exclusive
|
||||
BootstrapToken *BootstrapTokenDiscovery
|
||||
|
||||
// File is used to specify a file or URL to a kubeconfig file from which to load cluster information
|
||||
// BootstrapToken and File are mutually exclusive
|
||||
File *FileDiscovery
|
||||
|
||||
// TLSBootstrapToken is a token used for TLS bootstrapping.
|
||||
// If .BootstrapToken is set, this field is defaulted to .BootstrapToken.Token, but can be overridden.
|
||||
// If .File is set, this field **must be set** in case the KubeConfigFile does not contain any other authentication information
|
||||
TLSBootstrapToken string
|
||||
|
||||
// Timeout modifies the discovery timeout
|
||||
Timeout *metav1.Duration
|
||||
}
|
||||
|
||||
// BootstrapTokenDiscovery is used to set the options for bootstrap token based discovery
|
||||
type BootstrapTokenDiscovery struct {
|
||||
// Token is a token used to validate cluster information
|
||||
// fetched from the control-plane.
|
||||
Token string
|
||||
|
||||
// APIServerEndpoint is an IP or domain name to the API server from which info will be fetched.
|
||||
APIServerEndpoint string
|
||||
|
||||
// CACertHashes specifies a set of public key pins to verify
|
||||
// when token-based discovery is used. The root CA found during discovery
|
||||
// must match one of these values. Specifying an empty set disables root CA
|
||||
// pinning, which can be unsafe. Each hash is specified as "<type>:<value>",
|
||||
// where the only currently supported type is "sha256". This is a hex-encoded
|
||||
// SHA-256 hash of the Subject Public Key Info (SPKI) object in DER-encoded
|
||||
// ASN.1. These hashes can be calculated using, for example, OpenSSL:
|
||||
// openssl x509 -pubkey -in ca.crt openssl rsa -pubin -outform der 2>&/dev/null | openssl dgst -sha256 -hex
|
||||
CACertHashes []string
|
||||
|
||||
// UnsafeSkipCAVerification allows token-based discovery
|
||||
// without CA verification via CACertHashes. This can weaken
|
||||
// the security of kubeadm since other nodes can impersonate the control-plane.
|
||||
UnsafeSkipCAVerification bool
|
||||
}
|
||||
|
||||
// FileDiscovery is used to specify a file or URL to a kubeconfig file from which to load cluster information
|
||||
type FileDiscovery struct {
|
||||
// KubeConfigPath is used to specify the actual file path or URL to the kubeconfig file from which to load cluster information
|
||||
KubeConfigPath string
|
||||
}
|
||||
|
||||
// GetControlPlaneImageRepository returns name of image repository
|
||||
// for control plane images (API,Controller Manager,Scheduler and Proxy)
|
||||
// It will override location with CI registry name in case user requests special
|
||||
// Kubernetes version from CI build area.
|
||||
// (See: kubeadmconstants.DefaultCIImageRepository)
|
||||
func (cfg *ClusterConfiguration) GetControlPlaneImageRepository() string {
|
||||
if cfg.CIImageRepository != "" {
|
||||
return cfg.CIImageRepository
|
||||
}
|
||||
return cfg.ImageRepository
|
||||
}
|
||||
|
||||
// HostPathMount contains elements describing volumes that are mounted from the
|
||||
// host.
|
||||
type HostPathMount struct {
|
||||
// Name of the volume inside the pod template.
|
||||
Name string
|
||||
// HostPath is the path in the host that will be mounted inside
|
||||
// the pod.
|
||||
HostPath string
|
||||
// MountPath is the path inside the pod where hostPath will be mounted.
|
||||
MountPath string
|
||||
// ReadOnly controls write access to the volume
|
||||
ReadOnly bool
|
||||
// PathType is the type of the HostPath.
|
||||
PathType v1.HostPathType
|
||||
}
|
||||
|
||||
// CommonConfiguration defines the list of common configuration elements and the getter
|
||||
// methods that must exist for both the InitConfiguration and JoinConfiguration objects.
|
||||
// This is used internally to deduplicate the kubeadm preflight checks.
|
||||
type CommonConfiguration interface {
|
||||
GetCRISocket() string
|
||||
GetNodeName() string
|
||||
GetKubernetesVersion() string
|
||||
}
|
||||
|
||||
// GetCRISocket will return the CRISocket that is defined for the InitConfiguration.
|
||||
// This is used internally to deduplicate the kubeadm preflight checks.
|
||||
func (cfg *InitConfiguration) GetCRISocket() string {
|
||||
return cfg.NodeRegistration.CRISocket
|
||||
}
|
||||
|
||||
// GetNodeName will return the NodeName that is defined for the InitConfiguration.
|
||||
// This is used internally to deduplicate the kubeadm preflight checks.
|
||||
func (cfg *InitConfiguration) GetNodeName() string {
|
||||
return cfg.NodeRegistration.Name
|
||||
}
|
||||
|
||||
// GetKubernetesVersion will return the KubernetesVersion that is defined for the InitConfiguration.
|
||||
// This is used internally to deduplicate the kubeadm preflight checks.
|
||||
func (cfg *InitConfiguration) GetKubernetesVersion() string {
|
||||
return cfg.KubernetesVersion
|
||||
}
|
||||
|
||||
// GetCRISocket will return the CRISocket that is defined for the JoinConfiguration.
|
||||
// This is used internally to deduplicate the kubeadm preflight checks.
|
||||
func (cfg *JoinConfiguration) GetCRISocket() string {
|
||||
return cfg.NodeRegistration.CRISocket
|
||||
}
|
||||
|
||||
// GetNodeName will return the NodeName that is defined for the JoinConfiguration.
|
||||
// This is used internally to deduplicate the kubeadm preflight checks.
|
||||
func (cfg *JoinConfiguration) GetNodeName() string {
|
||||
return cfg.NodeRegistration.Name
|
||||
}
|
||||
|
||||
// GetKubernetesVersion will return an empty string since KubernetesVersion is not a
|
||||
// defined property for JoinConfiguration. This will just cause the regex validation
|
||||
// of the defined version to be skipped during the preflight checks.
|
||||
// This is used internally to deduplicate the kubeadm preflight checks.
|
||||
func (cfg *JoinConfiguration) GetKubernetesVersion() string {
|
||||
return ""
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bootstraptokenstring.go",
|
||||
"conversion.go",
|
||||
"defaults.go",
|
||||
"defaults_unix.go",
|
||||
"defaults_windows.go",
|
||||
"doc.go",
|
||||
"register.go",
|
||||
"types.go",
|
||||
"zz_generated.conversion.go",
|
||||
"zz_generated.deepcopy.go",
|
||||
"zz_generated.defaults.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/features:go_default_library",
|
||||
"//cmd/kubeadm/app/images:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1: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",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",
|
||||
"//vendor/github.com/pkg/errors: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 = [
|
||||
"bootstraptokenstring_test.go",
|
||||
"conversion_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
],
|
||||
)
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
||||
)
|
||||
|
||||
// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used
|
||||
// for both validation of the practically of the API server from a joining node's point
|
||||
// of view and as an authentication method for the node in the bootstrap phase of
|
||||
// "kubeadm join". This token is and should be short-lived
|
||||
type BootstrapTokenString struct {
|
||||
ID string
|
||||
Secret string
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (bts BootstrapTokenString) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf(`"%s"`, bts.String())), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaller interface.
|
||||
func (bts *BootstrapTokenString) UnmarshalJSON(b []byte) error {
|
||||
// If the token is represented as "", just return quickly without an error
|
||||
if len(b) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove unnecessary " characters coming from the JSON parser
|
||||
token := strings.Replace(string(b), `"`, ``, -1)
|
||||
// Convert the string Token to a BootstrapTokenString object
|
||||
newbts, err := NewBootstrapTokenString(token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bts.ID = newbts.ID
|
||||
bts.Secret = newbts.Secret
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the string representation of the BootstrapTokenString
|
||||
func (bts BootstrapTokenString) String() string {
|
||||
if len(bts.ID) > 0 && len(bts.Secret) > 0 {
|
||||
return bootstraputil.TokenFromIDAndSecret(bts.ID, bts.Secret)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewBootstrapTokenString converts the given Bootstrap Token as a string
|
||||
// to the BootstrapTokenString object used for serialization/deserialization
|
||||
// and internal usage. It also automatically validates that the given token
|
||||
// is of the right format
|
||||
func NewBootstrapTokenString(token string) (*BootstrapTokenString, error) {
|
||||
substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(token)
|
||||
// TODO: Add a constant for the 3 value here, and explain better why it's needed (other than because how the regexp parsin works)
|
||||
if len(substrs) != 3 {
|
||||
return nil, errors.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern)
|
||||
}
|
||||
|
||||
return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil
|
||||
}
|
||||
|
||||
// NewBootstrapTokenStringFromIDAndSecret is a wrapper around NewBootstrapTokenString
|
||||
// that allows the caller to specify the ID and Secret separately
|
||||
func NewBootstrapTokenStringFromIDAndSecret(id, secret string) (*BootstrapTokenString, error) {
|
||||
return NewBootstrapTokenString(bootstraputil.TokenFromIDAndSecret(id, secret))
|
||||
}
|
|
@ -1,249 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func TestMarshalJSON(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bts BootstrapTokenString
|
||||
expected string
|
||||
}{
|
||||
{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`},
|
||||
{BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`},
|
||||
{BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.bts.ID, func(t *testing.T) {
|
||||
b, err := json.Marshal(rt.bts)
|
||||
if err != nil {
|
||||
t.Fatalf("json.Marshal returned an unexpected error: %v", err)
|
||||
}
|
||||
if string(b) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
string(b),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalJSON(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
bts *BootstrapTokenString
|
||||
expectedError bool
|
||||
}{
|
||||
{`"f.s"`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef."`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true},
|
||||
{`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false},
|
||||
{`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.input, func(t *testing.T) {
|
||||
newbts := &BootstrapTokenString{}
|
||||
err := json.Unmarshal([]byte(rt.input), newbts)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err)
|
||||
} else if !reflect.DeepEqual(rt.bts, newbts) {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v",
|
||||
rt.bts,
|
||||
newbts,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONRoundtrip(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{`"abcdef.abcdef0123456789"`, nil},
|
||||
{"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.input, func(t *testing.T) {
|
||||
if err := roundtrip(rt.input, rt.bts); err != nil {
|
||||
t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func roundtrip(input string, bts *BootstrapTokenString) error {
|
||||
var b []byte
|
||||
var err error
|
||||
newbts := &BootstrapTokenString{}
|
||||
// If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string
|
||||
if len(input) > 0 {
|
||||
if err := json.Unmarshal([]byte(input), newbts); err != nil {
|
||||
return errors.Wrap(err, "expected no unmarshal error, got error")
|
||||
}
|
||||
if b, err = json.Marshal(newbts); err != nil {
|
||||
return errors.Wrap(err, "expected no marshal error, got error")
|
||||
}
|
||||
if input != string(b) {
|
||||
return errors.Errorf(
|
||||
"expected token: %s\n\t actual: %s",
|
||||
input,
|
||||
string(b),
|
||||
)
|
||||
}
|
||||
} else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object
|
||||
if b, err = json.Marshal(bts); err != nil {
|
||||
return errors.Wrap(err, "expected no marshal error, got error")
|
||||
}
|
||||
if err := json.Unmarshal(b, newbts); err != nil {
|
||||
return errors.Wrap(err, "expected no unmarshal error, got error")
|
||||
}
|
||||
if !reflect.DeepEqual(bts, newbts) {
|
||||
return errors.Errorf(
|
||||
"expected object: %v\n\t actual: %v",
|
||||
bts,
|
||||
newbts,
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestTokenFromIDAndSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bts BootstrapTokenString
|
||||
expected string
|
||||
}{
|
||||
{BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"},
|
||||
{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"},
|
||||
{BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.bts.ID, func(t *testing.T) {
|
||||
actual := rt.bts.String()
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBootstrapTokenString(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token string
|
||||
expectedError bool
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{token: "", expectedError: true, bts: nil},
|
||||
{token: ".", expectedError: true, bts: nil},
|
||||
{token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "123456.", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation
|
||||
{token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation
|
||||
{token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id
|
||||
{token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
|
||||
{token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
|
||||
{token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character
|
||||
{token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
|
||||
{token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
|
||||
{token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
{token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.token, func(t *testing.T) {
|
||||
actual, err := NewBootstrapTokenString(rt.token)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.token,
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else if !reflect.DeepEqual(actual, rt.bts) {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v",
|
||||
rt.token,
|
||||
rt.bts,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
id, secret string
|
||||
expectedError bool
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{id: "", secret: "", expectedError: true, bts: nil},
|
||||
{id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id
|
||||
{id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
|
||||
{id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
|
||||
{id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character
|
||||
{id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
|
||||
{id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
|
||||
{id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
{id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.id, func(t *testing.T) {
|
||||
actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.id,
|
||||
rt.secret,
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else if !reflect.DeepEqual(actual, rt.bts) {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v",
|
||||
rt.id,
|
||||
rt.secret,
|
||||
rt.bts,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,315 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
)
|
||||
|
||||
var imageRegEx = regexp.MustCompile(`(?P<repository>.+/)(?P<image>[^:]+)(?P<tag>:.+)`)
|
||||
|
||||
func Convert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
|
||||
if err := autoConvert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return Convert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(&in.APIEndpoint, &out.LocalAPIEndpoint, s)
|
||||
}
|
||||
|
||||
func Convert_kubeadm_InitConfiguration_To_v1alpha3_InitConfiguration(in *kubeadm.InitConfiguration, out *InitConfiguration, s conversion.Scope) error {
|
||||
if err := autoConvert_kubeadm_InitConfiguration_To_v1alpha3_InitConfiguration(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return Convert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(&in.LocalAPIEndpoint, &out.APIEndpoint, s)
|
||||
}
|
||||
|
||||
func Convert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(in *JoinConfiguration, out *kubeadm.JoinConfiguration, s conversion.Scope) error {
|
||||
if err := autoConvert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(in.ClusterName) != 0 {
|
||||
return errors.New("clusterName has been removed from JoinConfiguration and clusterName from ClusterConfiguration will be used instead. Please cleanup JoinConfiguration.ClusterName fields")
|
||||
}
|
||||
|
||||
if len(in.FeatureGates) != 0 {
|
||||
return errors.New("featureGates has been removed from JoinConfiguration and featureGates from ClusterConfiguration will be used instead. Please cleanup JoinConfiguration.FeatureGates fields")
|
||||
}
|
||||
|
||||
out.Discovery.Timeout = in.DiscoveryTimeout
|
||||
|
||||
if len(in.TLSBootstrapToken) != 0 {
|
||||
out.Discovery.TLSBootstrapToken = in.TLSBootstrapToken
|
||||
} else {
|
||||
out.Discovery.TLSBootstrapToken = in.Token
|
||||
}
|
||||
|
||||
if len(in.DiscoveryFile) != 0 {
|
||||
out.Discovery.File = &kubeadm.FileDiscovery{
|
||||
KubeConfigPath: in.DiscoveryFile,
|
||||
}
|
||||
} else {
|
||||
out.Discovery.BootstrapToken = &kubeadm.BootstrapTokenDiscovery{
|
||||
CACertHashes: in.DiscoveryTokenCACertHashes,
|
||||
UnsafeSkipCAVerification: in.DiscoveryTokenUnsafeSkipCAVerification,
|
||||
}
|
||||
if len(in.DiscoveryTokenAPIServers) != 0 {
|
||||
out.Discovery.BootstrapToken.APIServerEndpoint = in.DiscoveryTokenAPIServers[0]
|
||||
}
|
||||
if len(in.DiscoveryToken) != 0 {
|
||||
out.Discovery.BootstrapToken.Token = in.DiscoveryToken
|
||||
} else {
|
||||
out.Discovery.BootstrapToken.Token = in.Token
|
||||
}
|
||||
}
|
||||
|
||||
if in.ControlPlane == true {
|
||||
out.ControlPlane = &kubeadm.JoinControlPlane{}
|
||||
if err := autoConvert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(&in.APIEndpoint, &out.ControlPlane.LocalAPIEndpoint, s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_kubeadm_JoinConfiguration_To_v1alpha3_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error {
|
||||
if err := autoConvert_kubeadm_JoinConfiguration_To_v1alpha3_JoinConfiguration(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.DiscoveryTimeout = in.Discovery.Timeout
|
||||
out.TLSBootstrapToken = in.Discovery.TLSBootstrapToken
|
||||
|
||||
if in.Discovery.BootstrapToken != nil {
|
||||
out.DiscoveryToken = in.Discovery.BootstrapToken.Token
|
||||
out.DiscoveryTokenAPIServers = []string{in.Discovery.BootstrapToken.APIServerEndpoint}
|
||||
out.DiscoveryTokenCACertHashes = in.Discovery.BootstrapToken.CACertHashes
|
||||
out.DiscoveryTokenUnsafeSkipCAVerification = in.Discovery.BootstrapToken.UnsafeSkipCAVerification
|
||||
|
||||
} else if in.Discovery.File != nil {
|
||||
out.DiscoveryFile = in.Discovery.File.KubeConfigPath
|
||||
}
|
||||
|
||||
if in.ControlPlane != nil {
|
||||
out.ControlPlane = true
|
||||
if err := autoConvert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(&in.ControlPlane.LocalAPIEndpoint, &out.APIEndpoint, s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
|
||||
if err := autoConvert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(in.AuditPolicyConfiguration.Path) > 0 {
|
||||
return errors.New("AuditPolicyConfiguration has been removed from ClusterConfiguration. Please cleanup ClusterConfiguration.AuditPolicyConfiguration fields")
|
||||
}
|
||||
|
||||
out.APIServer.ExtraArgs = in.APIServerExtraArgs
|
||||
out.APIServer.CertSANs = in.APIServerCertSANs
|
||||
out.APIServer.TimeoutForControlPlane = &metav1.Duration{
|
||||
Duration: constants.DefaultControlPlaneTimeout,
|
||||
}
|
||||
if err := convertSlice_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(&in.APIServerExtraVolumes, &out.APIServer.ExtraVolumes, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.ControllerManager.ExtraArgs = in.ControllerManagerExtraArgs
|
||||
if err := convertSlice_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(&in.ControllerManagerExtraVolumes, &out.ControllerManager.ExtraVolumes, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.Scheduler.ExtraArgs = in.SchedulerExtraArgs
|
||||
if err := convertSlice_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(&in.SchedulerExtraVolumes, &out.Scheduler.ExtraVolumes, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := Convert_v1alpha3_UnifiedControlPlaneImage_To_kubeadm_UseHyperKubeImage(in, out); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// converting v1alpha3 featureGate CoreDNS to internal DNS.Type
|
||||
if features.Enabled(in.FeatureGates, features.CoreDNS) {
|
||||
out.DNS.Type = kubeadm.CoreDNS
|
||||
} else {
|
||||
out.DNS.Type = kubeadm.KubeDNS
|
||||
}
|
||||
delete(out.FeatureGates, features.CoreDNS)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha3_UnifiedControlPlaneImage_To_kubeadm_UseHyperKubeImage(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration) error {
|
||||
if len(in.UnifiedControlPlaneImage) == 0 {
|
||||
out.UseHyperKubeImage = false
|
||||
return nil
|
||||
}
|
||||
|
||||
k8sImageTag := kubeadmutil.KubernetesVersionToImageTag(in.KubernetesVersion)
|
||||
expectedImage := images.GetGenericImage(in.ImageRepository, constants.HyperKube, k8sImageTag)
|
||||
if expectedImage == in.UnifiedControlPlaneImage {
|
||||
out.UseHyperKubeImage = true
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.Errorf("cannot convert unifiedControlPlaneImage=%q to useHyperKubeImage", in.UnifiedControlPlaneImage)
|
||||
}
|
||||
|
||||
func Convert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(in *kubeadm.ClusterConfiguration, out *ClusterConfiguration, s conversion.Scope) error {
|
||||
if err := autoConvert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.APIServerExtraArgs = in.APIServer.ExtraArgs
|
||||
out.APIServerCertSANs = in.APIServer.CertSANs
|
||||
if err := convertSlice_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(&in.APIServer.ExtraVolumes, &out.APIServerExtraVolumes, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.ControllerManagerExtraArgs = in.ControllerManager.ExtraArgs
|
||||
if err := convertSlice_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(&in.ControllerManager.ExtraVolumes, &out.ControllerManagerExtraVolumes, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.SchedulerExtraArgs = in.Scheduler.ExtraArgs
|
||||
if err := convertSlice_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(&in.Scheduler.ExtraVolumes, &out.SchedulerExtraVolumes, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if in.UseHyperKubeImage {
|
||||
out.UnifiedControlPlaneImage = images.GetKubernetesImage("", in)
|
||||
} else {
|
||||
out.UnifiedControlPlaneImage = ""
|
||||
}
|
||||
|
||||
// converting internal DNS.Type to v1alpha3 featureGate CoreDNS (this is only for getting roundtrip passing, but it is never used in reality)
|
||||
if out.FeatureGates == nil {
|
||||
out.FeatureGates = map[string]bool{}
|
||||
}
|
||||
if in.DNS.Type == kubeadm.KubeDNS {
|
||||
out.FeatureGates[features.CoreDNS] = false
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
|
||||
if err := autoConvert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.ReadOnly = !in.Writable
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
|
||||
if err := autoConvert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.Writable = !in.ReadOnly
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertSlice_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(in *[]HostPathMount, out *[]kubeadm.HostPathMount, s conversion.Scope) error {
|
||||
if *in != nil {
|
||||
*out = make([]kubeadm.HostPathMount, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*out = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertSlice_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(in *[]kubeadm.HostPathMount, out *[]HostPathMount, s conversion.Scope) error {
|
||||
if *in != nil {
|
||||
*out = make([]HostPathMount, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*out = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error {
|
||||
if err := autoConvert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var err error
|
||||
out.ImageMeta, err = etcdImageToImageMeta(in.Image)
|
||||
return err
|
||||
}
|
||||
|
||||
func etcdImageToImageMeta(image string) (kubeadm.ImageMeta, error) {
|
||||
// empty image -> empty image meta
|
||||
if image == "" {
|
||||
return kubeadm.ImageMeta{}, nil
|
||||
}
|
||||
|
||||
matches := imageRegEx.FindStringSubmatch(image)
|
||||
if len(matches) != 4 {
|
||||
return kubeadm.ImageMeta{}, errors.New("Conversion Error: kubeadm does not support converting v1alpha3 configurations with etcd image without explicit repository or tag definition. Please fix the image name")
|
||||
}
|
||||
|
||||
imageRepository := strings.TrimSuffix(matches[1], "/")
|
||||
imageName := matches[2]
|
||||
imageTag := strings.TrimPrefix(matches[3], ":")
|
||||
|
||||
if imageName != constants.Etcd {
|
||||
return kubeadm.ImageMeta{}, errors.New("Conversion Error: kubeadm does not support converting v1alpha3 configurations with etcd imageName different than etcd. Please fix the image name")
|
||||
}
|
||||
|
||||
return kubeadm.ImageMeta{
|
||||
ImageRepository: imageRepository,
|
||||
ImageTag: imageTag,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func Convert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error {
|
||||
if err := autoConvert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// converting internal LocalEtcd.ImageMeta to v1alpha3 LocalEtcd.Image (this is only for getting roundtrip passing, but it is
|
||||
// never used in reality)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,218 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestJoinConfigurationConversion(t *testing.T) {
|
||||
testcases := map[string]struct {
|
||||
old *JoinConfiguration
|
||||
expectedError bool
|
||||
}{
|
||||
"conversion succeeds": {
|
||||
old: &JoinConfiguration{},
|
||||
expectedError: false,
|
||||
},
|
||||
"cluster name fails to be converted": {
|
||||
old: &JoinConfiguration{
|
||||
ClusterName: "kubernetes",
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
"feature gates fails to be converted": {
|
||||
old: &JoinConfiguration{
|
||||
FeatureGates: map[string]bool{
|
||||
"someGate": true,
|
||||
},
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
}
|
||||
for name, tc := range testcases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
internal := &kubeadm.JoinConfiguration{}
|
||||
err := Convert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(tc.old, internal, nil)
|
||||
if (err != nil) != tc.expectedError {
|
||||
t.Errorf("ImageToImageMeta returned unexpected error: %v, saw: %v", tc.expectedError, (err != nil))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitConfigurationConversion(t *testing.T) {
|
||||
testcases := map[string]struct {
|
||||
old *InitConfiguration
|
||||
expectedErr bool
|
||||
}{
|
||||
"conversion succeeds": {
|
||||
old: &InitConfiguration{},
|
||||
expectedErr: false,
|
||||
},
|
||||
"feature gates fails to be converted": {
|
||||
old: &InitConfiguration{
|
||||
ClusterConfiguration: ClusterConfiguration{
|
||||
AuditPolicyConfiguration: AuditPolicyConfiguration{
|
||||
Path: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: true,
|
||||
},
|
||||
}
|
||||
for name, tc := range testcases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
internal := &kubeadm.InitConfiguration{}
|
||||
err := Convert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(tc.old, internal, nil)
|
||||
if (err != nil) != tc.expectedErr {
|
||||
t.Errorf("no error was expected but '%s' was found", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertToUseHyperKubeImage(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
in *ClusterConfiguration
|
||||
useHyperKubeImage bool
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
desc: "unset UnifiedControlPlaneImage sets UseHyperKubeImage to false",
|
||||
in: &ClusterConfiguration{},
|
||||
useHyperKubeImage: false,
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
desc: "matching UnifiedControlPlaneImage sets UseHyperKubeImage to true",
|
||||
in: &ClusterConfiguration{
|
||||
ImageRepository: "k8s.gcr.io",
|
||||
KubernetesVersion: "v1.12.2",
|
||||
UnifiedControlPlaneImage: "k8s.gcr.io/hyperkube:v1.12.2",
|
||||
},
|
||||
useHyperKubeImage: true,
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
desc: "mismatching UnifiedControlPlaneImage tag causes an error",
|
||||
in: &ClusterConfiguration{
|
||||
ImageRepository: "k8s.gcr.io",
|
||||
KubernetesVersion: "v1.12.0",
|
||||
UnifiedControlPlaneImage: "k8s.gcr.io/hyperkube:v1.12.2",
|
||||
},
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
desc: "mismatching UnifiedControlPlaneImage repo causes an error",
|
||||
in: &ClusterConfiguration{
|
||||
ImageRepository: "my.repo",
|
||||
KubernetesVersion: "v1.12.2",
|
||||
UnifiedControlPlaneImage: "k8s.gcr.io/hyperkube:v1.12.2",
|
||||
},
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
desc: "mismatching UnifiedControlPlaneImage image name causes an error",
|
||||
in: &ClusterConfiguration{
|
||||
ImageRepository: "k8s.gcr.io",
|
||||
KubernetesVersion: "v1.12.2",
|
||||
UnifiedControlPlaneImage: "k8s.gcr.io/otherimage:v1.12.2",
|
||||
},
|
||||
expectedErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
out := &kubeadm.ClusterConfiguration{}
|
||||
err := Convert_v1alpha3_UnifiedControlPlaneImage_To_kubeadm_UseHyperKubeImage(test.in, out)
|
||||
if test.expectedErr {
|
||||
if err == nil {
|
||||
t.Fatalf("unexpected success, UseHyperKubeImage: %t", out.UseHyperKubeImage)
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected failure: %v", err)
|
||||
}
|
||||
if out.UseHyperKubeImage != test.useHyperKubeImage {
|
||||
t.Fatalf("mismatching result from conversion:\n\tExpected: %t\n\tReceived: %t", test.useHyperKubeImage, out.UseHyperKubeImage)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEtcdImageToImageMeta(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
image string
|
||||
expectedImageMeta kubeadm.ImageMeta
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "Empty image -> Empty image meta",
|
||||
image: "",
|
||||
expectedImageMeta: kubeadm.ImageMeta{
|
||||
ImageRepository: "",
|
||||
ImageTag: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "image with tag and repository",
|
||||
image: "custom.repo/etcd:custom.tag",
|
||||
expectedImageMeta: kubeadm.ImageMeta{
|
||||
ImageRepository: "custom.repo",
|
||||
ImageTag: "custom.tag",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "image with custom imageName",
|
||||
image: "real.repo/custom-image-name-for-etcd:real.tag",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "image without repository",
|
||||
image: "etcd:real.tag",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "image without tag",
|
||||
image: "real.repo/etcd",
|
||||
expectedError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ret, err := etcdImageToImageMeta(test.image)
|
||||
|
||||
if (err != nil) != test.expectedError {
|
||||
t.Errorf("etcdImageToImageMeta returned unexpected error: %v, saw: %v", test.expectedError, (err != nil))
|
||||
return
|
||||
}
|
||||
|
||||
if ret != test.expectedImageMeta {
|
||||
t.Errorf("etcdImageToImageMeta returned unexpected ImageMeta: %v, saw: %v", test.expectedImageMeta, ret)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,191 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultServiceDNSDomain defines default cluster-internal domain name for Services and Pods
|
||||
DefaultServiceDNSDomain = "cluster.local"
|
||||
// DefaultServicesSubnet defines default service subnet range
|
||||
DefaultServicesSubnet = "10.96.0.0/12"
|
||||
// DefaultClusterDNSIP defines default DNS IP
|
||||
DefaultClusterDNSIP = "10.96.0.10"
|
||||
// DefaultKubernetesVersion defines default kubernetes version
|
||||
DefaultKubernetesVersion = "stable-1"
|
||||
// DefaultAPIBindPort defines default API port
|
||||
DefaultAPIBindPort = 6443
|
||||
// DefaultCertificatesDir defines default certificate directory
|
||||
DefaultCertificatesDir = "/etc/kubernetes/pki"
|
||||
// DefaultImageRepository defines default image registry
|
||||
DefaultImageRepository = "k8s.gcr.io"
|
||||
// DefaultManifestsDir defines default manifests directory
|
||||
DefaultManifestsDir = "/etc/kubernetes/manifests"
|
||||
// DefaultClusterName defines the default cluster name
|
||||
DefaultClusterName = "kubernetes"
|
||||
|
||||
// DefaultEtcdDataDir defines default location of etcd where static pods will save data to
|
||||
DefaultEtcdDataDir = "/var/lib/etcd"
|
||||
// DefaultProxyBindAddressv4 is the default bind address when the advertise address is v4
|
||||
DefaultProxyBindAddressv4 = "0.0.0.0"
|
||||
// DefaultProxyBindAddressv6 is the default bind address when the advertise address is v6
|
||||
DefaultProxyBindAddressv6 = "::"
|
||||
// DefaultDiscoveryTimeout specifies the default discovery timeout for kubeadm (used unless one is specified in the JoinConfiguration)
|
||||
DefaultDiscoveryTimeout = 5 * time.Minute
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultAuditPolicyLogMaxAge is defined as a var so its address can be taken
|
||||
// It is the number of days to store audit logs
|
||||
DefaultAuditPolicyLogMaxAge = int32(2)
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
return RegisterDefaults(scheme)
|
||||
}
|
||||
|
||||
// SetDefaults_InitConfiguration assigns default values for the InitConfiguration
|
||||
func SetDefaults_InitConfiguration(obj *InitConfiguration) {
|
||||
SetDefaults_ClusterConfiguration(&obj.ClusterConfiguration)
|
||||
SetDefaults_BootstrapTokens(obj)
|
||||
SetDefaults_APIEndpoint(&obj.APIEndpoint)
|
||||
}
|
||||
|
||||
// SetDefaults_ClusterConfiguration assigns default values for the ClusterConfiguration
|
||||
func SetDefaults_ClusterConfiguration(obj *ClusterConfiguration) {
|
||||
if obj.KubernetesVersion == "" {
|
||||
obj.KubernetesVersion = DefaultKubernetesVersion
|
||||
}
|
||||
|
||||
if obj.Networking.ServiceSubnet == "" {
|
||||
obj.Networking.ServiceSubnet = DefaultServicesSubnet
|
||||
}
|
||||
|
||||
if obj.Networking.DNSDomain == "" {
|
||||
obj.Networking.DNSDomain = DefaultServiceDNSDomain
|
||||
}
|
||||
|
||||
if obj.CertificatesDir == "" {
|
||||
obj.CertificatesDir = DefaultCertificatesDir
|
||||
}
|
||||
|
||||
if obj.ImageRepository == "" {
|
||||
obj.ImageRepository = DefaultImageRepository
|
||||
}
|
||||
|
||||
if obj.ClusterName == "" {
|
||||
obj.ClusterName = DefaultClusterName
|
||||
}
|
||||
|
||||
SetDefaults_Etcd(obj)
|
||||
SetDefaults_AuditPolicyConfiguration(obj)
|
||||
}
|
||||
|
||||
// SetDefaults_Etcd assigns default values for the Proxy
|
||||
func SetDefaults_Etcd(obj *ClusterConfiguration) {
|
||||
if obj.Etcd.External == nil && obj.Etcd.Local == nil {
|
||||
obj.Etcd.Local = &LocalEtcd{}
|
||||
}
|
||||
if obj.Etcd.Local != nil {
|
||||
if obj.Etcd.Local.DataDir == "" {
|
||||
obj.Etcd.Local.DataDir = DefaultEtcdDataDir
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_JoinConfiguration assigns default values to a regular node
|
||||
func SetDefaults_JoinConfiguration(obj *JoinConfiguration) {
|
||||
if obj.CACertPath == "" {
|
||||
obj.CACertPath = DefaultCACertPath
|
||||
}
|
||||
if len(obj.TLSBootstrapToken) == 0 {
|
||||
obj.TLSBootstrapToken = obj.Token
|
||||
}
|
||||
if len(obj.DiscoveryToken) == 0 && len(obj.DiscoveryFile) == 0 {
|
||||
obj.DiscoveryToken = obj.Token
|
||||
}
|
||||
// Make sure file URLs become paths
|
||||
if len(obj.DiscoveryFile) != 0 {
|
||||
u, err := url.Parse(obj.DiscoveryFile)
|
||||
if err == nil && u.Scheme == "file" {
|
||||
obj.DiscoveryFile = u.Path
|
||||
}
|
||||
}
|
||||
if obj.DiscoveryTimeout == nil {
|
||||
obj.DiscoveryTimeout = &metav1.Duration{
|
||||
Duration: DefaultDiscoveryTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
SetDefaults_APIEndpoint(&obj.APIEndpoint)
|
||||
}
|
||||
|
||||
// SetDefaults_AuditPolicyConfiguration sets default values for the AuditPolicyConfiguration
|
||||
func SetDefaults_AuditPolicyConfiguration(obj *ClusterConfiguration) {
|
||||
if obj.AuditPolicyConfiguration.LogDir == "" {
|
||||
obj.AuditPolicyConfiguration.LogDir = constants.StaticPodAuditPolicyLogDir
|
||||
}
|
||||
if obj.AuditPolicyConfiguration.LogMaxAge == nil {
|
||||
obj.AuditPolicyConfiguration.LogMaxAge = &DefaultAuditPolicyLogMaxAge
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_BootstrapTokens sets the defaults for the .BootstrapTokens field
|
||||
// If the slice is empty, it's defaulted with one token. Otherwise it just loops
|
||||
// through the slice and sets the defaults for the omitempty fields that are TTL,
|
||||
// Usages and Groups. Token is NOT defaulted with a random one in the API defaulting
|
||||
// layer, but set to a random value later at runtime if not set before.
|
||||
func SetDefaults_BootstrapTokens(obj *InitConfiguration) {
|
||||
|
||||
if obj.BootstrapTokens == nil || len(obj.BootstrapTokens) == 0 {
|
||||
obj.BootstrapTokens = []BootstrapToken{{}}
|
||||
}
|
||||
|
||||
for i := range obj.BootstrapTokens {
|
||||
SetDefaults_BootstrapToken(&obj.BootstrapTokens[i])
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_BootstrapToken sets the defaults for an individual Bootstrap Token
|
||||
func SetDefaults_BootstrapToken(bt *BootstrapToken) {
|
||||
if bt.TTL == nil {
|
||||
bt.TTL = &metav1.Duration{
|
||||
Duration: constants.DefaultTokenDuration,
|
||||
}
|
||||
}
|
||||
if len(bt.Usages) == 0 {
|
||||
bt.Usages = constants.DefaultTokenUsages
|
||||
}
|
||||
|
||||
if len(bt.Groups) == 0 {
|
||||
bt.Groups = constants.DefaultTokenGroups
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_APIEndpoint sets the defaults for the API server instance deployed on a node.
|
||||
func SetDefaults_APIEndpoint(obj *APIEndpoint) {
|
||||
if obj.BindPort == 0 {
|
||||
obj.BindPort = DefaultAPIBindPort
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha3
|
||||
|
||||
const (
|
||||
// DefaultCACertPath defines default location of CA certificate on Linux
|
||||
DefaultCACertPath = "/etc/kubernetes/pki/ca.crt"
|
||||
)
|
|
@ -1,24 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha3
|
||||
|
||||
const (
|
||||
// DefaultCACertPath defines default location of CA certificate on Windows
|
||||
DefaultCACertPath = "C:/etc/kubernetes/pki/ca.crt"
|
||||
)
|
|
@ -1,273 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=kubeadm.k8s.io
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm
|
||||
|
||||
// Package v1alpha3 defines the v1alpha3 version of the kubeadm config file format, that is a big step
|
||||
// forward the objective of graduate kubeadm config to beta.
|
||||
//
|
||||
// One of the biggest changes introduced by this release is the re-design of how component config
|
||||
// can be provided to kubeadm; this will enable a improved stability of the kubeadm config while the efforts for
|
||||
// the implementation of component config across Kubernetes ecosystem continues.
|
||||
//
|
||||
// Another important change is the separation between cluster wide setting and runtime or node specific
|
||||
// settings, that is functional to the objective to introduce support for HA clusters in kubeadm.
|
||||
//
|
||||
// Migration from old kubeadm config versions
|
||||
//
|
||||
// Please convert your v1alpha2 configuration files to v1alpha3 using the kubeadm config migrate command of kubeadm v1.12.x
|
||||
// (conversion from older releases of kubeadm config files requires older release of kubeadm as well e.g.
|
||||
// kubeadm v1.11 should be used to migrate v1alpha1 to v1alpha2).
|
||||
//
|
||||
// Nevertheless, kubeadm v1.12.x will support reading from v1alpha2 version of the kubeadm config file format, but this support
|
||||
// will be dropped in the v1.13 release.
|
||||
//
|
||||
// Basics
|
||||
//
|
||||
// The preferred way to configure kubeadm is to pass an YAML configuration file with the --config option. Some of the
|
||||
// configuration options defined in the kubeadm config file are also available as command line flags, but only
|
||||
// the most common/simple use case are supported with this approach.
|
||||
//
|
||||
// A kubeadm config file could contain multiple configuration types separated using three dashes (“---”).
|
||||
//
|
||||
// The kubeadm config print-defaults command print the default values for all the kubeadm supported configuration types.
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
// kind: InitConfiguration
|
||||
// ...
|
||||
// ---
|
||||
// apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
// kind: ClusterConfiguration
|
||||
// ...
|
||||
// ---
|
||||
// apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
// kind: KubeletConfiguration
|
||||
// ...
|
||||
// ---
|
||||
// apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||
// kind: KubeProxyConfiguration
|
||||
// ...
|
||||
// ---
|
||||
// apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
// kind: JoinConfiguration
|
||||
// ...
|
||||
//
|
||||
// The list of configuration types that must be included in a configuration file depends by the action you are
|
||||
// performing (init or join) and by the configuration options you are going to use (defaults or advanced customization).
|
||||
//
|
||||
// If some configuration types are not provided, or provided only partially, kubeadm will use default values; defaults
|
||||
// provided by kubeadm includes also enforcing consistency of values across components when required (e.g.
|
||||
// cluster-cidr flag on controller manager and clusterCIDR on kube-proxy).
|
||||
//
|
||||
// Users are always allowed to override default values, with the only exception of a small subset of setting with
|
||||
// relevance for security (e.g. enforce authorization-mode Node and RBAC on api server)
|
||||
//
|
||||
// Starting from v1.12.1, if the user provides a configuration types that is not expected for the action you are performing,
|
||||
// kubeadm will ignore those types and print a warning.
|
||||
//
|
||||
// Kubeadm init configuration types
|
||||
//
|
||||
// When executing kubeadm init with the --config option, the following configuration types could be used:
|
||||
// InitConfiguration, ClusterConfiguration, KubeProxyConfiguration, KubeletConfiguration, but only one
|
||||
// between InitConfiguration and ClusterConfiguration is mandatory.
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
// kind: InitConfiguration
|
||||
// bootstrapTokens:
|
||||
// ...
|
||||
// nodeRegistration:
|
||||
// ...
|
||||
// apiEndpoint:
|
||||
// ...
|
||||
//
|
||||
// InitConfiguration (and as well ClusterConfiguration afterwards) are originated from the MasterConfiguration type
|
||||
// in the v1alpha2 kubeadm config version.
|
||||
//
|
||||
// - The InitConfiguration type should be used to configure runtime settings, that in case of kubeadm init
|
||||
// are the configuration of the bootstrap token and all the setting which are specific to the node where kubeadm
|
||||
// is executed, including:
|
||||
//
|
||||
// - NodeRegistration, that holds fields that relate to registering the new node to the cluster;
|
||||
// use it to customize the node name, the CRI socket to use or any other settings that should apply to this
|
||||
// node only (e.g. the node ip).
|
||||
//
|
||||
// - APIEndpoint, that represents the endpoint of the instance of the API server to be deployed on this node;
|
||||
// use it e.g. to customize the API server advertise address.
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
// kind: ClusterConfiguration
|
||||
// networking:
|
||||
// ...
|
||||
// etcd:
|
||||
// ...
|
||||
// apiServerExtraArgs:
|
||||
// ...
|
||||
// APIServerExtraVolumes:
|
||||
// ...
|
||||
// ...
|
||||
//
|
||||
// The ClusterConfiguration type should be used to configure cluster-wide settings,
|
||||
// including settings for:
|
||||
//
|
||||
// - Networking, that holds configuration for the networking topology of the cluster; use it e.g. to customize
|
||||
// node subnet or services subnet.
|
||||
//
|
||||
// - Etcd configurations; use it e.g. to customize the local etcd or to configure the API server
|
||||
// for using an external etcd cluster.
|
||||
//
|
||||
// - kube-apiserver, kube-scheduler, kube-controller-manager configurations; use it to customize control-plane
|
||||
// components by adding customized setting or overriding kubeadm default settings.
|
||||
//
|
||||
// apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||
// kind: KubeProxyConfiguration
|
||||
// ...
|
||||
//
|
||||
// The KubeProxyConfiguration type should be used to change the configuration passed to kube-proxy instances deployed
|
||||
// in the cluster. If this object is not provided or provided only partially, kubeadm applies defaults.
|
||||
//
|
||||
// See https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/ or https://godoc.org/k8s.io/kube-proxy/config/v1alpha1#KubeProxyConfiguration
|
||||
// for kube proxy official documentation.
|
||||
//
|
||||
// apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
// kind: KubeletConfiguration
|
||||
// ...
|
||||
//
|
||||
// The KubeletConfiguration type should be used to change the configurations that will be passed to all kubelet instances
|
||||
// deployed in the cluster. If this object is not provided or provided only partially, kubeadm applies defaults.
|
||||
//
|
||||
// See https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/ or https://godoc.org/k8s.io/kubelet/config/v1beta1#KubeletConfiguration
|
||||
// for kube proxy official documentation.
|
||||
//
|
||||
// Here is a fully populated example of a single YAML file containing multiple
|
||||
// configuration types to be used during a `kubeadm init` run.
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
// kind: InitConfiguration
|
||||
// bootstrapTokens:
|
||||
// - token: "9a08jv.c0izixklcxtmnze7"
|
||||
// description: "kubeadm bootstrap token"
|
||||
// ttl: "24h"
|
||||
// - token: "783bde.3f89s0fje9f38fhf"
|
||||
// description: "another bootstrap token"
|
||||
// usages:
|
||||
// - signing
|
||||
// groups:
|
||||
// - system:anonymous
|
||||
// nodeRegistration:
|
||||
// name: "ec2-10-100-0-1"
|
||||
// criSocket: "/var/run/dockershim.sock"
|
||||
// taints:
|
||||
// - key: "kubeadmNode"
|
||||
// value: "master"
|
||||
// effect: "NoSchedule"
|
||||
// kubeletExtraArgs:
|
||||
// cgroup-driver: "cgroupfs"
|
||||
// apiEndpoint:
|
||||
// advertiseAddress: "10.100.0.1"
|
||||
// bindPort: 6443
|
||||
// ---
|
||||
// apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
// kind: ClusterConfiguration
|
||||
// etcd:
|
||||
// # one of local or external
|
||||
// local:
|
||||
// image: "k8s.gcr.io/etcd-amd64:3.2.18"
|
||||
// dataDir: "/var/lib/etcd"
|
||||
// extraArgs:
|
||||
// listen-client-urls: "http://10.100.0.1:2379"
|
||||
// serverCertSANs:
|
||||
// - "ec2-10-100-0-1.compute-1.amazonaws.com"
|
||||
// peerCertSANs:
|
||||
// - "10.100.0.1"
|
||||
// external:
|
||||
// endpoints:
|
||||
// - "10.100.0.1:2379"
|
||||
// - "10.100.0.2:2379"
|
||||
// caFile: "/etcd/kubernetes/pki/etcd/etcd-ca.crt"
|
||||
// certFile: "/etcd/kubernetes/pki/etcd/etcd.crt"
|
||||
// certKey: "/etcd/kubernetes/pki/etcd/etcd.key"
|
||||
// networking:
|
||||
// serviceSubnet: "10.96.0.0/12"
|
||||
// podSubnet: "10.100.0.1/24"
|
||||
// dnsDomain: "cluster.local"
|
||||
// kubernetesVersion: "v1.12.0"
|
||||
// controlPlaneEndpoint: "10.100.0.1:6443"
|
||||
// apiServerExtraArgs:
|
||||
// authorization-mode: "Node,RBAC"
|
||||
// controllerManagerExtraArgs:
|
||||
// node-cidr-mask-size: 20
|
||||
// schedulerExtraArgs:
|
||||
// address: "10.100.0.1"
|
||||
// apiServerExtraVolumes:
|
||||
// - name: "some-volume"
|
||||
// hostPath: "/etc/some-path"
|
||||
// mountPath: "/etc/some-pod-path"
|
||||
// writable: true
|
||||
// pathType: File
|
||||
// controllerManagerExtraVolumes:
|
||||
// - name: "some-volume"
|
||||
// hostPath: "/etc/some-path"
|
||||
// mountPath: "/etc/some-pod-path"
|
||||
// writable: true
|
||||
// pathType: File
|
||||
// schedulerExtraVolumes:
|
||||
// - name: "some-volume"
|
||||
// hostPath: "/etc/some-path"
|
||||
// mountPath: "/etc/some-pod-path"
|
||||
// writable: true
|
||||
// pathType: File
|
||||
// apiServerCertSANs:
|
||||
// - "10.100.1.1"
|
||||
// - "ec2-10-100-0-1.compute-1.amazonaws.com"
|
||||
// certificatesDir: "/etc/kubernetes/pki"
|
||||
// imageRepository: "k8s.gcr.io"
|
||||
// unifiedControlPlaneImage: "k8s.gcr.io/controlplane:v1.12.0"
|
||||
// auditPolicy:
|
||||
// # https://kubernetes.io/docs/tasks/debug-application-cluster/audit/#audit-policy
|
||||
// path: "/var/log/audit/audit.json"
|
||||
// logDir: "/var/log/audit"
|
||||
// logMaxAge: 7 # in days
|
||||
// featureGates:
|
||||
// selfhosting: false
|
||||
// clusterName: "example-cluster"
|
||||
//
|
||||
// Kubeadm join configuration types
|
||||
//
|
||||
// When executing kubeadm join with the --config option, the JoinConfiguration type should be provided.
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
// kind: JoinConfiguration
|
||||
// ...
|
||||
//
|
||||
// JoinConfiguration is originated from NodeConfiguration type in the v1alpha2 kubeadm config version.
|
||||
//
|
||||
// The JoinConfiguration type should be used to configure runtime settings, that in case of kubeadm join
|
||||
// are the discovery method used for accessing the cluster info and all the setting which are specific
|
||||
// to the node where kubeadm is executed, including:
|
||||
//
|
||||
// - NodeRegistration, that holds fields that relate to registering the new node to the cluster;
|
||||
// use it to customize the node name, the CRI socket to use or any other settings that should apply to this
|
||||
// node only (e.g. the node ip).
|
||||
//
|
||||
// - APIEndpoint, that represents the endpoint of the instance of the API server to be eventually deployed on this node.
|
||||
//
|
||||
package v1alpha3 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
|
||||
|
||||
//TODO: The BootstrapTokenString object should move out to either k8s.io/client-go or k8s.io/api in the future
|
||||
//(probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now.
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "kubeadm.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha3"}
|
||||
|
||||
var (
|
||||
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
|
||||
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
|
||||
|
||||
// SchemeBuilder points to a list of functions added to Scheme.
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
// AddToScheme applies all the stored functions to the scheme.
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func init() {
|
||||
// We only register manually written functions here. The registration of the
|
||||
// generated functions takes place in the generated files. The separation
|
||||
// makes the code compile even when the generated files are missing.
|
||||
localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&InitConfiguration{},
|
||||
&ClusterConfiguration{},
|
||||
&ClusterStatus{},
|
||||
&JoinConfiguration{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
|
@ -1,333 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// InitConfiguration contains a list of elements that is specific "kubeadm init"-only runtime
|
||||
// information.
|
||||
type InitConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// ClusterConfiguration holds the cluster-wide information, and embeds that struct (which can be (un)marshalled separately as well)
|
||||
// When InitConfiguration is marshalled to bytes in the external version, this information IS NOT preserved (which can be seen from
|
||||
// the `json:"-"` tag. This is due to that when InitConfiguration is (un)marshalled, it turns into two YAML documents, one for the
|
||||
// InitConfiguration and ClusterConfiguration. Hence, the information must not be duplicated, and is therefore omitted here.
|
||||
ClusterConfiguration `json:"-"`
|
||||
|
||||
// `kubeadm init`-only information. These fields are solely used the first time `kubeadm init` runs.
|
||||
// After that, the information in the fields ARE NOT uploaded to the `kubeadm-config` ConfigMap
|
||||
// that is used by `kubeadm upgrade` for instance. These fields must be omitempty.
|
||||
|
||||
// BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create.
|
||||
// This information IS NOT uploaded to the kubeadm cluster configmap, partly because of its sensitive nature
|
||||
BootstrapTokens []BootstrapToken `json:"bootstrapTokens,omitempty"`
|
||||
|
||||
// NodeRegistration holds fields that relate to registering the new control-plane node to the cluster
|
||||
NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty"`
|
||||
|
||||
// APIEndpoint represents the endpoint of the instance of the API server to be deployed on this node.
|
||||
APIEndpoint APIEndpoint `json:"apiEndpoint,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// ClusterConfiguration contains cluster-wide configuration for a kubeadm cluster
|
||||
type ClusterConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// Etcd holds configuration for etcd.
|
||||
Etcd Etcd `json:"etcd"`
|
||||
|
||||
// Networking holds configuration for the networking topology of the cluster.
|
||||
Networking Networking `json:"networking"`
|
||||
|
||||
// KubernetesVersion is the target version of the control plane.
|
||||
KubernetesVersion string `json:"kubernetesVersion"`
|
||||
|
||||
// ControlPlaneEndpoint sets a stable IP address or DNS name for the control plane; it
|
||||
// can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port.
|
||||
// In case the ControlPlaneEndpoint is not specified, the AdvertiseAddress + BindPort
|
||||
// are used; in case the ControlPlaneEndpoint is specified but without a TCP port,
|
||||
// the BindPort is used.
|
||||
// Possible usages are:
|
||||
// e.g. In a cluster with more than one control plane instances, this field should be
|
||||
// assigned the address of the external load balancer in front of the
|
||||
// control plane instances.
|
||||
// e.g. in environments with enforced node recycling, the ControlPlaneEndpoint
|
||||
// could be used for assigning a stable DNS to the control plane.
|
||||
ControlPlaneEndpoint string `json:"controlPlaneEndpoint"`
|
||||
|
||||
// APIServerExtraArgs is a set of extra flags to pass to the API Server or override
|
||||
// default ones in form of <flagname>=<value>.
|
||||
// TODO: This is temporary and ideally we would like to switch all components to
|
||||
// use ComponentConfig + ConfigMaps.
|
||||
APIServerExtraArgs map[string]string `json:"apiServerExtraArgs,omitempty"`
|
||||
// ControllerManagerExtraArgs is a set of extra flags to pass to the Controller Manager
|
||||
// or override default ones in form of <flagname>=<value>
|
||||
// TODO: This is temporary and ideally we would like to switch all components to
|
||||
// use ComponentConfig + ConfigMaps.
|
||||
ControllerManagerExtraArgs map[string]string `json:"controllerManagerExtraArgs,omitempty"`
|
||||
// SchedulerExtraArgs is a set of extra flags to pass to the Scheduler or override
|
||||
// default ones in form of <flagname>=<value>
|
||||
// TODO: This is temporary and ideally we would like to switch all components to
|
||||
// use ComponentConfig + ConfigMaps.
|
||||
SchedulerExtraArgs map[string]string `json:"schedulerExtraArgs,omitempty"`
|
||||
|
||||
// APIServerExtraVolumes is an extra set of host volumes mounted to the API server.
|
||||
APIServerExtraVolumes []HostPathMount `json:"apiServerExtraVolumes,omitempty"`
|
||||
// ControllerManagerExtraVolumes is an extra set of host volumes mounted to the
|
||||
// Controller Manager.
|
||||
ControllerManagerExtraVolumes []HostPathMount `json:"controllerManagerExtraVolumes,omitempty"`
|
||||
// SchedulerExtraVolumes is an extra set of host volumes mounted to the scheduler.
|
||||
SchedulerExtraVolumes []HostPathMount `json:"schedulerExtraVolumes,omitempty"`
|
||||
|
||||
// APIServerCertSANs sets extra Subject Alternative Names for the API Server signing cert.
|
||||
APIServerCertSANs []string `json:"apiServerCertSANs,omitempty"`
|
||||
// CertificatesDir specifies where to store or look for all required certificates.
|
||||
CertificatesDir string `json:"certificatesDir"`
|
||||
|
||||
// ImageRepository what container registry to pull control plane images from
|
||||
ImageRepository string `json:"imageRepository"`
|
||||
// UnifiedControlPlaneImage specifies if a specific container image should
|
||||
// be used for all control plane components.
|
||||
UnifiedControlPlaneImage string `json:"unifiedControlPlaneImage"`
|
||||
|
||||
// AuditPolicyConfiguration defines the options for the api server audit system
|
||||
AuditPolicyConfiguration AuditPolicyConfiguration `json:"auditPolicy"`
|
||||
|
||||
// FeatureGates enabled by the user.
|
||||
FeatureGates map[string]bool `json:"featureGates,omitempty"`
|
||||
|
||||
// The cluster name
|
||||
ClusterName string `json:"clusterName,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// ClusterStatus contains the cluster status. The ClusterStatus will be stored in the kubeadm-config
|
||||
// ConfigMap in the cluster, and then updated by kubeadm when additional control plane instance joins or leaves the cluster.
|
||||
type ClusterStatus struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// APIEndpoints currently available in the cluster, one for each control plane/api server instance.
|
||||
// The key of the map is the IP of the host's default interface
|
||||
APIEndpoints map[string]APIEndpoint `json:"apiEndpoints"`
|
||||
}
|
||||
|
||||
// APIEndpoint struct contains elements of API server instance deployed on a node.
|
||||
type APIEndpoint struct {
|
||||
// AdvertiseAddress sets the IP address for the API server to advertise.
|
||||
AdvertiseAddress string `json:"advertiseAddress"`
|
||||
|
||||
// BindPort sets the secure port for the API Server to bind to.
|
||||
// Defaults to 6443.
|
||||
BindPort int32 `json:"bindPort"`
|
||||
}
|
||||
|
||||
// NodeRegistrationOptions holds fields that relate to registering a new control-plane or node to the cluster, either via "kubeadm init" or "kubeadm join"
|
||||
type NodeRegistrationOptions struct {
|
||||
|
||||
// Name is the `.Metadata.Name` field of the Node API object that will be created in this `kubeadm init` or `kubeadm join` operation.
|
||||
// This field is also used in the CommonName field of the kubelet's client certificate to the API server.
|
||||
// Defaults to the hostname of the node if not provided.
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// CRISocket is used to retrieve container runtime info. This information will be annotated to the Node API object, for later re-use
|
||||
CRISocket string `json:"criSocket,omitempty"`
|
||||
|
||||
// Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the `kubeadm init` process
|
||||
// it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your control-plane node, set this field to an
|
||||
// empty slice, i.e. `taints: {}` in the YAML file. This field is solely used for Node registration.
|
||||
Taints []v1.Taint `json:"taints,omitempty"`
|
||||
|
||||
// KubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file
|
||||
// kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap
|
||||
// Flags have higher priority when parsing. These values are local and specific to the node kubeadm is executing on.
|
||||
KubeletExtraArgs map[string]string `json:"kubeletExtraArgs,omitempty"`
|
||||
}
|
||||
|
||||
// Networking contains elements describing cluster's networking configuration
|
||||
type Networking struct {
|
||||
// ServiceSubnet is the subnet used by k8s services. Defaults to "10.96.0.0/12".
|
||||
ServiceSubnet string `json:"serviceSubnet"`
|
||||
// PodSubnet is the subnet used by pods.
|
||||
PodSubnet string `json:"podSubnet"`
|
||||
// DNSDomain is the dns domain used by k8s services. Defaults to "cluster.local".
|
||||
DNSDomain string `json:"dnsDomain"`
|
||||
}
|
||||
|
||||
// BootstrapToken describes one bootstrap token, stored as a Secret in the cluster
|
||||
type BootstrapToken struct {
|
||||
// Token is used for establishing bidirectional trust between nodes and control-planes.
|
||||
// Used for joining nodes in the cluster.
|
||||
Token *BootstrapTokenString `json:"token"`
|
||||
// Description sets a human-friendly message why this token exists and what it's used
|
||||
// for, so other administrators can know its purpose.
|
||||
Description string `json:"description,omitempty"`
|
||||
// TTL defines the time to live for this token. Defaults to 24h.
|
||||
// Expires and TTL are mutually exclusive.
|
||||
TTL *metav1.Duration `json:"ttl,omitempty"`
|
||||
// Expires specifies the timestamp when this token expires. Defaults to being set
|
||||
// dynamically at runtime based on the TTL. Expires and TTL are mutually exclusive.
|
||||
Expires *metav1.Time `json:"expires,omitempty"`
|
||||
// Usages describes the ways in which this token can be used. Can by default be used
|
||||
// for establishing bidirectional trust, but that can be changed here.
|
||||
Usages []string `json:"usages,omitempty"`
|
||||
// Groups specifies the extra groups that this token will authenticate as when/if
|
||||
// used for authentication
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
}
|
||||
|
||||
// Etcd contains elements describing Etcd configuration.
|
||||
type Etcd struct {
|
||||
|
||||
// Local provides configuration knobs for configuring the local etcd instance
|
||||
// Local and External are mutually exclusive
|
||||
Local *LocalEtcd `json:"local,omitempty"`
|
||||
|
||||
// External describes how to connect to an external etcd cluster
|
||||
// Local and External are mutually exclusive
|
||||
External *ExternalEtcd `json:"external,omitempty"`
|
||||
}
|
||||
|
||||
// LocalEtcd describes that kubeadm should run an etcd cluster locally
|
||||
type LocalEtcd struct {
|
||||
|
||||
// Image specifies which container image to use for running etcd.
|
||||
// If empty, automatically populated by kubeadm using the image
|
||||
// repository and default etcd version.
|
||||
Image string `json:"image"`
|
||||
|
||||
// DataDir is the directory etcd will place its data.
|
||||
// Defaults to "/var/lib/etcd".
|
||||
DataDir string `json:"dataDir"`
|
||||
|
||||
// ExtraArgs are extra arguments provided to the etcd binary
|
||||
// when run inside a static pod.
|
||||
ExtraArgs map[string]string `json:"extraArgs,omitempty"`
|
||||
|
||||
// ServerCertSANs sets extra Subject Alternative Names for the etcd server signing cert.
|
||||
ServerCertSANs []string `json:"serverCertSANs,omitempty"`
|
||||
// PeerCertSANs sets extra Subject Alternative Names for the etcd peer signing cert.
|
||||
PeerCertSANs []string `json:"peerCertSANs,omitempty"`
|
||||
}
|
||||
|
||||
// ExternalEtcd describes an external etcd cluster
|
||||
type ExternalEtcd struct {
|
||||
// Endpoints of etcd members. Required for ExternalEtcd.
|
||||
Endpoints []string `json:"endpoints"`
|
||||
// CAFile is an SSL Certificate Authority file used to secure etcd communication.
|
||||
CAFile string `json:"caFile"`
|
||||
// CertFile is an SSL certification file used to secure etcd communication.
|
||||
CertFile string `json:"certFile"`
|
||||
// KeyFile is an SSL key file used to secure etcd communication.
|
||||
KeyFile string `json:"keyFile"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// JoinConfiguration contains elements describing a particular node.
|
||||
// TODO: This struct should be replaced by dynamic kubelet configuration.
|
||||
type JoinConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// NodeRegistration holds fields that relate to registering the new control-plane node to the cluster
|
||||
NodeRegistration NodeRegistrationOptions `json:"nodeRegistration"`
|
||||
|
||||
// CACertPath is the path to the SSL certificate authority used to
|
||||
// secure comunications between node and control-plane.
|
||||
// Defaults to "/etc/kubernetes/pki/ca.crt".
|
||||
CACertPath string `json:"caCertPath"`
|
||||
// DiscoveryFile is a file or url to a kubeconfig file from which to
|
||||
// load cluster information.
|
||||
DiscoveryFile string `json:"discoveryFile"`
|
||||
// DiscoveryToken is a token used to validate cluster information
|
||||
// fetched from the control-plane.
|
||||
DiscoveryToken string `json:"discoveryToken"`
|
||||
// DiscoveryTokenAPIServers is a set of IPs to API servers from which info
|
||||
// will be fetched. Currently we only pay attention to one API server but
|
||||
// hope to support >1 in the future.
|
||||
DiscoveryTokenAPIServers []string `json:"discoveryTokenAPIServers,omitempty"`
|
||||
// DiscoveryTimeout modifies the discovery timeout
|
||||
DiscoveryTimeout *metav1.Duration `json:"discoveryTimeout,omitempty"`
|
||||
// TLSBootstrapToken is a token used for TLS bootstrapping.
|
||||
// Defaults to Token.
|
||||
TLSBootstrapToken string `json:"tlsBootstrapToken"`
|
||||
// Token is used for both discovery and TLS bootstrapping.
|
||||
Token string `json:"token"`
|
||||
|
||||
// ClusterName is the name for the cluster in kubeconfig.
|
||||
ClusterName string `json:"clusterName,omitempty"`
|
||||
|
||||
// DiscoveryTokenCACertHashes specifies a set of public key pins to verify
|
||||
// when token-based discovery is used. The root CA found during discovery
|
||||
// must match one of these values. Specifying an empty set disables root CA
|
||||
// pinning, which can be unsafe. Each hash is specified as "<type>:<value>",
|
||||
// where the only currently supported type is "sha256". This is a hex-encoded
|
||||
// SHA-256 hash of the Subject Public Key Info (SPKI) object in DER-encoded
|
||||
// ASN.1. These hashes can be calculated using, for example, OpenSSL:
|
||||
// openssl x509 -pubkey -in ca.crt openssl rsa -pubin -outform der 2>&/dev/null | openssl dgst -sha256 -hex
|
||||
DiscoveryTokenCACertHashes []string `json:"discoveryTokenCACertHashes,omitempty"`
|
||||
|
||||
// DiscoveryTokenUnsafeSkipCAVerification allows token-based discovery
|
||||
// without CA verification via DiscoveryTokenCACertHashes. This can weaken
|
||||
// the security of kubeadm since other nodes can impersonate the control-plane.
|
||||
DiscoveryTokenUnsafeSkipCAVerification bool `json:"discoveryTokenUnsafeSkipCAVerification"`
|
||||
|
||||
// ControlPlane flag specifies that the joining node should host an additional
|
||||
// control plane instance.
|
||||
ControlPlane bool `json:"controlPlane,omitempty"`
|
||||
|
||||
// APIEndpoint represents the endpoint of the instance of the API server eventually to be deployed on this node.
|
||||
APIEndpoint APIEndpoint `json:"apiEndpoint,omitempty"`
|
||||
|
||||
// FeatureGates enabled by the user.
|
||||
FeatureGates map[string]bool `json:"featureGates,omitempty"`
|
||||
}
|
||||
|
||||
// HostPathMount contains elements describing volumes that are mounted from the
|
||||
// host.
|
||||
type HostPathMount struct {
|
||||
// Name of the volume inside the pod template.
|
||||
Name string `json:"name"`
|
||||
// HostPath is the path in the host that will be mounted inside
|
||||
// the pod.
|
||||
HostPath string `json:"hostPath"`
|
||||
// MountPath is the path inside the pod where hostPath will be mounted.
|
||||
MountPath string `json:"mountPath"`
|
||||
// Writable controls write access to the volume
|
||||
Writable bool `json:"writable,omitempty"`
|
||||
// PathType is the type of the HostPath.
|
||||
PathType v1.HostPathType `json:"pathType,omitempty"`
|
||||
}
|
||||
|
||||
// AuditPolicyConfiguration holds the options for configuring the api server audit policy.
|
||||
type AuditPolicyConfiguration struct {
|
||||
// Path is the local path to an audit policy.
|
||||
Path string `json:"path"`
|
||||
// LogDir is the local path to the directory where logs should be stored.
|
||||
LogDir string `json:"logDir"`
|
||||
// LogMaxAge is the number of days logs will be stored for. 0 indicates forever.
|
||||
LogMaxAge *int32 `json:"logMaxAge,omitempty"`
|
||||
//TODO(chuckha) add other options for audit policy.
|
||||
}
|
|
@ -1,567 +0,0 @@
|
|||
// +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 v1alpha3
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
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((*APIEndpoint)(nil), (*kubeadm.APIEndpoint)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(a.(*APIEndpoint), b.(*kubeadm.APIEndpoint), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.APIEndpoint)(nil), (*APIEndpoint)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(a.(*kubeadm.APIEndpoint), b.(*APIEndpoint), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*BootstrapToken)(nil), (*kubeadm.BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_BootstrapToken_To_kubeadm_BootstrapToken(a.(*BootstrapToken), b.(*kubeadm.BootstrapToken), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapToken)(nil), (*BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_BootstrapToken_To_v1alpha3_BootstrapToken(a.(*kubeadm.BootstrapToken), b.(*BootstrapToken), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*BootstrapTokenString)(nil), (*kubeadm.BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(a.(*BootstrapTokenString), b.(*kubeadm.BootstrapTokenString), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapTokenString)(nil), (*BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_BootstrapTokenString_To_v1alpha3_BootstrapTokenString(a.(*kubeadm.BootstrapTokenString), b.(*BootstrapTokenString), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ClusterConfiguration)(nil), (*kubeadm.ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(a.(*ClusterConfiguration), b.(*kubeadm.ClusterConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ClusterStatus)(nil), (*kubeadm.ClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_ClusterStatus_To_kubeadm_ClusterStatus(a.(*ClusterStatus), b.(*kubeadm.ClusterStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterStatus)(nil), (*ClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_ClusterStatus_To_v1alpha3_ClusterStatus(a.(*kubeadm.ClusterStatus), b.(*ClusterStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*Etcd)(nil), (*kubeadm.Etcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_Etcd_To_kubeadm_Etcd(a.(*Etcd), b.(*kubeadm.Etcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.Etcd)(nil), (*Etcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_Etcd_To_v1alpha3_Etcd(a.(*kubeadm.Etcd), b.(*Etcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ExternalEtcd)(nil), (*kubeadm.ExternalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_ExternalEtcd_To_kubeadm_ExternalEtcd(a.(*ExternalEtcd), b.(*kubeadm.ExternalEtcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.ExternalEtcd)(nil), (*ExternalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_ExternalEtcd_To_v1alpha3_ExternalEtcd(a.(*kubeadm.ExternalEtcd), b.(*ExternalEtcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*HostPathMount)(nil), (*kubeadm.HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(a.(*HostPathMount), b.(*kubeadm.HostPathMount), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.HostPathMount)(nil), (*HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(a.(*kubeadm.HostPathMount), b.(*HostPathMount), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*InitConfiguration)(nil), (*kubeadm.InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(a.(*InitConfiguration), b.(*kubeadm.InitConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.InitConfiguration)(nil), (*InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_InitConfiguration_To_v1alpha3_InitConfiguration(a.(*kubeadm.InitConfiguration), b.(*InitConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*JoinConfiguration)(nil), (*kubeadm.JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(a.(*JoinConfiguration), b.(*kubeadm.JoinConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.JoinConfiguration)(nil), (*JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_JoinConfiguration_To_v1alpha3_JoinConfiguration(a.(*kubeadm.JoinConfiguration), b.(*JoinConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*LocalEtcd)(nil), (*kubeadm.LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(a.(*LocalEtcd), b.(*kubeadm.LocalEtcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.LocalEtcd)(nil), (*LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(a.(*kubeadm.LocalEtcd), b.(*LocalEtcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*Networking)(nil), (*kubeadm.Networking)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_Networking_To_kubeadm_Networking(a.(*Networking), b.(*kubeadm.Networking), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.Networking)(nil), (*Networking)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_Networking_To_v1alpha3_Networking(a.(*kubeadm.Networking), b.(*Networking), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*NodeRegistrationOptions)(nil), (*kubeadm.NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(a.(*NodeRegistrationOptions), b.(*kubeadm.NodeRegistrationOptions), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(a.(*kubeadm.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*kubeadm.HostPathMount)(nil), (*HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(a.(*kubeadm.HostPathMount), b.(*HostPathMount), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*kubeadm.InitConfiguration)(nil), (*InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_InitConfiguration_To_v1alpha3_InitConfiguration(a.(*kubeadm.InitConfiguration), b.(*InitConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*kubeadm.JoinConfiguration)(nil), (*JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_JoinConfiguration_To_v1alpha3_JoinConfiguration(a.(*kubeadm.JoinConfiguration), b.(*JoinConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*kubeadm.LocalEtcd)(nil), (*LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(a.(*kubeadm.LocalEtcd), b.(*LocalEtcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*ClusterConfiguration)(nil), (*kubeadm.ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(a.(*ClusterConfiguration), b.(*kubeadm.ClusterConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*HostPathMount)(nil), (*kubeadm.HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(a.(*HostPathMount), b.(*kubeadm.HostPathMount), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*InitConfiguration)(nil), (*kubeadm.InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(a.(*InitConfiguration), b.(*kubeadm.InitConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*JoinConfiguration)(nil), (*kubeadm.JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(a.(*JoinConfiguration), b.(*kubeadm.JoinConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*LocalEtcd)(nil), (*kubeadm.LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(a.(*LocalEtcd), b.(*kubeadm.LocalEtcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(in *APIEndpoint, out *kubeadm.APIEndpoint, s conversion.Scope) error {
|
||||
out.AdvertiseAddress = in.AdvertiseAddress
|
||||
out.BindPort = in.BindPort
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint is an autogenerated conversion function.
|
||||
func Convert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(in *APIEndpoint, out *kubeadm.APIEndpoint, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(in *kubeadm.APIEndpoint, out *APIEndpoint, s conversion.Scope) error {
|
||||
out.AdvertiseAddress = in.AdvertiseAddress
|
||||
out.BindPort = in.BindPort
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint is an autogenerated conversion function.
|
||||
func Convert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(in *kubeadm.APIEndpoint, out *APIEndpoint, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
|
||||
out.Token = (*kubeadm.BootstrapTokenString)(unsafe.Pointer(in.Token))
|
||||
out.Description = in.Description
|
||||
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
|
||||
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
|
||||
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
|
||||
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha3_BootstrapToken_To_kubeadm_BootstrapToken is an autogenerated conversion function.
|
||||
func Convert_v1alpha3_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha3_BootstrapToken_To_kubeadm_BootstrapToken(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_BootstrapToken_To_v1alpha3_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
|
||||
out.Token = (*BootstrapTokenString)(unsafe.Pointer(in.Token))
|
||||
out.Description = in.Description
|
||||
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
|
||||
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
|
||||
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
|
||||
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_BootstrapToken_To_v1alpha3_BootstrapToken is an autogenerated conversion function.
|
||||
func Convert_kubeadm_BootstrapToken_To_v1alpha3_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_BootstrapToken_To_v1alpha3_BootstrapToken(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
|
||||
out.ID = in.ID
|
||||
out.Secret = in.Secret
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha3_BootstrapTokenString_To_kubeadm_BootstrapTokenString is an autogenerated conversion function.
|
||||
func Convert_v1alpha3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_BootstrapTokenString_To_v1alpha3_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
|
||||
out.ID = in.ID
|
||||
out.Secret = in.Secret
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_BootstrapTokenString_To_v1alpha3_BootstrapTokenString is an autogenerated conversion function.
|
||||
func Convert_kubeadm_BootstrapTokenString_To_v1alpha3_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_BootstrapTokenString_To_v1alpha3_BootstrapTokenString(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_v1alpha3_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1alpha3_Networking_To_kubeadm_Networking(&in.Networking, &out.Networking, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.KubernetesVersion = in.KubernetesVersion
|
||||
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
|
||||
// WARNING: in.APIServerExtraArgs requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.ControllerManagerExtraArgs requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.SchedulerExtraArgs requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.APIServerExtraVolumes requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.ControllerManagerExtraVolumes requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.SchedulerExtraVolumes requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.APIServerCertSANs requires manual conversion: does not exist in peer-type
|
||||
out.CertificatesDir = in.CertificatesDir
|
||||
out.ImageRepository = in.ImageRepository
|
||||
// WARNING: in.UnifiedControlPlaneImage requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.AuditPolicyConfiguration requires manual conversion: does not exist in peer-type
|
||||
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
|
||||
out.ClusterName = in.ClusterName
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(in *kubeadm.ClusterConfiguration, out *ClusterConfiguration, s conversion.Scope) error {
|
||||
// INFO: in.ComponentConfigs opted out of conversion generation
|
||||
if err := Convert_kubeadm_Etcd_To_v1alpha3_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_kubeadm_Networking_To_v1alpha3_Networking(&in.Networking, &out.Networking, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.KubernetesVersion = in.KubernetesVersion
|
||||
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
|
||||
// WARNING: in.APIServer requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.ControllerManager requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.Scheduler requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.DNS requires manual conversion: does not exist in peer-type
|
||||
out.CertificatesDir = in.CertificatesDir
|
||||
out.ImageRepository = in.ImageRepository
|
||||
// INFO: in.CIImageRepository opted out of conversion generation
|
||||
// WARNING: in.UseHyperKubeImage requires manual conversion: does not exist in peer-type
|
||||
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
|
||||
out.ClusterName = in.ClusterName
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_ClusterStatus_To_kubeadm_ClusterStatus(in *ClusterStatus, out *kubeadm.ClusterStatus, s conversion.Scope) error {
|
||||
out.APIEndpoints = *(*map[string]kubeadm.APIEndpoint)(unsafe.Pointer(&in.APIEndpoints))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha3_ClusterStatus_To_kubeadm_ClusterStatus is an autogenerated conversion function.
|
||||
func Convert_v1alpha3_ClusterStatus_To_kubeadm_ClusterStatus(in *ClusterStatus, out *kubeadm.ClusterStatus, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha3_ClusterStatus_To_kubeadm_ClusterStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_ClusterStatus_To_v1alpha3_ClusterStatus(in *kubeadm.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
|
||||
out.APIEndpoints = *(*map[string]APIEndpoint)(unsafe.Pointer(&in.APIEndpoints))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_ClusterStatus_To_v1alpha3_ClusterStatus is an autogenerated conversion function.
|
||||
func Convert_kubeadm_ClusterStatus_To_v1alpha3_ClusterStatus(in *kubeadm.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_ClusterStatus_To_v1alpha3_ClusterStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
|
||||
if in.Local != nil {
|
||||
in, out := &in.Local, &out.Local
|
||||
*out = new(kubeadm.LocalEtcd)
|
||||
if err := Convert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Local = nil
|
||||
}
|
||||
out.External = (*kubeadm.ExternalEtcd)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha3_Etcd_To_kubeadm_Etcd is an autogenerated conversion function.
|
||||
func Convert_v1alpha3_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha3_Etcd_To_kubeadm_Etcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_Etcd_To_v1alpha3_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
|
||||
if in.Local != nil {
|
||||
in, out := &in.Local, &out.Local
|
||||
*out = new(LocalEtcd)
|
||||
if err := Convert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Local = nil
|
||||
}
|
||||
out.External = (*ExternalEtcd)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_Etcd_To_v1alpha3_Etcd is an autogenerated conversion function.
|
||||
func Convert_kubeadm_Etcd_To_v1alpha3_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_Etcd_To_v1alpha3_Etcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error {
|
||||
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
|
||||
out.CAFile = in.CAFile
|
||||
out.CertFile = in.CertFile
|
||||
out.KeyFile = in.KeyFile
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha3_ExternalEtcd_To_kubeadm_ExternalEtcd is an autogenerated conversion function.
|
||||
func Convert_v1alpha3_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha3_ExternalEtcd_To_kubeadm_ExternalEtcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_ExternalEtcd_To_v1alpha3_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error {
|
||||
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
|
||||
out.CAFile = in.CAFile
|
||||
out.CertFile = in.CertFile
|
||||
out.KeyFile = in.KeyFile
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_ExternalEtcd_To_v1alpha3_ExternalEtcd is an autogenerated conversion function.
|
||||
func Convert_kubeadm_ExternalEtcd_To_v1alpha3_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_ExternalEtcd_To_v1alpha3_ExternalEtcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.HostPath = in.HostPath
|
||||
out.MountPath = in.MountPath
|
||||
// WARNING: in.Writable requires manual conversion: does not exist in peer-type
|
||||
out.PathType = corev1.HostPathType(in.PathType)
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.HostPath = in.HostPath
|
||||
out.MountPath = in.MountPath
|
||||
// WARNING: in.ReadOnly requires manual conversion: does not exist in peer-type
|
||||
out.PathType = corev1.HostPathType(in.PathType)
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(&in.ClusterConfiguration, &out.ClusterConfiguration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.BootstrapTokens = *(*[]kubeadm.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
|
||||
if err := Convert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
// WARNING: in.APIEndpoint requires manual conversion: does not exist in peer-type
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_InitConfiguration_To_v1alpha3_InitConfiguration(in *kubeadm.InitConfiguration, out *InitConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(&in.ClusterConfiguration, &out.ClusterConfiguration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.BootstrapTokens = *(*[]BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
|
||||
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
// WARNING: in.LocalAPIEndpoint requires manual conversion: does not exist in peer-type
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(in *JoinConfiguration, out *kubeadm.JoinConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CACertPath = in.CACertPath
|
||||
// WARNING: in.DiscoveryFile requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.DiscoveryToken requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.DiscoveryTokenAPIServers requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.DiscoveryTimeout requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.TLSBootstrapToken requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.Token requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.ClusterName requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.DiscoveryTokenCACertHashes requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.DiscoveryTokenUnsafeSkipCAVerification requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.ControlPlane requires manual conversion: inconvertible types (bool vs *k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm.JoinControlPlane)
|
||||
// WARNING: in.APIEndpoint requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.FeatureGates requires manual conversion: does not exist in peer-type
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_JoinConfiguration_To_v1alpha3_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CACertPath = in.CACertPath
|
||||
// WARNING: in.Discovery requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.ControlPlane requires manual conversion: inconvertible types (*k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm.JoinControlPlane vs bool)
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error {
|
||||
// WARNING: in.Image requires manual conversion: does not exist in peer-type
|
||||
out.DataDir = in.DataDir
|
||||
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
|
||||
out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs))
|
||||
out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs))
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error {
|
||||
// WARNING: in.ImageMeta requires manual conversion: does not exist in peer-type
|
||||
out.DataDir = in.DataDir
|
||||
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
|
||||
out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs))
|
||||
out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs))
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
|
||||
out.ServiceSubnet = in.ServiceSubnet
|
||||
out.PodSubnet = in.PodSubnet
|
||||
out.DNSDomain = in.DNSDomain
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha3_Networking_To_kubeadm_Networking is an autogenerated conversion function.
|
||||
func Convert_v1alpha3_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha3_Networking_To_kubeadm_Networking(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_Networking_To_v1alpha3_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
|
||||
out.ServiceSubnet = in.ServiceSubnet
|
||||
out.PodSubnet = in.PodSubnet
|
||||
out.DNSDomain = in.DNSDomain
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_Networking_To_v1alpha3_Networking is an autogenerated conversion function.
|
||||
func Convert_kubeadm_Networking_To_v1alpha3_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_Networking_To_v1alpha3_Networking(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.CRISocket = in.CRISocket
|
||||
out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
|
||||
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions is an autogenerated conversion function.
|
||||
func Convert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.CRISocket = in.CRISocket
|
||||
out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
|
||||
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions is an autogenerated conversion function.
|
||||
func Convert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(in, out, s)
|
||||
}
|
|
@ -1,454 +0,0 @@
|
|||
// +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 v1alpha3
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
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 *APIEndpoint) DeepCopyInto(out *APIEndpoint) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIEndpoint.
|
||||
func (in *APIEndpoint) DeepCopy() *APIEndpoint {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(APIEndpoint)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AuditPolicyConfiguration) DeepCopyInto(out *AuditPolicyConfiguration) {
|
||||
*out = *in
|
||||
if in.LogMaxAge != nil {
|
||||
in, out := &in.LogMaxAge, &out.LogMaxAge
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuditPolicyConfiguration.
|
||||
func (in *AuditPolicyConfiguration) DeepCopy() *AuditPolicyConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AuditPolicyConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
|
||||
*out = *in
|
||||
if in.Token != nil {
|
||||
in, out := &in.Token, &out.Token
|
||||
*out = new(BootstrapTokenString)
|
||||
**out = **in
|
||||
}
|
||||
if in.TTL != nil {
|
||||
in, out := &in.TTL, &out.TTL
|
||||
*out = new(v1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
if in.Expires != nil {
|
||||
in, out := &in.Expires, &out.Expires
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Usages != nil {
|
||||
in, out := &in.Usages, &out.Usages
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Groups != nil {
|
||||
in, out := &in.Groups, &out.Groups
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken.
|
||||
func (in *BootstrapToken) DeepCopy() *BootstrapToken {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BootstrapToken)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BootstrapTokenString) DeepCopyInto(out *BootstrapTokenString) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenString.
|
||||
func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BootstrapTokenString)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.Etcd.DeepCopyInto(&out.Etcd)
|
||||
out.Networking = in.Networking
|
||||
if in.APIServerExtraArgs != nil {
|
||||
in, out := &in.APIServerExtraArgs, &out.APIServerExtraArgs
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.ControllerManagerExtraArgs != nil {
|
||||
in, out := &in.ControllerManagerExtraArgs, &out.ControllerManagerExtraArgs
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.SchedulerExtraArgs != nil {
|
||||
in, out := &in.SchedulerExtraArgs, &out.SchedulerExtraArgs
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.APIServerExtraVolumes != nil {
|
||||
in, out := &in.APIServerExtraVolumes, &out.APIServerExtraVolumes
|
||||
*out = make([]HostPathMount, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.ControllerManagerExtraVolumes != nil {
|
||||
in, out := &in.ControllerManagerExtraVolumes, &out.ControllerManagerExtraVolumes
|
||||
*out = make([]HostPathMount, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.SchedulerExtraVolumes != nil {
|
||||
in, out := &in.SchedulerExtraVolumes, &out.SchedulerExtraVolumes
|
||||
*out = make([]HostPathMount, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.APIServerCertSANs != nil {
|
||||
in, out := &in.APIServerCertSANs, &out.APIServerCertSANs
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
in.AuditPolicyConfiguration.DeepCopyInto(&out.AuditPolicyConfiguration)
|
||||
if in.FeatureGates != nil {
|
||||
in, out := &in.FeatureGates, &out.FeatureGates
|
||||
*out = make(map[string]bool, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterConfiguration.
|
||||
func (in *ClusterConfiguration) DeepCopy() *ClusterConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ClusterConfiguration) 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 *ClusterStatus) DeepCopyInto(out *ClusterStatus) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
if in.APIEndpoints != nil {
|
||||
in, out := &in.APIEndpoints, &out.APIEndpoints
|
||||
*out = make(map[string]APIEndpoint, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterStatus.
|
||||
func (in *ClusterStatus) DeepCopy() *ClusterStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ClusterStatus) 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 *Etcd) DeepCopyInto(out *Etcd) {
|
||||
*out = *in
|
||||
if in.Local != nil {
|
||||
in, out := &in.Local, &out.Local
|
||||
*out = new(LocalEtcd)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(ExternalEtcd)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Etcd.
|
||||
func (in *Etcd) DeepCopy() *Etcd {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Etcd)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalEtcd) DeepCopyInto(out *ExternalEtcd) {
|
||||
*out = *in
|
||||
if in.Endpoints != nil {
|
||||
in, out := &in.Endpoints, &out.Endpoints
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalEtcd.
|
||||
func (in *ExternalEtcd) DeepCopy() *ExternalEtcd {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExternalEtcd)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HostPathMount) DeepCopyInto(out *HostPathMount) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPathMount.
|
||||
func (in *HostPathMount) DeepCopy() *HostPathMount {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HostPathMount)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *InitConfiguration) DeepCopyInto(out *InitConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ClusterConfiguration.DeepCopyInto(&out.ClusterConfiguration)
|
||||
if in.BootstrapTokens != nil {
|
||||
in, out := &in.BootstrapTokens, &out.BootstrapTokens
|
||||
*out = make([]BootstrapToken, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
|
||||
out.APIEndpoint = in.APIEndpoint
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InitConfiguration.
|
||||
func (in *InitConfiguration) DeepCopy() *InitConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(InitConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *InitConfiguration) 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 *JoinConfiguration) DeepCopyInto(out *JoinConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
|
||||
if in.DiscoveryTokenAPIServers != nil {
|
||||
in, out := &in.DiscoveryTokenAPIServers, &out.DiscoveryTokenAPIServers
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.DiscoveryTimeout != nil {
|
||||
in, out := &in.DiscoveryTimeout, &out.DiscoveryTimeout
|
||||
*out = new(v1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
if in.DiscoveryTokenCACertHashes != nil {
|
||||
in, out := &in.DiscoveryTokenCACertHashes, &out.DiscoveryTokenCACertHashes
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
out.APIEndpoint = in.APIEndpoint
|
||||
if in.FeatureGates != nil {
|
||||
in, out := &in.FeatureGates, &out.FeatureGates
|
||||
*out = make(map[string]bool, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JoinConfiguration.
|
||||
func (in *JoinConfiguration) DeepCopy() *JoinConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JoinConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *JoinConfiguration) 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 *LocalEtcd) DeepCopyInto(out *LocalEtcd) {
|
||||
*out = *in
|
||||
if in.ExtraArgs != nil {
|
||||
in, out := &in.ExtraArgs, &out.ExtraArgs
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.ServerCertSANs != nil {
|
||||
in, out := &in.ServerCertSANs, &out.ServerCertSANs
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.PeerCertSANs != nil {
|
||||
in, out := &in.PeerCertSANs, &out.PeerCertSANs
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalEtcd.
|
||||
func (in *LocalEtcd) DeepCopy() *LocalEtcd {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(LocalEtcd)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Networking) DeepCopyInto(out *Networking) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Networking.
|
||||
func (in *Networking) DeepCopy() *Networking {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Networking)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) {
|
||||
*out = *in
|
||||
if in.Taints != nil {
|
||||
in, out := &in.Taints, &out.Taints
|
||||
*out = make([]corev1.Taint, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.KubeletExtraArgs != nil {
|
||||
in, out := &in.KubeletExtraArgs, &out.KubeletExtraArgs
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRegistrationOptions.
|
||||
func (in *NodeRegistrationOptions) DeepCopy() *NodeRegistrationOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NodeRegistrationOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
scheme.AddTypeDefaultingFunc(&ClusterConfiguration{}, func(obj interface{}) { SetObjectDefaults_ClusterConfiguration(obj.(*ClusterConfiguration)) })
|
||||
scheme.AddTypeDefaultingFunc(&ClusterStatus{}, func(obj interface{}) { SetObjectDefaults_ClusterStatus(obj.(*ClusterStatus)) })
|
||||
scheme.AddTypeDefaultingFunc(&InitConfiguration{}, func(obj interface{}) { SetObjectDefaults_InitConfiguration(obj.(*InitConfiguration)) })
|
||||
scheme.AddTypeDefaultingFunc(&JoinConfiguration{}, func(obj interface{}) { SetObjectDefaults_JoinConfiguration(obj.(*JoinConfiguration)) })
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetObjectDefaults_ClusterConfiguration(in *ClusterConfiguration) {
|
||||
SetDefaults_ClusterConfiguration(in)
|
||||
}
|
||||
|
||||
func SetObjectDefaults_ClusterStatus(in *ClusterStatus) {
|
||||
}
|
||||
|
||||
func SetObjectDefaults_InitConfiguration(in *InitConfiguration) {
|
||||
SetDefaults_InitConfiguration(in)
|
||||
SetObjectDefaults_ClusterConfiguration(&in.ClusterConfiguration)
|
||||
for i := range in.BootstrapTokens {
|
||||
a := &in.BootstrapTokens[i]
|
||||
SetDefaults_BootstrapToken(a)
|
||||
}
|
||||
SetDefaults_APIEndpoint(&in.APIEndpoint)
|
||||
}
|
||||
|
||||
func SetObjectDefaults_JoinConfiguration(in *JoinConfiguration) {
|
||||
SetDefaults_JoinConfiguration(in)
|
||||
SetDefaults_APIEndpoint(&in.APIEndpoint)
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bootstraptokenstring.go",
|
||||
"defaults.go",
|
||||
"defaults_unix.go",
|
||||
"defaults_windows.go",
|
||||
"doc.go",
|
||||
"register.go",
|
||||
"types.go",
|
||||
"zz_generated.conversion.go",
|
||||
"zz_generated.deepcopy.go",
|
||||
"zz_generated.defaults.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1: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",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["bootstraptokenstring_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["//vendor/github.com/pkg/errors: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"],
|
||||
)
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
||||
)
|
||||
|
||||
// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used
|
||||
// for both validation of the practically of the API server from a joining node's point
|
||||
// of view and as an authentication method for the node in the bootstrap phase of
|
||||
// "kubeadm join". This token is and should be short-lived
|
||||
type BootstrapTokenString struct {
|
||||
ID string
|
||||
Secret string
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (bts BootstrapTokenString) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf(`"%s"`, bts.String())), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaller interface.
|
||||
func (bts *BootstrapTokenString) UnmarshalJSON(b []byte) error {
|
||||
// If the token is represented as "", just return quickly without an error
|
||||
if len(b) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove unnecessary " characters coming from the JSON parser
|
||||
token := strings.Replace(string(b), `"`, ``, -1)
|
||||
// Convert the string Token to a BootstrapTokenString object
|
||||
newbts, err := NewBootstrapTokenString(token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bts.ID = newbts.ID
|
||||
bts.Secret = newbts.Secret
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the string representation of the BootstrapTokenString
|
||||
func (bts BootstrapTokenString) String() string {
|
||||
if len(bts.ID) > 0 && len(bts.Secret) > 0 {
|
||||
return bootstraputil.TokenFromIDAndSecret(bts.ID, bts.Secret)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewBootstrapTokenString converts the given Bootstrap Token as a string
|
||||
// to the BootstrapTokenString object used for serialization/deserialization
|
||||
// and internal usage. It also automatically validates that the given token
|
||||
// is of the right format
|
||||
func NewBootstrapTokenString(token string) (*BootstrapTokenString, error) {
|
||||
substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(token)
|
||||
// TODO: Add a constant for the 3 value here, and explain better why it's needed (other than because how the regexp parsin works)
|
||||
if len(substrs) != 3 {
|
||||
return nil, errors.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern)
|
||||
}
|
||||
|
||||
return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil
|
||||
}
|
||||
|
||||
// NewBootstrapTokenStringFromIDAndSecret is a wrapper around NewBootstrapTokenString
|
||||
// that allows the caller to specify the ID and Secret separately
|
||||
func NewBootstrapTokenStringFromIDAndSecret(id, secret string) (*BootstrapTokenString, error) {
|
||||
return NewBootstrapTokenString(bootstraputil.TokenFromIDAndSecret(id, secret))
|
||||
}
|
|
@ -1,249 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func TestMarshalJSON(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bts BootstrapTokenString
|
||||
expected string
|
||||
}{
|
||||
{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`},
|
||||
{BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`},
|
||||
{BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.bts.ID, func(t *testing.T) {
|
||||
b, err := json.Marshal(rt.bts)
|
||||
if err != nil {
|
||||
t.Fatalf("json.Marshal returned an unexpected error: %v", err)
|
||||
}
|
||||
if string(b) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
string(b),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalJSON(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
bts *BootstrapTokenString
|
||||
expectedError bool
|
||||
}{
|
||||
{`"f.s"`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef."`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true},
|
||||
{`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false},
|
||||
{`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.input, func(t *testing.T) {
|
||||
newbts := &BootstrapTokenString{}
|
||||
err := json.Unmarshal([]byte(rt.input), newbts)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err)
|
||||
} else if !reflect.DeepEqual(rt.bts, newbts) {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v",
|
||||
rt.bts,
|
||||
newbts,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONRoundtrip(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{`"abcdef.abcdef0123456789"`, nil},
|
||||
{"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.input, func(t *testing.T) {
|
||||
if err := roundtrip(rt.input, rt.bts); err != nil {
|
||||
t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func roundtrip(input string, bts *BootstrapTokenString) error {
|
||||
var b []byte
|
||||
var err error
|
||||
newbts := &BootstrapTokenString{}
|
||||
// If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string
|
||||
if len(input) > 0 {
|
||||
if err := json.Unmarshal([]byte(input), newbts); err != nil {
|
||||
return errors.Wrap(err, "expected no unmarshal error, got error")
|
||||
}
|
||||
if b, err = json.Marshal(newbts); err != nil {
|
||||
return errors.Wrap(err, "expected no marshal error, got error")
|
||||
}
|
||||
if input != string(b) {
|
||||
return errors.Errorf(
|
||||
"expected token: %s\n\t actual: %s",
|
||||
input,
|
||||
string(b),
|
||||
)
|
||||
}
|
||||
} else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object
|
||||
if b, err = json.Marshal(bts); err != nil {
|
||||
return errors.Wrap(err, "expected no marshal error, got error")
|
||||
}
|
||||
if err := json.Unmarshal(b, newbts); err != nil {
|
||||
return errors.Wrap(err, "expected no unmarshal error, got error")
|
||||
}
|
||||
if !reflect.DeepEqual(bts, newbts) {
|
||||
return errors.Errorf(
|
||||
"expected object: %v\n\t actual: %v",
|
||||
bts,
|
||||
newbts,
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestTokenFromIDAndSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bts BootstrapTokenString
|
||||
expected string
|
||||
}{
|
||||
{BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"},
|
||||
{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"},
|
||||
{BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.bts.ID, func(t *testing.T) {
|
||||
actual := rt.bts.String()
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBootstrapTokenString(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token string
|
||||
expectedError bool
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{token: "", expectedError: true, bts: nil},
|
||||
{token: ".", expectedError: true, bts: nil},
|
||||
{token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "123456.", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation
|
||||
{token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation
|
||||
{token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id
|
||||
{token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
|
||||
{token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
|
||||
{token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character
|
||||
{token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
|
||||
{token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
|
||||
{token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
{token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.token, func(t *testing.T) {
|
||||
actual, err := NewBootstrapTokenString(rt.token)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.token,
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else if !reflect.DeepEqual(actual, rt.bts) {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v",
|
||||
rt.token,
|
||||
rt.bts,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
id, secret string
|
||||
expectedError bool
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{id: "", secret: "", expectedError: true, bts: nil},
|
||||
{id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id
|
||||
{id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
|
||||
{id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
|
||||
{id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character
|
||||
{id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
|
||||
{id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
|
||||
{id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
{id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.id, func(t *testing.T) {
|
||||
actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.id,
|
||||
rt.secret,
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else if !reflect.DeepEqual(actual, rt.bts) {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v",
|
||||
rt.id,
|
||||
rt.secret,
|
||||
rt.bts,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,215 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultServiceDNSDomain defines default cluster-internal domain name for Services and Pods
|
||||
DefaultServiceDNSDomain = "cluster.local"
|
||||
// DefaultServicesSubnet defines default service subnet range
|
||||
DefaultServicesSubnet = "10.96.0.0/12"
|
||||
// DefaultClusterDNSIP defines default DNS IP
|
||||
DefaultClusterDNSIP = "10.96.0.10"
|
||||
// DefaultKubernetesVersion defines default kubernetes version
|
||||
DefaultKubernetesVersion = "stable-1"
|
||||
// DefaultAPIBindPort defines default API port
|
||||
DefaultAPIBindPort = 6443
|
||||
// DefaultCertificatesDir defines default certificate directory
|
||||
DefaultCertificatesDir = "/etc/kubernetes/pki"
|
||||
// DefaultImageRepository defines default image registry
|
||||
DefaultImageRepository = "k8s.gcr.io"
|
||||
// DefaultManifestsDir defines default manifests directory
|
||||
DefaultManifestsDir = "/etc/kubernetes/manifests"
|
||||
// DefaultClusterName defines the default cluster name
|
||||
DefaultClusterName = "kubernetes"
|
||||
|
||||
// DefaultEtcdDataDir defines default location of etcd where static pods will save data to
|
||||
DefaultEtcdDataDir = "/var/lib/etcd"
|
||||
// DefaultProxyBindAddressv4 is the default bind address when the advertise address is v4
|
||||
DefaultProxyBindAddressv4 = "0.0.0.0"
|
||||
// DefaultProxyBindAddressv6 is the default bind address when the advertise address is v6
|
||||
DefaultProxyBindAddressv6 = "::"
|
||||
// DefaultDiscoveryTimeout specifies the default discovery timeout for kubeadm (used unless one is specified in the JoinConfiguration)
|
||||
DefaultDiscoveryTimeout = 5 * time.Minute
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultAuditPolicyLogMaxAge is defined as a var so its address can be taken
|
||||
// It is the number of days to store audit logs
|
||||
DefaultAuditPolicyLogMaxAge = int32(2)
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
return RegisterDefaults(scheme)
|
||||
}
|
||||
|
||||
// SetDefaults_InitConfiguration assigns default values for the InitConfiguration
|
||||
func SetDefaults_InitConfiguration(obj *InitConfiguration) {
|
||||
SetDefaults_ClusterConfiguration(&obj.ClusterConfiguration)
|
||||
SetDefaults_BootstrapTokens(obj)
|
||||
SetDefaults_APIEndpoint(&obj.LocalAPIEndpoint)
|
||||
}
|
||||
|
||||
// SetDefaults_ClusterConfiguration assigns default values for the ClusterConfiguration
|
||||
func SetDefaults_ClusterConfiguration(obj *ClusterConfiguration) {
|
||||
if obj.KubernetesVersion == "" {
|
||||
obj.KubernetesVersion = DefaultKubernetesVersion
|
||||
}
|
||||
|
||||
if obj.Networking.ServiceSubnet == "" {
|
||||
obj.Networking.ServiceSubnet = DefaultServicesSubnet
|
||||
}
|
||||
|
||||
if obj.Networking.DNSDomain == "" {
|
||||
obj.Networking.DNSDomain = DefaultServiceDNSDomain
|
||||
}
|
||||
|
||||
if obj.CertificatesDir == "" {
|
||||
obj.CertificatesDir = DefaultCertificatesDir
|
||||
}
|
||||
|
||||
if obj.ImageRepository == "" {
|
||||
obj.ImageRepository = DefaultImageRepository
|
||||
}
|
||||
|
||||
if obj.ClusterName == "" {
|
||||
obj.ClusterName = DefaultClusterName
|
||||
}
|
||||
|
||||
SetDefaults_DNS(obj)
|
||||
SetDefaults_Etcd(obj)
|
||||
SetDefaults_APIServer(&obj.APIServer)
|
||||
}
|
||||
|
||||
// SetDefaults_APIServer assigns default values for the API Server
|
||||
func SetDefaults_APIServer(obj *APIServer) {
|
||||
if obj.TimeoutForControlPlane == nil {
|
||||
obj.TimeoutForControlPlane = &metav1.Duration{
|
||||
Duration: constants.DefaultControlPlaneTimeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_DNS assigns default values for the DNS component
|
||||
func SetDefaults_DNS(obj *ClusterConfiguration) {
|
||||
if obj.DNS.Type == "" {
|
||||
obj.DNS.Type = CoreDNS
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_Etcd assigns default values for the proxy
|
||||
func SetDefaults_Etcd(obj *ClusterConfiguration) {
|
||||
if obj.Etcd.External == nil && obj.Etcd.Local == nil {
|
||||
obj.Etcd.Local = &LocalEtcd{}
|
||||
}
|
||||
if obj.Etcd.Local != nil {
|
||||
if obj.Etcd.Local.DataDir == "" {
|
||||
obj.Etcd.Local.DataDir = DefaultEtcdDataDir
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_JoinConfiguration assigns default values to a regular node
|
||||
func SetDefaults_JoinConfiguration(obj *JoinConfiguration) {
|
||||
if obj.CACertPath == "" {
|
||||
obj.CACertPath = DefaultCACertPath
|
||||
}
|
||||
|
||||
SetDefaults_JoinControlPlane(obj.ControlPlane)
|
||||
SetDefaults_Discovery(&obj.Discovery)
|
||||
}
|
||||
|
||||
func SetDefaults_JoinControlPlane(obj *JoinControlPlane) {
|
||||
if obj != nil {
|
||||
SetDefaults_APIEndpoint(&obj.LocalAPIEndpoint)
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_Discovery assigns default values for the discovery process
|
||||
func SetDefaults_Discovery(obj *Discovery) {
|
||||
if len(obj.TLSBootstrapToken) == 0 && obj.BootstrapToken != nil {
|
||||
obj.TLSBootstrapToken = obj.BootstrapToken.Token
|
||||
}
|
||||
|
||||
if obj.Timeout == nil {
|
||||
obj.Timeout = &metav1.Duration{
|
||||
Duration: DefaultDiscoveryTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
if obj.File != nil {
|
||||
SetDefaults_FileDiscovery(obj.File)
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_FileDiscovery assigns default values for file based discovery
|
||||
func SetDefaults_FileDiscovery(obj *FileDiscovery) {
|
||||
// Make sure file URL becomes path
|
||||
if len(obj.KubeConfigPath) != 0 {
|
||||
u, err := url.Parse(obj.KubeConfigPath)
|
||||
if err == nil && u.Scheme == "file" {
|
||||
obj.KubeConfigPath = u.Path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_BootstrapTokens sets the defaults for the .BootstrapTokens field
|
||||
// If the slice is empty, it's defaulted with one token. Otherwise it just loops
|
||||
// through the slice and sets the defaults for the omitempty fields that are TTL,
|
||||
// Usages and Groups. Token is NOT defaulted with a random one in the API defaulting
|
||||
// layer, but set to a random value later at runtime if not set before.
|
||||
func SetDefaults_BootstrapTokens(obj *InitConfiguration) {
|
||||
|
||||
if obj.BootstrapTokens == nil || len(obj.BootstrapTokens) == 0 {
|
||||
obj.BootstrapTokens = []BootstrapToken{{}}
|
||||
}
|
||||
|
||||
for i := range obj.BootstrapTokens {
|
||||
SetDefaults_BootstrapToken(&obj.BootstrapTokens[i])
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_BootstrapToken sets the defaults for an individual Bootstrap Token
|
||||
func SetDefaults_BootstrapToken(bt *BootstrapToken) {
|
||||
if bt.TTL == nil {
|
||||
bt.TTL = &metav1.Duration{
|
||||
Duration: constants.DefaultTokenDuration,
|
||||
}
|
||||
}
|
||||
if len(bt.Usages) == 0 {
|
||||
bt.Usages = constants.DefaultTokenUsages
|
||||
}
|
||||
|
||||
if len(bt.Groups) == 0 {
|
||||
bt.Groups = constants.DefaultTokenGroups
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_APIEndpoint sets the defaults for the API server instance deployed on a node.
|
||||
func SetDefaults_APIEndpoint(obj *APIEndpoint) {
|
||||
if obj.BindPort == 0 {
|
||||
obj.BindPort = DefaultAPIBindPort
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
const (
|
||||
// DefaultCACertPath defines default location of CA certificate on Linux
|
||||
DefaultCACertPath = "/etc/kubernetes/pki/ca.crt"
|
||||
// DefaultUrlScheme defines default socket url prefix
|
||||
DefaultUrlScheme = "unix"
|
||||
)
|
|
@ -1,26 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
const (
|
||||
// DefaultCACertPath defines default location of CA certificate on Windows
|
||||
DefaultCACertPath = "C:/etc/kubernetes/pki/ca.crt"
|
||||
// DefaultUrlScheme defines default socket url prefix
|
||||
DefaultUrlScheme = "tcp"
|
||||
)
|
|
@ -1,280 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=kubeadm.k8s.io
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm
|
||||
|
||||
// Package v1beta1 defines the v1beta1 version of the kubeadm configuration file format.
|
||||
// This version graduates the configuration format to BETA and is a big step towards GA.
|
||||
//
|
||||
//A list of changes since v1alpha3:
|
||||
// - "apiServerEndpoint" in InitConfiguration was renamed to "localAPIEndpoint" for better clarity of what the field
|
||||
// represents.
|
||||
// - Common fields in ClusterConfiguration such as "*extraArgs" and "*extraVolumes" for control plane components are now moved
|
||||
// under component structs - i.e. "apiServer", "controllerManager", "scheduler".
|
||||
// - "auditPolicy" was removed from ClusterConfiguration. Please use "extraArgs" in "apiServer" to configure this feature instead.
|
||||
// - "unifiedControlPlaneImage" in ClusterConfiguration was changed to a boolean field called "useHyperKubeImage".
|
||||
// - ClusterConfiguration now has a "dns" field which can be used to select and configure the cluster DNS addon.
|
||||
// - "featureGates" still exists under ClusterConfiguration, but there are no supported feature gates in 1.13.
|
||||
// See the Kubernetes 1.13 changelog for further details.
|
||||
// - Both "localEtcd" and "dns" configurations now support custom image repositories.
|
||||
// - The "controlPlane*"-related fields in JoinConfiguration were refactored into a sub-structure.
|
||||
// - "clusterName" was removed from JoinConfiguration and the name is now fetched from the existing cluster.
|
||||
//
|
||||
// Migration from old kubeadm config versions
|
||||
//
|
||||
// Please convert your v1alpha3 configuration files to v1beta1 using the "kubeadm config migrate" command of kubeadm v1.13.x
|
||||
// (conversion from older releases of kubeadm config files requires older release of kubeadm as well e.g.
|
||||
// kubeadm v1.11 should be used to migrate v1alpha1 to v1alpha2; kubeadm v1.12 should be used to translate v1alpha2 to v1alpha3)
|
||||
//
|
||||
// Nevertheless, kubeadm v1.13.x will support reading from v1alpha3 version of the kubeadm config file format, but this support
|
||||
// will be dropped in the v1.14 release.
|
||||
//
|
||||
// Basics
|
||||
//
|
||||
// The preferred way to configure kubeadm is to pass an YAML configuration file with the --config option. Some of the
|
||||
// configuration options defined in the kubeadm config file are also available as command line flags, but only
|
||||
// the most common/simple use case are supported with this approach.
|
||||
//
|
||||
// A kubeadm config file could contain multiple configuration types separated using three dashes (“---”).
|
||||
//
|
||||
// kubeadm supports the following configuration types:
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1beta1
|
||||
// kind: InitConfiguration
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1beta1
|
||||
// kind: ClusterConfiguration
|
||||
//
|
||||
// apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
// kind: KubeletConfiguration
|
||||
//
|
||||
// apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||
// kind: KubeProxyConfiguration
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1beta1
|
||||
// kind: JoinConfiguration
|
||||
//
|
||||
// To print the defaults for "init" and "join" actions use the following commands:
|
||||
// kubeadm config print init-defaults
|
||||
// kubeadm config print join-defaults
|
||||
//
|
||||
// The list of configuration types that must be included in a configuration file depends by the action you are
|
||||
// performing (init or join) and by the configuration options you are going to use (defaults or advanced customization).
|
||||
//
|
||||
// If some configuration types are not provided, or provided only partially, kubeadm will use default values; defaults
|
||||
// provided by kubeadm includes also enforcing consistency of values across components when required (e.g.
|
||||
// cluster-cidr flag on controller manager and clusterCIDR on kube-proxy).
|
||||
//
|
||||
// Users are always allowed to override default values, with the only exception of a small subset of setting with
|
||||
// relevance for security (e.g. enforce authorization-mode Node and RBAC on api server)
|
||||
//
|
||||
// If the user provides a configuration types that is not expected for the action you are performing, kubeadm will
|
||||
// ignore those types and print a warning.
|
||||
//
|
||||
// Kubeadm init configuration types
|
||||
//
|
||||
// When executing kubeadm init with the --config option, the following configuration types could be used:
|
||||
// InitConfiguration, ClusterConfiguration, KubeProxyConfiguration, KubeletConfiguration, but only one
|
||||
// between InitConfiguration and ClusterConfiguration is mandatory.
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1beta1
|
||||
// kind: InitConfiguration
|
||||
// bootstrapTokens:
|
||||
// ...
|
||||
// nodeRegistration:
|
||||
// ...
|
||||
//
|
||||
// The InitConfiguration type should be used to configure runtime settings, that in case of kubeadm init
|
||||
// are the configuration of the bootstrap token and all the setting which are specific to the node where kubeadm
|
||||
// is executed, including:
|
||||
//
|
||||
// - NodeRegistration, that holds fields that relate to registering the new node to the cluster;
|
||||
// use it to customize the node name, the CRI socket to use or any other settings that should apply to this
|
||||
// node only (e.g. the node ip).
|
||||
//
|
||||
// - LocalAPIEndpoint, that represents the endpoint of the instance of the API server to be deployed on this node;
|
||||
// use it e.g. to customize the API server advertise address.
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1beta1
|
||||
// kind: ClusterConfiguration
|
||||
// networking:
|
||||
// ...
|
||||
// etcd:
|
||||
// ...
|
||||
// apiServer:
|
||||
// extraArgs:
|
||||
// ...
|
||||
// extraVolumes:
|
||||
// ...
|
||||
// ...
|
||||
//
|
||||
// The ClusterConfiguration type should be used to configure cluster-wide settings,
|
||||
// including settings for:
|
||||
//
|
||||
// - Networking, that holds configuration for the networking topology of the cluster; use it e.g. to customize
|
||||
// node subnet or services subnet.
|
||||
//
|
||||
// - Etcd configurations; use it e.g. to customize the local etcd or to configure the API server
|
||||
// for using an external etcd cluster.
|
||||
//
|
||||
// - kube-apiserver, kube-scheduler, kube-controller-manager configurations; use it to customize control-plane
|
||||
// components by adding customized setting or overriding kubeadm default settings.
|
||||
//
|
||||
// apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||
// kind: KubeProxyConfiguration
|
||||
// ...
|
||||
//
|
||||
// The KubeProxyConfiguration type should be used to change the configuration passed to kube-proxy instances deployed
|
||||
// in the cluster. If this object is not provided or provided only partially, kubeadm applies defaults.
|
||||
//
|
||||
// See https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/ or https://godoc.org/k8s.io/kube-proxy/config/v1alpha1#KubeProxyConfiguration
|
||||
// for kube proxy official documentation.
|
||||
//
|
||||
// apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
// kind: KubeletConfiguration
|
||||
// ...
|
||||
//
|
||||
// The KubeletConfiguration type should be used to change the configurations that will be passed to all kubelet instances
|
||||
// deployed in the cluster. If this object is not provided or provided only partially, kubeadm applies defaults.
|
||||
//
|
||||
// See https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/ or https://godoc.org/k8s.io/kubelet/config/v1beta1#KubeletConfiguration
|
||||
// for kubelet official documentation.
|
||||
//
|
||||
// Here is a fully populated example of a single YAML file containing multiple
|
||||
// configuration types to be used during a `kubeadm init` run.
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1beta1
|
||||
// kind: InitConfiguration
|
||||
// bootstrapTokens:
|
||||
// - token: "9a08jv.c0izixklcxtmnze7"
|
||||
// description: "kubeadm bootstrap token"
|
||||
// ttl: "24h"
|
||||
// - token: "783bde.3f89s0fje9f38fhf"
|
||||
// description: "another bootstrap token"
|
||||
// usages:
|
||||
// - authentication
|
||||
// - signing
|
||||
// groups:
|
||||
// - system:bootstrappers:kubeadm:default-node-token
|
||||
// nodeRegistration:
|
||||
// name: "ec2-10-100-0-1"
|
||||
// criSocket: "/var/run/dockershim.sock"
|
||||
// taints:
|
||||
// - key: "kubeadmNode"
|
||||
// value: "master"
|
||||
// effect: "NoSchedule"
|
||||
// kubeletExtraArgs:
|
||||
// cgroupDriver: "cgroupfs"
|
||||
// localAPIEndpoint:
|
||||
// advertiseAddress: "10.100.0.1"
|
||||
// bindPort: 6443
|
||||
// ---
|
||||
// apiVersion: kubeadm.k8s.io/v1beta1
|
||||
// kind: ClusterConfiguration
|
||||
// etcd:
|
||||
// # one of local or external
|
||||
// local:
|
||||
// imageRepository: "k8s.gcr.io"
|
||||
// imageTag: "3.2.24"
|
||||
// dataDir: "/var/lib/etcd"
|
||||
// extraArgs:
|
||||
// listen-client-urls: "http://10.100.0.1:2379"
|
||||
// serverCertSANs:
|
||||
// - "ec2-10-100-0-1.compute-1.amazonaws.com"
|
||||
// peerCertSANs:
|
||||
// - "10.100.0.1"
|
||||
// # external:
|
||||
// # endpoints:
|
||||
// # - "10.100.0.1:2379"
|
||||
// # - "10.100.0.2:2379"
|
||||
// # caFile: "/etcd/kubernetes/pki/etcd/etcd-ca.crt"
|
||||
// # certFile: "/etcd/kubernetes/pki/etcd/etcd.crt"
|
||||
// # keyFile: "/etcd/kubernetes/pki/etcd/etcd.key"
|
||||
// networking:
|
||||
// serviceSubnet: "10.96.0.0/12"
|
||||
// podSubnet: "10.100.0.1/24"
|
||||
// dnsDomain: "cluster.local"
|
||||
// kubernetesVersion: "v1.12.0"
|
||||
// controlPlaneEndpoint: "10.100.0.1:6443"
|
||||
// apiServer:
|
||||
// extraArgs:
|
||||
// authorization-mode: "Node,RBAC"
|
||||
// extraVolumes:
|
||||
// - name: "some-volume"
|
||||
// hostPath: "/etc/some-path"
|
||||
// mountPath: "/etc/some-pod-path"
|
||||
// readOnly: false
|
||||
// pathType: File
|
||||
// certSANs:
|
||||
// - "10.100.1.1"
|
||||
// - "ec2-10-100-0-1.compute-1.amazonaws.com"
|
||||
// timeoutForControlPlane: 4m0s
|
||||
// controllerManager:
|
||||
// extraArgs:
|
||||
// "node-cidr-mask-size": "20"
|
||||
// extraVolumes:
|
||||
// - name: "some-volume"
|
||||
// hostPath: "/etc/some-path"
|
||||
// mountPath: "/etc/some-pod-path"
|
||||
// readOnly: false
|
||||
// pathType: File
|
||||
// scheduler:
|
||||
// extraArgs:
|
||||
// address: "10.100.0.1"
|
||||
// extraVolumes:
|
||||
// - name: "some-volume"
|
||||
// hostPath: "/etc/some-path"
|
||||
// mountPath: "/etc/some-pod-path"
|
||||
// readOnly: false
|
||||
// pathType: File
|
||||
// certificatesDir: "/etc/kubernetes/pki"
|
||||
// imageRepository: "k8s.gcr.io"
|
||||
// useHyperKubeImage: false
|
||||
// clusterName: "example-cluster"
|
||||
// ---
|
||||
// apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
// kind: KubeletConfiguration
|
||||
// # kubelet specific options here
|
||||
// ---
|
||||
// apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||
// kind: KubeProxyConfiguration
|
||||
// # kube-proxy specific options here
|
||||
//
|
||||
// Kubeadm join configuration types
|
||||
//
|
||||
// When executing kubeadm join with the --config option, the JoinConfiguration type should be provided.
|
||||
//
|
||||
// apiVersion: kubeadm.k8s.io/v1beta1
|
||||
// kind: JoinConfiguration
|
||||
// ...
|
||||
//
|
||||
// The JoinConfiguration type should be used to configure runtime settings, that in case of kubeadm join
|
||||
// are the discovery method used for accessing the cluster info and all the setting which are specific
|
||||
// to the node where kubeadm is executed, including:
|
||||
//
|
||||
// - NodeRegistration, that holds fields that relate to registering the new node to the cluster;
|
||||
// use it to customize the node name, the CRI socket to use or any other settings that should apply to this
|
||||
// node only (e.g. the node ip).
|
||||
//
|
||||
// - APIEndpoint, that represents the endpoint of the instance of the API server to be eventually deployed on this node.
|
||||
//
|
||||
package v1beta1 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
|
||||
//TODO: The BootstrapTokenString object should move out to either k8s.io/client-go or k8s.io/api in the future
|
||||
//(probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now.
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "kubeadm.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
|
||||
|
||||
var (
|
||||
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
|
||||
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
|
||||
|
||||
// SchemeBuilder points to a list of functions added to Scheme.
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
// AddToScheme applies all the stored functions to the scheme.
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func init() {
|
||||
// We only register manually written functions here. The registration of the
|
||||
// generated functions takes place in the generated files. The separation
|
||||
// makes the code compile even when the generated files are missing.
|
||||
localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&InitConfiguration{},
|
||||
&ClusterConfiguration{},
|
||||
&ClusterStatus{},
|
||||
&JoinConfiguration{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
|
@ -1,390 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// InitConfiguration contains a list of elements that is specific "kubeadm init"-only runtime
|
||||
// information.
|
||||
type InitConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// ClusterConfiguration holds the cluster-wide information, and embeds that struct (which can be (un)marshalled separately as well)
|
||||
// When InitConfiguration is marshalled to bytes in the external version, this information IS NOT preserved (which can be seen from
|
||||
// the `json:"-"` tag. This is due to that when InitConfiguration is (un)marshalled, it turns into two YAML documents, one for the
|
||||
// InitConfiguration and ClusterConfiguration. Hence, the information must not be duplicated, and is therefore omitted here.
|
||||
ClusterConfiguration `json:"-"`
|
||||
|
||||
// `kubeadm init`-only information. These fields are solely used the first time `kubeadm init` runs.
|
||||
// After that, the information in the fields IS NOT uploaded to the `kubeadm-config` ConfigMap
|
||||
// that is used by `kubeadm upgrade` for instance. These fields must be omitempty.
|
||||
|
||||
// BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create.
|
||||
// This information IS NOT uploaded to the kubeadm cluster configmap, partly because of its sensitive nature
|
||||
BootstrapTokens []BootstrapToken `json:"bootstrapTokens,omitempty"`
|
||||
|
||||
// NodeRegistration holds fields that relate to registering the new control-plane node to the cluster
|
||||
NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty"`
|
||||
|
||||
// LocalAPIEndpoint represents the endpoint of the API server instance that's deployed on this control plane node
|
||||
// In HA setups, this differs from ClusterConfiguration.ControlPlaneEndpoint in the sense that ControlPlaneEndpoint
|
||||
// is the global endpoint for the cluster, which then loadbalances the requests to each individual API server. This
|
||||
// configuration object lets you customize what IP/DNS name and port the local API server advertises it's accessible
|
||||
// on. By default, kubeadm tries to auto-detect the IP of the default interface and use that, but in case that process
|
||||
// fails you may set the desired value here.
|
||||
LocalAPIEndpoint APIEndpoint `json:"localAPIEndpoint,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// ClusterConfiguration contains cluster-wide configuration for a kubeadm cluster
|
||||
type ClusterConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// Etcd holds configuration for etcd.
|
||||
Etcd Etcd `json:"etcd"`
|
||||
|
||||
// Networking holds configuration for the networking topology of the cluster.
|
||||
Networking Networking `json:"networking"`
|
||||
|
||||
// KubernetesVersion is the target version of the control plane.
|
||||
KubernetesVersion string `json:"kubernetesVersion"`
|
||||
|
||||
// ControlPlaneEndpoint sets a stable IP address or DNS name for the control plane; it
|
||||
// can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port.
|
||||
// In case the ControlPlaneEndpoint is not specified, the AdvertiseAddress + BindPort
|
||||
// are used; in case the ControlPlaneEndpoint is specified but without a TCP port,
|
||||
// the BindPort is used.
|
||||
// Possible usages are:
|
||||
// e.g. In a cluster with more than one control plane instances, this field should be
|
||||
// assigned the address of the external load balancer in front of the
|
||||
// control plane instances.
|
||||
// e.g. in environments with enforced node recycling, the ControlPlaneEndpoint
|
||||
// could be used for assigning a stable DNS to the control plane.
|
||||
ControlPlaneEndpoint string `json:"controlPlaneEndpoint"`
|
||||
|
||||
// APIServer contains extra settings for the API server control plane component
|
||||
APIServer APIServer `json:"apiServer,omitempty"`
|
||||
|
||||
// ControllerManager contains extra settings for the controller manager control plane component
|
||||
ControllerManager ControlPlaneComponent `json:"controllerManager,omitempty"`
|
||||
|
||||
// Scheduler contains extra settings for the scheduler control plane component
|
||||
Scheduler ControlPlaneComponent `json:"scheduler,omitempty"`
|
||||
|
||||
// DNS defines the options for the DNS add-on installed in the cluster.
|
||||
DNS DNS `json:"dns"`
|
||||
|
||||
// CertificatesDir specifies where to store or look for all required certificates.
|
||||
CertificatesDir string `json:"certificatesDir"`
|
||||
|
||||
// ImageRepository sets the container registry to pull images from.
|
||||
// If empty, `k8s.gcr.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`)
|
||||
// `gcr.io/kubernetes-ci-images` will be used as a default for control plane components and for kube-proxy, while `k8s.gcr.io`
|
||||
// will be used for all the other images.
|
||||
ImageRepository string `json:"imageRepository"`
|
||||
|
||||
// UseHyperKubeImage controls if hyperkube should be used for Kubernetes components instead of their respective separate images
|
||||
UseHyperKubeImage bool `json:"useHyperKubeImage,omitempty"`
|
||||
|
||||
// FeatureGates enabled by the user.
|
||||
FeatureGates map[string]bool `json:"featureGates,omitempty"`
|
||||
|
||||
// The cluster name
|
||||
ClusterName string `json:"clusterName,omitempty"`
|
||||
}
|
||||
|
||||
// ControlPlaneComponent holds settings common to control plane component of the cluster
|
||||
type ControlPlaneComponent struct {
|
||||
// ExtraArgs is an extra set of flags to pass to the control plane component.
|
||||
// TODO: This is temporary and ideally we would like to switch all components to
|
||||
// use ComponentConfig + ConfigMaps.
|
||||
ExtraArgs map[string]string `json:"extraArgs,omitempty"`
|
||||
|
||||
// ExtraVolumes is an extra set of host volumes, mounted to the control plane component.
|
||||
ExtraVolumes []HostPathMount `json:"extraVolumes,omitempty"`
|
||||
}
|
||||
|
||||
// APIServer holds settings necessary for API server deployments in the cluster
|
||||
type APIServer struct {
|
||||
ControlPlaneComponent `json:",inline"`
|
||||
|
||||
// CertSANs sets extra Subject Alternative Names for the API Server signing cert.
|
||||
CertSANs []string `json:"certSANs,omitempty"`
|
||||
|
||||
// TimeoutForControlPlane controls the timeout that we use for API server to appear
|
||||
TimeoutForControlPlane *metav1.Duration `json:"timeoutForControlPlane,omitempty"`
|
||||
}
|
||||
|
||||
// DNSAddOnType defines string identifying DNS add-on types
|
||||
type DNSAddOnType string
|
||||
|
||||
const (
|
||||
// CoreDNS add-on type
|
||||
CoreDNS DNSAddOnType = "CoreDNS"
|
||||
|
||||
// KubeDNS add-on type
|
||||
KubeDNS DNSAddOnType = "kube-dns"
|
||||
)
|
||||
|
||||
// DNS defines the DNS addon that should be used in the cluster
|
||||
type DNS struct {
|
||||
// Type defines the DNS add-on to be used
|
||||
Type DNSAddOnType `json:"type"`
|
||||
|
||||
// ImageMeta allows to customize the image used for the DNS component
|
||||
ImageMeta `json:",inline"`
|
||||
}
|
||||
|
||||
// ImageMeta allows to customize the image used for components that are not
|
||||
// originated from the Kubernetes/Kubernetes release process
|
||||
type ImageMeta struct {
|
||||
// ImageRepository sets the container registry to pull images from.
|
||||
// if not set, the ImageRepository defined in ClusterConfiguration will be used instead.
|
||||
ImageRepository string `json:"imageRepository,omitempty"`
|
||||
|
||||
// ImageTag allows to specify a tag for the image.
|
||||
// In case this value is set, kubeadm does not change automatically the version of the above components during upgrades.
|
||||
ImageTag string `json:"imageTag,omitempty"`
|
||||
|
||||
//TODO: evaluate if we need also a ImageName based on user feedbacks
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// ClusterStatus contains the cluster status. The ClusterStatus will be stored in the kubeadm-config
|
||||
// ConfigMap in the cluster, and then updated by kubeadm when additional control plane instance joins or leaves the cluster.
|
||||
type ClusterStatus struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// APIEndpoints currently available in the cluster, one for each control plane/api server instance.
|
||||
// The key of the map is the IP of the host's default interface
|
||||
APIEndpoints map[string]APIEndpoint `json:"apiEndpoints"`
|
||||
}
|
||||
|
||||
// APIEndpoint struct contains elements of API server instance deployed on a node.
|
||||
type APIEndpoint struct {
|
||||
// AdvertiseAddress sets the IP address for the API server to advertise.
|
||||
AdvertiseAddress string `json:"advertiseAddress"`
|
||||
|
||||
// BindPort sets the secure port for the API Server to bind to.
|
||||
// Defaults to 6443.
|
||||
BindPort int32 `json:"bindPort"`
|
||||
}
|
||||
|
||||
// NodeRegistrationOptions holds fields that relate to registering a new control-plane or node to the cluster, either via "kubeadm init" or "kubeadm join"
|
||||
type NodeRegistrationOptions struct {
|
||||
|
||||
// Name is the `.Metadata.Name` field of the Node API object that will be created in this `kubeadm init` or `kubeadm join` operation.
|
||||
// This field is also used in the CommonName field of the kubelet's client certificate to the API server.
|
||||
// Defaults to the hostname of the node if not provided.
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// CRISocket is used to retrieve container runtime info. This information will be annotated to the Node API object, for later re-use
|
||||
CRISocket string `json:"criSocket,omitempty"`
|
||||
|
||||
// Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the `kubeadm init` process
|
||||
// it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your control-plane node, set this field to an
|
||||
// empty slice, i.e. `taints: {}` in the YAML file. This field is solely used for Node registration.
|
||||
Taints []v1.Taint `json:"taints,omitempty"`
|
||||
|
||||
// KubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file
|
||||
// kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap
|
||||
// Flags have higher priority when parsing. These values are local and specific to the node kubeadm is executing on.
|
||||
KubeletExtraArgs map[string]string `json:"kubeletExtraArgs,omitempty"`
|
||||
}
|
||||
|
||||
// Networking contains elements describing cluster's networking configuration
|
||||
type Networking struct {
|
||||
// ServiceSubnet is the subnet used by k8s services. Defaults to "10.96.0.0/12".
|
||||
ServiceSubnet string `json:"serviceSubnet"`
|
||||
// PodSubnet is the subnet used by pods.
|
||||
PodSubnet string `json:"podSubnet"`
|
||||
// DNSDomain is the dns domain used by k8s services. Defaults to "cluster.local".
|
||||
DNSDomain string `json:"dnsDomain"`
|
||||
}
|
||||
|
||||
// BootstrapToken describes one bootstrap token, stored as a Secret in the cluster
|
||||
type BootstrapToken struct {
|
||||
// Token is used for establishing bidirectional trust between nodes and control-planes.
|
||||
// Used for joining nodes in the cluster.
|
||||
Token *BootstrapTokenString `json:"token"`
|
||||
// Description sets a human-friendly message why this token exists and what it's used
|
||||
// for, so other administrators can know its purpose.
|
||||
Description string `json:"description,omitempty"`
|
||||
// TTL defines the time to live for this token. Defaults to 24h.
|
||||
// Expires and TTL are mutually exclusive.
|
||||
TTL *metav1.Duration `json:"ttl,omitempty"`
|
||||
// Expires specifies the timestamp when this token expires. Defaults to being set
|
||||
// dynamically at runtime based on the TTL. Expires and TTL are mutually exclusive.
|
||||
Expires *metav1.Time `json:"expires,omitempty"`
|
||||
// Usages describes the ways in which this token can be used. Can by default be used
|
||||
// for establishing bidirectional trust, but that can be changed here.
|
||||
Usages []string `json:"usages,omitempty"`
|
||||
// Groups specifies the extra groups that this token will authenticate as when/if
|
||||
// used for authentication
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
}
|
||||
|
||||
// Etcd contains elements describing Etcd configuration.
|
||||
type Etcd struct {
|
||||
|
||||
// Local provides configuration knobs for configuring the local etcd instance
|
||||
// Local and External are mutually exclusive
|
||||
Local *LocalEtcd `json:"local,omitempty"`
|
||||
|
||||
// External describes how to connect to an external etcd cluster
|
||||
// Local and External are mutually exclusive
|
||||
External *ExternalEtcd `json:"external,omitempty"`
|
||||
}
|
||||
|
||||
// LocalEtcd describes that kubeadm should run an etcd cluster locally
|
||||
type LocalEtcd struct {
|
||||
// ImageMeta allows to customize the container used for etcd
|
||||
ImageMeta `json:",inline"`
|
||||
|
||||
// DataDir is the directory etcd will place its data.
|
||||
// Defaults to "/var/lib/etcd".
|
||||
DataDir string `json:"dataDir"`
|
||||
|
||||
// ExtraArgs are extra arguments provided to the etcd binary
|
||||
// when run inside a static pod.
|
||||
ExtraArgs map[string]string `json:"extraArgs,omitempty"`
|
||||
|
||||
// ServerCertSANs sets extra Subject Alternative Names for the etcd server signing cert.
|
||||
ServerCertSANs []string `json:"serverCertSANs,omitempty"`
|
||||
// PeerCertSANs sets extra Subject Alternative Names for the etcd peer signing cert.
|
||||
PeerCertSANs []string `json:"peerCertSANs,omitempty"`
|
||||
}
|
||||
|
||||
// ExternalEtcd describes an external etcd cluster.
|
||||
// Kubeadm has no knowledge of where certificate files live and they must be supplied.
|
||||
type ExternalEtcd struct {
|
||||
// Endpoints of etcd members. Required for ExternalEtcd.
|
||||
Endpoints []string `json:"endpoints"`
|
||||
|
||||
// CAFile is an SSL Certificate Authority file used to secure etcd communication.
|
||||
// Required if using a TLS connection.
|
||||
CAFile string `json:"caFile"`
|
||||
|
||||
// CertFile is an SSL certification file used to secure etcd communication.
|
||||
// Required if using a TLS connection.
|
||||
CertFile string `json:"certFile"`
|
||||
|
||||
// KeyFile is an SSL key file used to secure etcd communication.
|
||||
// Required if using a TLS connection.
|
||||
KeyFile string `json:"keyFile"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// JoinConfiguration contains elements describing a particular node.
|
||||
type JoinConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// NodeRegistration holds fields that relate to registering the new control-plane node to the cluster
|
||||
NodeRegistration NodeRegistrationOptions `json:"nodeRegistration"`
|
||||
|
||||
// CACertPath is the path to the SSL certificate authority used to
|
||||
// secure comunications between node and control-plane.
|
||||
// Defaults to "/etc/kubernetes/pki/ca.crt".
|
||||
CACertPath string `json:"caCertPath"`
|
||||
|
||||
// Discovery specifies the options for the kubelet to use during the TLS Bootstrap process
|
||||
Discovery Discovery `json:"discovery"`
|
||||
|
||||
// ControlPlane defines the additional control plane instance to be deployed on the joining node.
|
||||
// If nil, no additional control plane instance will be deployed.
|
||||
ControlPlane *JoinControlPlane `json:"controlPlane,omitempty"`
|
||||
}
|
||||
|
||||
// JoinControlPlane contains elements describing an additional control plane instance to be deployed on the joining node.
|
||||
type JoinControlPlane struct {
|
||||
// LocalAPIEndpoint represents the endpoint of the API server instance to be deployed on this node.
|
||||
LocalAPIEndpoint APIEndpoint `json:"localAPIEndpoint,omitempty"`
|
||||
}
|
||||
|
||||
// Discovery specifies the options for the kubelet to use during the TLS Bootstrap process
|
||||
type Discovery struct {
|
||||
// BootstrapToken is used to set the options for bootstrap token based discovery
|
||||
// BootstrapToken and File are mutually exclusive
|
||||
BootstrapToken *BootstrapTokenDiscovery `json:"bootstrapToken,omitempty"`
|
||||
|
||||
// File is used to specify a file or URL to a kubeconfig file from which to load cluster information
|
||||
// BootstrapToken and File are mutually exclusive
|
||||
File *FileDiscovery `json:"file,omitempty"`
|
||||
|
||||
// TLSBootstrapToken is a token used for TLS bootstrapping.
|
||||
// If .BootstrapToken is set, this field is defaulted to .BootstrapToken.Token, but can be overridden.
|
||||
// If .File is set, this field **must be set** in case the KubeConfigFile does not contain any other authentication information
|
||||
TLSBootstrapToken string `json:"tlsBootstrapToken"`
|
||||
|
||||
// Timeout modifies the discovery timeout
|
||||
Timeout *metav1.Duration `json:"timeout,omitempty"`
|
||||
}
|
||||
|
||||
// BootstrapTokenDiscovery is used to set the options for bootstrap token based discovery
|
||||
type BootstrapTokenDiscovery struct {
|
||||
// Token is a token used to validate cluster information
|
||||
// fetched from the control-plane.
|
||||
Token string `json:"token"`
|
||||
|
||||
// APIServerEndpoint is an IP or domain name to the API server from which info will be fetched.
|
||||
APIServerEndpoint string `json:"apiServerEndpoint,omitempty"`
|
||||
|
||||
// CACertHashes specifies a set of public key pins to verify
|
||||
// when token-based discovery is used. The root CA found during discovery
|
||||
// must match one of these values. Specifying an empty set disables root CA
|
||||
// pinning, which can be unsafe. Each hash is specified as "<type>:<value>",
|
||||
// where the only currently supported type is "sha256". This is a hex-encoded
|
||||
// SHA-256 hash of the Subject Public Key Info (SPKI) object in DER-encoded
|
||||
// ASN.1. These hashes can be calculated using, for example, OpenSSL:
|
||||
// openssl x509 -pubkey -in ca.crt openssl rsa -pubin -outform der 2>&/dev/null | openssl dgst -sha256 -hex
|
||||
CACertHashes []string `json:"caCertHashes,omitempty"`
|
||||
|
||||
// UnsafeSkipCAVerification allows token-based discovery
|
||||
// without CA verification via CACertHashes. This can weaken
|
||||
// the security of kubeadm since other nodes can impersonate the control-plane.
|
||||
UnsafeSkipCAVerification bool `json:"unsafeSkipCAVerification"`
|
||||
}
|
||||
|
||||
// FileDiscovery is used to specify a file or URL to a kubeconfig file from which to load cluster information
|
||||
type FileDiscovery struct {
|
||||
// KubeConfigPath is used to specify the actual file path or URL to the kubeconfig file from which to load cluster information
|
||||
KubeConfigPath string `json:"kubeConfigPath"`
|
||||
}
|
||||
|
||||
// HostPathMount contains elements describing volumes that are mounted from the
|
||||
// host.
|
||||
type HostPathMount struct {
|
||||
// Name of the volume inside the pod template.
|
||||
Name string `json:"name"`
|
||||
// HostPath is the path in the host that will be mounted inside
|
||||
// the pod.
|
||||
HostPath string `json:"hostPath"`
|
||||
// MountPath is the path inside the pod where hostPath will be mounted.
|
||||
MountPath string `json:"mountPath"`
|
||||
// ReadOnly controls write access to the volume
|
||||
ReadOnly bool `json:"readOnly,omitempty"`
|
||||
// PathType is the type of the HostPath.
|
||||
PathType v1.HostPathType `json:"pathType,omitempty"`
|
||||
}
|
|
@ -1,839 +0,0 @@
|
|||
// +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"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
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((*APIEndpoint)(nil), (*kubeadm.APIEndpoint)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(a.(*APIEndpoint), b.(*kubeadm.APIEndpoint), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.APIEndpoint)(nil), (*APIEndpoint)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(a.(*kubeadm.APIEndpoint), b.(*APIEndpoint), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*APIServer)(nil), (*kubeadm.APIServer)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_APIServer_To_kubeadm_APIServer(a.(*APIServer), b.(*kubeadm.APIServer), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.APIServer)(nil), (*APIServer)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_APIServer_To_v1beta1_APIServer(a.(*kubeadm.APIServer), b.(*APIServer), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*BootstrapToken)(nil), (*kubeadm.BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_BootstrapToken_To_kubeadm_BootstrapToken(a.(*BootstrapToken), b.(*kubeadm.BootstrapToken), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapToken)(nil), (*BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_BootstrapToken_To_v1beta1_BootstrapToken(a.(*kubeadm.BootstrapToken), b.(*BootstrapToken), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*BootstrapTokenDiscovery)(nil), (*kubeadm.BootstrapTokenDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(a.(*BootstrapTokenDiscovery), b.(*kubeadm.BootstrapTokenDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapTokenDiscovery)(nil), (*BootstrapTokenDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_BootstrapTokenDiscovery_To_v1beta1_BootstrapTokenDiscovery(a.(*kubeadm.BootstrapTokenDiscovery), b.(*BootstrapTokenDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*BootstrapTokenString)(nil), (*kubeadm.BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_BootstrapTokenString_To_kubeadm_BootstrapTokenString(a.(*BootstrapTokenString), b.(*kubeadm.BootstrapTokenString), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapTokenString)(nil), (*BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_BootstrapTokenString_To_v1beta1_BootstrapTokenString(a.(*kubeadm.BootstrapTokenString), b.(*BootstrapTokenString), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ClusterConfiguration)(nil), (*kubeadm.ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration(a.(*ClusterConfiguration), b.(*kubeadm.ClusterConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ClusterStatus)(nil), (*kubeadm.ClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_ClusterStatus_To_kubeadm_ClusterStatus(a.(*ClusterStatus), b.(*kubeadm.ClusterStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterStatus)(nil), (*ClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_ClusterStatus_To_v1beta1_ClusterStatus(a.(*kubeadm.ClusterStatus), b.(*ClusterStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ControlPlaneComponent)(nil), (*kubeadm.ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(a.(*ControlPlaneComponent), b.(*kubeadm.ControlPlaneComponent), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.ControlPlaneComponent)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(a.(*kubeadm.ControlPlaneComponent), b.(*ControlPlaneComponent), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*DNS)(nil), (*kubeadm.DNS)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_DNS_To_kubeadm_DNS(a.(*DNS), b.(*kubeadm.DNS), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.DNS)(nil), (*DNS)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_DNS_To_v1beta1_DNS(a.(*kubeadm.DNS), b.(*DNS), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*Discovery)(nil), (*kubeadm.Discovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_Discovery_To_kubeadm_Discovery(a.(*Discovery), b.(*kubeadm.Discovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.Discovery)(nil), (*Discovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_Discovery_To_v1beta1_Discovery(a.(*kubeadm.Discovery), b.(*Discovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*Etcd)(nil), (*kubeadm.Etcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_Etcd_To_kubeadm_Etcd(a.(*Etcd), b.(*kubeadm.Etcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.Etcd)(nil), (*Etcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_Etcd_To_v1beta1_Etcd(a.(*kubeadm.Etcd), b.(*Etcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ExternalEtcd)(nil), (*kubeadm.ExternalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_ExternalEtcd_To_kubeadm_ExternalEtcd(a.(*ExternalEtcd), b.(*kubeadm.ExternalEtcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.ExternalEtcd)(nil), (*ExternalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_ExternalEtcd_To_v1beta1_ExternalEtcd(a.(*kubeadm.ExternalEtcd), b.(*ExternalEtcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*FileDiscovery)(nil), (*kubeadm.FileDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_FileDiscovery_To_kubeadm_FileDiscovery(a.(*FileDiscovery), b.(*kubeadm.FileDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.FileDiscovery)(nil), (*FileDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_FileDiscovery_To_v1beta1_FileDiscovery(a.(*kubeadm.FileDiscovery), b.(*FileDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*HostPathMount)(nil), (*kubeadm.HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_HostPathMount_To_kubeadm_HostPathMount(a.(*HostPathMount), b.(*kubeadm.HostPathMount), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.HostPathMount)(nil), (*HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_HostPathMount_To_v1beta1_HostPathMount(a.(*kubeadm.HostPathMount), b.(*HostPathMount), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ImageMeta)(nil), (*kubeadm.ImageMeta)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(a.(*ImageMeta), b.(*kubeadm.ImageMeta), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.ImageMeta)(nil), (*ImageMeta)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(a.(*kubeadm.ImageMeta), b.(*ImageMeta), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*InitConfiguration)(nil), (*kubeadm.InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_InitConfiguration_To_kubeadm_InitConfiguration(a.(*InitConfiguration), b.(*kubeadm.InitConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.InitConfiguration)(nil), (*InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_InitConfiguration_To_v1beta1_InitConfiguration(a.(*kubeadm.InitConfiguration), b.(*InitConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*JoinConfiguration)(nil), (*kubeadm.JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_JoinConfiguration_To_kubeadm_JoinConfiguration(a.(*JoinConfiguration), b.(*kubeadm.JoinConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.JoinConfiguration)(nil), (*JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_JoinConfiguration_To_v1beta1_JoinConfiguration(a.(*kubeadm.JoinConfiguration), b.(*JoinConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*JoinControlPlane)(nil), (*kubeadm.JoinControlPlane)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_JoinControlPlane_To_kubeadm_JoinControlPlane(a.(*JoinControlPlane), b.(*kubeadm.JoinControlPlane), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.JoinControlPlane)(nil), (*JoinControlPlane)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_JoinControlPlane_To_v1beta1_JoinControlPlane(a.(*kubeadm.JoinControlPlane), b.(*JoinControlPlane), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*LocalEtcd)(nil), (*kubeadm.LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_LocalEtcd_To_kubeadm_LocalEtcd(a.(*LocalEtcd), b.(*kubeadm.LocalEtcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.LocalEtcd)(nil), (*LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_LocalEtcd_To_v1beta1_LocalEtcd(a.(*kubeadm.LocalEtcd), b.(*LocalEtcd), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*Networking)(nil), (*kubeadm.Networking)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_Networking_To_kubeadm_Networking(a.(*Networking), b.(*kubeadm.Networking), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.Networking)(nil), (*Networking)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_Networking_To_v1beta1_Networking(a.(*kubeadm.Networking), b.(*Networking), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*NodeRegistrationOptions)(nil), (*kubeadm.NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(a.(*NodeRegistrationOptions), b.(*kubeadm.NodeRegistrationOptions), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kubeadm.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(a.(*kubeadm.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(in *APIEndpoint, out *kubeadm.APIEndpoint, s conversion.Scope) error {
|
||||
out.AdvertiseAddress = in.AdvertiseAddress
|
||||
out.BindPort = in.BindPort
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint is an autogenerated conversion function.
|
||||
func Convert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(in *APIEndpoint, out *kubeadm.APIEndpoint, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(in *kubeadm.APIEndpoint, out *APIEndpoint, s conversion.Scope) error {
|
||||
out.AdvertiseAddress = in.AdvertiseAddress
|
||||
out.BindPort = in.BindPort
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint is an autogenerated conversion function.
|
||||
func Convert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(in *kubeadm.APIEndpoint, out *APIEndpoint, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_APIServer_To_kubeadm_APIServer(in *APIServer, out *kubeadm.APIServer, s conversion.Scope) error {
|
||||
if err := Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(&in.ControlPlaneComponent, &out.ControlPlaneComponent, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CertSANs = *(*[]string)(unsafe.Pointer(&in.CertSANs))
|
||||
out.TimeoutForControlPlane = (*v1.Duration)(unsafe.Pointer(in.TimeoutForControlPlane))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_APIServer_To_kubeadm_APIServer is an autogenerated conversion function.
|
||||
func Convert_v1beta1_APIServer_To_kubeadm_APIServer(in *APIServer, out *kubeadm.APIServer, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_APIServer_To_kubeadm_APIServer(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_APIServer_To_v1beta1_APIServer(in *kubeadm.APIServer, out *APIServer, s conversion.Scope) error {
|
||||
if err := Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(&in.ControlPlaneComponent, &out.ControlPlaneComponent, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CertSANs = *(*[]string)(unsafe.Pointer(&in.CertSANs))
|
||||
out.TimeoutForControlPlane = (*v1.Duration)(unsafe.Pointer(in.TimeoutForControlPlane))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_APIServer_To_v1beta1_APIServer is an autogenerated conversion function.
|
||||
func Convert_kubeadm_APIServer_To_v1beta1_APIServer(in *kubeadm.APIServer, out *APIServer, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_APIServer_To_v1beta1_APIServer(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
|
||||
out.Token = (*kubeadm.BootstrapTokenString)(unsafe.Pointer(in.Token))
|
||||
out.Description = in.Description
|
||||
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
|
||||
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
|
||||
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
|
||||
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_BootstrapToken_To_kubeadm_BootstrapToken is an autogenerated conversion function.
|
||||
func Convert_v1beta1_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_BootstrapToken_To_kubeadm_BootstrapToken(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_BootstrapToken_To_v1beta1_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
|
||||
out.Token = (*BootstrapTokenString)(unsafe.Pointer(in.Token))
|
||||
out.Description = in.Description
|
||||
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
|
||||
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
|
||||
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
|
||||
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_BootstrapToken_To_v1beta1_BootstrapToken is an autogenerated conversion function.
|
||||
func Convert_kubeadm_BootstrapToken_To_v1beta1_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_BootstrapToken_To_v1beta1_BootstrapToken(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(in *BootstrapTokenDiscovery, out *kubeadm.BootstrapTokenDiscovery, s conversion.Scope) error {
|
||||
out.Token = in.Token
|
||||
out.APIServerEndpoint = in.APIServerEndpoint
|
||||
out.CACertHashes = *(*[]string)(unsafe.Pointer(&in.CACertHashes))
|
||||
out.UnsafeSkipCAVerification = in.UnsafeSkipCAVerification
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery is an autogenerated conversion function.
|
||||
func Convert_v1beta1_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(in *BootstrapTokenDiscovery, out *kubeadm.BootstrapTokenDiscovery, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_BootstrapTokenDiscovery_To_v1beta1_BootstrapTokenDiscovery(in *kubeadm.BootstrapTokenDiscovery, out *BootstrapTokenDiscovery, s conversion.Scope) error {
|
||||
out.Token = in.Token
|
||||
out.APIServerEndpoint = in.APIServerEndpoint
|
||||
out.CACertHashes = *(*[]string)(unsafe.Pointer(&in.CACertHashes))
|
||||
out.UnsafeSkipCAVerification = in.UnsafeSkipCAVerification
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_BootstrapTokenDiscovery_To_v1beta1_BootstrapTokenDiscovery is an autogenerated conversion function.
|
||||
func Convert_kubeadm_BootstrapTokenDiscovery_To_v1beta1_BootstrapTokenDiscovery(in *kubeadm.BootstrapTokenDiscovery, out *BootstrapTokenDiscovery, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_BootstrapTokenDiscovery_To_v1beta1_BootstrapTokenDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
|
||||
out.ID = in.ID
|
||||
out.Secret = in.Secret
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_BootstrapTokenString_To_kubeadm_BootstrapTokenString is an autogenerated conversion function.
|
||||
func Convert_v1beta1_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_BootstrapTokenString_To_v1beta1_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
|
||||
out.ID = in.ID
|
||||
out.Secret = in.Secret
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_BootstrapTokenString_To_v1beta1_BootstrapTokenString is an autogenerated conversion function.
|
||||
func Convert_kubeadm_BootstrapTokenString_To_v1beta1_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_BootstrapTokenString_To_v1beta1_BootstrapTokenString(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_v1beta1_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta1_Networking_To_kubeadm_Networking(&in.Networking, &out.Networking, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.KubernetesVersion = in.KubernetesVersion
|
||||
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
|
||||
if err := Convert_v1beta1_APIServer_To_kubeadm_APIServer(&in.APIServer, &out.APIServer, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta1_DNS_To_kubeadm_DNS(&in.DNS, &out.DNS, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CertificatesDir = in.CertificatesDir
|
||||
out.ImageRepository = in.ImageRepository
|
||||
out.UseHyperKubeImage = in.UseHyperKubeImage
|
||||
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
|
||||
out.ClusterName = in.ClusterName
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration(in *kubeadm.ClusterConfiguration, out *ClusterConfiguration, s conversion.Scope) error {
|
||||
// INFO: in.ComponentConfigs opted out of conversion generation
|
||||
if err := Convert_kubeadm_Etcd_To_v1beta1_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_kubeadm_Networking_To_v1beta1_Networking(&in.Networking, &out.Networking, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.KubernetesVersion = in.KubernetesVersion
|
||||
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
|
||||
if err := Convert_kubeadm_APIServer_To_v1beta1_APIServer(&in.APIServer, &out.APIServer, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_kubeadm_DNS_To_v1beta1_DNS(&in.DNS, &out.DNS, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CertificatesDir = in.CertificatesDir
|
||||
out.ImageRepository = in.ImageRepository
|
||||
// INFO: in.CIImageRepository opted out of conversion generation
|
||||
out.UseHyperKubeImage = in.UseHyperKubeImage
|
||||
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
|
||||
out.ClusterName = in.ClusterName
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration is an autogenerated conversion function.
|
||||
func Convert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration(in *kubeadm.ClusterConfiguration, out *ClusterConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ClusterStatus_To_kubeadm_ClusterStatus(in *ClusterStatus, out *kubeadm.ClusterStatus, s conversion.Scope) error {
|
||||
out.APIEndpoints = *(*map[string]kubeadm.APIEndpoint)(unsafe.Pointer(&in.APIEndpoints))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ClusterStatus_To_kubeadm_ClusterStatus is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ClusterStatus_To_kubeadm_ClusterStatus(in *ClusterStatus, out *kubeadm.ClusterStatus, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ClusterStatus_To_kubeadm_ClusterStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_ClusterStatus_To_v1beta1_ClusterStatus(in *kubeadm.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
|
||||
out.APIEndpoints = *(*map[string]APIEndpoint)(unsafe.Pointer(&in.APIEndpoints))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_ClusterStatus_To_v1beta1_ClusterStatus is an autogenerated conversion function.
|
||||
func Convert_kubeadm_ClusterStatus_To_v1beta1_ClusterStatus(in *kubeadm.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_ClusterStatus_To_v1beta1_ClusterStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(in *ControlPlaneComponent, out *kubeadm.ControlPlaneComponent, s conversion.Scope) error {
|
||||
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
|
||||
out.ExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.ExtraVolumes))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(in *ControlPlaneComponent, out *kubeadm.ControlPlaneComponent, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(in *kubeadm.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error {
|
||||
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
|
||||
out.ExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.ExtraVolumes))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent is an autogenerated conversion function.
|
||||
func Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(in *kubeadm.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_DNS_To_kubeadm_DNS(in *DNS, out *kubeadm.DNS, s conversion.Scope) error {
|
||||
out.Type = kubeadm.DNSAddOnType(in.Type)
|
||||
if err := Convert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_DNS_To_kubeadm_DNS is an autogenerated conversion function.
|
||||
func Convert_v1beta1_DNS_To_kubeadm_DNS(in *DNS, out *kubeadm.DNS, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_DNS_To_kubeadm_DNS(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_DNS_To_v1beta1_DNS(in *kubeadm.DNS, out *DNS, s conversion.Scope) error {
|
||||
out.Type = DNSAddOnType(in.Type)
|
||||
if err := Convert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_DNS_To_v1beta1_DNS is an autogenerated conversion function.
|
||||
func Convert_kubeadm_DNS_To_v1beta1_DNS(in *kubeadm.DNS, out *DNS, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_DNS_To_v1beta1_DNS(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_Discovery_To_kubeadm_Discovery(in *Discovery, out *kubeadm.Discovery, s conversion.Scope) error {
|
||||
out.BootstrapToken = (*kubeadm.BootstrapTokenDiscovery)(unsafe.Pointer(in.BootstrapToken))
|
||||
out.File = (*kubeadm.FileDiscovery)(unsafe.Pointer(in.File))
|
||||
out.TLSBootstrapToken = in.TLSBootstrapToken
|
||||
out.Timeout = (*v1.Duration)(unsafe.Pointer(in.Timeout))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_Discovery_To_kubeadm_Discovery is an autogenerated conversion function.
|
||||
func Convert_v1beta1_Discovery_To_kubeadm_Discovery(in *Discovery, out *kubeadm.Discovery, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_Discovery_To_kubeadm_Discovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_Discovery_To_v1beta1_Discovery(in *kubeadm.Discovery, out *Discovery, s conversion.Scope) error {
|
||||
out.BootstrapToken = (*BootstrapTokenDiscovery)(unsafe.Pointer(in.BootstrapToken))
|
||||
out.File = (*FileDiscovery)(unsafe.Pointer(in.File))
|
||||
out.TLSBootstrapToken = in.TLSBootstrapToken
|
||||
out.Timeout = (*v1.Duration)(unsafe.Pointer(in.Timeout))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_Discovery_To_v1beta1_Discovery is an autogenerated conversion function.
|
||||
func Convert_kubeadm_Discovery_To_v1beta1_Discovery(in *kubeadm.Discovery, out *Discovery, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_Discovery_To_v1beta1_Discovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
|
||||
out.Local = (*kubeadm.LocalEtcd)(unsafe.Pointer(in.Local))
|
||||
out.External = (*kubeadm.ExternalEtcd)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_Etcd_To_kubeadm_Etcd is an autogenerated conversion function.
|
||||
func Convert_v1beta1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_Etcd_To_kubeadm_Etcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_Etcd_To_v1beta1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
|
||||
out.Local = (*LocalEtcd)(unsafe.Pointer(in.Local))
|
||||
out.External = (*ExternalEtcd)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_Etcd_To_v1beta1_Etcd is an autogenerated conversion function.
|
||||
func Convert_kubeadm_Etcd_To_v1beta1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_Etcd_To_v1beta1_Etcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error {
|
||||
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
|
||||
out.CAFile = in.CAFile
|
||||
out.CertFile = in.CertFile
|
||||
out.KeyFile = in.KeyFile
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ExternalEtcd_To_kubeadm_ExternalEtcd is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ExternalEtcd_To_kubeadm_ExternalEtcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_ExternalEtcd_To_v1beta1_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error {
|
||||
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
|
||||
out.CAFile = in.CAFile
|
||||
out.CertFile = in.CertFile
|
||||
out.KeyFile = in.KeyFile
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_ExternalEtcd_To_v1beta1_ExternalEtcd is an autogenerated conversion function.
|
||||
func Convert_kubeadm_ExternalEtcd_To_v1beta1_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_ExternalEtcd_To_v1beta1_ExternalEtcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_FileDiscovery_To_kubeadm_FileDiscovery(in *FileDiscovery, out *kubeadm.FileDiscovery, s conversion.Scope) error {
|
||||
out.KubeConfigPath = in.KubeConfigPath
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_FileDiscovery_To_kubeadm_FileDiscovery is an autogenerated conversion function.
|
||||
func Convert_v1beta1_FileDiscovery_To_kubeadm_FileDiscovery(in *FileDiscovery, out *kubeadm.FileDiscovery, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_FileDiscovery_To_kubeadm_FileDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_FileDiscovery_To_v1beta1_FileDiscovery(in *kubeadm.FileDiscovery, out *FileDiscovery, s conversion.Scope) error {
|
||||
out.KubeConfigPath = in.KubeConfigPath
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_FileDiscovery_To_v1beta1_FileDiscovery is an autogenerated conversion function.
|
||||
func Convert_kubeadm_FileDiscovery_To_v1beta1_FileDiscovery(in *kubeadm.FileDiscovery, out *FileDiscovery, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_FileDiscovery_To_v1beta1_FileDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.HostPath = in.HostPath
|
||||
out.MountPath = in.MountPath
|
||||
out.ReadOnly = in.ReadOnly
|
||||
out.PathType = corev1.HostPathType(in.PathType)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_HostPathMount_To_kubeadm_HostPathMount is an autogenerated conversion function.
|
||||
func Convert_v1beta1_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_HostPathMount_To_kubeadm_HostPathMount(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_HostPathMount_To_v1beta1_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.HostPath = in.HostPath
|
||||
out.MountPath = in.MountPath
|
||||
out.ReadOnly = in.ReadOnly
|
||||
out.PathType = corev1.HostPathType(in.PathType)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_HostPathMount_To_v1beta1_HostPathMount is an autogenerated conversion function.
|
||||
func Convert_kubeadm_HostPathMount_To_v1beta1_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_HostPathMount_To_v1beta1_HostPathMount(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(in *ImageMeta, out *kubeadm.ImageMeta, s conversion.Scope) error {
|
||||
out.ImageRepository = in.ImageRepository
|
||||
out.ImageTag = in.ImageTag
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ImageMeta_To_kubeadm_ImageMeta is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(in *ImageMeta, out *kubeadm.ImageMeta, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(in *kubeadm.ImageMeta, out *ImageMeta, s conversion.Scope) error {
|
||||
out.ImageRepository = in.ImageRepository
|
||||
out.ImageTag = in.ImageTag
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_ImageMeta_To_v1beta1_ImageMeta is an autogenerated conversion function.
|
||||
func Convert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(in *kubeadm.ImageMeta, out *ImageMeta, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration(&in.ClusterConfiguration, &out.ClusterConfiguration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.BootstrapTokens = *(*[]kubeadm.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
|
||||
if err := Convert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(&in.LocalAPIEndpoint, &out.LocalAPIEndpoint, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_InitConfiguration_To_kubeadm_InitConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta1_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_InitConfiguration_To_kubeadm_InitConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_InitConfiguration_To_v1beta1_InitConfiguration(in *kubeadm.InitConfiguration, out *InitConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration(&in.ClusterConfiguration, &out.ClusterConfiguration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.BootstrapTokens = *(*[]BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
|
||||
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(&in.LocalAPIEndpoint, &out.LocalAPIEndpoint, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_InitConfiguration_To_v1beta1_InitConfiguration is an autogenerated conversion function.
|
||||
func Convert_kubeadm_InitConfiguration_To_v1beta1_InitConfiguration(in *kubeadm.InitConfiguration, out *InitConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_InitConfiguration_To_v1beta1_InitConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_JoinConfiguration_To_kubeadm_JoinConfiguration(in *JoinConfiguration, out *kubeadm.JoinConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CACertPath = in.CACertPath
|
||||
if err := Convert_v1beta1_Discovery_To_kubeadm_Discovery(&in.Discovery, &out.Discovery, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.ControlPlane = (*kubeadm.JoinControlPlane)(unsafe.Pointer(in.ControlPlane))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_JoinConfiguration_To_kubeadm_JoinConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta1_JoinConfiguration_To_kubeadm_JoinConfiguration(in *JoinConfiguration, out *kubeadm.JoinConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_JoinConfiguration_To_kubeadm_JoinConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_JoinConfiguration_To_v1beta1_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error {
|
||||
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CACertPath = in.CACertPath
|
||||
if err := Convert_kubeadm_Discovery_To_v1beta1_Discovery(&in.Discovery, &out.Discovery, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.ControlPlane = (*JoinControlPlane)(unsafe.Pointer(in.ControlPlane))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_JoinConfiguration_To_v1beta1_JoinConfiguration is an autogenerated conversion function.
|
||||
func Convert_kubeadm_JoinConfiguration_To_v1beta1_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_JoinConfiguration_To_v1beta1_JoinConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_JoinControlPlane_To_kubeadm_JoinControlPlane(in *JoinControlPlane, out *kubeadm.JoinControlPlane, s conversion.Scope) error {
|
||||
if err := Convert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(&in.LocalAPIEndpoint, &out.LocalAPIEndpoint, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_JoinControlPlane_To_kubeadm_JoinControlPlane is an autogenerated conversion function.
|
||||
func Convert_v1beta1_JoinControlPlane_To_kubeadm_JoinControlPlane(in *JoinControlPlane, out *kubeadm.JoinControlPlane, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_JoinControlPlane_To_kubeadm_JoinControlPlane(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_JoinControlPlane_To_v1beta1_JoinControlPlane(in *kubeadm.JoinControlPlane, out *JoinControlPlane, s conversion.Scope) error {
|
||||
if err := Convert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(&in.LocalAPIEndpoint, &out.LocalAPIEndpoint, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_JoinControlPlane_To_v1beta1_JoinControlPlane is an autogenerated conversion function.
|
||||
func Convert_kubeadm_JoinControlPlane_To_v1beta1_JoinControlPlane(in *kubeadm.JoinControlPlane, out *JoinControlPlane, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_JoinControlPlane_To_v1beta1_JoinControlPlane(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error {
|
||||
if err := Convert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.DataDir = in.DataDir
|
||||
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
|
||||
out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs))
|
||||
out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_LocalEtcd_To_kubeadm_LocalEtcd is an autogenerated conversion function.
|
||||
func Convert_v1beta1_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_LocalEtcd_To_kubeadm_LocalEtcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_LocalEtcd_To_v1beta1_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error {
|
||||
if err := Convert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.DataDir = in.DataDir
|
||||
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
|
||||
out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs))
|
||||
out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_LocalEtcd_To_v1beta1_LocalEtcd is an autogenerated conversion function.
|
||||
func Convert_kubeadm_LocalEtcd_To_v1beta1_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_LocalEtcd_To_v1beta1_LocalEtcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
|
||||
out.ServiceSubnet = in.ServiceSubnet
|
||||
out.PodSubnet = in.PodSubnet
|
||||
out.DNSDomain = in.DNSDomain
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_Networking_To_kubeadm_Networking is an autogenerated conversion function.
|
||||
func Convert_v1beta1_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_Networking_To_kubeadm_Networking(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_Networking_To_v1beta1_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
|
||||
out.ServiceSubnet = in.ServiceSubnet
|
||||
out.PodSubnet = in.PodSubnet
|
||||
out.DNSDomain = in.DNSDomain
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_Networking_To_v1beta1_Networking is an autogenerated conversion function.
|
||||
func Convert_kubeadm_Networking_To_v1beta1_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_Networking_To_v1beta1_Networking(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.CRISocket = in.CRISocket
|
||||
out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
|
||||
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions is an autogenerated conversion function.
|
||||
func Convert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.CRISocket = in.CRISocket
|
||||
out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
|
||||
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions is an autogenerated conversion function.
|
||||
func Convert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(in, out, s)
|
||||
}
|
|
@ -1,552 +0,0 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
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 *APIEndpoint) DeepCopyInto(out *APIEndpoint) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIEndpoint.
|
||||
func (in *APIEndpoint) DeepCopy() *APIEndpoint {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(APIEndpoint)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *APIServer) DeepCopyInto(out *APIServer) {
|
||||
*out = *in
|
||||
in.ControlPlaneComponent.DeepCopyInto(&out.ControlPlaneComponent)
|
||||
if in.CertSANs != nil {
|
||||
in, out := &in.CertSANs, &out.CertSANs
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.TimeoutForControlPlane != nil {
|
||||
in, out := &in.TimeoutForControlPlane, &out.TimeoutForControlPlane
|
||||
*out = new(v1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServer.
|
||||
func (in *APIServer) DeepCopy() *APIServer {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(APIServer)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
|
||||
*out = *in
|
||||
if in.Token != nil {
|
||||
in, out := &in.Token, &out.Token
|
||||
*out = new(BootstrapTokenString)
|
||||
**out = **in
|
||||
}
|
||||
if in.TTL != nil {
|
||||
in, out := &in.TTL, &out.TTL
|
||||
*out = new(v1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
if in.Expires != nil {
|
||||
in, out := &in.Expires, &out.Expires
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Usages != nil {
|
||||
in, out := &in.Usages, &out.Usages
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Groups != nil {
|
||||
in, out := &in.Groups, &out.Groups
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken.
|
||||
func (in *BootstrapToken) DeepCopy() *BootstrapToken {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BootstrapToken)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BootstrapTokenDiscovery) DeepCopyInto(out *BootstrapTokenDiscovery) {
|
||||
*out = *in
|
||||
if in.CACertHashes != nil {
|
||||
in, out := &in.CACertHashes, &out.CACertHashes
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenDiscovery.
|
||||
func (in *BootstrapTokenDiscovery) DeepCopy() *BootstrapTokenDiscovery {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BootstrapTokenDiscovery)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BootstrapTokenString) DeepCopyInto(out *BootstrapTokenString) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenString.
|
||||
func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BootstrapTokenString)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.Etcd.DeepCopyInto(&out.Etcd)
|
||||
out.Networking = in.Networking
|
||||
in.APIServer.DeepCopyInto(&out.APIServer)
|
||||
in.ControllerManager.DeepCopyInto(&out.ControllerManager)
|
||||
in.Scheduler.DeepCopyInto(&out.Scheduler)
|
||||
out.DNS = in.DNS
|
||||
if in.FeatureGates != nil {
|
||||
in, out := &in.FeatureGates, &out.FeatureGates
|
||||
*out = make(map[string]bool, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterConfiguration.
|
||||
func (in *ClusterConfiguration) DeepCopy() *ClusterConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ClusterConfiguration) 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 *ClusterStatus) DeepCopyInto(out *ClusterStatus) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
if in.APIEndpoints != nil {
|
||||
in, out := &in.APIEndpoints, &out.APIEndpoints
|
||||
*out = make(map[string]APIEndpoint, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterStatus.
|
||||
func (in *ClusterStatus) DeepCopy() *ClusterStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ClusterStatus) 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 *ControlPlaneComponent) DeepCopyInto(out *ControlPlaneComponent) {
|
||||
*out = *in
|
||||
if in.ExtraArgs != nil {
|
||||
in, out := &in.ExtraArgs, &out.ExtraArgs
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.ExtraVolumes != nil {
|
||||
in, out := &in.ExtraVolumes, &out.ExtraVolumes
|
||||
*out = make([]HostPathMount, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneComponent.
|
||||
func (in *ControlPlaneComponent) DeepCopy() *ControlPlaneComponent {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ControlPlaneComponent)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DNS) DeepCopyInto(out *DNS) {
|
||||
*out = *in
|
||||
out.ImageMeta = in.ImageMeta
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNS.
|
||||
func (in *DNS) DeepCopy() *DNS {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DNS)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Discovery) DeepCopyInto(out *Discovery) {
|
||||
*out = *in
|
||||
if in.BootstrapToken != nil {
|
||||
in, out := &in.BootstrapToken, &out.BootstrapToken
|
||||
*out = new(BootstrapTokenDiscovery)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.File != nil {
|
||||
in, out := &in.File, &out.File
|
||||
*out = new(FileDiscovery)
|
||||
**out = **in
|
||||
}
|
||||
if in.Timeout != nil {
|
||||
in, out := &in.Timeout, &out.Timeout
|
||||
*out = new(v1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Discovery.
|
||||
func (in *Discovery) DeepCopy() *Discovery {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Discovery)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Etcd) DeepCopyInto(out *Etcd) {
|
||||
*out = *in
|
||||
if in.Local != nil {
|
||||
in, out := &in.Local, &out.Local
|
||||
*out = new(LocalEtcd)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(ExternalEtcd)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Etcd.
|
||||
func (in *Etcd) DeepCopy() *Etcd {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Etcd)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalEtcd) DeepCopyInto(out *ExternalEtcd) {
|
||||
*out = *in
|
||||
if in.Endpoints != nil {
|
||||
in, out := &in.Endpoints, &out.Endpoints
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalEtcd.
|
||||
func (in *ExternalEtcd) DeepCopy() *ExternalEtcd {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExternalEtcd)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FileDiscovery) DeepCopyInto(out *FileDiscovery) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileDiscovery.
|
||||
func (in *FileDiscovery) DeepCopy() *FileDiscovery {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FileDiscovery)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HostPathMount) DeepCopyInto(out *HostPathMount) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPathMount.
|
||||
func (in *HostPathMount) DeepCopy() *HostPathMount {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HostPathMount)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImageMeta) DeepCopyInto(out *ImageMeta) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageMeta.
|
||||
func (in *ImageMeta) DeepCopy() *ImageMeta {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImageMeta)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *InitConfiguration) DeepCopyInto(out *InitConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ClusterConfiguration.DeepCopyInto(&out.ClusterConfiguration)
|
||||
if in.BootstrapTokens != nil {
|
||||
in, out := &in.BootstrapTokens, &out.BootstrapTokens
|
||||
*out = make([]BootstrapToken, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
|
||||
out.LocalAPIEndpoint = in.LocalAPIEndpoint
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InitConfiguration.
|
||||
func (in *InitConfiguration) DeepCopy() *InitConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(InitConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *InitConfiguration) 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 *JoinConfiguration) DeepCopyInto(out *JoinConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
|
||||
in.Discovery.DeepCopyInto(&out.Discovery)
|
||||
if in.ControlPlane != nil {
|
||||
in, out := &in.ControlPlane, &out.ControlPlane
|
||||
*out = new(JoinControlPlane)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JoinConfiguration.
|
||||
func (in *JoinConfiguration) DeepCopy() *JoinConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JoinConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *JoinConfiguration) 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 *JoinControlPlane) DeepCopyInto(out *JoinControlPlane) {
|
||||
*out = *in
|
||||
out.LocalAPIEndpoint = in.LocalAPIEndpoint
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JoinControlPlane.
|
||||
func (in *JoinControlPlane) DeepCopy() *JoinControlPlane {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JoinControlPlane)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *LocalEtcd) DeepCopyInto(out *LocalEtcd) {
|
||||
*out = *in
|
||||
out.ImageMeta = in.ImageMeta
|
||||
if in.ExtraArgs != nil {
|
||||
in, out := &in.ExtraArgs, &out.ExtraArgs
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.ServerCertSANs != nil {
|
||||
in, out := &in.ServerCertSANs, &out.ServerCertSANs
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.PeerCertSANs != nil {
|
||||
in, out := &in.PeerCertSANs, &out.PeerCertSANs
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalEtcd.
|
||||
func (in *LocalEtcd) DeepCopy() *LocalEtcd {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(LocalEtcd)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Networking) DeepCopyInto(out *Networking) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Networking.
|
||||
func (in *Networking) DeepCopy() *Networking {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Networking)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) {
|
||||
*out = *in
|
||||
if in.Taints != nil {
|
||||
in, out := &in.Taints, &out.Taints
|
||||
*out = make([]corev1.Taint, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.KubeletExtraArgs != nil {
|
||||
in, out := &in.KubeletExtraArgs, &out.KubeletExtraArgs
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRegistrationOptions.
|
||||
func (in *NodeRegistrationOptions) DeepCopy() *NodeRegistrationOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NodeRegistrationOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
scheme.AddTypeDefaultingFunc(&ClusterConfiguration{}, func(obj interface{}) { SetObjectDefaults_ClusterConfiguration(obj.(*ClusterConfiguration)) })
|
||||
scheme.AddTypeDefaultingFunc(&ClusterStatus{}, func(obj interface{}) { SetObjectDefaults_ClusterStatus(obj.(*ClusterStatus)) })
|
||||
scheme.AddTypeDefaultingFunc(&InitConfiguration{}, func(obj interface{}) { SetObjectDefaults_InitConfiguration(obj.(*InitConfiguration)) })
|
||||
scheme.AddTypeDefaultingFunc(&JoinConfiguration{}, func(obj interface{}) { SetObjectDefaults_JoinConfiguration(obj.(*JoinConfiguration)) })
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetObjectDefaults_ClusterConfiguration(in *ClusterConfiguration) {
|
||||
SetDefaults_ClusterConfiguration(in)
|
||||
SetDefaults_APIServer(&in.APIServer)
|
||||
}
|
||||
|
||||
func SetObjectDefaults_ClusterStatus(in *ClusterStatus) {
|
||||
}
|
||||
|
||||
func SetObjectDefaults_InitConfiguration(in *InitConfiguration) {
|
||||
SetDefaults_InitConfiguration(in)
|
||||
SetObjectDefaults_ClusterConfiguration(&in.ClusterConfiguration)
|
||||
for i := range in.BootstrapTokens {
|
||||
a := &in.BootstrapTokens[i]
|
||||
SetDefaults_BootstrapToken(a)
|
||||
}
|
||||
SetDefaults_APIEndpoint(&in.LocalAPIEndpoint)
|
||||
}
|
||||
|
||||
func SetObjectDefaults_JoinConfiguration(in *JoinConfiguration) {
|
||||
SetDefaults_JoinConfiguration(in)
|
||||
SetDefaults_Discovery(&in.Discovery)
|
||||
if in.Discovery.File != nil {
|
||||
SetDefaults_FileDiscovery(in.Discovery.File)
|
||||
}
|
||||
if in.ControlPlane != nil {
|
||||
SetDefaults_JoinControlPlane(in.ControlPlane)
|
||||
SetDefaults_APIEndpoint(&in.ControlPlane.LocalAPIEndpoint)
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
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/cmd/kubeadm/app/apis/kubeadm/validation",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/options:go_default_library",
|
||||
"//cmd/kubeadm/app/componentconfigs:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/features:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//pkg/apis/core/validation:go_default_library",
|
||||
"//pkg/registry/core/service/ipallocator:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["validation_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//pkg/proxy/apis/config:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/k8s.io/utils/pointer: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"],
|
||||
)
|
|
@ -1,496 +0,0 @@
|
|||
/*
|
||||
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 (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
kubeadmcmdoptions "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
|
||||
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
||||
)
|
||||
|
||||
// ValidateInitConfiguration validates an InitConfiguration object and collects all encountered errors
|
||||
func ValidateInitConfiguration(c *kubeadm.InitConfiguration) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateNodeRegistrationOptions(&c.NodeRegistration, field.NewPath("nodeRegistration"))...)
|
||||
allErrs = append(allErrs, ValidateBootstrapTokens(c.BootstrapTokens, field.NewPath("bootstrapTokens"))...)
|
||||
allErrs = append(allErrs, ValidateClusterConfiguration(&c.ClusterConfiguration)...)
|
||||
allErrs = append(allErrs, ValidateAPIEndpoint(&c.LocalAPIEndpoint, field.NewPath("localAPIEndpoint"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateClusterConfiguration validates an ClusterConfiguration object and collects all encountered errors
|
||||
func ValidateClusterConfiguration(c *kubeadm.ClusterConfiguration) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateNetworking(&c.Networking, field.NewPath("networking"))...)
|
||||
allErrs = append(allErrs, ValidateAPIServer(&c.APIServer, field.NewPath("apiServer"))...)
|
||||
allErrs = append(allErrs, ValidateAbsolutePath(c.CertificatesDir, field.NewPath("certificatesDir"))...)
|
||||
allErrs = append(allErrs, ValidateFeatureGates(c.FeatureGates, field.NewPath("featureGates"))...)
|
||||
allErrs = append(allErrs, ValidateHostPort(c.ControlPlaneEndpoint, field.NewPath("controlPlaneEndpoint"))...)
|
||||
allErrs = append(allErrs, ValidateEtcd(&c.Etcd, field.NewPath("etcd"))...)
|
||||
allErrs = append(allErrs, componentconfigs.Known.Validate(c)...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateAPIServer validates a APIServer object and collects all encountered errors
|
||||
func ValidateAPIServer(a *kubeadm.APIServer, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateCertSANs(a.CertSANs, fldPath.Child("certSANs"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateJoinConfiguration validates node configuration and collects all encountered errors
|
||||
func ValidateJoinConfiguration(c *kubeadm.JoinConfiguration) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateDiscovery(&c.Discovery, field.NewPath("discovery"))...)
|
||||
allErrs = append(allErrs, ValidateNodeRegistrationOptions(&c.NodeRegistration, field.NewPath("nodeRegistration"))...)
|
||||
allErrs = append(allErrs, ValidateJoinControlPlane(c.ControlPlane, field.NewPath("controlPlane"))...)
|
||||
|
||||
if !filepath.IsAbs(c.CACertPath) || !strings.HasSuffix(c.CACertPath, ".crt") {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("caCertPath"), c.CACertPath, "the ca certificate path must be an absolute path"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateJoinControlPlane validates joining control plane configuration and collects all encountered errors
|
||||
func ValidateJoinControlPlane(c *kubeadm.JoinControlPlane, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if c != nil {
|
||||
allErrs = append(allErrs, ValidateAPIEndpoint(&c.LocalAPIEndpoint, fldPath.Child("localAPIEndpoint"))...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateNodeRegistrationOptions validates the NodeRegistrationOptions object
|
||||
func ValidateNodeRegistrationOptions(nro *kubeadm.NodeRegistrationOptions, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(nro.Name) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath, "--node-name or .nodeRegistration.name in the config file is a required value. It seems like this value couldn't be automatically detected in your environment, please specify the desired value using the CLI or config file."))
|
||||
} else {
|
||||
allErrs = append(allErrs, apivalidation.ValidateDNS1123Subdomain(nro.Name, field.NewPath("name"))...)
|
||||
}
|
||||
allErrs = append(allErrs, ValidateSocketPath(nro.CRISocket, fldPath.Child("criSocket"))...)
|
||||
// TODO: Maybe validate .Taints as well in the future using something like validateNodeTaints() in pkg/apis/core/validation
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateDiscovery validates discovery related configuration and collects all encountered errors
|
||||
func ValidateDiscovery(d *kubeadm.Discovery, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if d.BootstrapToken == nil && d.File == nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, "", "bootstrapToken or file must be set"))
|
||||
}
|
||||
|
||||
if d.BootstrapToken != nil && d.File != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, "", "bootstrapToken and file cannot both be set"))
|
||||
}
|
||||
|
||||
if d.BootstrapToken != nil {
|
||||
allErrs = append(allErrs, ValidateDiscoveryBootstrapToken(d.BootstrapToken, fldPath.Child("bootstrapToken"))...)
|
||||
allErrs = append(allErrs, ValidateToken(d.TLSBootstrapToken, fldPath.Child("tlsBootstrapToken"))...)
|
||||
}
|
||||
|
||||
if d.File != nil {
|
||||
allErrs = append(allErrs, ValidateDiscoveryFile(d.File, fldPath.Child("file"))...)
|
||||
if len(d.TLSBootstrapToken) != 0 {
|
||||
allErrs = append(allErrs, ValidateToken(d.TLSBootstrapToken, fldPath.Child("tlsBootstrapToken"))...)
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateDiscoveryBootstrapToken validates bootstrap token discovery configuration
|
||||
func ValidateDiscoveryBootstrapToken(b *kubeadm.BootstrapTokenDiscovery, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if len(b.APIServerEndpoint) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath, "APIServerEndpoint is not set"))
|
||||
}
|
||||
|
||||
if len(b.CACertHashes) == 0 && !b.UnsafeSkipCAVerification {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, "", "using token-based discovery without caCertHashes can be unsafe. Set unsafeSkipCAVerification to continue"))
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, ValidateToken(b.Token, fldPath.Child(kubeadmcmdoptions.TokenStr))...)
|
||||
allErrs = append(allErrs, ValidateDiscoveryTokenAPIServer(b.APIServerEndpoint, fldPath.Child("apiServerEndpoints"))...)
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateDiscoveryFile validates file discovery configuration
|
||||
func ValidateDiscoveryFile(f *kubeadm.FileDiscovery, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
allErrs = append(allErrs, ValidateDiscoveryKubeConfigPath(f.KubeConfigPath, fldPath.Child("kubeConfigPath"))...)
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateDiscoveryTokenAPIServer validates discovery token for API server
|
||||
func ValidateDiscoveryTokenAPIServer(apiServer string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
_, _, err := net.SplitHostPort(apiServer)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, apiServer, err.Error()))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateDiscoveryKubeConfigPath validates location of a discovery file
|
||||
func ValidateDiscoveryKubeConfigPath(discoveryFile string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
u, err := url.Parse(discoveryFile)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, discoveryFile, "not a valid HTTPS URL or a file on disk"))
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if u.Scheme == "" {
|
||||
// URIs with no scheme should be treated as files
|
||||
if _, err := os.Stat(discoveryFile); os.IsNotExist(err) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, discoveryFile, "not a valid HTTPS URL or a file on disk"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if u.Scheme != "https" {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, discoveryFile, "if a URL is used, the scheme must be https"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateBootstrapTokens validates a slice of BootstrapToken objects
|
||||
func ValidateBootstrapTokens(bts []kubeadm.BootstrapToken, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
for i, bt := range bts {
|
||||
btPath := fldPath.Child(fmt.Sprintf("%d", i))
|
||||
allErrs = append(allErrs, ValidateToken(bt.Token.String(), btPath.Child(kubeadmcmdoptions.TokenStr))...)
|
||||
allErrs = append(allErrs, ValidateTokenUsages(bt.Usages, btPath.Child(kubeadmcmdoptions.TokenUsages))...)
|
||||
allErrs = append(allErrs, ValidateTokenGroups(bt.Usages, bt.Groups, btPath.Child(kubeadmcmdoptions.TokenGroups))...)
|
||||
|
||||
if bt.Expires != nil && bt.TTL != nil {
|
||||
allErrs = append(allErrs, field.Invalid(btPath, "", "the BootstrapToken .TTL and .Expires fields are mutually exclusive"))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateToken validates a Bootstrap Token
|
||||
func ValidateToken(token string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if !bootstraputil.IsValidBootstrapToken(token) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, token, "the bootstrap token is invalid"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateTokenGroups validates token groups
|
||||
func ValidateTokenGroups(usages []string, groups []string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
// adding groups only makes sense for authentication
|
||||
usagesSet := sets.NewString(usages...)
|
||||
usageAuthentication := strings.TrimPrefix(bootstrapapi.BootstrapTokenUsageAuthentication, bootstrapapi.BootstrapTokenUsagePrefix)
|
||||
if len(groups) > 0 && !usagesSet.Has(usageAuthentication) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, groups, fmt.Sprintf("token groups cannot be specified unless --usages includes %q", usageAuthentication)))
|
||||
}
|
||||
|
||||
// validate any extra group names
|
||||
for _, group := range groups {
|
||||
if err := bootstraputil.ValidateBootstrapGroupName(group); err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, groups, err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateTokenUsages validates token usages
|
||||
func ValidateTokenUsages(usages []string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
// validate usages
|
||||
if err := bootstraputil.ValidateUsages(usages); err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, usages, err.Error()))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateEtcd validates the .Etcd sub-struct.
|
||||
func ValidateEtcd(e *kubeadm.Etcd, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
localPath := fldPath.Child("local")
|
||||
externalPath := fldPath.Child("external")
|
||||
|
||||
if e.Local == nil && e.External == nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, "", "either .Etcd.Local or .Etcd.External is required"))
|
||||
return allErrs
|
||||
}
|
||||
if e.Local != nil && e.External != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, "", ".Etcd.Local and .Etcd.External are mutually exclusive"))
|
||||
return allErrs
|
||||
}
|
||||
if e.Local != nil {
|
||||
allErrs = append(allErrs, ValidateAbsolutePath(e.Local.DataDir, localPath.Child("dataDir"))...)
|
||||
allErrs = append(allErrs, ValidateCertSANs(e.Local.ServerCertSANs, localPath.Child("serverCertSANs"))...)
|
||||
allErrs = append(allErrs, ValidateCertSANs(e.Local.PeerCertSANs, localPath.Child("peerCertSANs"))...)
|
||||
}
|
||||
if e.External != nil {
|
||||
requireHTTPS := true
|
||||
// Only allow the http scheme if no certs/keys are passed
|
||||
if e.External.CAFile == "" && e.External.CertFile == "" && e.External.KeyFile == "" {
|
||||
requireHTTPS = false
|
||||
}
|
||||
// Require either none or both of the cert/key pair
|
||||
if (e.External.CertFile == "" && e.External.KeyFile != "") || (e.External.CertFile != "" && e.External.KeyFile == "") {
|
||||
allErrs = append(allErrs, field.Invalid(externalPath, "", "either both or none of .Etcd.External.CertFile and .Etcd.External.KeyFile must be set"))
|
||||
}
|
||||
// If the cert and key are specified, require the VA as well
|
||||
if e.External.CertFile != "" && e.External.KeyFile != "" && e.External.CAFile == "" {
|
||||
allErrs = append(allErrs, field.Invalid(externalPath, "", "setting .Etcd.External.CertFile and .Etcd.External.KeyFile requires .Etcd.External.CAFile"))
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, ValidateURLs(e.External.Endpoints, requireHTTPS, externalPath.Child("endpoints"))...)
|
||||
if e.External.CAFile != "" {
|
||||
allErrs = append(allErrs, ValidateAbsolutePath(e.External.CAFile, externalPath.Child("caFile"))...)
|
||||
}
|
||||
if e.External.CertFile != "" {
|
||||
allErrs = append(allErrs, ValidateAbsolutePath(e.External.CertFile, externalPath.Child("certFile"))...)
|
||||
}
|
||||
if e.External.KeyFile != "" {
|
||||
allErrs = append(allErrs, ValidateAbsolutePath(e.External.KeyFile, externalPath.Child("keyFile"))...)
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCertSANs validates alternative names
|
||||
func ValidateCertSANs(altnames []string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
for _, altname := range altnames {
|
||||
if errs := validation.IsDNS1123Subdomain(altname); len(errs) != 0 {
|
||||
if net.ParseIP(altname) == nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, altname, fmt.Sprintf("altname is not a valid IP address or DNS label: %s", strings.Join(errs, "; "))))
|
||||
}
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateURLs validates the URLs given in the string slice, makes sure they are parseable. Optionally, it can enforcs HTTPS usage.
|
||||
func ValidateURLs(urls []string, requireHTTPS bool, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
for _, urlstr := range urls {
|
||||
u, err := url.Parse(urlstr)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, urlstr, fmt.Sprintf("URL parse error: %v", err)))
|
||||
continue
|
||||
}
|
||||
if requireHTTPS && u.Scheme != "https" {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, urlstr, "the URL must be using the HTTPS scheme"))
|
||||
}
|
||||
if u.Scheme == "" {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, urlstr, "the URL without scheme is not allowed"))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIPFromString validates ip address
|
||||
func ValidateIPFromString(ipaddr string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if net.ParseIP(ipaddr) == nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, ipaddr, "ip address is not valid"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidatePort validates port numbers
|
||||
func ValidatePort(port int32, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if _, err := kubeadmutil.ParsePort(strconv.Itoa(int(port))); err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, port, "port number is not valid"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateHostPort validates host[:port] endpoints
|
||||
func ValidateHostPort(endpoint string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if _, _, err := kubeadmutil.ParseHostPort(endpoint); endpoint != "" && err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, endpoint, "endpoint is not valid"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIPNetFromString validates network portion of ip address
|
||||
func ValidateIPNetFromString(subnet string, minAddrs int64, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
_, svcSubnet, err := net.ParseCIDR(subnet)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, subnet, "couldn't parse subnet"))
|
||||
return allErrs
|
||||
}
|
||||
numAddresses := ipallocator.RangeSize(svcSubnet)
|
||||
if numAddresses < minAddrs {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, subnet, "subnet is too small"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateNetworking validates networking configuration
|
||||
func ValidateNetworking(c *kubeadm.Networking, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, apivalidation.ValidateDNS1123Subdomain(c.DNSDomain, field.NewPath("dnsDomain"))...)
|
||||
allErrs = append(allErrs, ValidateIPNetFromString(c.ServiceSubnet, constants.MinimumAddressesInServiceSubnet, field.NewPath("serviceSubnet"))...)
|
||||
if len(c.PodSubnet) != 0 {
|
||||
allErrs = append(allErrs, ValidateIPNetFromString(c.PodSubnet, constants.MinimumAddressesInServiceSubnet, field.NewPath("podSubnet"))...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateAbsolutePath validates whether provided path is absolute or not
|
||||
func ValidateAbsolutePath(path string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if !filepath.IsAbs(path) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, path, "path is not absolute"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateMixedArguments validates passed arguments
|
||||
func ValidateMixedArguments(flag *pflag.FlagSet) error {
|
||||
// If --config isn't set, we have nothing to validate
|
||||
if !flag.Changed("config") {
|
||||
return nil
|
||||
}
|
||||
|
||||
mixedInvalidFlags := []string{}
|
||||
flag.Visit(func(f *pflag.Flag) {
|
||||
if isAllowedFlag(f.Name) {
|
||||
// "--skip-*" flags or other allowed flags can be set with --config
|
||||
return
|
||||
}
|
||||
mixedInvalidFlags = append(mixedInvalidFlags, f.Name)
|
||||
})
|
||||
|
||||
if len(mixedInvalidFlags) != 0 {
|
||||
return errors.Errorf("can not mix '--config' with arguments %v", mixedInvalidFlags)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isAllowedFlag(flagName string) bool {
|
||||
knownFlags := sets.NewString(kubeadmcmdoptions.CfgPath,
|
||||
kubeadmcmdoptions.IgnorePreflightErrors,
|
||||
kubeadmcmdoptions.DryRun,
|
||||
kubeadmcmdoptions.KubeconfigPath,
|
||||
kubeadmcmdoptions.NodeName,
|
||||
kubeadmcmdoptions.NodeCRISocket,
|
||||
kubeadmcmdoptions.KubeconfigDir,
|
||||
kubeadmcmdoptions.UploadCerts,
|
||||
kubeadmcmdoptions.CertificateKey,
|
||||
"print-join-command", "rootfs", "v")
|
||||
if knownFlags.Has(flagName) {
|
||||
return true
|
||||
}
|
||||
return strings.HasPrefix(flagName, "skip-")
|
||||
}
|
||||
|
||||
// ValidateFeatureGates validates provided feature gates
|
||||
func ValidateFeatureGates(featureGates map[string]bool, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
// check valid feature names are provided
|
||||
for k := range featureGates {
|
||||
if !features.Supports(features.InitFeatureGates, k) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, featureGates,
|
||||
fmt.Sprintf("%s is not a valid feature name.", k)))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateAPIEndpoint validates API server's endpoint
|
||||
func ValidateAPIEndpoint(c *kubeadm.APIEndpoint, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateIPFromString(c.AdvertiseAddress, fldPath.Child("advertiseAddress"))...)
|
||||
allErrs = append(allErrs, ValidatePort(c.BindPort, fldPath.Child("bindPort"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIgnorePreflightErrors validates duplicates in ignore-preflight-errors flag.
|
||||
func ValidateIgnorePreflightErrors(ignorePreflightErrors []string) (sets.String, error) {
|
||||
ignoreErrors := sets.NewString()
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
for _, item := range ignorePreflightErrors {
|
||||
ignoreErrors.Insert(strings.ToLower(item)) // parameters are case insensitive
|
||||
}
|
||||
|
||||
if ignoreErrors.Has("all") && ignoreErrors.Len() > 1 {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("ignore-preflight-errors"), strings.Join(ignoreErrors.List(), ","), "don't specify individual checks if 'all' is used"))
|
||||
}
|
||||
|
||||
return ignoreErrors, allErrs.ToAggregate()
|
||||
}
|
||||
|
||||
// ValidateSocketPath validates format of socket path or url
|
||||
func ValidateSocketPath(socket string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
u, err := url.Parse(socket)
|
||||
if err != nil {
|
||||
return append(allErrs, field.Invalid(fldPath, socket, fmt.Sprintf("URL parsing error: %v", err)))
|
||||
}
|
||||
|
||||
if u.Scheme == "" {
|
||||
if !filepath.IsAbs(u.Path) {
|
||||
return append(allErrs, field.Invalid(fldPath, socket, fmt.Sprintf("path is not absolute: %s", socket)))
|
||||
}
|
||||
} else if u.Scheme != kubeadmapiv1beta1.DefaultUrlScheme {
|
||||
return append(allErrs, field.Invalid(fldPath, socket, fmt.Sprintf("URL scheme %s is not supported", u.Scheme)))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
|
@ -1,876 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validation
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
kubeproxyconfig "k8s.io/kubernetes/pkg/proxy/apis/config"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
func TestValidateToken(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token string
|
||||
expected bool
|
||||
}{
|
||||
{"772ef5.6b6baab1d4a0a171", true},
|
||||
{".6b6baab1d4a0a171", false},
|
||||
{"772ef5.", false},
|
||||
{"772ef5.6b6baab1d4a0a171", true},
|
||||
{".6b6baab1d4a0a171", false},
|
||||
{"772ef5.", false},
|
||||
{"abcdef.1234567890123456@foobar", false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
err := ValidateToken(rt.token, nil).ToAggregate()
|
||||
if (err == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateToken:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(err == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateValidateTokenUsages(t *testing.T) {
|
||||
var tests = []struct {
|
||||
u []string
|
||||
f *field.Path
|
||||
expected bool
|
||||
}{
|
||||
{[]string{}, nil, true}, // supported (no usages)
|
||||
{[]string{"signing", "authentication"}, nil, true}, // supported
|
||||
{[]string{"something else"}, nil, false}, // usage not supported
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateTokenUsages(rt.u, rt.f)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateTokenUsages:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateTokenGroups(t *testing.T) {
|
||||
var tests = []struct {
|
||||
u []string
|
||||
g []string
|
||||
f *field.Path
|
||||
expected bool
|
||||
}{
|
||||
{[]string{"some usage"}, []string{"some group"}, nil, false}, // groups doesn't makes sense if usage authentication
|
||||
{[]string{"authentication"}, []string{"some group"}, nil, false}, // group not supported
|
||||
{[]string{"authentication"}, []string{"system:bootstrappers:anygroup"}, nil, true}, // supported
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateTokenGroups(rt.u, rt.g, rt.f)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateTokenGroups:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateNodeRegistrationOptions(t *testing.T) {
|
||||
var tests = []struct {
|
||||
nodeName string
|
||||
criSocket string
|
||||
expectedErrors bool
|
||||
}{
|
||||
{"", "/some/path", true}, // node name can't be empty
|
||||
{"INVALID-NODENAME", "/some/path", true}, // Upper cases is invalid
|
||||
{"invalid-nodename-", "/some/path", true}, // Can't have trailing dashes
|
||||
{"invalid-node?name", "/some/path", true}, // Unsupported characters
|
||||
{"valid-nodename", "/some/path", false}, // supported
|
||||
{"valid-nodename-with-numbers01234", "/some/path/with/numbers/01234/", false}, // supported, with numbers as well
|
||||
{"valid-nodename", kubeadmapiv1beta1.DefaultUrlScheme + "://" + "/some/path", false}, // supported, with socket url
|
||||
{"valid-nodename", "bla:///some/path", true}, // unsupported url scheme
|
||||
{"valid-nodename", ":::", true}, // unparseable url
|
||||
}
|
||||
for _, rt := range tests {
|
||||
nro := kubeadm.NodeRegistrationOptions{Name: rt.nodeName, CRISocket: rt.criSocket}
|
||||
actual := ValidateNodeRegistrationOptions(&nro, field.NewPath("nodeRegistration"))
|
||||
actualErrors := len(actual) > 0
|
||||
if actualErrors != rt.expectedErrors {
|
||||
t.Errorf(
|
||||
"failed ValidateNodeRegistrationOptions: value: %v\n\texpected: %t\n\t actual: %t",
|
||||
nro,
|
||||
rt.expectedErrors,
|
||||
actualErrors,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCertSANs(t *testing.T) {
|
||||
var tests = []struct {
|
||||
sans []string
|
||||
expected bool
|
||||
}{
|
||||
{[]string{}, true}, // ok if not provided
|
||||
{[]string{"1,2,,3"}, false}, // not a DNS label or IP
|
||||
{[]string{"my-hostname", "???&?.garbage"}, false}, // not valid
|
||||
{[]string{"my-hostname", "my.subdomain", "1.2.3.4"}, true}, // supported
|
||||
{[]string{"my-hostname2", "my.other.subdomain", "10.0.0.10"}, true}, // supported
|
||||
{[]string{"my-hostname", "my.subdomain", "2001:db8::4"}, true}, // supported
|
||||
{[]string{"my-hostname2", "my.other.subdomain", "2001:db8::10"}, true}, // supported
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateCertSANs(rt.sans, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateCertSANs:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIPFromString(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
ip string
|
||||
expected bool
|
||||
}{
|
||||
{"invalid missing address", "", false},
|
||||
{"invalid missing decimal points in IPv4 address", "1234", false},
|
||||
{"invalid incomplete IPv4 address", "1.2", false},
|
||||
{"invalid IPv4 CIDR provided instead of IPv4 address", "1.2.3.4/16", false},
|
||||
{"valid IPv4 address", "1.2.3.4", true},
|
||||
{"valid IPv6 address", "2001:db8::1", true},
|
||||
{"invalid IPv6 CIDR provided instead of IPv6 address", "2001:db8::1/64", false},
|
||||
{"invalid hex character in IPv6 address", "2001:xb8::", false},
|
||||
{"invalid use of colons in IPv6 address", "2001::db8::", false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateIPFromString(rt.ip, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"%s test case failed:\n\texpected: %t\n\t actual: %t",
|
||||
rt.name,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIPNetFromString(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
subnet string
|
||||
minaddrs int64
|
||||
expected bool
|
||||
}{
|
||||
{"invalid missing CIDR", "", 0, false},
|
||||
{"invalid CIDR missing decimal points in IPv4 address and / mask", "1234", 0, false},
|
||||
{"invalid CIDR use of letters instead of numbers and / mask", "abc", 0, false},
|
||||
{"invalid IPv4 address provided instead of CIDR representation", "1.2.3.4", 0, false},
|
||||
{"invalid IPv6 address provided instead of CIDR representation", "2001:db8::1", 0, false},
|
||||
{"valid, but IPv4 CIDR too small. At least 10 addresses needed", "10.0.0.16/29", 10, false},
|
||||
{"valid, but IPv6 CIDR too small. At least 10 addresses needed", "2001:db8::/125", 10, false},
|
||||
{"valid IPv4 CIDR", "10.0.0.16/12", 10, true},
|
||||
{"valid IPv6 CIDR", "2001:db8::/98", 10, true},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateIPNetFromString(rt.subnet, rt.minaddrs, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"%s test case failed :\n\texpected: %t\n\t actual: %t",
|
||||
rt.name,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateHostPort(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
s string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "Valid DNS address / port",
|
||||
s: "cp.k8s.io:8081",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Valid DNS address",
|
||||
s: "cp.k8s.io",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Valid IPv4 address / port",
|
||||
s: "1.2.3.4:8081",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Valid IPv4 address",
|
||||
s: "1.2.3.4",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Valid IPv6 address / port",
|
||||
s: "[2001:db7::1]:8081",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Valid IPv6 address",
|
||||
s: "2001:db7::1",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid IPv4 address, but valid DNS",
|
||||
s: "1.2.34",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid DNS",
|
||||
s: "a.B.c.d.e",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid IPv6 address",
|
||||
s: "2001:db7:1",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid BindPort",
|
||||
s: "1.2.3.4:0",
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateHostPort(rt.s, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"%s test case failed:\n\texpected: %t\n\t actual: %t",
|
||||
rt.name,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateAPIEndpoint(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
s *kubeadm.APIEndpoint
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "Valid IPv4 address / port",
|
||||
s: &kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "4.5.6.7",
|
||||
BindPort: 6443,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Valid IPv6 address / port",
|
||||
s: &kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "2001:db7::2",
|
||||
BindPort: 6443,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid IPv4 address",
|
||||
s: &kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "1.2.34",
|
||||
BindPort: 6443,
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid IPv6 address",
|
||||
s: &kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "2001:db7:1",
|
||||
BindPort: 6443,
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid BindPort",
|
||||
s: &kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "4.5.6.7",
|
||||
BindPort: 0,
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateAPIEndpoint(rt.s, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"%s test case failed:\n\texpected: %t\n\t actual: %t",
|
||||
rt.name,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Create a separated test for ValidateClusterConfiguration
|
||||
func TestValidateInitConfiguration(t *testing.T) {
|
||||
nodename := "valid-nodename"
|
||||
var tests = []struct {
|
||||
name string
|
||||
s *kubeadm.InitConfiguration
|
||||
expected bool
|
||||
}{
|
||||
{"invalid missing InitConfiguration",
|
||||
&kubeadm.InitConfiguration{}, false},
|
||||
{"invalid missing token with IPv4 service subnet",
|
||||
&kubeadm.InitConfiguration{
|
||||
LocalAPIEndpoint: kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 6443,
|
||||
},
|
||||
ClusterConfiguration: kubeadm.ClusterConfiguration{
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "10.96.0.1/12",
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/cert/dir",
|
||||
},
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"},
|
||||
}, false},
|
||||
{"invalid missing token with IPv6 service subnet",
|
||||
&kubeadm.InitConfiguration{
|
||||
LocalAPIEndpoint: kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 6443,
|
||||
},
|
||||
ClusterConfiguration: kubeadm.ClusterConfiguration{
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "2001:db8::1/98",
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/cert/dir",
|
||||
},
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"},
|
||||
}, false},
|
||||
{"invalid missing node name",
|
||||
&kubeadm.InitConfiguration{
|
||||
LocalAPIEndpoint: kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 6443,
|
||||
},
|
||||
ClusterConfiguration: kubeadm.ClusterConfiguration{
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "10.96.0.1/12",
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
},
|
||||
}, false},
|
||||
{"valid InitConfiguration with incorrect IPv4 pod subnet",
|
||||
&kubeadm.InitConfiguration{
|
||||
LocalAPIEndpoint: kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 6443,
|
||||
},
|
||||
ClusterConfiguration: kubeadm.ClusterConfiguration{
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "10.96.0.1/12",
|
||||
DNSDomain: "cluster.local",
|
||||
PodSubnet: "10.0.1.15",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
},
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"},
|
||||
}, false},
|
||||
{"valid InitConfiguration with IPv4 service subnet",
|
||||
&kubeadm.InitConfiguration{
|
||||
LocalAPIEndpoint: kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 6443,
|
||||
},
|
||||
ClusterConfiguration: kubeadm.ClusterConfiguration{
|
||||
Etcd: kubeadm.Etcd{
|
||||
Local: &kubeadm.LocalEtcd{
|
||||
DataDir: "/some/path",
|
||||
},
|
||||
},
|
||||
ComponentConfigs: kubeadm.ComponentConfigs{
|
||||
KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{
|
||||
BindAddress: "192.168.59.103",
|
||||
HealthzBindAddress: "0.0.0.0:10256",
|
||||
MetricsBindAddress: "127.0.0.1:10249",
|
||||
ClusterCIDR: "192.168.59.0/24",
|
||||
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||
MasqueradeAll: true,
|
||||
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||
},
|
||||
IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{
|
||||
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{
|
||||
Max: utilpointer.Int32Ptr(2),
|
||||
MaxPerCore: utilpointer.Int32Ptr(1),
|
||||
Min: utilpointer.Int32Ptr(1),
|
||||
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
},
|
||||
},
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "10.96.0.1/12",
|
||||
DNSDomain: "cluster.local",
|
||||
PodSubnet: "10.0.1.15/16",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
},
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"},
|
||||
}, true},
|
||||
{"valid InitConfiguration using IPv6 service subnet",
|
||||
&kubeadm.InitConfiguration{
|
||||
LocalAPIEndpoint: kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "1:2:3::4",
|
||||
BindPort: 3446,
|
||||
},
|
||||
ClusterConfiguration: kubeadm.ClusterConfiguration{
|
||||
Etcd: kubeadm.Etcd{
|
||||
Local: &kubeadm.LocalEtcd{
|
||||
DataDir: "/some/path",
|
||||
},
|
||||
},
|
||||
ComponentConfigs: kubeadm.ComponentConfigs{
|
||||
KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{
|
||||
BindAddress: "192.168.59.103",
|
||||
HealthzBindAddress: "0.0.0.0:10256",
|
||||
MetricsBindAddress: "127.0.0.1:10249",
|
||||
ClusterCIDR: "192.168.59.0/24",
|
||||
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||
MasqueradeAll: true,
|
||||
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||
},
|
||||
IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{
|
||||
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{
|
||||
Max: utilpointer.Int32Ptr(2),
|
||||
MaxPerCore: utilpointer.Int32Ptr(1),
|
||||
Min: utilpointer.Int32Ptr(1),
|
||||
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
},
|
||||
},
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "2001:db8::1/98",
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
},
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"},
|
||||
}, true},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateInitConfiguration(rt.s)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"%s test case failed:\n\texpected: %t\n\t actual: %t",
|
||||
rt.name,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateJoinConfiguration(t *testing.T) {
|
||||
var tests = []struct {
|
||||
s *kubeadm.JoinConfiguration
|
||||
expected bool
|
||||
}{
|
||||
{&kubeadm.JoinConfiguration{}, false},
|
||||
{&kubeadm.JoinConfiguration{
|
||||
CACertPath: "/some/cert.crt",
|
||||
Discovery: kubeadm.Discovery{
|
||||
BootstrapToken: &kubeadm.BootstrapTokenDiscovery{
|
||||
Token: "abcdef.1234567890123456@foobar",
|
||||
},
|
||||
File: &kubeadm.FileDiscovery{
|
||||
KubeConfigPath: "foo",
|
||||
},
|
||||
},
|
||||
}, false},
|
||||
{&kubeadm.JoinConfiguration{ // Pass without JoinControlPlane
|
||||
CACertPath: "/some/cert.crt",
|
||||
Discovery: kubeadm.Discovery{
|
||||
BootstrapToken: &kubeadm.BootstrapTokenDiscovery{
|
||||
Token: "abcdef.1234567890123456",
|
||||
APIServerEndpoint: "1.2.3.4:6443",
|
||||
CACertHashes: []string{"aaaa"},
|
||||
},
|
||||
TLSBootstrapToken: "abcdef.1234567890123456",
|
||||
},
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{
|
||||
Name: "aaa",
|
||||
CRISocket: "/var/run/dockershim.sock",
|
||||
},
|
||||
}, true},
|
||||
{&kubeadm.JoinConfiguration{ // Pass with JoinControlPlane
|
||||
CACertPath: "/some/cert.crt",
|
||||
Discovery: kubeadm.Discovery{
|
||||
BootstrapToken: &kubeadm.BootstrapTokenDiscovery{
|
||||
Token: "abcdef.1234567890123456",
|
||||
APIServerEndpoint: "1.2.3.4:6443",
|
||||
CACertHashes: []string{"aaaa"},
|
||||
},
|
||||
TLSBootstrapToken: "abcdef.1234567890123456",
|
||||
},
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{
|
||||
Name: "aaa",
|
||||
CRISocket: "/var/run/dockershim.sock",
|
||||
},
|
||||
ControlPlane: &kubeadm.JoinControlPlane{
|
||||
LocalAPIEndpoint: kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 1234,
|
||||
},
|
||||
},
|
||||
}, true},
|
||||
{&kubeadm.JoinConfiguration{ // Fail JoinControlPlane.AdvertiseAddress validation
|
||||
CACertPath: "/some/cert.crt",
|
||||
Discovery: kubeadm.Discovery{
|
||||
BootstrapToken: &kubeadm.BootstrapTokenDiscovery{
|
||||
Token: "abcdef.1234567890123456",
|
||||
APIServerEndpoint: "1.2.3.4:6443",
|
||||
CACertHashes: []string{"aaaa"},
|
||||
},
|
||||
TLSBootstrapToken: "abcdef.1234567890123456",
|
||||
},
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{
|
||||
Name: "aaa",
|
||||
CRISocket: "/var/run/dockershim.sock",
|
||||
},
|
||||
ControlPlane: &kubeadm.JoinControlPlane{
|
||||
LocalAPIEndpoint: kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "aaa",
|
||||
BindPort: 1234,
|
||||
},
|
||||
},
|
||||
}, false},
|
||||
{&kubeadm.JoinConfiguration{ // Fail JoinControlPlane.BindPort validation
|
||||
CACertPath: "/some/cert.crt",
|
||||
Discovery: kubeadm.Discovery{
|
||||
BootstrapToken: &kubeadm.BootstrapTokenDiscovery{
|
||||
Token: "abcdef.1234567890123456",
|
||||
APIServerEndpoint: "1.2.3.4:6443",
|
||||
CACertHashes: []string{"aaaa"},
|
||||
},
|
||||
TLSBootstrapToken: "abcdef.1234567890123456",
|
||||
},
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{
|
||||
Name: "aaa",
|
||||
CRISocket: "/var/run/dockershim.sock",
|
||||
},
|
||||
ControlPlane: &kubeadm.JoinControlPlane{
|
||||
LocalAPIEndpoint: kubeadm.APIEndpoint{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: -1,
|
||||
},
|
||||
},
|
||||
}, false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateJoinConfiguration(rt.s)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateJoinConfiguration:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateMixedArguments(t *testing.T) {
|
||||
var tests = []struct {
|
||||
args []string
|
||||
expected bool
|
||||
}{
|
||||
// Expected to succeed, --config is mixed with skip-* flags only or no other flags
|
||||
{[]string{"--foo=bar"}, true},
|
||||
{[]string{"--config=hello"}, true},
|
||||
{[]string{"--config=hello", "--ignore-preflight-errors=all"}, true},
|
||||
{[]string{"--config=hello", "--skip-token-print=true"}, true},
|
||||
{[]string{"--config=hello", "--ignore-preflight-errors=baz", "--skip-token-print"}, true},
|
||||
// Expected to fail, --config is mixed with the --foo flag
|
||||
{[]string{"--config=hello", "--ignore-preflight-errors=baz", "--foo=bar"}, false},
|
||||
{[]string{"--config=hello", "--foo=bar"}, false},
|
||||
}
|
||||
|
||||
var cfgPath string
|
||||
var ignorePreflightErrors []string
|
||||
for _, rt := range tests {
|
||||
f := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
if f.Parsed() {
|
||||
t.Error("f.Parse() = true before Parse")
|
||||
}
|
||||
f.String("foo", "", "flag bound to config object")
|
||||
f.StringSliceVar(&ignorePreflightErrors, "ignore-preflight-errors", ignorePreflightErrors, "flag not bound to config object")
|
||||
f.Bool("skip-token-print", false, "flag not bound to config object")
|
||||
f.StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file")
|
||||
if err := f.Parse(rt.args); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
actual := ValidateMixedArguments(f)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateMixedArguments:\n\texpected: %t\n\t actual: %t testdata: %v",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
rt.args,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateFeatureGates(t *testing.T) {
|
||||
type featureFlag map[string]bool
|
||||
var tests = []struct {
|
||||
featureGates featureFlag
|
||||
expected bool
|
||||
}{
|
||||
{featureFlag{"Unknown": true}, false},
|
||||
{featureFlag{"Unknown": false}, false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateFeatureGates(rt.featureGates, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed featureGates %v:\n\texpected: %t\n\t actual: %t",
|
||||
rt.featureGates,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIgnorePreflightErrors(t *testing.T) {
|
||||
var tests = []struct {
|
||||
ignorePreflightErrors []string
|
||||
expectedLen int
|
||||
expectedError bool
|
||||
}{
|
||||
{[]string{}, 0, false}, // empty list
|
||||
{[]string{"check1", "check2"}, 2, false}, // non-duplicate
|
||||
{[]string{"check1", "check2", "check1"}, 2, false}, // duplicates
|
||||
{[]string{"check1", "check2", "all"}, 3, true}, // non-duplicate, but 'all' present together wth individual checks
|
||||
{[]string{"all"}, 1, false}, // skip all checks by using new flag
|
||||
{[]string{"all"}, 1, false}, // skip all checks by using both old and new flags at the same time
|
||||
}
|
||||
for _, rt := range tests {
|
||||
result, err := ValidateIgnorePreflightErrors(rt.ignorePreflightErrors)
|
||||
switch {
|
||||
case err != nil && !rt.expectedError:
|
||||
t.Errorf("ValidateIgnorePreflightErrors: unexpected error for input (%s), error: %v", rt.ignorePreflightErrors, err)
|
||||
case err == nil && rt.expectedError:
|
||||
t.Errorf("ValidateIgnorePreflightErrors: expected error for input (%s) but got: %v", rt.ignorePreflightErrors, result)
|
||||
case result.Len() != rt.expectedLen:
|
||||
t.Errorf("ValidateIgnorePreflightErrors: expected Len = %d for input (%s) but got: %v, %v", rt.expectedLen, rt.ignorePreflightErrors, result.Len(), result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDiscovery(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
d *kubeadm.Discovery
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
"invalid: .BootstrapToken and .File cannot both be set",
|
||||
&kubeadm.Discovery{
|
||||
BootstrapToken: &kubeadm.BootstrapTokenDiscovery{
|
||||
Token: "abcdef.1234567890123456",
|
||||
},
|
||||
File: &kubeadm.FileDiscovery{
|
||||
KubeConfigPath: "https://url/file.conf",
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid: .BootstrapToken or .File must be set",
|
||||
&kubeadm.Discovery{},
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t *testing.T) {
|
||||
err := ValidateDiscovery(rt.d, nil).ToAggregate()
|
||||
if (err == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"test case failed: ValidateDiscovery:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(err == nil),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDiscoveryBootstrapToken(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
btd *kubeadm.BootstrapTokenDiscovery
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
"invalid: .APIServerEndpoint not set",
|
||||
&kubeadm.BootstrapTokenDiscovery{
|
||||
Token: "abcdef.1234567890123456",
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid: using token-based discovery without .BootstrapToken.CACertHashes and .BootstrapToken.UnsafeSkipCAVerification",
|
||||
&kubeadm.BootstrapTokenDiscovery{
|
||||
Token: "abcdef.1234567890123456",
|
||||
APIServerEndpoint: "192.168.122.100:6443",
|
||||
UnsafeSkipCAVerification: false,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid: using token-based discovery with .BootstrapToken.CACertHashes",
|
||||
&kubeadm.BootstrapTokenDiscovery{
|
||||
Token: "abcdef.1234567890123456",
|
||||
APIServerEndpoint: "192.168.122.100:6443",
|
||||
CACertHashes: []string{"sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc"},
|
||||
UnsafeSkipCAVerification: false,
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"valid: using token-based discovery with .BootstrapToken.CACertHashe but skip ca verification",
|
||||
&kubeadm.BootstrapTokenDiscovery{
|
||||
Token: "abcdef.1234567890123456",
|
||||
APIServerEndpoint: "192.168.122.100:6443",
|
||||
CACertHashes: []string{"sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc"},
|
||||
UnsafeSkipCAVerification: true,
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t *testing.T) {
|
||||
err := ValidateDiscoveryBootstrapToken(rt.btd, nil).ToAggregate()
|
||||
if (err == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"test case failed: ValidateDiscoveryBootstrapToken:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(err == nil),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDiscoveryTokenAPIServer(t *testing.T) {
|
||||
var tests = []struct {
|
||||
apiServerEndpoint string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
"192.168.122.100",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"192.168.122.100:6443",
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateDiscoveryTokenAPIServer(rt.apiServerEndpoint, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateDiscoveryTokenAPIServer:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDiscoveryKubeConfigPath(t *testing.T) {
|
||||
tmpfile, err := ioutil.TempFile("/tmp", "test_discovery_file")
|
||||
if err != nil {
|
||||
t.Errorf("Error creating temporary file: %v", err)
|
||||
}
|
||||
defer os.Remove(tmpfile.Name())
|
||||
|
||||
var tests = []struct {
|
||||
s string
|
||||
expected bool
|
||||
}{
|
||||
{"foo", false},
|
||||
{"/foo/bar/file_which_i_believe_not_existing.conf", false},
|
||||
{tmpfile.Name(), true},
|
||||
{"http://[::1]a", false},
|
||||
{"http://url/file.conf", false},
|
||||
{"https://u r l/file.conf", false},
|
||||
{"https://url/file.conf", true},
|
||||
}
|
||||
for i, rt := range tests {
|
||||
actual := ValidateDiscoveryKubeConfigPath(rt.s, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"%d: failed ValidateDiscoveryKubeConfigPath:\n\texpected: %t\n\t actual: %t",
|
||||
i,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,581 +0,0 @@
|
|||
// +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 kubeadm
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
config "k8s.io/kubernetes/pkg/kubelet/apis/config"
|
||||
apisconfig "k8s.io/kubernetes/pkg/proxy/apis/config"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *APIEndpoint) DeepCopyInto(out *APIEndpoint) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIEndpoint.
|
||||
func (in *APIEndpoint) DeepCopy() *APIEndpoint {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(APIEndpoint)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *APIServer) DeepCopyInto(out *APIServer) {
|
||||
*out = *in
|
||||
in.ControlPlaneComponent.DeepCopyInto(&out.ControlPlaneComponent)
|
||||
if in.CertSANs != nil {
|
||||
in, out := &in.CertSANs, &out.CertSANs
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.TimeoutForControlPlane != nil {
|
||||
in, out := &in.TimeoutForControlPlane, &out.TimeoutForControlPlane
|
||||
*out = new(v1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServer.
|
||||
func (in *APIServer) DeepCopy() *APIServer {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(APIServer)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
|
||||
*out = *in
|
||||
if in.Token != nil {
|
||||
in, out := &in.Token, &out.Token
|
||||
*out = new(BootstrapTokenString)
|
||||
**out = **in
|
||||
}
|
||||
if in.TTL != nil {
|
||||
in, out := &in.TTL, &out.TTL
|
||||
*out = new(v1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
if in.Expires != nil {
|
||||
in, out := &in.Expires, &out.Expires
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Usages != nil {
|
||||
in, out := &in.Usages, &out.Usages
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Groups != nil {
|
||||
in, out := &in.Groups, &out.Groups
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken.
|
||||
func (in *BootstrapToken) DeepCopy() *BootstrapToken {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BootstrapToken)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BootstrapTokenDiscovery) DeepCopyInto(out *BootstrapTokenDiscovery) {
|
||||
*out = *in
|
||||
if in.CACertHashes != nil {
|
||||
in, out := &in.CACertHashes, &out.CACertHashes
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenDiscovery.
|
||||
func (in *BootstrapTokenDiscovery) DeepCopy() *BootstrapTokenDiscovery {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BootstrapTokenDiscovery)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BootstrapTokenString) DeepCopyInto(out *BootstrapTokenString) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenString.
|
||||
func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BootstrapTokenString)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ComponentConfigs.DeepCopyInto(&out.ComponentConfigs)
|
||||
in.Etcd.DeepCopyInto(&out.Etcd)
|
||||
out.Networking = in.Networking
|
||||
in.APIServer.DeepCopyInto(&out.APIServer)
|
||||
in.ControllerManager.DeepCopyInto(&out.ControllerManager)
|
||||
in.Scheduler.DeepCopyInto(&out.Scheduler)
|
||||
out.DNS = in.DNS
|
||||
if in.FeatureGates != nil {
|
||||
in, out := &in.FeatureGates, &out.FeatureGates
|
||||
*out = make(map[string]bool, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterConfiguration.
|
||||
func (in *ClusterConfiguration) DeepCopy() *ClusterConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ClusterConfiguration) 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 *ClusterStatus) DeepCopyInto(out *ClusterStatus) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
if in.APIEndpoints != nil {
|
||||
in, out := &in.APIEndpoints, &out.APIEndpoints
|
||||
*out = make(map[string]APIEndpoint, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterStatus.
|
||||
func (in *ClusterStatus) DeepCopy() *ClusterStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ClusterStatus) 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 *ComponentConfigs) DeepCopyInto(out *ComponentConfigs) {
|
||||
*out = *in
|
||||
if in.Kubelet != nil {
|
||||
in, out := &in.Kubelet, &out.Kubelet
|
||||
*out = new(config.KubeletConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.KubeProxy != nil {
|
||||
in, out := &in.KubeProxy, &out.KubeProxy
|
||||
*out = new(apisconfig.KubeProxyConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentConfigs.
|
||||
func (in *ComponentConfigs) DeepCopy() *ComponentConfigs {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ComponentConfigs)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ControlPlaneComponent) DeepCopyInto(out *ControlPlaneComponent) {
|
||||
*out = *in
|
||||
if in.ExtraArgs != nil {
|
||||
in, out := &in.ExtraArgs, &out.ExtraArgs
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.ExtraVolumes != nil {
|
||||
in, out := &in.ExtraVolumes, &out.ExtraVolumes
|
||||
*out = make([]HostPathMount, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneComponent.
|
||||
func (in *ControlPlaneComponent) DeepCopy() *ControlPlaneComponent {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ControlPlaneComponent)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DNS) DeepCopyInto(out *DNS) {
|
||||
*out = *in
|
||||
out.ImageMeta = in.ImageMeta
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNS.
|
||||
func (in *DNS) DeepCopy() *DNS {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DNS)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Discovery) DeepCopyInto(out *Discovery) {
|
||||
*out = *in
|
||||
if in.BootstrapToken != nil {
|
||||
in, out := &in.BootstrapToken, &out.BootstrapToken
|
||||
*out = new(BootstrapTokenDiscovery)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.File != nil {
|
||||
in, out := &in.File, &out.File
|
||||
*out = new(FileDiscovery)
|
||||
**out = **in
|
||||
}
|
||||
if in.Timeout != nil {
|
||||
in, out := &in.Timeout, &out.Timeout
|
||||
*out = new(v1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Discovery.
|
||||
func (in *Discovery) DeepCopy() *Discovery {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Discovery)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Etcd) DeepCopyInto(out *Etcd) {
|
||||
*out = *in
|
||||
if in.Local != nil {
|
||||
in, out := &in.Local, &out.Local
|
||||
*out = new(LocalEtcd)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(ExternalEtcd)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Etcd.
|
||||
func (in *Etcd) DeepCopy() *Etcd {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Etcd)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalEtcd) DeepCopyInto(out *ExternalEtcd) {
|
||||
*out = *in
|
||||
if in.Endpoints != nil {
|
||||
in, out := &in.Endpoints, &out.Endpoints
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalEtcd.
|
||||
func (in *ExternalEtcd) DeepCopy() *ExternalEtcd {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExternalEtcd)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FileDiscovery) DeepCopyInto(out *FileDiscovery) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileDiscovery.
|
||||
func (in *FileDiscovery) DeepCopy() *FileDiscovery {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FileDiscovery)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HostPathMount) DeepCopyInto(out *HostPathMount) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPathMount.
|
||||
func (in *HostPathMount) DeepCopy() *HostPathMount {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HostPathMount)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImageMeta) DeepCopyInto(out *ImageMeta) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageMeta.
|
||||
func (in *ImageMeta) DeepCopy() *ImageMeta {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImageMeta)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *InitConfiguration) DeepCopyInto(out *InitConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ClusterConfiguration.DeepCopyInto(&out.ClusterConfiguration)
|
||||
if in.BootstrapTokens != nil {
|
||||
in, out := &in.BootstrapTokens, &out.BootstrapTokens
|
||||
*out = make([]BootstrapToken, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
|
||||
out.LocalAPIEndpoint = in.LocalAPIEndpoint
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InitConfiguration.
|
||||
func (in *InitConfiguration) DeepCopy() *InitConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(InitConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *InitConfiguration) 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 *JoinConfiguration) DeepCopyInto(out *JoinConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
|
||||
in.Discovery.DeepCopyInto(&out.Discovery)
|
||||
if in.ControlPlane != nil {
|
||||
in, out := &in.ControlPlane, &out.ControlPlane
|
||||
*out = new(JoinControlPlane)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JoinConfiguration.
|
||||
func (in *JoinConfiguration) DeepCopy() *JoinConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JoinConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *JoinConfiguration) 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 *JoinControlPlane) DeepCopyInto(out *JoinControlPlane) {
|
||||
*out = *in
|
||||
out.LocalAPIEndpoint = in.LocalAPIEndpoint
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JoinControlPlane.
|
||||
func (in *JoinControlPlane) DeepCopy() *JoinControlPlane {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JoinControlPlane)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *LocalEtcd) DeepCopyInto(out *LocalEtcd) {
|
||||
*out = *in
|
||||
out.ImageMeta = in.ImageMeta
|
||||
if in.ExtraArgs != nil {
|
||||
in, out := &in.ExtraArgs, &out.ExtraArgs
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.ServerCertSANs != nil {
|
||||
in, out := &in.ServerCertSANs, &out.ServerCertSANs
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.PeerCertSANs != nil {
|
||||
in, out := &in.PeerCertSANs, &out.PeerCertSANs
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalEtcd.
|
||||
func (in *LocalEtcd) DeepCopy() *LocalEtcd {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(LocalEtcd)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Networking) DeepCopyInto(out *Networking) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Networking.
|
||||
func (in *Networking) DeepCopy() *Networking {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Networking)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) {
|
||||
*out = *in
|
||||
if in.Taints != nil {
|
||||
in, out := &in.Taints, &out.Taints
|
||||
*out = make([]corev1.Taint, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.KubeletExtraArgs != nil {
|
||||
in, out := &in.KubeletExtraArgs, &out.KubeletExtraArgs
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRegistrationOptions.
|
||||
func (in *NodeRegistrationOptions) DeepCopy() *NodeRegistrationOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NodeRegistrationOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"cmd.go",
|
||||
"completion.go",
|
||||
"config.go",
|
||||
"init.go",
|
||||
"join.go",
|
||||
"reset.go",
|
||||
"token.go",
|
||||
"version.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha3:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/alpha:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/options:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/phases:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/phases/init:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/phases/join:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/phases/workflow:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/upgrade:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/util:go_default_library",
|
||||
"//cmd/kubeadm/app/componentconfigs:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/discovery:go_default_library",
|
||||
"//cmd/kubeadm/app/features:go_default_library",
|
||||
"//cmd/kubeadm/app/images:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/certs:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/etcd:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/uploadconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/preflight:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//cmd/kubeadm/app/util/apiclient:go_default_library",
|
||||
"//cmd/kubeadm/app/util/config:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/util/runtime:go_default_library",
|
||||
"//cmd/kubeadm/app/util/staticpod:go_default_library",
|
||||
"//pkg/util/initsystem:go_default_library",
|
||||
"//pkg/version: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/util/duration:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/version:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",
|
||||
"//vendor/github.com/lithammer/dedent:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/sigs.k8s.io/yaml:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"completion_test.go",
|
||||
"config_test.go",
|
||||
"init_test.go",
|
||||
"join_test.go",
|
||||
"reset_test.go",
|
||||
"token_test.go",
|
||||
"version_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/options:go_default_library",
|
||||
"//cmd/kubeadm/app/componentconfigs:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/features:go_default_library",
|
||||
"//cmd/kubeadm/app/preflight:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//cmd/kubeadm/app/util/config:go_default_library",
|
||||
"//cmd/kubeadm/app/util/runtime:go_default_library",
|
||||
"//cmd/kubeadm/test:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//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/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/github.com/lithammer/dedent:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||
"//vendor/sigs.k8s.io/yaml:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//cmd/kubeadm/app/cmd/alpha:all-srcs",
|
||||
"//cmd/kubeadm/app/cmd/options:all-srcs",
|
||||
"//cmd/kubeadm/app/cmd/phases:all-srcs",
|
||||
"//cmd/kubeadm/app/cmd/upgrade:all-srcs",
|
||||
"//cmd/kubeadm/app/cmd/util:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -1,73 +0,0 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"alpha.go",
|
||||
"certs.go",
|
||||
"kubeconfig.go",
|
||||
"kubelet.go",
|
||||
"selfhosting.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/alpha",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/options:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/phases:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/util:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_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",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//cmd/kubeadm/app/util/apiclient:go_default_library",
|
||||
"//cmd/kubeadm/app/util/config:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//pkg/util/normalizer:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec: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 = [
|
||||
"certs_test.go",
|
||||
"kubeconfig_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/certs:go_default_library",
|
||||
"//cmd/kubeadm/app/util/certs:go_default_library",
|
||||
"//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",
|
||||
],
|
||||
)
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package alpha
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
)
|
||||
|
||||
// NewCmdAlpha returns "kubeadm alpha" command.
|
||||
func NewCmdAlpha(in io.Reader, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "alpha",
|
||||
Short: "Kubeadm experimental sub-commands",
|
||||
}
|
||||
|
||||
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.
|
||||
// current phases implemented as cobra.Commands should become workflow.Phases, while other utilities
|
||||
// hosted under kubeadm alpha phases command should found a new home under kubeadm alpha (without phases)
|
||||
cmd.AddCommand(newCmdPhase(out))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newCmdPhase(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "phase",
|
||||
Short: "Invoke subsets of kubeadm functions separately for a manual install",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
|
@ -1,182 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package alpha
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/renewal"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
genericLongDesc = normalizer.LongDesc(`
|
||||
Renews the %[1]s, and saves them into %[2]s.cert and %[2]s.key files.
|
||||
|
||||
Extra attributes such as SANs will be based on the existing certificates, there is no need to resupply them.
|
||||
`)
|
||||
allLongDesc = normalizer.LongDesc(`
|
||||
Renews all known certificates necessary to run the control plane. Renewals are run unconditionally, regardless
|
||||
of expiration date. Renewals can also be run individually for more control.
|
||||
`)
|
||||
)
|
||||
|
||||
// newCmdCertsUtility returns main command for certs phase
|
||||
func newCmdCertsUtility() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "certs",
|
||||
Aliases: []string{"certificates"},
|
||||
Short: "Commands related to handling kubernetes certificates",
|
||||
}
|
||||
|
||||
cmd.AddCommand(newCmdCertsRenewal())
|
||||
return cmd
|
||||
}
|
||||
|
||||
// newCmdCertsRenewal creates a new `cert renew` command.
|
||||
func newCmdCertsRenewal() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "renew",
|
||||
Short: "Renews certificates for a Kubernetes cluster",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
RunE: cmdutil.SubCmdRunE("renew"),
|
||||
}
|
||||
|
||||
cmd.AddCommand(getRenewSubCommands()...)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type renewConfig struct {
|
||||
cfgPath string
|
||||
kubeconfigPath string
|
||||
cfg kubeadmapiv1beta1.InitConfiguration
|
||||
useAPI bool
|
||||
useCSR bool
|
||||
csrPath string
|
||||
}
|
||||
|
||||
func getRenewSubCommands() []*cobra.Command {
|
||||
cfg := &renewConfig{}
|
||||
// Default values for the cobra help text
|
||||
kubeadmscheme.Scheme.Default(&cfg.cfg)
|
||||
|
||||
certTree, err := certsphase.GetDefaultCertList().AsMap().CertTree()
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
cmdList := []*cobra.Command{}
|
||||
funcList := []func(){}
|
||||
|
||||
for caCert, certs := range certTree {
|
||||
// Don't offer to renew CAs; would cause serious consequences
|
||||
for _, cert := range certs {
|
||||
// get the cobra.Command skeleton for this command
|
||||
cmd := generateRenewalCommand(cert, cfg)
|
||||
// get the implementation of renewing this certificate
|
||||
renewalFunc := generateRenewalFunction(cert, caCert, cfg)
|
||||
// install the implementation into the command
|
||||
cmd.Run = func(*cobra.Command, []string) { renewalFunc() }
|
||||
cmdList = append(cmdList, cmd)
|
||||
// Collect renewal functions for `renew all`
|
||||
funcList = append(funcList, renewalFunc)
|
||||
}
|
||||
}
|
||||
|
||||
allCmd := &cobra.Command{
|
||||
Use: "all",
|
||||
Short: "renew all available certificates",
|
||||
Long: allLongDesc,
|
||||
Run: func(*cobra.Command, []string) {
|
||||
for _, f := range funcList {
|
||||
f()
|
||||
}
|
||||
},
|
||||
}
|
||||
addFlags(allCmd, cfg)
|
||||
|
||||
cmdList = append(cmdList, allCmd)
|
||||
return cmdList
|
||||
}
|
||||
|
||||
func addFlags(cmd *cobra.Command, cfg *renewConfig) {
|
||||
options.AddConfigFlag(cmd.Flags(), &cfg.cfgPath)
|
||||
options.AddCertificateDirFlag(cmd.Flags(), &cfg.cfg.CertificatesDir)
|
||||
options.AddKubeConfigFlag(cmd.Flags(), &cfg.kubeconfigPath)
|
||||
options.AddCSRFlag(cmd.Flags(), &cfg.useCSR)
|
||||
options.AddCSRDirFlag(cmd.Flags(), &cfg.csrPath)
|
||||
cmd.Flags().BoolVar(&cfg.useAPI, "use-api", cfg.useAPI, "Use the Kubernetes certificate API to renew certificates")
|
||||
}
|
||||
|
||||
func generateRenewalFunction(cert *certsphase.KubeadmCert, caCert *certsphase.KubeadmCert, cfg *renewConfig) func() {
|
||||
return func() {
|
||||
internalcfg, err := configutil.LoadOrDefaultInitConfiguration(cfg.cfgPath, &cfg.cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
if cfg.useCSR {
|
||||
path := cfg.csrPath
|
||||
if path == "" {
|
||||
path = cfg.cfg.CertificatesDir
|
||||
}
|
||||
err := certsphase.CreateCSR(cert, internalcfg, path)
|
||||
kubeadmutil.CheckErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
renewer, err := getRenewer(cfg, caCert.BaseName)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = renewal.RenewExistingCert(internalcfg.CertificatesDir, cert.BaseName, renewer)
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
func generateRenewalCommand(cert *certsphase.KubeadmCert, cfg *renewConfig) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: cert.Name,
|
||||
Short: fmt.Sprintf("Generates the %s", cert.LongName),
|
||||
Long: fmt.Sprintf(genericLongDesc, cert.LongName, cert.BaseName),
|
||||
}
|
||||
addFlags(cmd, cfg)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func getRenewer(cfg *renewConfig, caCertBaseName string) (renewal.Interface, error) {
|
||||
if cfg.useAPI {
|
||||
kubeConfigPath := cmdutil.GetKubeConfigPath(cfg.kubeconfigPath)
|
||||
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return renewal.NewCertsAPIRenawal(client), nil
|
||||
}
|
||||
|
||||
caCert, caKey, err := certsphase.LoadCertificateAuthority(cfg.cfg.CertificatesDir, caCertBaseName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return renewal.NewFileRenewal(caCert, caKey), nil
|
||||
}
|
|
@ -1,235 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package alpha
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
certstestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
|
||||
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
|
||||
cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
|
||||
)
|
||||
|
||||
func TestCommandsGenerated(t *testing.T) {
|
||||
expectedFlags := []string{
|
||||
"cert-dir",
|
||||
"config",
|
||||
"use-api",
|
||||
}
|
||||
|
||||
expectedCommands := []string{
|
||||
"renew all",
|
||||
|
||||
"renew apiserver",
|
||||
"renew apiserver-kubelet-client",
|
||||
"renew apiserver-etcd-client",
|
||||
|
||||
"renew front-proxy-client",
|
||||
|
||||
"renew etcd-server",
|
||||
"renew etcd-peer",
|
||||
"renew etcd-healthcheck-client",
|
||||
}
|
||||
|
||||
renewCmd := newCmdCertsRenewal()
|
||||
|
||||
fakeRoot := &cobra.Command{}
|
||||
fakeRoot.AddCommand(renewCmd)
|
||||
|
||||
for _, cmdPath := range expectedCommands {
|
||||
t.Run(cmdPath, func(t *testing.T) {
|
||||
cmd, rem, _ := fakeRoot.Find(strings.Split(cmdPath, " "))
|
||||
if cmd == nil || len(rem) != 0 {
|
||||
t.Fatalf("couldn't locate command %q (%v)", cmdPath, rem)
|
||||
}
|
||||
|
||||
for _, flag := range expectedFlags {
|
||||
if cmd.Flags().Lookup(flag) == nil {
|
||||
t.Errorf("couldn't find expected flag --%s", flag)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunRenewCommands(t *testing.T) {
|
||||
tests := []struct {
|
||||
command string
|
||||
baseNames []string
|
||||
caBaseNames []string
|
||||
}{
|
||||
{
|
||||
command: "all",
|
||||
baseNames: []string{
|
||||
kubeadmconstants.APIServerCertAndKeyBaseName,
|
||||
kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName,
|
||||
kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName,
|
||||
kubeadmconstants.FrontProxyClientCertAndKeyBaseName,
|
||||
kubeadmconstants.EtcdServerCertAndKeyBaseName,
|
||||
kubeadmconstants.EtcdPeerCertAndKeyBaseName,
|
||||
kubeadmconstants.EtcdHealthcheckClientCertAndKeyBaseName,
|
||||
},
|
||||
caBaseNames: []string{
|
||||
kubeadmconstants.CACertAndKeyBaseName,
|
||||
kubeadmconstants.FrontProxyCACertAndKeyBaseName,
|
||||
kubeadmconstants.EtcdCACertAndKeyBaseName,
|
||||
},
|
||||
},
|
||||
{
|
||||
command: "apiserver",
|
||||
baseNames: []string{kubeadmconstants.APIServerCertAndKeyBaseName},
|
||||
caBaseNames: []string{kubeadmconstants.CACertAndKeyBaseName},
|
||||
},
|
||||
{
|
||||
command: "apiserver-kubelet-client",
|
||||
baseNames: []string{kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName},
|
||||
caBaseNames: []string{kubeadmconstants.CACertAndKeyBaseName},
|
||||
},
|
||||
{
|
||||
command: "apiserver-etcd-client",
|
||||
baseNames: []string{kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName},
|
||||
caBaseNames: []string{kubeadmconstants.EtcdCACertAndKeyBaseName},
|
||||
},
|
||||
{
|
||||
command: "front-proxy-client",
|
||||
baseNames: []string{kubeadmconstants.FrontProxyClientCertAndKeyBaseName},
|
||||
caBaseNames: []string{kubeadmconstants.FrontProxyCACertAndKeyBaseName},
|
||||
},
|
||||
{
|
||||
command: "etcd-server",
|
||||
baseNames: []string{kubeadmconstants.EtcdServerCertAndKeyBaseName},
|
||||
caBaseNames: []string{kubeadmconstants.EtcdCACertAndKeyBaseName},
|
||||
},
|
||||
{
|
||||
command: "etcd-peer",
|
||||
baseNames: []string{kubeadmconstants.EtcdPeerCertAndKeyBaseName},
|
||||
caBaseNames: []string{kubeadmconstants.EtcdCACertAndKeyBaseName},
|
||||
},
|
||||
{
|
||||
command: "etcd-healthcheck-client",
|
||||
baseNames: []string{kubeadmconstants.EtcdHealthcheckClientCertAndKeyBaseName},
|
||||
caBaseNames: []string{kubeadmconstants.EtcdCACertAndKeyBaseName},
|
||||
},
|
||||
}
|
||||
|
||||
renewCmds := getRenewSubCommands()
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.command, func(t *testing.T) {
|
||||
tmpDir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
caCert, caKey := certstestutil.SetupCertificateAuthorithy(t)
|
||||
|
||||
for _, caBaseName := range test.caBaseNames {
|
||||
if err := pkiutil.WriteCertAndKey(tmpDir, caBaseName, caCert, caKey); err != nil {
|
||||
t.Fatalf("couldn't write out CA: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
certTmpl := x509.Certificate{
|
||||
Subject: pkix.Name{
|
||||
CommonName: "test-cert",
|
||||
Organization: []string{"sig-cluster-lifecycle"},
|
||||
},
|
||||
DNSNames: []string{"test-domain.space"},
|
||||
SerialNumber: new(big.Int).SetInt64(0),
|
||||
NotBefore: time.Now().Add(-time.Hour * 24 * 365),
|
||||
NotAfter: time.Now().Add(-time.Hour),
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
|
||||
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't generate private key: %v", err)
|
||||
}
|
||||
|
||||
certDERBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, caCert, key.Public(), caKey)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't generate private key: %v", err)
|
||||
}
|
||||
cert, err := x509.ParseCertificate(certDERBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't generate private key: %v", err)
|
||||
}
|
||||
|
||||
for _, baseName := range test.baseNames {
|
||||
if err := pkiutil.WriteCertAndKey(tmpDir, baseName, cert, key); err != nil {
|
||||
t.Fatalf("couldn't write out initial certificate")
|
||||
}
|
||||
}
|
||||
|
||||
cmdtestutil.RunSubCommand(t, renewCmds, test.command, fmt.Sprintf("--cert-dir=%s", tmpDir))
|
||||
|
||||
for _, baseName := range test.baseNames {
|
||||
newCert, newKey, err := pkiutil.TryLoadCertAndKeyFromDisk(tmpDir, baseName)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't load renewed certificate: %v", err)
|
||||
}
|
||||
|
||||
certstestutil.AssertCertificateIsSignedByCa(t, newCert, caCert)
|
||||
|
||||
pool := x509.NewCertPool()
|
||||
pool.AddCert(caCert)
|
||||
|
||||
_, err = newCert.Verify(x509.VerifyOptions{
|
||||
DNSName: "test-domain.space",
|
||||
Roots: pool,
|
||||
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("couldn't verify renewed cert: %v", err)
|
||||
}
|
||||
|
||||
pubKey, ok := newCert.PublicKey.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
t.Errorf("unknown public key type %T", newCert.PublicKey)
|
||||
} else if pubKey.N.Cmp(newKey.N) != 0 {
|
||||
t.Error("private key does not match public key")
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenewUsingCSR(t *testing.T) {
|
||||
tmpDir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
cert := &certs.KubeadmCertEtcdServer
|
||||
|
||||
renewCmds := getRenewSubCommands()
|
||||
cmdtestutil.RunSubCommand(t, renewCmds, cert.Name, "--csr-only", "--csr-dir="+tmpDir)
|
||||
|
||||
if _, _, err := pkiutil.TryLoadCSRAndKeyFromDisk(tmpDir, cert.BaseName); err != nil {
|
||||
t.Fatalf("couldn't load certificate %q: %v", cert.BaseName, err)
|
||||
}
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package 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
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package 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")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,164 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package alpha
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
utilsexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
var (
|
||||
kubeletConfigDownloadLongDesc = normalizer.LongDesc(`
|
||||
Downloads the kubelet configuration from a ConfigMap of the form "kubelet-config-1.X" in the cluster,
|
||||
where X is the minor version of the kubelet. Either kubeadm autodetects the kubelet version by exec-ing
|
||||
"kubelet --version" or respects the --kubelet-version parameter.
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
|
||||
kubeletConfigDownloadExample = normalizer.Examples(fmt.Sprintf(`
|
||||
# Downloads the kubelet configuration from the ConfigMap in the cluster. Autodetects the kubelet version.
|
||||
kubeadm alpha phase kubelet config download
|
||||
|
||||
# Downloads the kubelet configuration from the ConfigMap in the cluster. Uses a specific desired kubelet version.
|
||||
kubeadm alpha phase kubelet config download --kubelet-version %s
|
||||
`, constants.CurrentKubernetesVersion))
|
||||
|
||||
kubeletConfigEnableDynamicLongDesc = normalizer.LongDesc(`
|
||||
Enables or updates dynamic kubelet configuration for a Node, against the kubelet-config-1.X ConfigMap in the cluster,
|
||||
where X is the minor version of the desired kubelet version.
|
||||
|
||||
WARNING: This feature is still experimental, and disabled by default. Enable only if you know what you are doing, as it
|
||||
may have surprising side-effects at this stage.
|
||||
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
|
||||
kubeletConfigEnableDynamicExample = normalizer.Examples(fmt.Sprintf(`
|
||||
# Enables dynamic kubelet configuration for a Node.
|
||||
kubeadm alpha phase kubelet enable-dynamic-config --node-name node-1 --kubelet-version %s
|
||||
|
||||
WARNING: This feature is still experimental, and disabled by default. Enable only if you know what you are doing, as it
|
||||
may have surprising side-effects at this stage.
|
||||
`, constants.CurrentKubernetesVersion))
|
||||
)
|
||||
|
||||
// newCmdKubeletUtility returns command for `kubeadm phase kubelet`
|
||||
func newCmdKubeletUtility() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "kubelet",
|
||||
Short: "Commands related to handling the kubelet",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
}
|
||||
|
||||
cmd.AddCommand(newCmdKubeletConfig())
|
||||
return cmd
|
||||
}
|
||||
|
||||
// newCmdKubeletConfig returns command for `kubeadm phase kubelet config`
|
||||
func newCmdKubeletConfig() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Utilities for kubelet configuration",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
}
|
||||
|
||||
cmd.AddCommand(newCmdKubeletConfigDownload())
|
||||
cmd.AddCommand(newCmdKubeletConfigEnableDynamic())
|
||||
return cmd
|
||||
}
|
||||
|
||||
// newCmdKubeletConfigDownload calls cobra.Command for downloading the kubelet configuration from the kubelet-config-1.X ConfigMap in the cluster
|
||||
func newCmdKubeletConfigDownload() *cobra.Command {
|
||||
var kubeletVersionStr string
|
||||
// TODO: Be smarter about this and be able to load multiple kubeconfig files in different orders of precedence
|
||||
kubeConfigFile := constants.GetKubeletKubeConfigPath()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "download",
|
||||
Short: "Downloads the kubelet configuration from the cluster ConfigMap kubelet-config-1.X, where X is the minor version of the kubelet.",
|
||||
Long: kubeletConfigDownloadLongDesc,
|
||||
Example: kubeletConfigDownloadExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
kubeletVersion, err := getKubeletVersion(kubeletVersionStr)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = kubeletphase.DownloadConfig(client, kubeletVersion, constants.KubeletRunDirectory)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile)
|
||||
cmd.Flags().StringVar(&kubeletVersionStr, "kubelet-version", kubeletVersionStr, "The desired version for the kubelet. Defaults to being autodetected from 'kubelet --version'.")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func getKubeletVersion(kubeletVersionStr string) (*version.Version, error) {
|
||||
if len(kubeletVersionStr) > 0 {
|
||||
return version.ParseSemantic(kubeletVersionStr)
|
||||
}
|
||||
return preflight.GetKubeletVersion(utilsexec.New())
|
||||
}
|
||||
|
||||
// newCmdKubeletConfigEnableDynamic calls cobra.Command for enabling dynamic kubelet configuration on node
|
||||
// This feature is still in alpha and an experimental state
|
||||
func newCmdKubeletConfigEnableDynamic() *cobra.Command {
|
||||
var nodeName, kubeletVersionStr string
|
||||
var kubeConfigFile string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "enable-dynamic",
|
||||
Short: "EXPERIMENTAL: Enables or updates dynamic kubelet configuration for a Node",
|
||||
Long: kubeletConfigEnableDynamicLongDesc,
|
||||
Example: kubeletConfigEnableDynamicExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(nodeName) == 0 {
|
||||
kubeadmutil.CheckErr(errors.New("The --node-name argument is required"))
|
||||
}
|
||||
if len(kubeletVersionStr) == 0 {
|
||||
kubeadmutil.CheckErr(errors.New("The --kubelet-version argument is required"))
|
||||
}
|
||||
|
||||
kubeletVersion, err := version.ParseSemantic(kubeletVersionStr)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
kubeConfigFile = cmdutil.GetKubeConfigPath(kubeConfigFile)
|
||||
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = kubeletphase.EnableDynamicConfigForNode(client, nodeName, kubeletVersion)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile)
|
||||
cmd.Flags().StringVar(&nodeName, "node-name", nodeName, "Name of the node that should enable the dynamic kubelet configuration")
|
||||
cmd.Flags().StringVar(&kubeletVersionStr, "kubelet-version", kubeletVersionStr, "The desired version for the kubelet")
|
||||
return cmd
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package alpha
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"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"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
selfhostingLongDesc = normalizer.LongDesc(`
|
||||
Converts static Pod files for control plane components into self-hosted DaemonSets configured via the Kubernetes API.
|
||||
|
||||
See the documentation for self-hosting limitations.
|
||||
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
|
||||
selfhostingExample = normalizer.Examples(`
|
||||
# Converts a static Pod-hosted control plane into a self-hosted one.
|
||||
|
||||
kubeadm alpha phase self-hosting convert-from-staticpods
|
||||
`)
|
||||
)
|
||||
|
||||
// NewCmdSelfhosting returns the self-hosting Cobra command
|
||||
func NewCmdSelfhosting(in io.Reader) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "selfhosting",
|
||||
Aliases: []string{"selfhosted", "self-hosting"},
|
||||
Short: "Makes a kubeadm cluster self-hosted",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
}
|
||||
|
||||
cmd.AddCommand(getSelfhostingSubCommand(in))
|
||||
return cmd
|
||||
}
|
||||
|
||||
// getSelfhostingSubCommand returns sub commands for Self-hosting phase
|
||||
func getSelfhostingSubCommand(in io.Reader) *cobra.Command {
|
||||
|
||||
cfg := &kubeadmapiv1beta1.InitConfiguration{}
|
||||
// Default values for the cobra help text
|
||||
kubeadmscheme.Scheme.Default(cfg)
|
||||
|
||||
var cfgPath, featureGatesString, kubeConfigFile string
|
||||
forcePivot, certsInSecrets := false, false
|
||||
|
||||
// Creates the UX Command
|
||||
cmd := &cobra.Command{
|
||||
Use: "pivot",
|
||||
Aliases: []string{"from-staticpods"},
|
||||
Short: "Converts a static Pod-hosted control plane into a self-hosted one",
|
||||
Long: selfhostingLongDesc,
|
||||
Example: selfhostingExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
var err error
|
||||
|
||||
if !forcePivot {
|
||||
fmt.Println("WARNING: self-hosted clusters are not supported by kubeadm upgrade and by other kubeadm commands!")
|
||||
fmt.Print("[pivot] are you sure you want to proceed? [y/n]: ")
|
||||
s := bufio.NewScanner(in)
|
||||
s.Scan()
|
||||
|
||||
err = s.Err()
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
if strings.ToLower(s.Text()) != "y" {
|
||||
kubeadmutil.CheckErr(errors.New("aborted pivot operation"))
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("[pivot] pivoting cluster to self-hosted")
|
||||
|
||||
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
|
||||
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
|
||||
// Gets the Kubernetes client
|
||||
kubeConfigFile = cmdutil.GetKubeConfigPath(kubeConfigFile)
|
||||
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
|
||||
// of the version from the internet when executing LoadOrDefaultInitConfiguration
|
||||
phases.SetKubernetesVersion(&cfg.ClusterConfiguration)
|
||||
|
||||
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
|
||||
internalcfg, err := configutil.LoadOrDefaultInitConfiguration(cfgPath, cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Converts the Static Pod-hosted control plane into a self-hosted one
|
||||
waiter := apiclient.NewKubeWaiter(client, 2*time.Minute, os.Stdout)
|
||||
err = selfhosting.CreateSelfHostedControlPlane(constants.GetStaticPodDirectory(), constants.KubernetesDir, internalcfg, client, waiter, false, certsInSecrets)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
// Add flags to the command
|
||||
// flags bound to the configuration object
|
||||
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, `The path where certificates are stored`)
|
||||
options.AddConfigFlag(cmd.Flags(), &cfgPath)
|
||||
|
||||
cmd.Flags().BoolVarP(
|
||||
&certsInSecrets, "store-certs-in-secrets", "s",
|
||||
false, "Enable storing certs in secrets")
|
||||
|
||||
cmd.Flags().BoolVarP(
|
||||
&forcePivot, "force", "f", false,
|
||||
"Pivot the cluster without prompting for confirmation",
|
||||
)
|
||||
|
||||
// flags that are not bound to the configuration object
|
||||
// Note: All flags that are not bound to the cfg object should be whitelisted in cmd/kubeadm/app/apis/kubeadm/validation/validation.go
|
||||
options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile)
|
||||
|
||||
return cmd
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/lithammer/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/alpha"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
// Register the kubeadm configuration types because CLI flag generation
|
||||
// depends on the generated defaults.
|
||||
)
|
||||
|
||||
// NewKubeadmCommand returns cobra.Command to run kubeadm command
|
||||
func NewKubeadmCommand(in io.Reader, out, err io.Writer) *cobra.Command {
|
||||
var rootfsPath string
|
||||
|
||||
cmds := &cobra.Command{
|
||||
Use: "kubeadm",
|
||||
Short: "kubeadm: easily bootstrap a secure Kubernetes cluster",
|
||||
Long: dedent.Dedent(`
|
||||
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ KUBEADM │
|
||||
│ Easily bootstrap a secure Kubernetes cluster │
|
||||
│ │
|
||||
│ Please give us feedback at: │
|
||||
│ https://github.com/kubernetes/kubeadm/issues │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
|
||||
Example usage:
|
||||
|
||||
Create a two-machine cluster with one control-plane node
|
||||
(which controls the cluster), and one worker node
|
||||
(where your workloads, like Pods and Deployments run).
|
||||
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ On the first machine: │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ control-plane# kubeadm init │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ On the second machine: │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ worker# kubeadm join <arguments-returned-from-init> │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
|
||||
You can then repeat the second step on as many other machines as you like.
|
||||
|
||||
`),
|
||||
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if rootfsPath != "" {
|
||||
if err := kubeadmutil.Chroot(rootfsPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmds.ResetFlags()
|
||||
|
||||
cmds.AddCommand(NewCmdCompletion(out, ""))
|
||||
cmds.AddCommand(NewCmdConfig(out))
|
||||
cmds.AddCommand(NewCmdInit(out, nil))
|
||||
cmds.AddCommand(NewCmdJoin(out, nil))
|
||||
cmds.AddCommand(NewCmdReset(in, out))
|
||||
cmds.AddCommand(NewCmdVersion(out))
|
||||
cmds.AddCommand(NewCmdToken(out, err))
|
||||
cmds.AddCommand(upgrade.NewCmdUpgrade(out))
|
||||
cmds.AddCommand(alpha.NewCmdAlpha(in, out))
|
||||
|
||||
AddKubeadmOtherFlags(cmds.PersistentFlags(), &rootfsPath)
|
||||
|
||||
return cmds
|
||||
}
|
||||
|
||||
// AddKubeadmOtherFlags adds flags that are not bound to a configuration file to the given flagset
|
||||
func AddKubeadmOtherFlags(flagSet *pflag.FlagSet, rootfsPath *string) {
|
||||
flagSet.StringVar(
|
||||
rootfsPath, "rootfs", *rootfsPath,
|
||||
"[EXPERIMENTAL] The path to the 'real' host root filesystem.",
|
||||
)
|
||||
}
|
|
@ -1,303 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/lithammer/dedent"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/klog"
|
||||
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
)
|
||||
|
||||
const defaultBoilerPlate = `
|
||||
# Copyright 2017 The Kubernetes Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
`
|
||||
|
||||
var (
|
||||
completionLong = dedent.Dedent(`
|
||||
Output shell completion code for the specified shell (bash or zsh).
|
||||
The shell code must be evaluated to provide interactive
|
||||
completion of kubeadm commands. This can be done by sourcing it from
|
||||
the .bash_profile.
|
||||
|
||||
Note: this requires the bash-completion framework.
|
||||
|
||||
To install it on Mac use homebrew:
|
||||
$ brew install bash-completion
|
||||
Once installed, bash_completion must be evaluated. This can be done by adding the
|
||||
following line to the .bash_profile
|
||||
$ source $(brew --prefix)/etc/bash_completion
|
||||
|
||||
If bash-completion is not installed on Linux, please install the 'bash-completion' package
|
||||
via your distribution's package manager.
|
||||
|
||||
Note for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2`)
|
||||
|
||||
completionExample = dedent.Dedent(`
|
||||
# Install bash completion on a Mac using homebrew
|
||||
brew install bash-completion
|
||||
printf "\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n" >> $HOME/.bash_profile
|
||||
source $HOME/.bash_profile
|
||||
|
||||
# Load the kubeadm completion code for bash into the current shell
|
||||
source <(kubeadm completion bash)
|
||||
|
||||
# Write bash completion code to a file and source it from .bash_profile
|
||||
kubeadm completion bash > ~/.kube/kubeadm_completion.bash.inc
|
||||
printf "\n# Kubeadm shell completion\nsource '$HOME/.kube/kubeadm_completion.bash.inc'\n" >> $HOME/.bash_profile
|
||||
source $HOME/.bash_profile
|
||||
|
||||
# Load the kubeadm completion code for zsh[1] into the current shell
|
||||
source <(kubeadm completion zsh)`)
|
||||
)
|
||||
|
||||
var (
|
||||
completionShells = map[string]func(out io.Writer, cmd *cobra.Command) error{
|
||||
"bash": runCompletionBash,
|
||||
"zsh": runCompletionZsh,
|
||||
}
|
||||
)
|
||||
|
||||
// GetSupportedShells returns a list of supported shells
|
||||
func GetSupportedShells() []string {
|
||||
shells := []string{}
|
||||
for s := range completionShells {
|
||||
shells = append(shells, s)
|
||||
}
|
||||
return shells
|
||||
}
|
||||
|
||||
// NewCmdCompletion returns the "kubeadm completion" command
|
||||
func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "completion SHELL",
|
||||
Short: "Output shell completion code for the specified shell (bash or zsh).",
|
||||
Long: completionLong,
|
||||
Example: completionExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunCompletion(out, boilerPlate, cmd, args)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
ValidArgs: GetSupportedShells(),
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// RunCompletion checks given arguments and executes command
|
||||
func RunCompletion(out io.Writer, boilerPlate string, cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("shell not specified")
|
||||
}
|
||||
if len(args) > 1 {
|
||||
return errors.New("too many arguments. expected only the shell type")
|
||||
}
|
||||
run, found := completionShells[args[0]]
|
||||
if !found {
|
||||
return errors.Errorf("unsupported shell type %q", args[0])
|
||||
}
|
||||
|
||||
if len(boilerPlate) == 0 {
|
||||
boilerPlate = defaultBoilerPlate
|
||||
}
|
||||
if _, err := out.Write([]byte(boilerPlate)); err != nil {
|
||||
return err
|
||||
}
|
||||
return run(out, cmd.Parent())
|
||||
}
|
||||
|
||||
func runCompletionBash(out io.Writer, kubeadm *cobra.Command) error {
|
||||
klog.V(1).Infoln("[completion] writing completion code for Bash")
|
||||
return kubeadm.GenBashCompletion(out)
|
||||
}
|
||||
|
||||
func runCompletionZsh(out io.Writer, kubeadm *cobra.Command) error {
|
||||
zshInitialization := `
|
||||
__kubeadm_bash_source() {
|
||||
alias shopt=':'
|
||||
alias _expand=_bash_expand
|
||||
alias _complete=_bash_comp
|
||||
emulate -L sh
|
||||
setopt kshglob noshglob braceexpand
|
||||
|
||||
source "$@"
|
||||
}
|
||||
|
||||
__kubeadm_type() {
|
||||
# -t is not supported by zsh
|
||||
if [ "$1" == "-t" ]; then
|
||||
shift
|
||||
|
||||
# fake Bash 4 to disable "complete -o nospace". Instead
|
||||
# "compopt +-o nospace" is used in the code to toggle trailing
|
||||
# spaces. We don't support that, but leave trailing spaces on
|
||||
# all the time
|
||||
if [ "$1" = "__kubeadm_compopt" ]; then
|
||||
echo builtin
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
type "$@"
|
||||
}
|
||||
|
||||
__kubeadm_compgen() {
|
||||
local completions w
|
||||
completions=( $(compgen "$@") ) || return $?
|
||||
|
||||
# filter by given word as prefix
|
||||
while [[ "$1" = -* && "$1" != -- ]]; do
|
||||
shift
|
||||
shift
|
||||
done
|
||||
if [[ "$1" == -- ]]; then
|
||||
shift
|
||||
fi
|
||||
for w in "${completions[@]}"; do
|
||||
if [[ "${w}" = "$1"* ]]; then
|
||||
echo "${w}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
__kubeadm_compopt() {
|
||||
true # don't do anything. Not supported by bashcompinit in zsh
|
||||
}
|
||||
|
||||
__kubeadm_ltrim_colon_completions()
|
||||
{
|
||||
if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
|
||||
# Remove colon-word prefix from COMPREPLY items
|
||||
local colon_word=${1%${1##*:}}
|
||||
local i=${#COMPREPLY[*]}
|
||||
while [[ $((--i)) -ge 0 ]]; do
|
||||
COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
__kubeadm_get_comp_words_by_ref() {
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[${COMP_CWORD}-1]}"
|
||||
words=("${COMP_WORDS[@]}")
|
||||
cword=("${COMP_CWORD[@]}")
|
||||
}
|
||||
|
||||
__kubeadm_filedir() {
|
||||
local RET OLD_IFS w qw
|
||||
|
||||
__kubectl_debug "_filedir $@ cur=$cur"
|
||||
if [[ "$1" = \~* ]]; then
|
||||
# somehow does not work. Maybe, zsh does not call this at all
|
||||
eval echo "$1"
|
||||
return 0
|
||||
fi
|
||||
|
||||
OLD_IFS="$IFS"
|
||||
IFS=$'\n'
|
||||
if [ "$1" = "-d" ]; then
|
||||
shift
|
||||
RET=( $(compgen -d) )
|
||||
else
|
||||
RET=( $(compgen -f) )
|
||||
fi
|
||||
IFS="$OLD_IFS"
|
||||
|
||||
IFS="," __kubectl_debug "RET=${RET[@]} len=${#RET[@]}"
|
||||
|
||||
for w in ${RET[@]}; do
|
||||
if [[ ! "${w}" = "${cur}"* ]]; then
|
||||
continue
|
||||
fi
|
||||
if eval "[[ \"\${w}\" = *.$1 || -d \"\${w}\" ]]"; then
|
||||
qw="$(__kubeadm_quote "${w}")"
|
||||
if [ -d "${w}" ]; then
|
||||
COMPREPLY+=("${qw}/")
|
||||
else
|
||||
COMPREPLY+=("${qw}")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
__kubeadm_quote() {
|
||||
if [[ $1 == \'* || $1 == \"* ]]; then
|
||||
# Leave out first character
|
||||
printf %q "${1:1}"
|
||||
else
|
||||
printf %q "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
autoload -U +X bashcompinit && bashcompinit
|
||||
|
||||
# use word boundary patterns for BSD or GNU sed
|
||||
LWORD='[[:<:]]'
|
||||
RWORD='[[:>:]]'
|
||||
if sed --help 2>&1 | grep -q GNU; then
|
||||
LWORD='\<'
|
||||
RWORD='\>'
|
||||
fi
|
||||
|
||||
__kubeadm_convert_bash_to_zsh() {
|
||||
sed \
|
||||
-e 's/declare -F/whence -w/' \
|
||||
-e 's/local \([a-zA-Z0-9_]*\)=/local \1; \1=/' \
|
||||
-e 's/flags+=("\(--.*\)=")/flags+=("\1"); two_word_flags+=("\1")/' \
|
||||
-e 's/must_have_one_flag+=("\(--.*\)=")/must_have_one_flag+=("\1")/' \
|
||||
-e "s/${LWORD}_filedir${RWORD}/__kubeadm_filedir/g" \
|
||||
-e "s/${LWORD}_get_comp_words_by_ref${RWORD}/__kubeadm_get_comp_words_by_ref/g" \
|
||||
-e "s/${LWORD}__ltrim_colon_completions${RWORD}/__kubeadm_ltrim_colon_completions/g" \
|
||||
-e "s/${LWORD}compgen${RWORD}/__kubeadm_compgen/g" \
|
||||
-e "s/${LWORD}compopt${RWORD}/__kubeadm_compopt/g" \
|
||||
-e "s/${LWORD}declare${RWORD}/builtin declare/g" \
|
||||
-e "s/\\\$(type${RWORD}/\$(__kubeadm_type/g" \
|
||||
<<'BASH_COMPLETION_EOF'
|
||||
`
|
||||
klog.V(1).Infoln("[completion] writing completion code for Zsh")
|
||||
out.Write([]byte(zshInitialization))
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
kubeadm.GenBashCompletion(buf)
|
||||
klog.V(1).Infoln("[completion] writing completion code for Bash")
|
||||
out.Write(buf.Bytes())
|
||||
|
||||
zshTail := `
|
||||
BASH_COMPLETION_EOF
|
||||
}
|
||||
|
||||
__kubeadm_bash_source <(__kubeadm_convert_bash_to_zsh)
|
||||
`
|
||||
out.Write([]byte(zshTail))
|
||||
return nil
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const shellsError = "Unexpected empty completion shells list"
|
||||
|
||||
func TestNewCmdCompletion(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
shells := GetSupportedShells()
|
||||
if len(shells) == 0 {
|
||||
t.Errorf(shellsError)
|
||||
}
|
||||
// test NewCmdCompletion with a valid shell.
|
||||
// use a dummy parent command as NewCmdCompletion needs it.
|
||||
parentCmd := &cobra.Command{}
|
||||
args := []string{"completion", shells[0]}
|
||||
parentCmd.SetArgs(args)
|
||||
cmd := NewCmdCompletion(&out, "")
|
||||
parentCmd.AddCommand(cmd)
|
||||
if err := parentCmd.Execute(); err != nil {
|
||||
t.Errorf("Cannot exectute NewCmdCompletion: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCompletion(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
type TestCase struct {
|
||||
name string
|
||||
args []string
|
||||
expectedError bool
|
||||
}
|
||||
|
||||
testCases := []TestCase{
|
||||
{
|
||||
name: "invalid: missing argument",
|
||||
args: []string{},
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid: too many arguments",
|
||||
args: []string{"", ""},
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid: unsupported shell name",
|
||||
args: []string{"unsupported"},
|
||||
expectedError: true,
|
||||
},
|
||||
}
|
||||
|
||||
// test all supported shells
|
||||
shells := GetSupportedShells()
|
||||
if len(shells) == 0 {
|
||||
t.Errorf(shellsError)
|
||||
}
|
||||
for _, shell := range shells {
|
||||
test := TestCase{
|
||||
name: "valid: test shell " + shell,
|
||||
args: []string{shell},
|
||||
}
|
||||
testCases = append(testCases, test)
|
||||
}
|
||||
|
||||
// use dummy cobra commands
|
||||
parentCmd := &cobra.Command{}
|
||||
cmd := &cobra.Command{}
|
||||
parentCmd.AddCommand(cmd)
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if err := RunCompletion(&out, "", cmd, tc.args); (err != nil) != tc.expectedError {
|
||||
t.Errorf("Test case %q: TestRunCompletion expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,527 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/lithammer/dedent"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
"k8s.io/klog"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
phaseutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
utilruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime"
|
||||
utilsexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
var (
|
||||
// placeholderToken is only set statically to make kubeadm not randomize the token on every run
|
||||
placeholderToken = kubeadmapiv1beta1.BootstrapToken{
|
||||
Token: &kubeadmapiv1beta1.BootstrapTokenString{
|
||||
ID: "abcdef",
|
||||
Secret: "0123456789abcdef",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// NewCmdConfig returns cobra.Command for "kubeadm config" command
|
||||
func NewCmdConfig(out io.Writer) *cobra.Command {
|
||||
var kubeConfigFile string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Manage configuration for a kubeadm cluster persisted in a ConfigMap in the cluster.",
|
||||
Long: fmt.Sprintf(dedent.Dedent(`
|
||||
There is a ConfigMap in the %s namespace called %q that kubeadm uses to store internal configuration about the
|
||||
cluster. kubeadm CLI v1.8.0+ automatically creates this ConfigMap with the config used with 'kubeadm init', but if you
|
||||
initialized your cluster using kubeadm v1.7.x or lower, you must use the 'config upload' command to create this
|
||||
ConfigMap. This is required so that 'kubeadm upgrade' can configure your upgraded cluster correctly.
|
||||
`), metav1.NamespaceSystem, constants.KubeadmConfigConfigMap),
|
||||
// Without this callback, if a user runs just the "upload"
|
||||
// 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: cmdutil.SubCmdRunE("config"),
|
||||
}
|
||||
|
||||
options.AddKubeConfigFlag(cmd.PersistentFlags(), &kubeConfigFile)
|
||||
|
||||
kubeConfigFile = cmdutil.GetKubeConfigPath(kubeConfigFile)
|
||||
cmd.AddCommand(NewCmdConfigPrint(out))
|
||||
cmd.AddCommand(NewCmdConfigMigrate(out))
|
||||
cmd.AddCommand(NewCmdConfigUpload(out, &kubeConfigFile))
|
||||
cmd.AddCommand(NewCmdConfigView(out, &kubeConfigFile))
|
||||
cmd.AddCommand(NewCmdConfigImages(out))
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigPrint returns cobra.Command for "kubeadm config print" command
|
||||
func NewCmdConfigPrint(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "print",
|
||||
Short: "Print configuration",
|
||||
Long: "This command prints configurations for subcommands provided.",
|
||||
RunE: cmdutil.SubCmdRunE("print"),
|
||||
}
|
||||
cmd.AddCommand(NewCmdConfigPrintInitDefaults(out))
|
||||
cmd.AddCommand(NewCmdConfigPrintJoinDefaults(out))
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigPrintInitDefaults returns cobra.Command for "kubeadm config print init-defaults" command
|
||||
func NewCmdConfigPrintInitDefaults(out io.Writer) *cobra.Command {
|
||||
return newCmdConfigPrintActionDefaults(out, "init", getDefaultInitConfigBytes)
|
||||
}
|
||||
|
||||
// NewCmdConfigPrintJoinDefaults returns cobra.Command for "kubeadm config print join-defaults" command
|
||||
func NewCmdConfigPrintJoinDefaults(out io.Writer) *cobra.Command {
|
||||
return newCmdConfigPrintActionDefaults(out, "join", getDefaultNodeConfigBytes)
|
||||
}
|
||||
|
||||
func newCmdConfigPrintActionDefaults(out io.Writer, action string, configBytesProc func() ([]byte, error)) *cobra.Command {
|
||||
componentConfigs := []string{}
|
||||
cmd := &cobra.Command{
|
||||
Use: fmt.Sprintf("%s-defaults", action),
|
||||
Short: fmt.Sprintf("Print default %s configuration, that can be used for 'kubeadm %s'", action, action),
|
||||
Long: fmt.Sprintf(dedent.Dedent(`
|
||||
This command prints objects such as the default %s configuration that is used for 'kubeadm %s'.
|
||||
|
||||
Note that sensitive values like the Bootstrap Token fields are replaced with placeholder values like %q in order to pass validation but
|
||||
not perform the real computation for creating a token.
|
||||
`), action, action, placeholderToken),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
runConfigPrintActionDefaults(out, componentConfigs, configBytesProc)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringSliceVar(&componentConfigs, "component-configs", componentConfigs,
|
||||
fmt.Sprintf("A comma-separated list for component config API objects to print the default values for. Available values: %v. If this flag is not set, no component configs will be printed.", getSupportedComponentConfigAPIObjects()))
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runConfigPrintActionDefaults(out io.Writer, componentConfigs []string, configBytesProc func() ([]byte, error)) {
|
||||
initialConfig, err := configBytesProc()
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
allBytes := [][]byte{initialConfig}
|
||||
for _, componentConfig := range componentConfigs {
|
||||
cfgBytes, err := getDefaultComponentConfigBytes(componentConfig)
|
||||
kubeadmutil.CheckErr(err)
|
||||
allBytes = append(allBytes, cfgBytes)
|
||||
}
|
||||
|
||||
fmt.Fprint(out, string(bytes.Join(allBytes, []byte(constants.YAMLDocumentSeparator))))
|
||||
}
|
||||
|
||||
func getDefaultComponentConfigBytes(apiObject string) ([]byte, error) {
|
||||
registration, ok := componentconfigs.Known[componentconfigs.RegistrationKind(apiObject)]
|
||||
if !ok {
|
||||
return []byte{}, errors.Errorf("--component-configs needs to contain some of %v", getSupportedComponentConfigAPIObjects())
|
||||
}
|
||||
|
||||
defaultedInitConfig, err := getDefaultedInitConfig()
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
realObj, ok := registration.GetFromInternalConfig(&defaultedInitConfig.ClusterConfiguration)
|
||||
if !ok {
|
||||
return []byte{}, errors.New("GetFromInternalConfig failed")
|
||||
}
|
||||
|
||||
return registration.Marshal(realObj)
|
||||
}
|
||||
|
||||
// getSupportedComponentConfigAPIObjects returns all currently supported component config API object names
|
||||
func getSupportedComponentConfigAPIObjects() []string {
|
||||
objects := []string{}
|
||||
for componentType := range componentconfigs.Known {
|
||||
objects = append(objects, string(componentType))
|
||||
}
|
||||
return objects
|
||||
}
|
||||
|
||||
func getDefaultedInitConfig() (*kubeadmapi.InitConfiguration, error) {
|
||||
return configutil.DefaultedInitConfiguration(&kubeadmapiv1beta1.InitConfiguration{
|
||||
// TODO: Probably move to getDefaultedClusterConfig?
|
||||
LocalAPIEndpoint: kubeadmapiv1beta1.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
|
||||
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
|
||||
KubernetesVersion: fmt.Sprintf("v1.%d.0", constants.MinimumControlPlaneVersion.Minor()+1),
|
||||
},
|
||||
BootstrapTokens: []kubeadmapiv1beta1.BootstrapToken{placeholderToken},
|
||||
NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{
|
||||
CRISocket: constants.DefaultDockerCRISocket, // avoid CRI detection
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func getDefaultInitConfigBytes() ([]byte, error) {
|
||||
internalcfg, err := getDefaultedInitConfig()
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
return configutil.MarshalKubeadmConfigObject(internalcfg)
|
||||
}
|
||||
|
||||
func getDefaultNodeConfigBytes() ([]byte, error) {
|
||||
internalcfg, err := configutil.DefaultedJoinConfiguration(&kubeadmapiv1beta1.JoinConfiguration{
|
||||
Discovery: kubeadmapiv1beta1.Discovery{
|
||||
BootstrapToken: &kubeadmapiv1beta1.BootstrapTokenDiscovery{
|
||||
Token: placeholderToken.Token.String(),
|
||||
APIServerEndpoint: "kube-apiserver:6443",
|
||||
UnsafeSkipCAVerification: true, // TODO: UnsafeSkipCAVerification: true needs to be set for validation to pass, but shouldn't be recommended as the default
|
||||
},
|
||||
},
|
||||
NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{
|
||||
CRISocket: constants.DefaultDockerCRISocket, // avoid CRI detection
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
return configutil.MarshalKubeadmConfigObject(internalcfg)
|
||||
}
|
||||
|
||||
// NewCmdConfigMigrate returns cobra.Command for "kubeadm config migrate" command
|
||||
func NewCmdConfigMigrate(out io.Writer) *cobra.Command {
|
||||
var oldCfgPath, newCfgPath string
|
||||
cmd := &cobra.Command{
|
||||
Use: "migrate",
|
||||
Short: "Read an older version of the kubeadm configuration API types from a file, and output the similar config object for the newer version.",
|
||||
Long: fmt.Sprintf(dedent.Dedent(`
|
||||
This command lets you convert configuration objects of older versions to the latest supported version,
|
||||
locally in the CLI tool without ever touching anything in the cluster.
|
||||
In this version of kubeadm, the following API versions are supported:
|
||||
- %s
|
||||
- %s
|
||||
|
||||
Further, kubeadm can only write out config of version %q, but read both types.
|
||||
So regardless of what version you pass to the --old-config parameter here, the API object will be
|
||||
read, deserialized, defaulted, converted, validated, and re-serialized when written to stdout or
|
||||
--new-config if specified.
|
||||
|
||||
In other words, the output of this command is what kubeadm actually would read internally if you
|
||||
submitted this file to "kubeadm init"
|
||||
`), kubeadmapiv1alpha3.SchemeGroupVersion.String(), kubeadmapiv1beta1.SchemeGroupVersion.String(), kubeadmapiv1beta1.SchemeGroupVersion.String()),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(oldCfgPath) == 0 {
|
||||
kubeadmutil.CheckErr(errors.New("The --old-config flag is mandatory"))
|
||||
}
|
||||
|
||||
oldCfgBytes, err := ioutil.ReadFile(oldCfgPath)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
outputBytes, err := configutil.MigrateOldConfig(oldCfgBytes)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
if newCfgPath == "" {
|
||||
fmt.Fprint(out, string(outputBytes))
|
||||
} else {
|
||||
if err := ioutil.WriteFile(newCfgPath, outputBytes, 0644); err != nil {
|
||||
kubeadmutil.CheckErr(errors.Wrapf(err, "failed to write the new configuration to the file %q", newCfgPath))
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringVar(&oldCfgPath, "old-config", "", "Path to the kubeadm config file that is using an old API version and should be converted. This flag is mandatory.")
|
||||
cmd.Flags().StringVar(&newCfgPath, "new-config", "", "Path to the resulting equivalent kubeadm config file using the new API version. Optional, if not specified output will be sent to STDOUT.")
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigUpload returns cobra.Command for "kubeadm config upload" command
|
||||
func NewCmdConfigUpload(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "upload",
|
||||
Short: "Upload configuration about the current state, so that 'kubeadm upgrade' can later know how to configure the upgraded cluster.",
|
||||
RunE: cmdutil.SubCmdRunE("upload"),
|
||||
}
|
||||
|
||||
cmd.AddCommand(NewCmdConfigUploadFromFile(out, kubeConfigFile))
|
||||
cmd.AddCommand(NewCmdConfigUploadFromFlags(out, kubeConfigFile))
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigView returns cobra.Command for "kubeadm config view" command
|
||||
func NewCmdConfigView(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "view",
|
||||
Short: "View the kubeadm configuration stored inside the cluster.",
|
||||
Long: fmt.Sprintf(dedent.Dedent(`
|
||||
Using this command, you can view the ConfigMap in the cluster where the configuration for kubeadm is located.
|
||||
|
||||
The configuration is located in the %q namespace in the %q ConfigMap.
|
||||
`), metav1.NamespaceSystem, constants.KubeadmConfigConfigMap),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
klog.V(1).Infoln("[config] retrieving ClientSet from file")
|
||||
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = RunConfigView(out, client)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmdConfigUploadFromFile verifies given Kubernetes config file and returns cobra.Command for
|
||||
// "kubeadm config upload from-file" command
|
||||
func NewCmdConfigUploadFromFile(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
var cfgPath string
|
||||
cmd := &cobra.Command{
|
||||
Use: "from-file",
|
||||
Short: "Upload a configuration file to the in-cluster ConfigMap for kubeadm configuration.",
|
||||
Long: fmt.Sprintf(dedent.Dedent(`
|
||||
Using this command, you can upload configuration to the ConfigMap in the cluster using the same config file you gave to 'kubeadm init'.
|
||||
If you initialized your cluster using a v1.7.x or lower kubeadm client and used the --config option, you need to run this command with the
|
||||
same config file before upgrading to v1.8 using 'kubeadm upgrade'.
|
||||
|
||||
The configuration is located in the %q namespace in the %q ConfigMap.
|
||||
`), metav1.NamespaceSystem, constants.KubeadmConfigConfigMap),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(cfgPath) == 0 {
|
||||
kubeadmutil.CheckErr(errors.New("The --config flag is mandatory"))
|
||||
}
|
||||
|
||||
klog.V(1).Infoln("[config] retrieving ClientSet from file")
|
||||
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Default both statically and dynamically, convert to internal API type, and validate everything
|
||||
internalcfg, err := configutil.LoadInitConfigurationFromFile(cfgPath)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Upload the configuration using the file
|
||||
klog.V(1).Infof("[config] uploading configuration")
|
||||
err = uploadconfig.UploadConfiguration(internalcfg, client)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
options.AddConfigFlag(cmd.Flags(), &cfgPath)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigUploadFromFlags returns cobra.Command for "kubeadm config upload from-flags" command
|
||||
func NewCmdConfigUploadFromFlags(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
cfg := &kubeadmapiv1beta1.InitConfiguration{}
|
||||
kubeadmscheme.Scheme.Default(cfg)
|
||||
|
||||
var featureGatesString string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "from-flags",
|
||||
Short: "Create the in-cluster configuration file for the first time from using flags.",
|
||||
Long: fmt.Sprintf(dedent.Dedent(`
|
||||
Using this command, you can upload configuration to the ConfigMap in the cluster using the same flags you gave to 'kubeadm init'.
|
||||
If you initialized your cluster using a v1.7.x or lower kubeadm client and set certain flags, you need to run this command with the
|
||||
same flags before upgrading to v1.8 using 'kubeadm upgrade'.
|
||||
|
||||
The configuration is located in the %q namespace in the %q ConfigMap.
|
||||
`), metav1.NamespaceSystem, constants.KubeadmConfigConfigMap),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
klog.V(1).Infoln("[config] creating new FeatureGates")
|
||||
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
klog.V(1).Infoln("[config] retrieving ClientSet from file")
|
||||
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
|
||||
// of the version from the internet when executing DefaultedInitConfiguration
|
||||
phaseutil.SetKubernetesVersion(&cfg.ClusterConfiguration)
|
||||
|
||||
// Default both statically and dynamically, convert to internal API type, and validate everything
|
||||
klog.V(1).Infoln("[config] converting to internal API type")
|
||||
internalcfg, err := configutil.DefaultedInitConfiguration(cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Finally, upload the configuration
|
||||
klog.V(1).Infof("[config] uploading configuration")
|
||||
err = uploadconfig.UploadConfiguration(internalcfg, client)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
AddInitConfigFlags(cmd.PersistentFlags(), cfg, &featureGatesString)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// RunConfigView gets the configuration persisted in the cluster
|
||||
func RunConfigView(out io.Writer, client clientset.Interface) error {
|
||||
|
||||
klog.V(1).Infoln("[config] getting the cluster configuration")
|
||||
cfgConfigMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(constants.KubeadmConfigConfigMap, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// No need to append \n as that already exists in the ConfigMap
|
||||
fmt.Fprintf(out, "%s", cfgConfigMap.Data[constants.ClusterConfigurationConfigMapKey])
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewCmdConfigImages returns the "kubeadm config images" command
|
||||
func NewCmdConfigImages(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "images",
|
||||
Short: "Interact with container images used by kubeadm.",
|
||||
RunE: cmdutil.SubCmdRunE("images"),
|
||||
}
|
||||
cmd.AddCommand(NewCmdConfigImagesList(out, nil))
|
||||
cmd.AddCommand(NewCmdConfigImagesPull())
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigImagesPull returns the `kubeadm config images pull` command
|
||||
func NewCmdConfigImagesPull() *cobra.Command {
|
||||
externalcfg := &kubeadmapiv1beta1.InitConfiguration{}
|
||||
kubeadmscheme.Scheme.Default(externalcfg)
|
||||
var cfgPath, featureGatesString string
|
||||
var err error
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "pull",
|
||||
Short: "Pull images used by kubeadm.",
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
externalcfg.ClusterConfiguration.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString)
|
||||
kubeadmutil.CheckErr(err)
|
||||
internalcfg, err := configutil.LoadOrDefaultInitConfiguration(cfgPath, externalcfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
containerRuntime, err := utilruntime.NewContainerRuntime(utilsexec.New(), internalcfg.GetCRISocket())
|
||||
kubeadmutil.CheckErr(err)
|
||||
imagesPull := NewImagesPull(containerRuntime, images.GetAllImages(&internalcfg.ClusterConfiguration))
|
||||
kubeadmutil.CheckErr(imagesPull.PullAll())
|
||||
},
|
||||
}
|
||||
AddImagesCommonConfigFlags(cmd.PersistentFlags(), externalcfg, &cfgPath, &featureGatesString)
|
||||
cmdutil.AddCRISocketFlag(cmd.PersistentFlags(), &externalcfg.NodeRegistration.CRISocket)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// ImagesPull is the struct used to hold information relating to image pulling
|
||||
type ImagesPull struct {
|
||||
runtime utilruntime.ContainerRuntime
|
||||
images []string
|
||||
}
|
||||
|
||||
// NewImagesPull initializes and returns the `kubeadm config images pull` command
|
||||
func NewImagesPull(runtime utilruntime.ContainerRuntime, images []string) *ImagesPull {
|
||||
return &ImagesPull{
|
||||
runtime: runtime,
|
||||
images: images,
|
||||
}
|
||||
}
|
||||
|
||||
// PullAll pulls all images that the ImagesPull knows about
|
||||
func (ip *ImagesPull) PullAll() error {
|
||||
for _, image := range ip.images {
|
||||
if err := ip.runtime.PullImage(image); err != nil {
|
||||
return errors.Wrapf(err, "failed to pull image %q", image)
|
||||
}
|
||||
fmt.Printf("[config/images] Pulled %s\n", image)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewCmdConfigImagesList returns the "kubeadm config images list" command
|
||||
func NewCmdConfigImagesList(out io.Writer, mockK8sVersion *string) *cobra.Command {
|
||||
externalcfg := &kubeadmapiv1beta1.InitConfiguration{}
|
||||
kubeadmscheme.Scheme.Default(externalcfg)
|
||||
var cfgPath, featureGatesString string
|
||||
var err error
|
||||
|
||||
// This just sets the Kubernetes version for unit testing so kubeadm won't try to
|
||||
// lookup the latest release from the internet.
|
||||
if mockK8sVersion != nil {
|
||||
externalcfg.KubernetesVersion = *mockK8sVersion
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "Print a list of images kubeadm will use. The configuration file is used in case any images or image repositories are customized.",
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
externalcfg.ClusterConfiguration.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString)
|
||||
kubeadmutil.CheckErr(err)
|
||||
imagesList, err := NewImagesList(cfgPath, externalcfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
kubeadmutil.CheckErr(imagesList.Run(out))
|
||||
},
|
||||
}
|
||||
AddImagesCommonConfigFlags(cmd.PersistentFlags(), externalcfg, &cfgPath, &featureGatesString)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewImagesList returns the underlying struct for the "kubeadm config images list" command
|
||||
func NewImagesList(cfgPath string, cfg *kubeadmapiv1beta1.InitConfiguration) (*ImagesList, error) {
|
||||
initcfg, err := configutil.LoadOrDefaultInitConfiguration(cfgPath, cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert cfg to an internal cfg")
|
||||
}
|
||||
|
||||
return &ImagesList{
|
||||
cfg: initcfg,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ImagesList defines the struct used for "kubeadm config images list"
|
||||
type ImagesList struct {
|
||||
cfg *kubeadmapi.InitConfiguration
|
||||
}
|
||||
|
||||
// Run runs the images command and writes the result to the io.Writer passed in
|
||||
func (i *ImagesList) Run(out io.Writer) error {
|
||||
imgs := images.GetAllImages(&i.cfg.ClusterConfiguration)
|
||||
for _, img := range imgs {
|
||||
fmt.Fprintln(out, img)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddImagesCommonConfigFlags adds the flags that configure kubeadm (and affect the images kubeadm will use)
|
||||
func AddImagesCommonConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.InitConfiguration, cfgPath *string, featureGatesString *string) {
|
||||
flagSet.StringVar(
|
||||
&cfg.ClusterConfiguration.KubernetesVersion, "kubernetes-version", cfg.ClusterConfiguration.KubernetesVersion,
|
||||
`Choose a specific Kubernetes version for the control plane.`,
|
||||
)
|
||||
flagSet.StringVar(featureGatesString, "feature-gates", *featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+
|
||||
"Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n"))
|
||||
flagSet.StringVar(cfgPath, "config", *cfgPath, "Path to kubeadm config file.")
|
||||
}
|
|
@ -1,391 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/lithammer/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
utilruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime"
|
||||
"k8s.io/utils/exec"
|
||||
fakeexec "k8s.io/utils/exec/testing"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultNumberOfImages = 8
|
||||
)
|
||||
|
||||
// dummyKubernetesVersion is just used for unit testing, in order to not make
|
||||
// kubeadm lookup dl.k8s.io to resolve what the latest stable release is
|
||||
var dummyKubernetesVersion = constants.MinimumControlPlaneVersion.String()
|
||||
|
||||
func TestNewCmdConfigImagesList(t *testing.T) {
|
||||
var output bytes.Buffer
|
||||
mockK8sVersion := dummyKubernetesVersion
|
||||
images := NewCmdConfigImagesList(&output, &mockK8sVersion)
|
||||
images.Run(nil, nil)
|
||||
actual := strings.Split(output.String(), "\n")
|
||||
if len(actual) != defaultNumberOfImages {
|
||||
t.Fatalf("Expected %v but found %v images", defaultNumberOfImages, len(actual))
|
||||
}
|
||||
}
|
||||
|
||||
func TestImagesListRunWithCustomConfigPath(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
expectedImageCount int
|
||||
// each string provided here must appear in at least one image returned by Run
|
||||
expectedImageSubstrings []string
|
||||
configContents []byte
|
||||
}{
|
||||
{
|
||||
name: "set k8s version",
|
||||
expectedImageCount: defaultNumberOfImages,
|
||||
expectedImageSubstrings: []string{
|
||||
constants.CurrentKubernetesVersion.String(),
|
||||
},
|
||||
configContents: []byte(dedent.Dedent(fmt.Sprintf(`
|
||||
apiVersion: kubeadm.k8s.io/v1beta1
|
||||
kind: ClusterConfiguration
|
||||
kubernetesVersion: %s
|
||||
`, constants.CurrentKubernetesVersion))),
|
||||
},
|
||||
{
|
||||
name: "use coredns",
|
||||
expectedImageCount: defaultNumberOfImages,
|
||||
expectedImageSubstrings: []string{
|
||||
"coredns",
|
||||
},
|
||||
configContents: []byte(dedent.Dedent(fmt.Sprintf(`
|
||||
apiVersion: kubeadm.k8s.io/v1beta1
|
||||
kind: ClusterConfiguration
|
||||
kubernetesVersion: %s
|
||||
`, constants.MinimumControlPlaneVersion))),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
tmpDir, err := ioutil.TempDir("", "kubeadm-images-test")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create temporary directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
configFilePath := filepath.Join(tmpDir, "test-config-file")
|
||||
if err := ioutil.WriteFile(configFilePath, tc.configContents, 0644); err != nil {
|
||||
t.Fatalf("Failed writing a config file: %v", err)
|
||||
}
|
||||
|
||||
i, err := NewImagesList(configFilePath, &kubeadmapiv1beta1.InitConfiguration{
|
||||
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
|
||||
KubernetesVersion: dummyKubernetesVersion,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed getting the kubeadm images command: %v", err)
|
||||
}
|
||||
var output bytes.Buffer
|
||||
if i.Run(&output) != nil {
|
||||
t.Fatalf("Error from running the images command: %v", err)
|
||||
}
|
||||
actual := strings.Split(output.String(), "\n")
|
||||
if len(actual) != tc.expectedImageCount {
|
||||
t.Fatalf("did not get the same number of images: actual: %v expected: %v. Actual value: %v", len(actual), tc.expectedImageCount, actual)
|
||||
}
|
||||
|
||||
for _, substring := range tc.expectedImageSubstrings {
|
||||
if !strings.Contains(output.String(), substring) {
|
||||
t.Errorf("Expected to find %v but did not in this list of images: %v", substring, actual)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigImagesListRunWithoutPath(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
cfg kubeadmapiv1beta1.InitConfiguration
|
||||
expectedImages int
|
||||
}{
|
||||
{
|
||||
name: "empty config",
|
||||
expectedImages: defaultNumberOfImages,
|
||||
cfg: kubeadmapiv1beta1.InitConfiguration{
|
||||
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
|
||||
KubernetesVersion: dummyKubernetesVersion,
|
||||
},
|
||||
NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{
|
||||
CRISocket: constants.DefaultDockerCRISocket,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "external etcd configuration",
|
||||
cfg: kubeadmapiv1beta1.InitConfiguration{
|
||||
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
|
||||
Etcd: kubeadmapiv1beta1.Etcd{
|
||||
External: &kubeadmapiv1beta1.ExternalEtcd{
|
||||
Endpoints: []string{"https://some.etcd.com:2379"},
|
||||
},
|
||||
},
|
||||
KubernetesVersion: dummyKubernetesVersion,
|
||||
},
|
||||
NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{
|
||||
CRISocket: constants.DefaultDockerCRISocket,
|
||||
},
|
||||
},
|
||||
expectedImages: defaultNumberOfImages - 1,
|
||||
},
|
||||
{
|
||||
name: "coredns enabled",
|
||||
cfg: kubeadmapiv1beta1.InitConfiguration{
|
||||
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
|
||||
KubernetesVersion: dummyKubernetesVersion,
|
||||
},
|
||||
NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{
|
||||
CRISocket: constants.DefaultDockerCRISocket,
|
||||
},
|
||||
},
|
||||
expectedImages: defaultNumberOfImages,
|
||||
},
|
||||
{
|
||||
name: "kube-dns enabled",
|
||||
cfg: kubeadmapiv1beta1.InitConfiguration{
|
||||
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
|
||||
KubernetesVersion: dummyKubernetesVersion,
|
||||
DNS: kubeadmapiv1beta1.DNS{
|
||||
Type: kubeadmapiv1beta1.KubeDNS,
|
||||
},
|
||||
},
|
||||
NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{
|
||||
CRISocket: constants.DefaultDockerCRISocket,
|
||||
},
|
||||
},
|
||||
expectedImages: defaultNumberOfImages + 2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
i, err := NewImagesList("", &tc.cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("did not expect an error while creating the Images command: %v", err)
|
||||
}
|
||||
|
||||
var output bytes.Buffer
|
||||
if i.Run(&output) != nil {
|
||||
t.Fatalf("did not expect an error running the Images command: %v", err)
|
||||
}
|
||||
|
||||
actual := strings.Split(output.String(), "\n")
|
||||
if len(actual) != tc.expectedImages {
|
||||
t.Fatalf("expected %v images but got %v", tc.expectedImages, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestImagesPull(t *testing.T) {
|
||||
fcmd := fakeexec.FakeCmd{
|
||||
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||
func() ([]byte, error) { return nil, nil },
|
||||
func() ([]byte, error) { return nil, nil },
|
||||
func() ([]byte, error) { return nil, nil },
|
||||
func() ([]byte, error) { return nil, nil },
|
||||
func() ([]byte, error) { return nil, nil },
|
||||
},
|
||||
}
|
||||
|
||||
fexec := fakeexec.FakeExec{
|
||||
CommandScript: []fakeexec.FakeCommandAction{
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
},
|
||||
LookPathFunc: func(cmd string) (string, error) { return "/usr/bin/docker", nil },
|
||||
}
|
||||
|
||||
containerRuntime, err := utilruntime.NewContainerRuntime(&fexec, constants.DefaultDockerCRISocket)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected NewContainerRuntime error: %v", err)
|
||||
}
|
||||
|
||||
images := []string{"a", "b", "c", "d", "a"}
|
||||
ip := NewImagesPull(containerRuntime, images)
|
||||
|
||||
err = ip.PullAll()
|
||||
if err != nil {
|
||||
t.Fatalf("expected nil but found %v", err)
|
||||
}
|
||||
|
||||
if fcmd.CombinedOutputCalls != len(images) {
|
||||
t.Errorf("expected %d calls, got %d", len(images), fcmd.CombinedOutputCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMigrate(t *testing.T) {
|
||||
cfg := []byte(dedent.Dedent(`
|
||||
# This is intentionally testing an old API version and the old kind naming and making sure the output is correct
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
kind: InitConfiguration
|
||||
`))
|
||||
configFile, cleanup := tempConfig(t, cfg)
|
||||
defer cleanup()
|
||||
|
||||
var output bytes.Buffer
|
||||
command := NewCmdConfigMigrate(&output)
|
||||
if err := command.Flags().Set("old-config", configFile); err != nil {
|
||||
t.Fatalf("failed to set old-config flag")
|
||||
}
|
||||
newConfigPath := filepath.Join(filepath.Dir(configFile), "new-migrated-config")
|
||||
if err := command.Flags().Set("new-config", newConfigPath); err != nil {
|
||||
t.Fatalf("failed to set new-config flag")
|
||||
}
|
||||
command.Run(nil, nil)
|
||||
if _, err := configutil.LoadInitConfigurationFromFile(newConfigPath); err != nil {
|
||||
t.Fatalf("Could not read output back into internal type: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the name of the file created and a cleanup callback
|
||||
func tempConfig(t *testing.T, config []byte) (string, func()) {
|
||||
t.Helper()
|
||||
tmpDir, err := ioutil.TempDir("", "kubeadm-migration-test")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create temporary directory: %v", err)
|
||||
}
|
||||
configFilePath := filepath.Join(tmpDir, "test-config-file")
|
||||
if err := ioutil.WriteFile(configFilePath, config, 0644); err != nil {
|
||||
os.RemoveAll(tmpDir)
|
||||
t.Fatalf("Failed writing a config file: %v", err)
|
||||
}
|
||||
return configFilePath, func() {
|
||||
os.RemoveAll(tmpDir)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewCmdConfigPrintActionDefaults(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
expectedKinds []string // need to be sorted
|
||||
componentConfigs string
|
||||
cmdProc func(out io.Writer) *cobra.Command
|
||||
}{
|
||||
{
|
||||
name: "InitConfiguration: No component configs",
|
||||
expectedKinds: []string{
|
||||
constants.ClusterConfigurationKind,
|
||||
constants.InitConfigurationKind,
|
||||
},
|
||||
cmdProc: NewCmdConfigPrintInitDefaults,
|
||||
},
|
||||
{
|
||||
name: "InitConfiguration: KubeProxyConfiguration",
|
||||
expectedKinds: []string{
|
||||
constants.ClusterConfigurationKind,
|
||||
constants.InitConfigurationKind,
|
||||
string(componentconfigs.KubeProxyConfigurationKind),
|
||||
},
|
||||
componentConfigs: "KubeProxyConfiguration",
|
||||
cmdProc: NewCmdConfigPrintInitDefaults,
|
||||
},
|
||||
{
|
||||
name: "InitConfiguration: KubeProxyConfiguration and KubeletConfiguration",
|
||||
expectedKinds: []string{
|
||||
constants.ClusterConfigurationKind,
|
||||
constants.InitConfigurationKind,
|
||||
string(componentconfigs.KubeProxyConfigurationKind),
|
||||
string(componentconfigs.KubeletConfigurationKind),
|
||||
},
|
||||
componentConfigs: "KubeProxyConfiguration,KubeletConfiguration",
|
||||
cmdProc: NewCmdConfigPrintInitDefaults,
|
||||
},
|
||||
{
|
||||
name: "JoinConfiguration: No component configs",
|
||||
expectedKinds: []string{
|
||||
constants.JoinConfigurationKind,
|
||||
},
|
||||
cmdProc: NewCmdConfigPrintJoinDefaults,
|
||||
},
|
||||
{
|
||||
name: "JoinConfiguration: KubeProxyConfiguration",
|
||||
expectedKinds: []string{
|
||||
constants.JoinConfigurationKind,
|
||||
string(componentconfigs.KubeProxyConfigurationKind),
|
||||
},
|
||||
componentConfigs: "KubeProxyConfiguration",
|
||||
cmdProc: NewCmdConfigPrintJoinDefaults,
|
||||
},
|
||||
{
|
||||
name: "JoinConfiguration: KubeProxyConfiguration and KubeletConfiguration",
|
||||
expectedKinds: []string{
|
||||
constants.JoinConfigurationKind,
|
||||
string(componentconfigs.KubeProxyConfigurationKind),
|
||||
string(componentconfigs.KubeletConfigurationKind),
|
||||
},
|
||||
componentConfigs: "KubeProxyConfiguration,KubeletConfiguration",
|
||||
cmdProc: NewCmdConfigPrintJoinDefaults,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
var output bytes.Buffer
|
||||
|
||||
command := test.cmdProc(&output)
|
||||
if err := command.Flags().Set("component-configs", test.componentConfigs); err != nil {
|
||||
t.Fatalf("failed to set component-configs flag")
|
||||
}
|
||||
command.Run(nil, nil)
|
||||
|
||||
gvkmap, err := kubeadmutil.SplitYAMLDocuments(output.Bytes())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
|
||||
}
|
||||
|
||||
gotKinds := []string{}
|
||||
for gvk := range gvkmap {
|
||||
gotKinds = append(gotKinds, gvk.Kind)
|
||||
}
|
||||
|
||||
sort.Strings(gotKinds)
|
||||
|
||||
if !reflect.DeepEqual(gotKinds, test.expectedKinds) {
|
||||
t.Fatalf("kinds not matching:\n\texpectedKinds: %v\n\tgotKinds: %v\n", test.expectedKinds, gotKinds)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,559 +0,0 @@
|
|||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/lithammer/dedent"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
phases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/init"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
)
|
||||
|
||||
var (
|
||||
initDoneTempl = template.Must(template.New("init").Parse(dedent.Dedent(`
|
||||
Your Kubernetes control-plane has initialized successfully!
|
||||
|
||||
To start using your cluster, you need to run the following as a regular user:
|
||||
|
||||
mkdir -p $HOME/.kube
|
||||
sudo cp -i {{.KubeConfigPath}} $HOME/.kube/config
|
||||
sudo chown $(id -u):$(id -g) $HOME/.kube/config
|
||||
|
||||
You should now deploy a pod network to the cluster.
|
||||
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
|
||||
https://kubernetes.io/docs/concepts/cluster-administration/addons/
|
||||
|
||||
{{if .ControlPlaneEndpoint -}}
|
||||
{{if .UploadCerts -}}
|
||||
You can now join any number of the control-plane node running the following command on each as root:
|
||||
|
||||
{{.joinControlPlaneCommand}}
|
||||
|
||||
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
|
||||
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
|
||||
"kubeadm init phase upload-certs --experimental-upload-certs" to reload certs afterward.
|
||||
|
||||
{{else -}}
|
||||
You can now join any number of control-plane nodes by copying certificate authorities
|
||||
and service account keys on each node and then running the following as root:
|
||||
|
||||
{{.joinControlPlaneCommand}}
|
||||
|
||||
{{end}}{{end}}Then you can join any number of worker nodes by running the following on each as root:
|
||||
|
||||
{{.joinWorkerCommand}}
|
||||
`)))
|
||||
)
|
||||
|
||||
// initOptions defines all the init options exposed via flags by kubeadm init.
|
||||
// Please note that this structure includes the public kubeadm config API, but only a subset of the options
|
||||
// supported by this api will be exposed as a flag.
|
||||
type initOptions struct {
|
||||
cfgPath string
|
||||
skipTokenPrint bool
|
||||
dryRun bool
|
||||
kubeconfigDir string
|
||||
kubeconfigPath string
|
||||
featureGatesString string
|
||||
ignorePreflightErrors []string
|
||||
bto *options.BootstrapTokenOptions
|
||||
externalcfg *kubeadmapiv1beta1.InitConfiguration
|
||||
uploadCerts bool
|
||||
certificateKey string
|
||||
skipCertificateKeyPrint bool
|
||||
}
|
||||
|
||||
// compile-time assert that the local data object satisfies the phases data interface.
|
||||
var _ phases.InitData = &initData{}
|
||||
|
||||
// initData defines all the runtime information used when running the kubeadm init worklow;
|
||||
// this data is shared across all the phases that are included in the workflow.
|
||||
type initData struct {
|
||||
cfg *kubeadmapi.InitConfiguration
|
||||
skipTokenPrint bool
|
||||
dryRun bool
|
||||
kubeconfigDir string
|
||||
kubeconfigPath string
|
||||
ignorePreflightErrors sets.String
|
||||
certificatesDir string
|
||||
dryRunDir string
|
||||
externalCA bool
|
||||
client clientset.Interface
|
||||
waiter apiclient.Waiter
|
||||
outputWriter io.Writer
|
||||
uploadCerts bool
|
||||
certificateKey string
|
||||
skipCertificateKeyPrint bool
|
||||
}
|
||||
|
||||
// NewCmdInit returns "kubeadm init" command.
|
||||
// NB. initOptions is exposed as parameter for allowing unit testing of
|
||||
// the newInitOptions method, that implements all the command options validation logic
|
||||
func NewCmdInit(out io.Writer, initOptions *initOptions) *cobra.Command {
|
||||
if initOptions == nil {
|
||||
initOptions = newInitOptions()
|
||||
}
|
||||
initRunner := workflow.NewRunner()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Run this command in order to set up the Kubernetes control plane.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
c, err := initRunner.InitData(args)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
data := c.(*initData)
|
||||
fmt.Printf("[init] Using Kubernetes version: %s\n", data.cfg.KubernetesVersion)
|
||||
|
||||
err = initRunner.Run(args)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = showJoinCommand(data, out)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
|
||||
// adds flags to the init command
|
||||
// init command local flags could be eventually inherited by the sub-commands automatically generated for phases
|
||||
AddInitConfigFlags(cmd.Flags(), initOptions.externalcfg, &initOptions.featureGatesString)
|
||||
AddInitOtherFlags(cmd.Flags(), initOptions)
|
||||
initOptions.bto.AddTokenFlag(cmd.Flags())
|
||||
initOptions.bto.AddTTLFlag(cmd.Flags())
|
||||
options.AddImageMetaFlags(cmd.Flags(), &initOptions.externalcfg.ImageRepository)
|
||||
|
||||
// defines additional flag that are not used by the init command but that could be eventually used
|
||||
// by the sub-commands automatically generated for phases
|
||||
initRunner.SetAdditionalFlags(func(flags *flag.FlagSet) {
|
||||
options.AddKubeConfigFlag(flags, &initOptions.kubeconfigPath)
|
||||
options.AddKubeConfigDirFlag(flags, &initOptions.kubeconfigDir)
|
||||
options.AddControlPlanExtraArgsFlags(flags, &initOptions.externalcfg.APIServer.ExtraArgs, &initOptions.externalcfg.ControllerManager.ExtraArgs, &initOptions.externalcfg.Scheduler.ExtraArgs)
|
||||
})
|
||||
|
||||
// initialize the workflow runner with the list of phases
|
||||
initRunner.AppendPhase(phases.NewPreflightPhase())
|
||||
initRunner.AppendPhase(phases.NewKubeletStartPhase())
|
||||
initRunner.AppendPhase(phases.NewCertsPhase())
|
||||
initRunner.AppendPhase(phases.NewKubeConfigPhase())
|
||||
initRunner.AppendPhase(phases.NewControlPlanePhase())
|
||||
initRunner.AppendPhase(phases.NewEtcdPhase())
|
||||
initRunner.AppendPhase(phases.NewWaitControlPlanePhase())
|
||||
initRunner.AppendPhase(phases.NewUploadConfigPhase())
|
||||
initRunner.AppendPhase(phases.NewUploadCertsPhase())
|
||||
initRunner.AppendPhase(phases.NewMarkControlPlanePhase())
|
||||
initRunner.AppendPhase(phases.NewBootstrapTokenPhase())
|
||||
initRunner.AppendPhase(phases.NewAddonPhase())
|
||||
|
||||
// sets the data builder function, that will be used by the runner
|
||||
// both when running the entire workflow or single phases
|
||||
initRunner.SetDataInitializer(func(cmd *cobra.Command, args []string) (workflow.RunData, error) {
|
||||
return newInitData(cmd, args, initOptions, out)
|
||||
})
|
||||
|
||||
// binds the Runner to kubeadm init command by altering
|
||||
// command help, adding --skip-phases flag and by adding phases subcommands
|
||||
initRunner.BindToCommand(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// AddInitConfigFlags adds init flags bound to the config to the specified flagset
|
||||
func AddInitConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.InitConfiguration, featureGatesString *string) {
|
||||
flagSet.StringVar(
|
||||
&cfg.LocalAPIEndpoint.AdvertiseAddress, options.APIServerAdvertiseAddress, cfg.LocalAPIEndpoint.AdvertiseAddress,
|
||||
"The IP address the API Server will advertise it's listening on. If not set the default network interface will be used.",
|
||||
)
|
||||
flagSet.Int32Var(
|
||||
&cfg.LocalAPIEndpoint.BindPort, options.APIServerBindPort, cfg.LocalAPIEndpoint.BindPort,
|
||||
"Port for the API Server to bind to.",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.Networking.ServiceSubnet, options.NetworkingServiceSubnet, cfg.Networking.ServiceSubnet,
|
||||
"Use alternative range of IP address for service VIPs.",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.Networking.PodSubnet, options.NetworkingPodSubnet, cfg.Networking.PodSubnet,
|
||||
"Specify range of IP addresses for the pod network. If set, the control plane will automatically allocate CIDRs for every node.",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.Networking.DNSDomain, options.NetworkingDNSDomain, cfg.Networking.DNSDomain,
|
||||
`Use alternative domain for services, e.g. "myorg.internal".`,
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.KubernetesVersion, options.KubernetesVersion, cfg.KubernetesVersion,
|
||||
`Choose a specific Kubernetes version for the control plane.`,
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.CertificatesDir, options.CertificatesDir, cfg.CertificatesDir,
|
||||
`The path where to save and store the certificates.`,
|
||||
)
|
||||
flagSet.StringSliceVar(
|
||||
&cfg.APIServer.CertSANs, options.APIServerCertSANs, cfg.APIServer.CertSANs,
|
||||
`Optional extra Subject Alternative Names (SANs) to use for the API Server serving certificate. Can be both IP addresses and DNS names.`,
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.NodeRegistration.Name, options.NodeName, cfg.NodeRegistration.Name,
|
||||
`Specify the node name.`,
|
||||
)
|
||||
cmdutil.AddCRISocketFlag(flagSet, &cfg.NodeRegistration.CRISocket)
|
||||
flagSet.StringVar(featureGatesString, options.FeatureGatesString, *featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+
|
||||
"Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n"))
|
||||
}
|
||||
|
||||
// AddInitOtherFlags adds init flags that are not bound to a configuration file to the given flagset
|
||||
// Note: All flags that are not bound to the cfg object should be allowed in cmd/kubeadm/app/apis/kubeadm/validation/validation.go
|
||||
func AddInitOtherFlags(flagSet *flag.FlagSet, initOptions *initOptions) {
|
||||
options.AddConfigFlag(flagSet, &initOptions.cfgPath)
|
||||
flagSet.StringSliceVar(
|
||||
&initOptions.ignorePreflightErrors, options.IgnorePreflightErrors, initOptions.ignorePreflightErrors,
|
||||
"A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.",
|
||||
)
|
||||
flagSet.BoolVar(
|
||||
&initOptions.skipTokenPrint, options.SkipTokenPrint, initOptions.skipTokenPrint,
|
||||
"Skip printing of the default bootstrap token generated by 'kubeadm init'.",
|
||||
)
|
||||
flagSet.BoolVar(
|
||||
&initOptions.dryRun, options.DryRun, initOptions.dryRun,
|
||||
"Don't apply any changes; just output what would be done.",
|
||||
)
|
||||
flagSet.BoolVar(
|
||||
&initOptions.uploadCerts, options.UploadCerts, initOptions.uploadCerts,
|
||||
"Upload control-plane certificates to the kubeadm-certs Secret.",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&initOptions.certificateKey, options.CertificateKey, "",
|
||||
"Key used to encrypt the control-plane certificates in the kubeadm-certs Secret.",
|
||||
)
|
||||
flagSet.BoolVar(
|
||||
&initOptions.skipCertificateKeyPrint, options.SkipCertificateKeyPrint, initOptions.skipCertificateKeyPrint,
|
||||
"Don't print the key used to encrypt the control-plane certificates.",
|
||||
)
|
||||
}
|
||||
|
||||
// newInitOptions returns a struct ready for being used for creating cmd init flags.
|
||||
func newInitOptions() *initOptions {
|
||||
// initialize the public kubeadm config API by applying defaults
|
||||
externalcfg := &kubeadmapiv1beta1.InitConfiguration{}
|
||||
kubeadmscheme.Scheme.Default(externalcfg)
|
||||
|
||||
// Create the options object for the bootstrap token-related flags, and override the default value for .Description
|
||||
bto := options.NewBootstrapTokenOptions()
|
||||
bto.Description = "The default bootstrap token generated by 'kubeadm init'."
|
||||
|
||||
return &initOptions{
|
||||
externalcfg: externalcfg,
|
||||
bto: bto,
|
||||
kubeconfigDir: kubeadmconstants.KubernetesDir,
|
||||
kubeconfigPath: kubeadmconstants.GetAdminKubeConfigPath(),
|
||||
uploadCerts: false,
|
||||
}
|
||||
}
|
||||
|
||||
// newInitData returns a new initData struct to be used for the execution of the kubeadm init workflow.
|
||||
// This func takes care of validating initOptions passed to the command, and then it converts
|
||||
// options into the internal InitConfiguration type that is used as input all the phases in the kubeadm init workflow
|
||||
func newInitData(cmd *cobra.Command, args []string, options *initOptions, out io.Writer) (*initData, error) {
|
||||
// Re-apply defaults to the public kubeadm API (this will set only values not exposed/not set as a flags)
|
||||
kubeadmscheme.Scheme.Default(options.externalcfg)
|
||||
|
||||
// Validate standalone flags values and/or combination of flags and then assigns
|
||||
// validated values to the public kubeadm config API when applicable
|
||||
var err error
|
||||
if options.externalcfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, options.featureGatesString); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(options.ignorePreflightErrors)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = validation.ValidateMixedArguments(cmd.Flags()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = options.bto.ApplyTo(options.externalcfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Either use the config file if specified, or convert public kubeadm API to the internal InitConfiguration
|
||||
// and validates InitConfiguration
|
||||
cfg, err := configutil.LoadOrDefaultInitConfiguration(options.cfgPath, options.externalcfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// override node name and CRI socket from the command line options
|
||||
if options.externalcfg.NodeRegistration.Name != "" {
|
||||
cfg.NodeRegistration.Name = options.externalcfg.NodeRegistration.Name
|
||||
}
|
||||
if options.externalcfg.NodeRegistration.CRISocket != "" {
|
||||
cfg.NodeRegistration.CRISocket = options.externalcfg.NodeRegistration.CRISocket
|
||||
}
|
||||
|
||||
if err := configutil.VerifyAPIServerBindAddress(cfg.LocalAPIEndpoint.AdvertiseAddress); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := features.ValidateVersion(features.InitFeatureGates, cfg.FeatureGates, cfg.KubernetesVersion); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if dry running creates a temporary folder for saving kubeadm generated files
|
||||
dryRunDir := ""
|
||||
if options.dryRun {
|
||||
if dryRunDir, err = ioutil.TempDir("", "kubeadm-init-dryrun"); err != nil {
|
||||
return nil, errors.Wrap(err, "couldn't create a temporary directory")
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if an external CA is provided by the user (when the CA Cert is present but the CA Key is not)
|
||||
externalCA, err := certsphase.UsingExternalCA(&cfg.ClusterConfiguration)
|
||||
if externalCA {
|
||||
// In case the certificates signed by CA (that should be provided by the user) are missing or invalid,
|
||||
// returns, because kubeadm can't regenerate them without the CA Key
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "invalid or incomplete external CA")
|
||||
}
|
||||
|
||||
// Validate that also the required kubeconfig files exists and are invalid, because
|
||||
// kubeadm can't regenerate them without the CA Key
|
||||
kubeconfigDir := options.kubeconfigDir
|
||||
if options.dryRun {
|
||||
kubeconfigDir = dryRunDir
|
||||
}
|
||||
if err := kubeconfigphase.ValidateKubeconfigsForExternalCA(kubeconfigDir, cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if an external Front-Proxy CA is provided by the user (when the Front-Proxy CA Cert is present but the Front-Proxy CA Key is not)
|
||||
externalFrontProxyCA, err := certsphase.UsingExternalFrontProxyCA(&cfg.ClusterConfiguration)
|
||||
if externalFrontProxyCA {
|
||||
// In case the certificates signed by Front-Proxy CA (that should be provided by the user) are missing or invalid,
|
||||
// returns, because kubeadm can't regenerate them without the Front-Proxy CA Key
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "invalid or incomplete external front-proxy CA")
|
||||
}
|
||||
}
|
||||
|
||||
if options.uploadCerts && (externalCA || externalFrontProxyCA) {
|
||||
return nil, errors.New("can't use upload-certs with an external CA or an external front-proxy CA")
|
||||
}
|
||||
|
||||
return &initData{
|
||||
cfg: cfg,
|
||||
certificatesDir: cfg.CertificatesDir,
|
||||
skipTokenPrint: options.skipTokenPrint,
|
||||
dryRun: options.dryRun,
|
||||
dryRunDir: dryRunDir,
|
||||
kubeconfigDir: options.kubeconfigDir,
|
||||
kubeconfigPath: options.kubeconfigPath,
|
||||
ignorePreflightErrors: ignorePreflightErrorsSet,
|
||||
externalCA: externalCA,
|
||||
outputWriter: out,
|
||||
uploadCerts: options.uploadCerts,
|
||||
certificateKey: options.certificateKey,
|
||||
skipCertificateKeyPrint: options.skipCertificateKeyPrint,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UploadCerts returns Uploadcerts flag.
|
||||
func (d *initData) UploadCerts() bool {
|
||||
return d.uploadCerts
|
||||
}
|
||||
|
||||
// CertificateKey returns the key used to encrypt the certs.
|
||||
func (d *initData) CertificateKey() string {
|
||||
return d.certificateKey
|
||||
}
|
||||
|
||||
// SetCertificateKey set the key used to encrypt the certs.
|
||||
func (d *initData) SetCertificateKey(key string) {
|
||||
d.certificateKey = key
|
||||
}
|
||||
|
||||
// SkipCertificateKeyPrint returns the skipCertificateKeyPrint flag.
|
||||
func (d *initData) SkipCertificateKeyPrint() bool {
|
||||
return d.skipCertificateKeyPrint
|
||||
}
|
||||
|
||||
// Cfg returns initConfiguration.
|
||||
func (d *initData) Cfg() *kubeadmapi.InitConfiguration {
|
||||
return d.cfg
|
||||
}
|
||||
|
||||
// DryRun returns the DryRun flag.
|
||||
func (d *initData) DryRun() bool {
|
||||
return d.dryRun
|
||||
}
|
||||
|
||||
// SkipTokenPrint returns the SkipTokenPrint flag.
|
||||
func (d *initData) SkipTokenPrint() bool {
|
||||
return d.skipTokenPrint
|
||||
}
|
||||
|
||||
// IgnorePreflightErrors returns the IgnorePreflightErrors flag.
|
||||
func (d *initData) IgnorePreflightErrors() sets.String {
|
||||
return d.ignorePreflightErrors
|
||||
}
|
||||
|
||||
// CertificateWriteDir returns the path to the certificate folder or the temporary folder path in case of DryRun.
|
||||
func (d *initData) CertificateWriteDir() string {
|
||||
if d.dryRun {
|
||||
return d.dryRunDir
|
||||
}
|
||||
return d.certificatesDir
|
||||
}
|
||||
|
||||
// CertificateDir returns the CertificateDir as originally specified by the user.
|
||||
func (d *initData) CertificateDir() string {
|
||||
return d.certificatesDir
|
||||
}
|
||||
|
||||
// KubeConfigDir returns the path of the Kubernetes configuration folder or the temporary folder path in case of DryRun.
|
||||
func (d *initData) KubeConfigDir() string {
|
||||
if d.dryRun {
|
||||
return d.dryRunDir
|
||||
}
|
||||
return d.kubeconfigDir
|
||||
}
|
||||
|
||||
// KubeConfigPath returns the path to the kubeconfig file to use for connecting to Kubernetes
|
||||
func (d *initData) KubeConfigPath() string {
|
||||
if d.dryRun {
|
||||
d.kubeconfigPath = filepath.Join(d.dryRunDir, kubeadmconstants.AdminKubeConfigFileName)
|
||||
}
|
||||
return d.kubeconfigPath
|
||||
}
|
||||
|
||||
// ManifestDir returns the path where manifest should be stored or the temporary folder path in case of DryRun.
|
||||
func (d *initData) ManifestDir() string {
|
||||
if d.dryRun {
|
||||
return d.dryRunDir
|
||||
}
|
||||
return kubeadmconstants.GetStaticPodDirectory()
|
||||
}
|
||||
|
||||
// KubeletDir returns path of the kubelet configuration folder or the temporary folder in case of DryRun.
|
||||
func (d *initData) KubeletDir() string {
|
||||
if d.dryRun {
|
||||
return d.dryRunDir
|
||||
}
|
||||
return kubeadmconstants.KubeletRunDirectory
|
||||
}
|
||||
|
||||
// ExternalCA returns true if an external CA is provided by the user.
|
||||
func (d *initData) ExternalCA() bool {
|
||||
return d.externalCA
|
||||
}
|
||||
|
||||
// OutputWriter returns the io.Writer used to write output to by this command.
|
||||
func (d *initData) OutputWriter() io.Writer {
|
||||
return d.outputWriter
|
||||
}
|
||||
|
||||
// Client returns a Kubernetes client to be used by kubeadm.
|
||||
// This function is implemented as a singleton, thus avoiding to recreate the client when it is used by different phases.
|
||||
// Important. This function must be called after the admin.conf kubeconfig file is created.
|
||||
func (d *initData) Client() (clientset.Interface, error) {
|
||||
if d.client == nil {
|
||||
if d.dryRun {
|
||||
// If we're dry-running, we should create a faked client that answers some GETs in order to be able to do the full init flow and just logs the rest of requests
|
||||
dryRunGetter := apiclient.NewInitDryRunGetter(d.cfg.NodeRegistration.Name, d.cfg.Networking.ServiceSubnet)
|
||||
d.client = apiclient.NewDryRunClient(dryRunGetter, os.Stdout)
|
||||
} else {
|
||||
// If we're acting for real, we should create a connection to the API server and wait for it to come up
|
||||
var err error
|
||||
d.client, err = kubeconfigutil.ClientSetFromFile(d.KubeConfigPath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return d.client, nil
|
||||
}
|
||||
|
||||
// Tokens returns an array of token strings.
|
||||
func (d *initData) Tokens() []string {
|
||||
tokens := []string{}
|
||||
for _, bt := range d.cfg.BootstrapTokens {
|
||||
tokens = append(tokens, bt.Token.String())
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
func printJoinCommand(out io.Writer, adminKubeConfigPath, token string, i *initData) error {
|
||||
joinControlPlaneCommand, err := cmdutil.GetJoinControlPlaneCommand(adminKubeConfigPath, token, i.certificateKey, i.skipTokenPrint, i.skipCertificateKeyPrint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
joinWorkerCommand, err := cmdutil.GetJoinWorkerCommand(adminKubeConfigPath, token, i.skipTokenPrint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := map[string]interface{}{
|
||||
"KubeConfigPath": adminKubeConfigPath,
|
||||
"ControlPlaneEndpoint": i.Cfg().ControlPlaneEndpoint,
|
||||
"UploadCerts": i.uploadCerts,
|
||||
"joinControlPlaneCommand": joinControlPlaneCommand,
|
||||
"joinWorkerCommand": joinWorkerCommand,
|
||||
}
|
||||
|
||||
return initDoneTempl.Execute(out, ctx)
|
||||
}
|
||||
|
||||
// showJoinCommand prints the join command after all the phases in init have finished
|
||||
func showJoinCommand(i *initData, out io.Writer) error {
|
||||
adminKubeConfigPath := i.KubeConfigPath()
|
||||
|
||||
// Prints the join command, multiple times in case the user has multiple tokens
|
||||
for _, token := range i.Tokens() {
|
||||
if err := printJoinCommand(out, adminKubeConfigPath, token, i); err != nil {
|
||||
return errors.Wrap(err, "failed to print join command")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,511 +0,0 @@
|
|||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/lithammer/dedent"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
clientcmd "k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/klog"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
phases "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/join"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
)
|
||||
|
||||
var (
|
||||
joinWorkerNodeDoneMsg = dedent.Dedent(`
|
||||
This node has joined the cluster:
|
||||
* Certificate signing request was sent to apiserver and a response was received.
|
||||
* The Kubelet was informed of the new secure connection details.
|
||||
|
||||
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
|
||||
|
||||
`)
|
||||
|
||||
joinControPlaneDoneTemp = template.Must(template.New("join").Parse(dedent.Dedent(`
|
||||
This node has joined the cluster and a new control plane instance was created:
|
||||
|
||||
* Certificate signing request was sent to apiserver and approval was received.
|
||||
* The Kubelet was informed of the new secure connection details.
|
||||
* Control plane (master) label and taint were applied to the new node.
|
||||
* The Kubernetes control plane instances scaled up.
|
||||
{{.etcdMessage}}
|
||||
|
||||
To start administering your cluster from this node, you need to run the following as a regular user:
|
||||
|
||||
mkdir -p $HOME/.kube
|
||||
sudo cp -i {{.KubeConfigPath}} $HOME/.kube/config
|
||||
sudo chown $(id -u):$(id -g) $HOME/.kube/config
|
||||
|
||||
Run 'kubectl get nodes' to see this node join the cluster.
|
||||
|
||||
`)))
|
||||
|
||||
joinLongDescription = dedent.Dedent(`
|
||||
When joining a kubeadm initialized cluster, we need to establish
|
||||
bidirectional trust. This is split into discovery (having the Node
|
||||
trust the Kubernetes Control Plane) and TLS bootstrap (having the
|
||||
Kubernetes Control Plane trust the Node).
|
||||
|
||||
There are 2 main schemes for discovery. The first is to use a shared
|
||||
token along with the IP address of the API server. The second is to
|
||||
provide a file - a subset of the standard kubeconfig file. This file
|
||||
can be a local file or downloaded via an HTTPS URL. The forms are
|
||||
kubeadm join --discovery-token abcdef.1234567890abcdef 1.2.3.4:6443,
|
||||
kubeadm join --discovery-file path/to/file.conf, or kubeadm join
|
||||
--discovery-file https://url/file.conf. Only one form can be used. If
|
||||
the discovery information is loaded from a URL, HTTPS must be used.
|
||||
Also, in that case the host installed CA bundle is used to verify
|
||||
the connection.
|
||||
|
||||
If you use a shared token for discovery, you should also pass the
|
||||
--discovery-token-ca-cert-hash flag to validate the public key of the
|
||||
root certificate authority (CA) presented by the Kubernetes Control Plane.
|
||||
The value of this flag is specified as "<hash-type>:<hex-encoded-value>",
|
||||
where the supported hash type is "sha256". The hash is calculated over
|
||||
the bytes of the Subject Public Key Info (SPKI) object (as in RFC7469).
|
||||
This value is available in the output of "kubeadm init" or can be
|
||||
calculated using standard tools. The --discovery-token-ca-cert-hash flag
|
||||
may be repeated multiple times to allow more than one public key.
|
||||
|
||||
If you cannot know the CA public key hash ahead of time, you can pass
|
||||
the --discovery-token-unsafe-skip-ca-verification flag to disable this
|
||||
verification. This weakens the kubeadm security model since other nodes
|
||||
can potentially impersonate the Kubernetes Control Plane.
|
||||
|
||||
The TLS bootstrap mechanism is also driven via a shared token. This is
|
||||
used to temporarily authenticate with the Kubernetes Control Plane to submit a
|
||||
certificate signing request (CSR) for a locally created key pair. By
|
||||
default, kubeadm will set up the Kubernetes Control Plane to automatically
|
||||
approve these signing requests. This token is passed in with the
|
||||
--tls-bootstrap-token abcdef.1234567890abcdef flag.
|
||||
|
||||
Often times the same token is used for both parts. In this case, the
|
||||
--token flag can be used instead of specifying each token individually.
|
||||
`)
|
||||
)
|
||||
|
||||
// joinOptions defines all the options exposed via flags by kubeadm join.
|
||||
// Please note that this structure includes the public kubeadm config API, but only a subset of the options
|
||||
// supported by this api will be exposed as a flag.
|
||||
type joinOptions struct {
|
||||
cfgPath string
|
||||
token string
|
||||
controlPlane bool
|
||||
ignorePreflightErrors []string
|
||||
externalcfg *kubeadmapiv1beta1.JoinConfiguration
|
||||
certificateKey string
|
||||
}
|
||||
|
||||
// compile-time assert that the local data object satisfies the phases data interface.
|
||||
var _ phases.JoinData = &joinData{}
|
||||
|
||||
// joinData defines all the runtime information used when running the kubeadm join worklow;
|
||||
// this data is shared across all the phases that are included in the workflow.
|
||||
type joinData struct {
|
||||
cfg *kubeadmapi.JoinConfiguration
|
||||
skipTokenPrint bool
|
||||
initCfg *kubeadmapi.InitConfiguration
|
||||
tlsBootstrapCfg *clientcmdapi.Config
|
||||
clientSet *clientset.Clientset
|
||||
ignorePreflightErrors sets.String
|
||||
outputWriter io.Writer
|
||||
certificateKey string
|
||||
}
|
||||
|
||||
// NewCmdJoin returns "kubeadm join" command.
|
||||
// NB. joinOptions is exposed as parameter for allowing unit testing of
|
||||
// the newJoinData method, that implements all the command options validation logic
|
||||
func NewCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command {
|
||||
if joinOptions == nil {
|
||||
joinOptions = newJoinOptions()
|
||||
}
|
||||
joinRunner := workflow.NewRunner()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "join [api-server-endpoint]",
|
||||
Short: "Run this on any machine you wish to join an existing cluster",
|
||||
Long: joinLongDescription,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
c, err := joinRunner.InitData(args)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
data := c.(*joinData)
|
||||
|
||||
err = joinRunner.Run(args)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// if the node is hosting a new control plane instance
|
||||
if data.cfg.ControlPlane != nil {
|
||||
// outputs the join control plane done message and exit
|
||||
etcdMessage := ""
|
||||
if data.initCfg.Etcd.External == nil {
|
||||
etcdMessage = "* A new etcd member was added to the local/stacked etcd cluster."
|
||||
}
|
||||
|
||||
ctx := map[string]string{
|
||||
"KubeConfigPath": kubeadmconstants.GetAdminKubeConfigPath(),
|
||||
"etcdMessage": etcdMessage,
|
||||
}
|
||||
joinControPlaneDoneTemp.Execute(data.outputWriter, ctx)
|
||||
|
||||
} else {
|
||||
// otherwise, if the node joined as a worker node;
|
||||
// outputs the join done message and exit
|
||||
fmt.Fprintf(data.outputWriter, joinWorkerNodeDoneMsg)
|
||||
}
|
||||
},
|
||||
// We accept the control-plane location as an optional positional argument
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
}
|
||||
|
||||
addJoinConfigFlags(cmd.Flags(), joinOptions.externalcfg)
|
||||
addJoinOtherFlags(cmd.Flags(), joinOptions)
|
||||
|
||||
joinRunner.AppendPhase(phases.NewPreflightPhase())
|
||||
joinRunner.AppendPhase(phases.NewControlPlanePreparePhase())
|
||||
joinRunner.AppendPhase(phases.NewCheckEtcdPhase())
|
||||
joinRunner.AppendPhase(phases.NewKubeletStartPhase())
|
||||
joinRunner.AppendPhase(phases.NewControlPlaneJoinPhase())
|
||||
|
||||
// sets the data builder function, that will be used by the runner
|
||||
// both when running the entire workflow or single phases
|
||||
joinRunner.SetDataInitializer(func(cmd *cobra.Command, args []string) (workflow.RunData, error) {
|
||||
return newJoinData(cmd, args, joinOptions, out)
|
||||
})
|
||||
|
||||
// binds the Runner to kubeadm join command by altering
|
||||
// command help, adding --skip-phases flag and by adding phases subcommands
|
||||
joinRunner.BindToCommand(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// addJoinConfigFlags adds join flags bound to the config to the specified flagset
|
||||
func addJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.JoinConfiguration) {
|
||||
flagSet.StringVar(
|
||||
&cfg.NodeRegistration.Name, options.NodeName, cfg.NodeRegistration.Name,
|
||||
`Specify the node name.`,
|
||||
)
|
||||
// add control plane endpoint flags to the specified flagset
|
||||
flagSet.StringVar(
|
||||
&cfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress, options.APIServerAdvertiseAddress, cfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress,
|
||||
"If the node should host a new control plane instance, the IP address the API Server will advertise it's listening on. If not set the default network interface will be used.",
|
||||
)
|
||||
flagSet.Int32Var(
|
||||
&cfg.ControlPlane.LocalAPIEndpoint.BindPort, options.APIServerBindPort, cfg.ControlPlane.LocalAPIEndpoint.BindPort,
|
||||
"If the node should host a new control plane instance, the port for the API Server to bind to.",
|
||||
)
|
||||
// adds bootstrap token specific discovery flags to the specified flagset
|
||||
flagSet.StringVar(
|
||||
&cfg.Discovery.BootstrapToken.Token, options.TokenDiscovery, "",
|
||||
"For token-based discovery, the token used to validate cluster information fetched from the API server.",
|
||||
)
|
||||
flagSet.StringSliceVar(
|
||||
&cfg.Discovery.BootstrapToken.CACertHashes, options.TokenDiscoveryCAHash, []string{},
|
||||
"For token-based discovery, validate that the root CA public key matches this hash (format: \"<type>:<value>\").",
|
||||
)
|
||||
flagSet.BoolVar(
|
||||
&cfg.Discovery.BootstrapToken.UnsafeSkipCAVerification, options.TokenDiscoverySkipCAHash, false,
|
||||
"For token-based discovery, allow joining without --discovery-token-ca-cert-hash pinning.",
|
||||
)
|
||||
// discovery via kube config file flag
|
||||
flagSet.StringVar(
|
||||
&cfg.Discovery.File.KubeConfigPath, options.FileDiscovery, "",
|
||||
"For file-based discovery, a file or URL from which to load cluster information.",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.Discovery.TLSBootstrapToken, options.TLSBootstrapToken, cfg.Discovery.TLSBootstrapToken,
|
||||
`Specify the token used to temporarily authenticate with the Kubernetes Control Plane while joining the node.`,
|
||||
)
|
||||
cmdutil.AddCRISocketFlag(flagSet, &cfg.NodeRegistration.CRISocket)
|
||||
}
|
||||
|
||||
// addJoinOtherFlags adds join flags that are not bound to a configuration file to the given flagset
|
||||
func addJoinOtherFlags(flagSet *flag.FlagSet, joinOptions *joinOptions) {
|
||||
flagSet.StringVar(
|
||||
&joinOptions.cfgPath, options.CfgPath, joinOptions.cfgPath,
|
||||
"Path to kubeadm config file.",
|
||||
)
|
||||
flagSet.StringSliceVar(
|
||||
&joinOptions.ignorePreflightErrors, options.IgnorePreflightErrors, joinOptions.ignorePreflightErrors,
|
||||
"A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&joinOptions.token, options.TokenStr, "",
|
||||
"Use this token for both discovery-token and tls-bootstrap-token when those values are not provided.",
|
||||
)
|
||||
flagSet.BoolVar(
|
||||
&joinOptions.controlPlane, options.ControlPlane, joinOptions.controlPlane,
|
||||
"Create a new control plane instance on this node",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&joinOptions.certificateKey, options.CertificateKey, "",
|
||||
"Use this key to decrypt the certificate secrets uploaded by init.",
|
||||
)
|
||||
}
|
||||
|
||||
// newJoinOptions returns a struct ready for being used for creating cmd join flags.
|
||||
func newJoinOptions() *joinOptions {
|
||||
// initialize the public kubeadm config API by applying defaults
|
||||
externalcfg := &kubeadmapiv1beta1.JoinConfiguration{}
|
||||
|
||||
// Add optional config objects to host flags.
|
||||
// un-set objects will be cleaned up afterwards (into newJoinData func)
|
||||
externalcfg.Discovery.File = &kubeadmapiv1beta1.FileDiscovery{}
|
||||
externalcfg.Discovery.BootstrapToken = &kubeadmapiv1beta1.BootstrapTokenDiscovery{}
|
||||
externalcfg.ControlPlane = &kubeadmapiv1beta1.JoinControlPlane{}
|
||||
|
||||
// Apply defaults
|
||||
kubeadmscheme.Scheme.Default(externalcfg)
|
||||
|
||||
return &joinOptions{
|
||||
externalcfg: externalcfg,
|
||||
}
|
||||
}
|
||||
|
||||
// newJoinData returns a new joinData struct to be used for the execution of the kubeadm join workflow.
|
||||
// This func takes care of validating joinOptions passed to the command, and then it converts
|
||||
// options into the internal JoinConfiguration type that is used as input all the phases in the kubeadm join workflow
|
||||
func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Writer) (*joinData, error) {
|
||||
// Re-apply defaults to the public kubeadm API (this will set only values not exposed/not set as a flags)
|
||||
kubeadmscheme.Scheme.Default(opt.externalcfg)
|
||||
|
||||
// Validate standalone flags values and/or combination of flags and then assigns
|
||||
// validated values to the public kubeadm config API when applicable
|
||||
|
||||
// if a token is provided, use this value for both discovery-token and tls-bootstrap-token when those values are not provided
|
||||
if len(opt.token) > 0 {
|
||||
if len(opt.externalcfg.Discovery.TLSBootstrapToken) == 0 {
|
||||
opt.externalcfg.Discovery.TLSBootstrapToken = opt.token
|
||||
}
|
||||
if len(opt.externalcfg.Discovery.BootstrapToken.Token) == 0 {
|
||||
opt.externalcfg.Discovery.BootstrapToken.Token = opt.token
|
||||
}
|
||||
}
|
||||
|
||||
// if a file or URL from which to load cluster information was not provided, unset the Discovery.File object
|
||||
if len(opt.externalcfg.Discovery.File.KubeConfigPath) == 0 {
|
||||
opt.externalcfg.Discovery.File = nil
|
||||
}
|
||||
|
||||
// if an APIServerEndpoint from which to retrieve cluster information was not provided, unset the Discovery.BootstrapToken object
|
||||
if len(args) == 0 {
|
||||
opt.externalcfg.Discovery.BootstrapToken = nil
|
||||
} else {
|
||||
if len(opt.cfgPath) == 0 && len(args) > 1 {
|
||||
klog.Warningf("[preflight] WARNING: More than one API server endpoint supplied on command line %v. Using the first one.", args)
|
||||
}
|
||||
opt.externalcfg.Discovery.BootstrapToken.APIServerEndpoint = args[0]
|
||||
}
|
||||
|
||||
// if not joining a control plane, unset the ControlPlane object
|
||||
if !opt.controlPlane {
|
||||
opt.externalcfg.ControlPlane = nil
|
||||
}
|
||||
|
||||
// if the admin.conf file already exists, use it for skipping the discovery process.
|
||||
// NB. this case can happen when we are joining a control-plane node only (and phases are invoked atomically)
|
||||
var adminKubeConfigPath = kubeadmconstants.GetAdminKubeConfigPath()
|
||||
var tlsBootstrapCfg *clientcmdapi.Config
|
||||
if _, err := os.Stat(adminKubeConfigPath); err == nil && opt.controlPlane {
|
||||
// use the admin.conf as tlsBootstrapCfg, that is the kubeconfig file used for reading the kubeadm-config during discovery
|
||||
klog.V(1).Infof("[preflight] found %s. Use it for skipping discovery", adminKubeConfigPath)
|
||||
tlsBootstrapCfg, err = clientcmd.LoadFromFile(adminKubeConfigPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error loading %s", adminKubeConfigPath)
|
||||
}
|
||||
}
|
||||
|
||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(opt.ignorePreflightErrors)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = validation.ValidateMixedArguments(cmd.Flags()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Either use the config file if specified, or convert public kubeadm API to the internal JoinConfiguration
|
||||
// and validates JoinConfiguration
|
||||
if opt.externalcfg.NodeRegistration.Name == "" {
|
||||
klog.V(1).Infoln("[preflight] found NodeName empty; using OS hostname as NodeName")
|
||||
}
|
||||
|
||||
if opt.externalcfg.ControlPlane != nil && opt.externalcfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress == "" {
|
||||
klog.V(1).Infoln("[preflight] found advertiseAddress empty; using default interface's IP address as advertiseAddress")
|
||||
}
|
||||
|
||||
// in case the command doesn't have flags for discovery, makes the join cfg validation pass checks on discovery
|
||||
if cmd.Flags().Lookup(options.FileDiscovery) == nil {
|
||||
if _, err := os.Stat(adminKubeConfigPath); os.IsNotExist(err) {
|
||||
return nil, errors.Errorf("File %s does not exists. Please use 'kubeadm join phase control-plane-prepare' subcommands to generate it.", adminKubeConfigPath)
|
||||
}
|
||||
klog.V(1).Infof("[preflight] found discovery flags missing for this command. using FileDiscovery: %s", adminKubeConfigPath)
|
||||
opt.externalcfg.Discovery.File = &kubeadmapiv1beta1.FileDiscovery{KubeConfigPath: adminKubeConfigPath}
|
||||
opt.externalcfg.Discovery.BootstrapToken = nil //NB. this could be removed when we get better control on args (e.g. phases without discovery should have NoArgs )
|
||||
}
|
||||
|
||||
cfg, err := configutil.LoadOrDefaultJoinConfiguration(opt.cfgPath, opt.externalcfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// override node name and CRI socket from the command line opt
|
||||
if opt.externalcfg.NodeRegistration.Name != "" {
|
||||
cfg.NodeRegistration.Name = opt.externalcfg.NodeRegistration.Name
|
||||
}
|
||||
if opt.externalcfg.NodeRegistration.CRISocket != "" {
|
||||
cfg.NodeRegistration.CRISocket = opt.externalcfg.NodeRegistration.CRISocket
|
||||
}
|
||||
|
||||
if cfg.ControlPlane != nil {
|
||||
if err := configutil.VerifyAPIServerBindAddress(cfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &joinData{
|
||||
cfg: cfg,
|
||||
tlsBootstrapCfg: tlsBootstrapCfg,
|
||||
ignorePreflightErrors: ignorePreflightErrorsSet,
|
||||
outputWriter: out,
|
||||
certificateKey: opt.certificateKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CertificateKey returns the key used to encrypt the certs.
|
||||
func (j *joinData) CertificateKey() string {
|
||||
return j.certificateKey
|
||||
}
|
||||
|
||||
// Cfg returns the JoinConfiguration.
|
||||
func (j *joinData) Cfg() *kubeadmapi.JoinConfiguration {
|
||||
return j.cfg
|
||||
}
|
||||
|
||||
// TLSBootstrapCfg returns the cluster-info (kubeconfig).
|
||||
func (j *joinData) TLSBootstrapCfg() (*clientcmdapi.Config, error) {
|
||||
if j.tlsBootstrapCfg != nil {
|
||||
return j.tlsBootstrapCfg, nil
|
||||
}
|
||||
klog.V(1).Infoln("[preflight] Discovering cluster-info")
|
||||
tlsBootstrapCfg, err := discovery.For(j.cfg)
|
||||
j.tlsBootstrapCfg = tlsBootstrapCfg
|
||||
return tlsBootstrapCfg, err
|
||||
}
|
||||
|
||||
// InitCfg returns the InitConfiguration.
|
||||
func (j *joinData) InitCfg() (*kubeadmapi.InitConfiguration, error) {
|
||||
if j.initCfg != nil {
|
||||
return j.initCfg, nil
|
||||
}
|
||||
if _, err := j.TLSBootstrapCfg(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
klog.V(1).Infoln("[preflight] Fetching init configuration")
|
||||
initCfg, err := fetchInitConfigurationFromJoinConfiguration(j.cfg, j.tlsBootstrapCfg)
|
||||
j.initCfg = initCfg
|
||||
return initCfg, err
|
||||
}
|
||||
|
||||
// ClientSet returns the ClientSet for accessing the cluster with the identity defined in admin.conf.
|
||||
func (j *joinData) ClientSet() (*clientset.Clientset, error) {
|
||||
if j.clientSet != nil {
|
||||
return j.clientSet, nil
|
||||
}
|
||||
path := kubeadmconstants.GetAdminKubeConfigPath()
|
||||
client, err := kubeconfigutil.ClientSetFromFile(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "[preflight] couldn't create Kubernetes client")
|
||||
}
|
||||
j.clientSet = client
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// IgnorePreflightErrors returns the list of preflight errors to ignore.
|
||||
func (j *joinData) IgnorePreflightErrors() sets.String {
|
||||
return j.ignorePreflightErrors
|
||||
}
|
||||
|
||||
// OutputWriter returns the io.Writer used to write messages such as the "join done" message.
|
||||
func (j *joinData) OutputWriter() io.Writer {
|
||||
return j.outputWriter
|
||||
}
|
||||
|
||||
// fetchInitConfigurationFromJoinConfiguration retrieves the init configuration from a join configuration, performing the discovery
|
||||
func fetchInitConfigurationFromJoinConfiguration(cfg *kubeadmapi.JoinConfiguration, tlsBootstrapCfg *clientcmdapi.Config) (*kubeadmapi.InitConfiguration, error) {
|
||||
// Retrieves the kubeadm configuration
|
||||
klog.V(1).Infoln("[preflight] Retrieving KubeConfig objects")
|
||||
initConfiguration, err := fetchInitConfiguration(tlsBootstrapCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create the final KubeConfig file with the cluster name discovered after fetching the cluster configuration
|
||||
clusterinfo := kubeconfigutil.GetClusterFromKubeConfig(tlsBootstrapCfg)
|
||||
tlsBootstrapCfg.Clusters = map[string]*clientcmdapi.Cluster{
|
||||
initConfiguration.ClusterName: clusterinfo,
|
||||
}
|
||||
tlsBootstrapCfg.Contexts[tlsBootstrapCfg.CurrentContext].Cluster = initConfiguration.ClusterName
|
||||
|
||||
// injects into the kubeadm configuration the information about the joining node
|
||||
initConfiguration.NodeRegistration = cfg.NodeRegistration
|
||||
if cfg.ControlPlane != nil {
|
||||
initConfiguration.LocalAPIEndpoint = cfg.ControlPlane.LocalAPIEndpoint
|
||||
}
|
||||
|
||||
return initConfiguration, nil
|
||||
}
|
||||
|
||||
// fetchInitConfiguration reads the cluster configuration from the kubeadm-admin configMap
|
||||
func fetchInitConfiguration(tlsBootstrapCfg *clientcmdapi.Config) (*kubeadmapi.InitConfiguration, error) {
|
||||
// creates a client to access the cluster using the bootstrap token identity
|
||||
tlsClient, err := kubeconfigutil.ToClientSet(tlsBootstrapCfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to access the cluster")
|
||||
}
|
||||
|
||||
// Fetches the init configuration
|
||||
initConfiguration, err := configutil.FetchInitConfigurationFromCluster(tlsClient, os.Stdout, "preflight", true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap")
|
||||
}
|
||||
|
||||
return initConfiguration, nil
|
||||
}
|
|
@ -1,245 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
)
|
||||
|
||||
const (
|
||||
testJoinConfig = `apiVersion: kubeadm.k8s.io/v1beta1
|
||||
kind: JoinConfiguration
|
||||
discovery:
|
||||
bootstrapToken:
|
||||
token: abcdef.0123456789abcdef
|
||||
apiServerEndpoint: 1.2.3.4:6443
|
||||
unsafeSkipCAVerification: true
|
||||
nodeRegistration:
|
||||
criSocket: /run/containerd/containerd.sock
|
||||
name: someName
|
||||
`
|
||||
)
|
||||
|
||||
func TestNewJoinData(t *testing.T) {
|
||||
// create temp directory
|
||||
tmpDir, err := ioutil.TempDir("", "kubeadm-join-test")
|
||||
if err != nil {
|
||||
t.Errorf("Unable to create temporary directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// create config file
|
||||
configFilePath := filepath.Join(tmpDir, "test-config-file")
|
||||
cfgFile, err := os.Create(configFilePath)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to create file %q: %v", configFilePath, err)
|
||||
}
|
||||
defer cfgFile.Close()
|
||||
if _, err = cfgFile.WriteString(testJoinConfig); err != nil {
|
||||
t.Fatalf("Unable to write file %q: %v", configFilePath, err)
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
flags map[string]string
|
||||
validate func(*testing.T, *joinData)
|
||||
expectError bool
|
||||
}{
|
||||
// Join data passed using flags
|
||||
{
|
||||
name: "fails if no discovery method set",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "fails if both file and bootstrap discovery methods set",
|
||||
args: []string{"1.2.3.4:6443"},
|
||||
flags: map[string]string{
|
||||
options.FileDiscovery: "https://foo",
|
||||
options.TokenDiscovery: "abcdef.0123456789abcdef",
|
||||
options.TokenDiscoverySkipCAHash: "true",
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "pass if file discovery is set",
|
||||
flags: map[string]string{
|
||||
options.FileDiscovery: "https://foo",
|
||||
},
|
||||
validate: func(t *testing.T, data *joinData) {
|
||||
// validate that file discovery settings are set into join data
|
||||
if data.cfg.Discovery.File == nil || data.cfg.Discovery.File.KubeConfigPath != "https://foo" {
|
||||
t.Errorf("Invalid data.cfg.Discovery.File")
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "pass if bootstrap discovery is set",
|
||||
args: []string{"1.2.3.4:6443", "5.6.7.8:6443"},
|
||||
flags: map[string]string{
|
||||
options.TokenDiscovery: "abcdef.0123456789abcdef",
|
||||
options.TokenDiscoverySkipCAHash: "true",
|
||||
},
|
||||
validate: func(t *testing.T, data *joinData) {
|
||||
// validate that bootstrap discovery settings are set into join data
|
||||
if data.cfg.Discovery.BootstrapToken == nil ||
|
||||
data.cfg.Discovery.BootstrapToken.APIServerEndpoint != "1.2.3.4:6443" || //only first arg should be kept as APIServerEndpoint
|
||||
data.cfg.Discovery.BootstrapToken.Token != "abcdef.0123456789abcdef" ||
|
||||
data.cfg.Discovery.BootstrapToken.UnsafeSkipCAVerification != true {
|
||||
t.Errorf("Invalid data.cfg.Discovery.BootstrapToken")
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "--token sets TLSBootstrapToken and BootstrapToken.Token if unset",
|
||||
args: []string{"1.2.3.4:6443"},
|
||||
flags: map[string]string{
|
||||
options.TokenStr: "abcdef.0123456789abcdef",
|
||||
options.TokenDiscoverySkipCAHash: "true",
|
||||
},
|
||||
validate: func(t *testing.T, data *joinData) {
|
||||
// validate that token sets both TLSBootstrapToken and BootstrapToken.Token into join data
|
||||
if data.cfg.Discovery.TLSBootstrapToken != "abcdef.0123456789abcdef" ||
|
||||
data.cfg.Discovery.BootstrapToken == nil ||
|
||||
data.cfg.Discovery.BootstrapToken.Token != "abcdef.0123456789abcdef" {
|
||||
t.Errorf("Invalid TLSBootstrapToken or BootstrapToken.Token")
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "--token doesn't override TLSBootstrapToken and BootstrapToken.Token if set",
|
||||
args: []string{"1.2.3.4:6443"},
|
||||
flags: map[string]string{
|
||||
options.TokenStr: "aaaaaa.0123456789aaaaaa",
|
||||
options.TLSBootstrapToken: "abcdef.0123456789abcdef",
|
||||
options.TokenDiscovery: "defghi.0123456789defghi",
|
||||
options.TokenDiscoverySkipCAHash: "true",
|
||||
},
|
||||
validate: func(t *testing.T, data *joinData) {
|
||||
// validate that TLSBootstrapToken and BootstrapToken.Token values are preserved into join data
|
||||
if data.cfg.Discovery.TLSBootstrapToken != "abcdef.0123456789abcdef" ||
|
||||
data.cfg.Discovery.BootstrapToken == nil ||
|
||||
data.cfg.Discovery.BootstrapToken.Token != "defghi.0123456789defghi" {
|
||||
t.Errorf("Invalid TLSBootstrapToken or BootstrapToken.Token")
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "control plane setting are preserved if --control-plane flag is set",
|
||||
flags: map[string]string{
|
||||
options.ControlPlane: "true",
|
||||
options.APIServerAdvertiseAddress: "1.2.3.4",
|
||||
options.APIServerBindPort: "1234",
|
||||
options.FileDiscovery: "https://foo", //required only to pass discovery validation
|
||||
},
|
||||
validate: func(t *testing.T, data *joinData) {
|
||||
// validate that control plane attributes are set in join data
|
||||
if data.cfg.ControlPlane == nil ||
|
||||
data.cfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress != "1.2.3.4" ||
|
||||
data.cfg.ControlPlane.LocalAPIEndpoint.BindPort != 1234 {
|
||||
t.Errorf("Invalid ControlPlane")
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "control plane setting are cleaned up if --control-plane flag is not set",
|
||||
flags: map[string]string{
|
||||
options.ControlPlane: "false",
|
||||
options.APIServerAdvertiseAddress: "1.2.3.4",
|
||||
options.APIServerBindPort: "1.2.3.4",
|
||||
options.FileDiscovery: "https://foo", //required only to pass discovery validation
|
||||
},
|
||||
validate: func(t *testing.T, data *joinData) {
|
||||
// validate that control plane attributes are unset in join data
|
||||
if data.cfg.ControlPlane != nil {
|
||||
t.Errorf("Invalid ControlPlane")
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "fails if invalid preflight checks are provided",
|
||||
flags: map[string]string{
|
||||
options.IgnorePreflightErrors: "all,something-else",
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
|
||||
// Join data passed using config file
|
||||
{
|
||||
name: "Pass with config from file",
|
||||
flags: map[string]string{
|
||||
options.CfgPath: configFilePath,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "--cri-socket and --node-name flags override config from file",
|
||||
flags: map[string]string{
|
||||
options.CfgPath: configFilePath,
|
||||
options.NodeCRISocket: "/var/run/crio/crio.sock",
|
||||
options.NodeName: "anotherName",
|
||||
},
|
||||
validate: func(t *testing.T, data *joinData) {
|
||||
// validate that cri-socket and node-name are overwritten
|
||||
if data.cfg.NodeRegistration.CRISocket != "/var/run/crio/crio.sock" {
|
||||
t.Errorf("Invalid NodeRegistration.CRISocket")
|
||||
}
|
||||
if data.cfg.NodeRegistration.Name != "anotherName" {
|
||||
t.Errorf("Invalid NodeRegistration.Name")
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "fail if mixedArguments are passed",
|
||||
flags: map[string]string{
|
||||
options.CfgPath: configFilePath,
|
||||
options.APIServerAdvertiseAddress: "1.2.3.4",
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// initialize an external join option and inject it to the join cmd
|
||||
joinOptions := newJoinOptions()
|
||||
cmd := NewCmdJoin(nil, joinOptions)
|
||||
|
||||
// sets cmd flags (that will be reflected on the join options)
|
||||
for f, v := range tc.flags {
|
||||
cmd.Flags().Set(f, v)
|
||||
}
|
||||
|
||||
// test newJoinData method
|
||||
data, err := newJoinData(cmd, tc.args, joinOptions, nil)
|
||||
if err != nil && !tc.expectError {
|
||||
t.Fatalf("newJoinData returned unexpected error: %v", err)
|
||||
}
|
||||
if err == nil && tc.expectError {
|
||||
t.Fatalf("newJoinData didn't return error when expected")
|
||||
}
|
||||
|
||||
// exec additional validation on the returned value
|
||||
if tc.validate != nil {
|
||||
tc.validate(t, data)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"certs.go",
|
||||
"constant.go",
|
||||
"doc.go",
|
||||
"generic.go",
|
||||
"token.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/cli/flag:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag: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"],
|
||||
)
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package options
|
||||
|
||||
import "github.com/spf13/pflag"
|
||||
|
||||
// AddCertificateDirFlag adds the --certs-dir flag to the given flagset
|
||||
func AddCertificateDirFlag(fs *pflag.FlagSet, certsDir *string) {
|
||||
fs.StringVar(certsDir, CertificatesDir, *certsDir, "The path where to save the certificates")
|
||||
}
|
||||
|
||||
// AddCSRFlag adds the --csr-only flag to the given flagset
|
||||
func AddCSRFlag(fs *pflag.FlagSet, csr *bool) {
|
||||
fs.BoolVar(csr, CSROnly, *csr, "Create CSRs instead of generating certificates")
|
||||
}
|
||||
|
||||
// AddCSRDirFlag adds the --csr-dir flag to the given flagset
|
||||
func AddCSRDirFlag(fs *pflag.FlagSet, csrDir *string) {
|
||||
fs.StringVar(csrDir, CSRDir, *csrDir, "The path to output the CSRs and private keys to")
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
/*
|
||||
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 options
|
||||
|
||||
const (
|
||||
// APIServerAdvertiseAddress flag sets the IP address the API Server will advertise it's listening on. Specify '0.0.0.0' to use the address of the default network interface.
|
||||
APIServerAdvertiseAddress = "apiserver-advertise-address"
|
||||
|
||||
// APIServerBindPort flag sets the port for the API Server to bind to.
|
||||
APIServerBindPort = "apiserver-bind-port"
|
||||
|
||||
// APIServerCertSANs flag sets extra Subject Alternative Names (SANs) to use for the API Server serving certificate. Can be both IP addresses and DNS names.
|
||||
APIServerCertSANs = "apiserver-cert-extra-sans"
|
||||
|
||||
// APIServerExtraArgs flag sets a extra flags to pass to the API Server or override default ones in form of <flagname>=<value>.
|
||||
APIServerExtraArgs = "apiserver-extra-args"
|
||||
|
||||
// CertificatesDir flag sets the path where to save and read the certificates.
|
||||
CertificatesDir = "cert-dir"
|
||||
|
||||
// CfgPath flag sets the path to kubeadm config file.
|
||||
CfgPath = "config"
|
||||
|
||||
// ControllerManagerExtraArgs flag sets extra flags to pass to the Controller Manager or override default ones in form of <flagname>=<value>.
|
||||
ControllerManagerExtraArgs = "controller-manager-extra-args"
|
||||
|
||||
// DryRun flag instruct kubeadm to don't apply any changes; just output what would be done.
|
||||
DryRun = "dry-run"
|
||||
|
||||
// FeatureGatesString flag sets key=value pairs that describe feature gates for various features.
|
||||
FeatureGatesString = "feature-gates"
|
||||
|
||||
// IgnorePreflightErrors sets the path a list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.
|
||||
IgnorePreflightErrors = "ignore-preflight-errors"
|
||||
|
||||
// ImageRepository sets the container registry to pull control plane images from.
|
||||
ImageRepository = "image-repository"
|
||||
|
||||
// KubeconfigDir flag sets the path where to save the kubeconfig file.
|
||||
KubeconfigDir = "kubeconfig-dir"
|
||||
|
||||
// KubeconfigPath flag sets the kubeconfig file to use when talking to the cluster. If the flag is not set, a set of standard locations are searched for an existing KubeConfig file.
|
||||
KubeconfigPath = "kubeconfig"
|
||||
|
||||
// KubernetesVersion flag sets the Kubernetes version for the control plane.
|
||||
KubernetesVersion = "kubernetes-version"
|
||||
|
||||
// NetworkingDNSDomain flag sets the domain for services, e.g. "myorg.internal".
|
||||
NetworkingDNSDomain = "service-dns-domain"
|
||||
|
||||
// NetworkingServiceSubnet flag sets the range of IP address for service VIPs.
|
||||
NetworkingServiceSubnet = "service-cidr"
|
||||
|
||||
// NetworkingPodSubnet flag sets the range of IP addresses for the pod network. If set, the control plane will automatically allocate CIDRs for every node.
|
||||
NetworkingPodSubnet = "pod-network-cidr"
|
||||
|
||||
// NodeCRISocket flag sets the CRI socket to connect to.
|
||||
NodeCRISocket = "cri-socket"
|
||||
|
||||
// NodeName flag sets the node name.
|
||||
NodeName = "node-name"
|
||||
|
||||
// SchedulerExtraArgs flag sets extra flags to pass to the Scheduler or override default ones in form of <flagname>=<value>".
|
||||
SchedulerExtraArgs = "scheduler-extra-args"
|
||||
|
||||
// SkipTokenPrint flag instruct kubeadm to skip printing of the default bootstrap token generated by 'kubeadm init'.
|
||||
SkipTokenPrint = "skip-token-print"
|
||||
|
||||
// CSROnly flag instructs kubeadm to create CSRs instead of automatically creating or renewing certs
|
||||
CSROnly = "csr-only"
|
||||
|
||||
// CSRDir flag sets the location for CSRs and flags to be output
|
||||
CSRDir = "csr-dir"
|
||||
|
||||
// TokenStr flags sets both the discovery-token and the tls-bootstrap-token when those values are not provided
|
||||
TokenStr = "token"
|
||||
|
||||
// TokenTTL flag sets the time to live for token
|
||||
TokenTTL = "token-ttl"
|
||||
|
||||
// TokenUsages flag sets the usages of the token
|
||||
TokenUsages = "usages"
|
||||
|
||||
// TokenGroups flag sets the authentication groups of the token
|
||||
TokenGroups = "groups"
|
||||
|
||||
// TokenDescription flag sets the description of the token
|
||||
TokenDescription = "description"
|
||||
|
||||
// TLSBootstrapToken flag sets the token used to temporarily authenticate with the Kubernetes Control Plane to submit a certificate signing request (CSR) for a locally created key pair
|
||||
TLSBootstrapToken = "tls-bootstrap-token"
|
||||
|
||||
// TokenDiscovery flag sets the token used to validate cluster information fetched from the API server (for token-based discovery)
|
||||
TokenDiscovery = "discovery-token"
|
||||
|
||||
// TokenDiscoveryCAHash flag instruct kubeadm to validate that the root CA public key matches this hash (for token-based discovery)
|
||||
TokenDiscoveryCAHash = "discovery-token-ca-cert-hash"
|
||||
|
||||
// TokenDiscoverySkipCAHash flag instruct kubeadm to skip CA hash verification (for token-based discovery)
|
||||
TokenDiscoverySkipCAHash = "discovery-token-unsafe-skip-ca-verification"
|
||||
|
||||
// FileDiscovery flag sets the file or URL from which to load cluster information (for file-based discovery)
|
||||
FileDiscovery = "discovery-file"
|
||||
|
||||
// ControlPlane flag instruct kubeadm to create a new control plane instance on this node
|
||||
ControlPlane = "experimental-control-plane"
|
||||
|
||||
// UploadCerts flag instruct kubeadm to upload certificates
|
||||
UploadCerts = "experimental-upload-certs"
|
||||
|
||||
// CertificateKey flag sets the key used to encrypt and decrypt certificate secrets
|
||||
CertificateKey = "certificate-key"
|
||||
|
||||
// SkipCertificateKeyPrint flag instruct kubeadm to skip printing certificate key used to encrypt certs by 'kubeadm init'.
|
||||
SkipCertificateKeyPrint = "skip-certificate-key-print"
|
||||
)
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Package options provide a central point for defining flags for kubeadm cobra commands,
|
||||
no matter if hard coded commands or autogenerated command for phases.
|
||||
|
||||
New kubeadm flags should always be defined in this package as a constant before their usage,
|
||||
in order to enforce naming consistency across different commands and to control flag proliferation.
|
||||
|
||||
In addition to defining the flags, the package also contains set of utilities for flag management.
|
||||
|
||||
For additional details about how flags are managed in phases, please refer to the
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" package.
|
||||
*/
|
||||
package options
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
)
|
||||
|
||||
// AddKubeConfigFlag adds the --kubeconfig flag to the given flagset
|
||||
func AddKubeConfigFlag(fs *pflag.FlagSet, kubeConfigFile *string) {
|
||||
fs.StringVar(kubeConfigFile, KubeconfigPath, *kubeConfigFile, "The kubeconfig file to use when talking to the cluster. If the flag is not set, a set of standard locations can be searched for an existing kubeconfig file.")
|
||||
// Note that DefValue is the text shown in the terminal and not the default value assigned to the flag
|
||||
fs.Lookup(KubeconfigPath).DefValue = constants.GetAdminKubeConfigPath()
|
||||
}
|
||||
|
||||
// AddKubeConfigDirFlag adds the --kubeconfig-dir flag to the given flagset
|
||||
func AddKubeConfigDirFlag(fs *pflag.FlagSet, kubeConfigDir *string) {
|
||||
fs.StringVar(kubeConfigDir, KubeconfigDir, *kubeConfigDir, "The path where to save the kubeconfig file.")
|
||||
}
|
||||
|
||||
// AddConfigFlag adds the --config flag to the given flagset
|
||||
func AddConfigFlag(fs *pflag.FlagSet, cfgPath *string) {
|
||||
fs.StringVar(cfgPath, CfgPath, *cfgPath, "Path to a kubeadm configuration file.")
|
||||
}
|
||||
|
||||
// AddIgnorePreflightErrorsFlag adds the --ignore-preflight-errors flag to the given flagset
|
||||
func AddIgnorePreflightErrorsFlag(fs *pflag.FlagSet, ignorePreflightErrors *[]string) {
|
||||
fs.StringSliceVar(
|
||||
ignorePreflightErrors, IgnorePreflightErrors, *ignorePreflightErrors,
|
||||
"A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.",
|
||||
)
|
||||
}
|
||||
|
||||
// AddControlPlanExtraArgsFlags adds the ExtraArgs flags for control plane components
|
||||
func AddControlPlanExtraArgsFlags(fs *pflag.FlagSet, apiServerExtraArgs, controllerManagerExtraArgs, schedulerExtraArgs *map[string]string) {
|
||||
fs.Var(cliflag.NewMapStringString(apiServerExtraArgs), APIServerExtraArgs, "A set of extra flags to pass to the API Server or override default ones in form of <flagname>=<value>")
|
||||
fs.Var(cliflag.NewMapStringString(controllerManagerExtraArgs), ControllerManagerExtraArgs, "A set of extra flags to pass to the Controller Manager or override default ones in form of <flagname>=<value>")
|
||||
fs.Var(cliflag.NewMapStringString(schedulerExtraArgs), SchedulerExtraArgs, "A set of extra flags to pass to the Scheduler or override default ones in form of <flagname>=<value>")
|
||||
}
|
||||
|
||||
// AddImageMetaFlags adds the --image-repository flag to the given flagset
|
||||
func AddImageMetaFlags(fs *pflag.FlagSet, imageRepository *string) {
|
||||
fs.StringVar(imageRepository, ImageRepository, *imageRepository, "Choose a container registry to pull control plane images from")
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
)
|
||||
|
||||
// NewBootstrapTokenOptions creates a new BootstrapTokenOptions object with the default values
|
||||
func NewBootstrapTokenOptions() *BootstrapTokenOptions {
|
||||
bto := &BootstrapTokenOptions{&kubeadmapiv1beta1.BootstrapToken{}, ""}
|
||||
kubeadmapiv1beta1.SetDefaults_BootstrapToken(bto.BootstrapToken)
|
||||
return bto
|
||||
}
|
||||
|
||||
// BootstrapTokenOptions is a wrapper struct for adding bootstrap token-related flags to a FlagSet
|
||||
// and applying the parsed flags to a InitConfiguration object later at runtime
|
||||
// TODO: In the future, we might want to group the flags in a better way than adding them all individually like this
|
||||
type BootstrapTokenOptions struct {
|
||||
*kubeadmapiv1beta1.BootstrapToken
|
||||
TokenStr string
|
||||
}
|
||||
|
||||
// AddTokenFlag adds the --token flag to the given flagset
|
||||
func (bto *BootstrapTokenOptions) AddTokenFlag(fs *pflag.FlagSet) {
|
||||
fs.StringVar(
|
||||
&bto.TokenStr, TokenStr, "",
|
||||
"The token to use for establishing bidirectional trust between nodes and control-plane nodes. The format is [a-z0-9]{6}\\.[a-z0-9]{16} - e.g. abcdef.0123456789abcdef",
|
||||
)
|
||||
}
|
||||
|
||||
// AddTTLFlag adds the --token-ttl flag to the given flagset
|
||||
func (bto *BootstrapTokenOptions) AddTTLFlag(fs *pflag.FlagSet) {
|
||||
bto.AddTTLFlagWithName(fs, TokenTTL)
|
||||
}
|
||||
|
||||
// AddTTLFlagWithName adds the --token-ttl flag with a custom flag name given flagset
|
||||
func (bto *BootstrapTokenOptions) AddTTLFlagWithName(fs *pflag.FlagSet, flagName string) {
|
||||
fs.DurationVar(
|
||||
&bto.TTL.Duration, flagName, bto.TTL.Duration,
|
||||
"The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire",
|
||||
)
|
||||
}
|
||||
|
||||
// AddUsagesFlag adds the --usages flag to the given flagset
|
||||
func (bto *BootstrapTokenOptions) AddUsagesFlag(fs *pflag.FlagSet) {
|
||||
fs.StringSliceVar(
|
||||
&bto.Usages, TokenUsages, bto.Usages,
|
||||
fmt.Sprintf("Describes the ways in which this token can be used. You can pass --usages multiple times or provide a comma separated list of options. Valid options: [%s]", strings.Join(kubeadmconstants.DefaultTokenUsages, ",")),
|
||||
)
|
||||
}
|
||||
|
||||
// AddGroupsFlag adds the --groups flag to the given flagset
|
||||
func (bto *BootstrapTokenOptions) AddGroupsFlag(fs *pflag.FlagSet) {
|
||||
fs.StringSliceVar(
|
||||
&bto.Groups, TokenGroups, bto.Groups,
|
||||
fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q", bootstrapapi.BootstrapGroupPattern),
|
||||
)
|
||||
}
|
||||
|
||||
// AddDescriptionFlag adds the --description flag to the given flagset
|
||||
func (bto *BootstrapTokenOptions) AddDescriptionFlag(fs *pflag.FlagSet) {
|
||||
fs.StringVar(
|
||||
&bto.Description, TokenDescription, bto.Description,
|
||||
"A human friendly description of how this token is used.",
|
||||
)
|
||||
}
|
||||
|
||||
// ApplyTo applies the values set internally in the BootstrapTokenOptions object to a InitConfiguration object at runtime
|
||||
// If --token was specified in the CLI (as a string), it's parsed and validated before it's added to the BootstrapToken object.
|
||||
func (bto *BootstrapTokenOptions) ApplyTo(cfg *kubeadmapiv1beta1.InitConfiguration) error {
|
||||
if len(bto.TokenStr) > 0 {
|
||||
var err error
|
||||
bto.Token, err = kubeadmapiv1beta1.NewBootstrapTokenString(bto.TokenStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Set the token specified by the flags as the first and only token to create in case --config is not specified
|
||||
cfg.BootstrapTokens = []kubeadmapiv1beta1.BootstrapToken{*bto.BootstrapToken}
|
||||
return nil
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["util.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//cmd/kubeadm/app/cmd/phases/init:all-srcs",
|
||||
"//cmd/kubeadm/app/cmd/phases/join:all-srcs",
|
||||
"//cmd/kubeadm/app/cmd/phases/workflow:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package phases
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
dnsaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
|
||||
proxyaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
coreDNSAddonLongDesc = normalizer.LongDesc(`
|
||||
Installs the CoreDNS addon components via the API server.
|
||||
Please note that although the DNS server is deployed, it will not be scheduled until CNI is installed.
|
||||
`)
|
||||
|
||||
kubeProxyAddonLongDesc = normalizer.LongDesc(`
|
||||
Installs the kube-proxy addon components via the API server.
|
||||
`)
|
||||
)
|
||||
|
||||
// NewAddonPhase returns the addon Cobra command
|
||||
func NewAddonPhase() workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: "addon",
|
||||
Short: "Installs required addons for passing Conformance tests",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
Phases: []workflow.Phase{
|
||||
{
|
||||
Name: "all",
|
||||
Short: "Installs all the addons",
|
||||
InheritFlags: getAddonPhaseFlags("all"),
|
||||
RunAllSiblings: true,
|
||||
},
|
||||
{
|
||||
Name: "coredns",
|
||||
Short: "Installs the CoreDNS addon to a Kubernetes cluster",
|
||||
Long: coreDNSAddonLongDesc,
|
||||
InheritFlags: getAddonPhaseFlags("coredns"),
|
||||
Run: runCoreDNSAddon,
|
||||
},
|
||||
{
|
||||
Name: "kube-proxy",
|
||||
Short: "Installs the kube-proxy addon to a Kubernetes cluster",
|
||||
Long: kubeProxyAddonLongDesc,
|
||||
InheritFlags: getAddonPhaseFlags("kube-proxy"),
|
||||
Run: runKubeProxyAddon,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getInitData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.Interface, error) {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return nil, nil, errors.New("addon phase invoked with an invalid data struct")
|
||||
}
|
||||
cfg := data.Cfg()
|
||||
client, err := data.Client()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return cfg, client, err
|
||||
}
|
||||
|
||||
// runCoreDNSAddon installs CoreDNS addon to a Kubernetes cluster
|
||||
func runCoreDNSAddon(c workflow.RunData) error {
|
||||
cfg, client, err := getInitData(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dnsaddon.EnsureDNSAddon(&cfg.ClusterConfiguration, client)
|
||||
}
|
||||
|
||||
// runKubeProxyAddon installs KubeProxy addon to a Kubernetes cluster
|
||||
func runKubeProxyAddon(c workflow.RunData) error {
|
||||
cfg, client, err := getInitData(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return proxyaddon.EnsureProxyAddon(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, client)
|
||||
}
|
||||
|
||||
func getAddonPhaseFlags(name string) []string {
|
||||
flags := []string{
|
||||
options.CfgPath,
|
||||
options.KubeconfigPath,
|
||||
options.KubernetesVersion,
|
||||
options.ImageRepository,
|
||||
}
|
||||
if name == "all" || name == "kube-proxy" {
|
||||
flags = append(flags,
|
||||
options.APIServerAdvertiseAddress,
|
||||
options.APIServerBindPort,
|
||||
options.NetworkingPodSubnet,
|
||||
)
|
||||
}
|
||||
if name == "all" || name == "coredns" {
|
||||
flags = append(flags,
|
||||
options.FeatureGatesString,
|
||||
options.NetworkingDNSDomain,
|
||||
options.NetworkingServiceSubnet,
|
||||
)
|
||||
}
|
||||
return flags
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package phases
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
|
||||
nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
bootstrapTokenLongDesc = normalizer.LongDesc(`
|
||||
Bootstrap tokens are used for establishing bidirectional trust between a node joining
|
||||
the cluster and a the control-plane node.
|
||||
|
||||
This command makes all the configurations required to make bootstrap tokens works
|
||||
and then creates an initial token.
|
||||
`)
|
||||
|
||||
bootstrapTokenExamples = normalizer.Examples(`
|
||||
# Makes all the bootstrap token configurations and creates an initial token, functionally
|
||||
# equivalent to what generated by kubeadm init.
|
||||
kubeadm init phase bootstrap-token
|
||||
`)
|
||||
)
|
||||
|
||||
// NewBootstrapTokenPhase returns the phase to bootstrapToken
|
||||
func NewBootstrapTokenPhase() workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: "bootstrap-token",
|
||||
Aliases: []string{"bootstraptoken"},
|
||||
Short: "Generates bootstrap tokens used to join a node to a cluster",
|
||||
Example: bootstrapTokenExamples,
|
||||
Long: bootstrapTokenLongDesc,
|
||||
InheritFlags: []string{
|
||||
options.CfgPath,
|
||||
options.KubeconfigPath,
|
||||
options.SkipTokenPrint,
|
||||
},
|
||||
Run: runBootstrapToken,
|
||||
}
|
||||
}
|
||||
|
||||
func runBootstrapToken(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("bootstrap-token phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
client, err := data.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !data.SkipTokenPrint() {
|
||||
tokens := data.Tokens()
|
||||
if len(tokens) == 1 {
|
||||
fmt.Printf("[bootstrap-token] Using token: %s\n", tokens[0])
|
||||
} else if len(tokens) > 1 {
|
||||
fmt.Printf("[bootstrap-token] Using tokens: %v\n", tokens)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles")
|
||||
// Create the default node bootstrap token
|
||||
if err := nodebootstraptokenphase.UpdateOrCreateTokens(client, false, data.Cfg().BootstrapTokens); err != nil {
|
||||
return errors.Wrap(err, "error updating or creating token")
|
||||
}
|
||||
// Create RBAC rules that makes the bootstrap tokens able to post CSRs
|
||||
if err := nodebootstraptokenphase.AllowBootstrapTokensToPostCSRs(client); err != nil {
|
||||
return errors.Wrap(err, "error allowing bootstrap tokens to post CSRs")
|
||||
}
|
||||
// Create RBAC rules that makes the bootstrap tokens able to get their CSRs approved automatically
|
||||
if err := nodebootstraptokenphase.AutoApproveNodeBootstrapTokens(client); err != nil {
|
||||
return errors.Wrap(err, "error auto-approving node bootstrap tokens")
|
||||
}
|
||||
|
||||
// Create/update RBAC rules that makes the nodes to rotate certificates and get their CSRs approved automatically
|
||||
if err := nodebootstraptokenphase.AutoApproveNodeCertificateRotation(client); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create the cluster-info ConfigMap with the associated RBAC rules
|
||||
if err := clusterinfophase.CreateBootstrapConfigMapIfNotExists(client, data.KubeConfigPath()); err != nil {
|
||||
return errors.Wrap(err, "error creating bootstrap ConfigMap")
|
||||
}
|
||||
if err := clusterinfophase.CreateClusterInfoRBACRules(client); err != nil {
|
||||
return errors.Wrap(err, "error creating clusterinfo RBAC rules")
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,287 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package phases
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
saKeyLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the private key for signing service account tokens along with its public key, and saves them into
|
||||
%s and %s files.
|
||||
If both files already exist, kubeadm skips the generation step and existing files will be used.
|
||||
`+cmdutil.AlphaDisclaimer), kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName)
|
||||
|
||||
genericLongDesc = normalizer.LongDesc(`
|
||||
Generates the %[1]s, and saves them into %[2]s.cert and %[2]s.key files.%[3]s
|
||||
|
||||
If both files already exist, kubeadm skips the generation step and existing files will be used.
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
)
|
||||
|
||||
var (
|
||||
csrOnly bool
|
||||
csrDir string
|
||||
)
|
||||
|
||||
// NewCertsPhase returns the phase for the certs
|
||||
func NewCertsPhase() workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: "certs",
|
||||
Short: "Certificate generation",
|
||||
Phases: newCertSubPhases(),
|
||||
Run: runCerts,
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
}
|
||||
}
|
||||
|
||||
func localFlags() *pflag.FlagSet {
|
||||
set := pflag.NewFlagSet("csr", pflag.ExitOnError)
|
||||
options.AddCSRFlag(set, &csrOnly)
|
||||
options.AddCSRDirFlag(set, &csrDir)
|
||||
return set
|
||||
}
|
||||
|
||||
// newCertSubPhases returns sub phases for certs phase
|
||||
func newCertSubPhases() []workflow.Phase {
|
||||
subPhases := []workflow.Phase{}
|
||||
|
||||
// All subphase
|
||||
allPhase := workflow.Phase{
|
||||
Name: "all",
|
||||
Short: "Generates all certificates",
|
||||
InheritFlags: getCertPhaseFlags("all"),
|
||||
RunAllSiblings: true,
|
||||
}
|
||||
|
||||
subPhases = append(subPhases, allPhase)
|
||||
|
||||
certTree, _ := certsphase.GetDefaultCertList().AsMap().CertTree()
|
||||
|
||||
for ca, certList := range certTree {
|
||||
caPhase := newCertSubPhase(ca, runCAPhase(ca))
|
||||
subPhases = append(subPhases, caPhase)
|
||||
|
||||
for _, cert := range certList {
|
||||
certPhase := newCertSubPhase(cert, runCertPhase(cert, ca))
|
||||
certPhase.LocalFlags = localFlags()
|
||||
subPhases = append(subPhases, certPhase)
|
||||
}
|
||||
}
|
||||
|
||||
// SA creates the private/public key pair, which doesn't use x509 at all
|
||||
saPhase := workflow.Phase{
|
||||
Name: "sa",
|
||||
Short: "Generates a private key for signing service account tokens along with its public key",
|
||||
Long: saKeyLongDesc,
|
||||
Run: runCertsSa,
|
||||
InheritFlags: []string{options.CertificatesDir},
|
||||
}
|
||||
|
||||
subPhases = append(subPhases, saPhase)
|
||||
|
||||
return subPhases
|
||||
}
|
||||
|
||||
func newCertSubPhase(certSpec *certsphase.KubeadmCert, run func(c workflow.RunData) error) workflow.Phase {
|
||||
phase := workflow.Phase{
|
||||
Name: certSpec.Name,
|
||||
Short: fmt.Sprintf("Generates the %s", certSpec.LongName),
|
||||
Long: fmt.Sprintf(
|
||||
genericLongDesc,
|
||||
certSpec.LongName,
|
||||
certSpec.BaseName,
|
||||
getSANDescription(certSpec),
|
||||
),
|
||||
Run: run,
|
||||
InheritFlags: getCertPhaseFlags(certSpec.Name),
|
||||
}
|
||||
return phase
|
||||
}
|
||||
|
||||
func getCertPhaseFlags(name string) []string {
|
||||
flags := []string{
|
||||
options.CertificatesDir,
|
||||
options.CfgPath,
|
||||
options.CSROnly,
|
||||
options.CSRDir,
|
||||
}
|
||||
if name == "all" || name == "apiserver" {
|
||||
flags = append(flags,
|
||||
options.APIServerAdvertiseAddress,
|
||||
options.APIServerCertSANs,
|
||||
options.NetworkingDNSDomain,
|
||||
options.NetworkingServiceSubnet,
|
||||
)
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
func getSANDescription(certSpec *certsphase.KubeadmCert) string {
|
||||
//Defaulted config we will use to get SAN certs
|
||||
defaultConfig := &kubeadmapiv1beta1.InitConfiguration{
|
||||
LocalAPIEndpoint: kubeadmapiv1beta1.APIEndpoint{
|
||||
// GetAPIServerAltNames errors without an AdvertiseAddress; this is as good as any.
|
||||
AdvertiseAddress: "127.0.0.1",
|
||||
},
|
||||
}
|
||||
defaultInternalConfig := &kubeadmapi.InitConfiguration{}
|
||||
|
||||
kubeadmscheme.Scheme.Default(defaultConfig)
|
||||
err := kubeadmscheme.Scheme.Convert(defaultConfig, defaultInternalConfig, nil)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
certConfig, err := certSpec.GetConfig(defaultInternalConfig)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
if len(certConfig.AltNames.DNSNames) == 0 && len(certConfig.AltNames.IPs) == 0 {
|
||||
return ""
|
||||
}
|
||||
// This mutates the certConfig, but we're throwing it after we construct the command anyway
|
||||
sans := []string{}
|
||||
|
||||
for _, dnsName := range certConfig.AltNames.DNSNames {
|
||||
if dnsName != "" {
|
||||
sans = append(sans, dnsName)
|
||||
}
|
||||
}
|
||||
|
||||
for _, ip := range certConfig.AltNames.IPs {
|
||||
sans = append(sans, ip.String())
|
||||
}
|
||||
return fmt.Sprintf("\n\nDefault SANs are %s", strings.Join(sans, ", "))
|
||||
}
|
||||
|
||||
func runCertsSa(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("certs phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
// if external CA mode, skip service account key generation
|
||||
if data.ExternalCA() {
|
||||
fmt.Printf("[certs] Using existing sa keys\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
// create the new service account key (or use existing)
|
||||
return certsphase.CreateServiceAccountKeyAndPublicKeyFiles(data.CertificateWriteDir())
|
||||
}
|
||||
|
||||
func runCerts(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("certs phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
fmt.Printf("[certs] Using certificateDir folder %q\n", data.CertificateWriteDir())
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCAPhase(ca *certsphase.KubeadmCert) func(c workflow.RunData) error {
|
||||
return func(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("certs phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
if _, err := pkiutil.TryLoadCertFromDisk(data.CertificateDir(), ca.BaseName); err == nil {
|
||||
if _, err := pkiutil.TryLoadKeyFromDisk(data.CertificateDir(), ca.BaseName); err == nil {
|
||||
fmt.Printf("[certs] Using existing %s certificate authority\n", ca.BaseName)
|
||||
return nil
|
||||
}
|
||||
fmt.Printf("[certs] Using existing %s keyless certificate authority\n", ca.BaseName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// if using external etcd, skips etcd certificate authority generation
|
||||
if data.Cfg().Etcd.External != nil && ca.Name == "etcd-ca" {
|
||||
fmt.Printf("[certs] External etcd mode: Skipping %s certificate authority generation\n", ca.BaseName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// if dryrunning, write certificates authority to a temporary folder (and defer restore to the path originally specified by the user)
|
||||
cfg := data.Cfg()
|
||||
cfg.CertificatesDir = data.CertificateWriteDir()
|
||||
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
|
||||
|
||||
// create the new certificate authority (or use existing)
|
||||
return certsphase.CreateCACertAndKeyFiles(ca, cfg)
|
||||
}
|
||||
}
|
||||
|
||||
func runCertPhase(cert *certsphase.KubeadmCert, caCert *certsphase.KubeadmCert) func(c workflow.RunData) error {
|
||||
return func(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("certs phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
if certData, _, err := pkiutil.TryLoadCertAndKeyFromDisk(data.CertificateDir(), cert.BaseName); err == nil {
|
||||
caCertData, err := pkiutil.TryLoadCertFromDisk(data.CertificateDir(), caCert.BaseName)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "couldn't load CA certificate %s", caCert.Name)
|
||||
}
|
||||
|
||||
if err := certData.CheckSignatureFrom(caCertData); err != nil {
|
||||
return errors.Wrapf(err, "[certs] certificate %s not signed by CA certificate %s", cert.BaseName, caCert.BaseName)
|
||||
}
|
||||
|
||||
fmt.Printf("[certs] Using existing %s certificate and key on disk\n", cert.BaseName)
|
||||
return nil
|
||||
}
|
||||
|
||||
if csrOnly {
|
||||
fmt.Printf("[certs] Generating CSR for %s instead of certificate\n", cert.BaseName)
|
||||
if csrDir == "" {
|
||||
csrDir = data.CertificateWriteDir()
|
||||
}
|
||||
|
||||
return certsphase.CreateCSR(cert, data.Cfg(), csrDir)
|
||||
}
|
||||
|
||||
// if using external etcd, skips etcd certificates generation
|
||||
if data.Cfg().Etcd.External != nil && cert.CAName == "etcd-ca" {
|
||||
fmt.Printf("[certs] External etcd mode: Skipping %s certificate authority generation\n", cert.BaseName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// if dryrunning, write certificates to a temporary folder (and defer restore to the path originally specified by the user)
|
||||
cfg := data.Cfg()
|
||||
cfg.CertificatesDir = data.CertificateWriteDir()
|
||||
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
|
||||
|
||||
// create the new certificate (or use existing)
|
||||
return certsphase.CreateCertAndKeyFilesWithCA(cert, caCert, cfg)
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package phases
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
certstestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
|
||||
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
|
||||
)
|
||||
|
||||
type testCertsData struct {
|
||||
testInitData
|
||||
cfg *kubeadmapi.InitConfiguration
|
||||
}
|
||||
|
||||
func (t *testCertsData) Cfg() *kubeadmapi.InitConfiguration { return t.cfg }
|
||||
func (t *testCertsData) ExternalCA() bool { return false }
|
||||
func (t *testCertsData) CertificateDir() string { return t.cfg.CertificatesDir }
|
||||
func (t *testCertsData) CertificateWriteDir() string { return t.cfg.CertificatesDir }
|
||||
|
||||
func TestCertsWithCSRs(t *testing.T) {
|
||||
csrDir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(csrDir)
|
||||
certDir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(certDir)
|
||||
cert := &certs.KubeadmCertAPIServer
|
||||
|
||||
certsData := &testCertsData{
|
||||
cfg: testutil.GetDefaultInternalConfig(t),
|
||||
}
|
||||
certsData.cfg.CertificatesDir = certDir
|
||||
|
||||
// global vars
|
||||
csrOnly = true
|
||||
csrDir = certDir
|
||||
defer func() {
|
||||
csrOnly = false
|
||||
}()
|
||||
|
||||
phase := NewCertsPhase()
|
||||
// find the api cert phase
|
||||
var apiServerPhase *workflow.Phase
|
||||
for _, phase := range phase.Phases {
|
||||
if phase.Name == cert.Name {
|
||||
apiServerPhase = &phase
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if apiServerPhase == nil {
|
||||
t.Fatalf("couldn't find apiserver phase")
|
||||
}
|
||||
|
||||
err := apiServerPhase.Run(certsData)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't run API server phase: %v", err)
|
||||
}
|
||||
|
||||
if _, _, err := pkiutil.TryLoadCSRAndKeyFromDisk(csrDir, cert.BaseName); err != nil {
|
||||
t.Fatalf("couldn't load certificate %q: %v", cert.BaseName, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateSparseCerts(t *testing.T) {
|
||||
for _, test := range certstestutil.GetSparseCertTestCases(t) {
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
certstestutil.WritePKIFiles(t, tmpdir, test.Files)
|
||||
|
||||
r := workflow.NewRunner()
|
||||
r.AppendPhase(NewCertsPhase())
|
||||
r.SetDataInitializer(func(*cobra.Command, []string) (workflow.RunData, error) {
|
||||
certsData := &testCertsData{
|
||||
cfg: testutil.GetDefaultInternalConfig(t),
|
||||
}
|
||||
certsData.cfg.CertificatesDir = tmpdir
|
||||
return certsData, nil
|
||||
})
|
||||
|
||||
if err := r.Run([]string{}); (err != nil) != test.ExpectError {
|
||||
t.Fatalf("expected error to be %t, got %t (%v)", test.ExpectError, (err != nil), err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package phases
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
controlPlaneExample = normalizer.Examples(`
|
||||
# Generates all static Pod manifest files for control plane components,
|
||||
# functionally equivalent to what is generated by kubeadm init.
|
||||
kubeadm init phase control-plane all
|
||||
|
||||
# Generates all static Pod manifest files using options read from a configuration file.
|
||||
kubeadm init phase control-plane all --config config.yaml
|
||||
`)
|
||||
|
||||
controlPlanePhaseProperties = map[string]struct {
|
||||
name string
|
||||
short string
|
||||
}{
|
||||
kubeadmconstants.KubeAPIServer: {
|
||||
name: "apiserver",
|
||||
short: getPhaseDescription(kubeadmconstants.KubeAPIServer),
|
||||
},
|
||||
kubeadmconstants.KubeControllerManager: {
|
||||
name: "controller-manager",
|
||||
short: getPhaseDescription(kubeadmconstants.KubeControllerManager),
|
||||
},
|
||||
kubeadmconstants.KubeScheduler: {
|
||||
name: "scheduler",
|
||||
short: getPhaseDescription(kubeadmconstants.KubeScheduler),
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func getPhaseDescription(component string) string {
|
||||
return fmt.Sprintf("Generates the %s static Pod manifest", component)
|
||||
}
|
||||
|
||||
// NewControlPlanePhase creates a kubeadm workflow phase that implements bootstrapping the control plane.
|
||||
func NewControlPlanePhase() workflow.Phase {
|
||||
phase := workflow.Phase{
|
||||
Name: "control-plane",
|
||||
Short: "Generates all static Pod manifest files necessary to establish the control plane",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
Phases: []workflow.Phase{
|
||||
{
|
||||
Name: "all",
|
||||
Short: "Generates all static Pod manifest files",
|
||||
InheritFlags: getControlPlanePhaseFlags("all"),
|
||||
Example: controlPlaneExample,
|
||||
RunAllSiblings: true,
|
||||
},
|
||||
newControlPlaneSubphase(kubeadmconstants.KubeAPIServer),
|
||||
newControlPlaneSubphase(kubeadmconstants.KubeControllerManager),
|
||||
newControlPlaneSubphase(kubeadmconstants.KubeScheduler),
|
||||
},
|
||||
Run: runControlPlanePhase,
|
||||
}
|
||||
return phase
|
||||
}
|
||||
|
||||
func newControlPlaneSubphase(component string) workflow.Phase {
|
||||
phase := workflow.Phase{
|
||||
Name: controlPlanePhaseProperties[component].name,
|
||||
Short: controlPlanePhaseProperties[component].short,
|
||||
Run: runControlPlaneSubphase(component),
|
||||
InheritFlags: getControlPlanePhaseFlags(component),
|
||||
}
|
||||
return phase
|
||||
}
|
||||
|
||||
func getControlPlanePhaseFlags(name string) []string {
|
||||
flags := []string{
|
||||
options.CfgPath,
|
||||
options.CertificatesDir,
|
||||
options.KubernetesVersion,
|
||||
options.ImageRepository,
|
||||
}
|
||||
if name == "all" || name == kubeadmconstants.KubeAPIServer {
|
||||
flags = append(flags,
|
||||
options.APIServerAdvertiseAddress,
|
||||
options.APIServerBindPort,
|
||||
options.APIServerExtraArgs,
|
||||
options.FeatureGatesString,
|
||||
options.NetworkingServiceSubnet,
|
||||
)
|
||||
}
|
||||
if name == "all" || name == kubeadmconstants.KubeControllerManager {
|
||||
flags = append(flags,
|
||||
options.ControllerManagerExtraArgs,
|
||||
options.NetworkingPodSubnet,
|
||||
)
|
||||
}
|
||||
if name == "all" || name == kubeadmconstants.KubeScheduler {
|
||||
flags = append(flags,
|
||||
options.SchedulerExtraArgs,
|
||||
)
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
func runControlPlanePhase(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("control-plane phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
fmt.Printf("[control-plane] Using manifest folder %q\n", data.ManifestDir())
|
||||
return nil
|
||||
}
|
||||
|
||||
func runControlPlaneSubphase(component string) func(c workflow.RunData) error {
|
||||
return func(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("control-plane phase invoked with an invalid data struct")
|
||||
}
|
||||
cfg := data.Cfg()
|
||||
|
||||
fmt.Printf("[control-plane] Creating static Pod manifest for %q\n", component)
|
||||
return controlplane.CreateStaticPodFiles(data.ManifestDir(), &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, component)
|
||||
}
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package phases
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
etcdLocalExample = normalizer.Examples(`
|
||||
# Generates the static Pod manifest file for etcd, functionally
|
||||
# equivalent to what is generated by kubeadm init.
|
||||
kubeadm init phase etcd local
|
||||
|
||||
# Generates the static Pod manifest file for etcd using options
|
||||
# read from a configuration file.
|
||||
kubeadm init phase etcd local --config config.yaml
|
||||
`)
|
||||
)
|
||||
|
||||
// NewEtcdPhase creates a kubeadm workflow phase that implements handling of etcd.
|
||||
func NewEtcdPhase() workflow.Phase {
|
||||
phase := workflow.Phase{
|
||||
Name: "etcd",
|
||||
Short: "Generates static Pod manifest file for local etcd.",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
Phases: []workflow.Phase{
|
||||
newEtcdLocalSubPhase(),
|
||||
},
|
||||
}
|
||||
return phase
|
||||
}
|
||||
|
||||
func newEtcdLocalSubPhase() workflow.Phase {
|
||||
phase := workflow.Phase{
|
||||
Name: "local",
|
||||
Short: "Generates the static Pod manifest file for a local, single-node local etcd instance.",
|
||||
Example: etcdLocalExample,
|
||||
Run: runEtcdPhaseLocal(),
|
||||
InheritFlags: getEtcdPhaseFlags(),
|
||||
}
|
||||
return phase
|
||||
}
|
||||
|
||||
func getEtcdPhaseFlags() []string {
|
||||
flags := []string{
|
||||
options.CertificatesDir,
|
||||
options.CfgPath,
|
||||
options.ImageRepository,
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
func runEtcdPhaseLocal() func(c workflow.RunData) error {
|
||||
return func(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("etcd phase invoked with an invalid data struct")
|
||||
}
|
||||
cfg := data.Cfg()
|
||||
|
||||
// Add etcd static pod spec only if external etcd is not configured
|
||||
if cfg.Etcd.External == nil {
|
||||
// creates target folder if doesn't exist already
|
||||
if !data.DryRun() {
|
||||
if err := os.MkdirAll(cfg.Etcd.Local.DataDir, 0700); err != nil {
|
||||
return errors.Wrapf(err, "failed to create etcd directory %q", cfg.Etcd.Local.DataDir)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("[dryrun] Would ensure that %q directory is present\n", cfg.Etcd.Local.DataDir)
|
||||
}
|
||||
fmt.Printf("[etcd] Creating static Pod manifest for local etcd in %q\n", data.ManifestDir())
|
||||
if err := etcdphase.CreateLocalEtcdStaticPodManifestFile(data.ManifestDir(), cfg.NodeRegistration.Name, &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint); err != nil {
|
||||
return errors.Wrap(err, "error creating local etcd static pod manifest file")
|
||||
}
|
||||
} else {
|
||||
klog.V(1).Infoln("[etcd] External etcd mode. Skipping the creation of a manifest for local etcd")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package phases
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
kubeconfigFilePhaseProperties = map[string]struct {
|
||||
name string
|
||||
short string
|
||||
long string
|
||||
}{
|
||||
kubeadmconstants.AdminKubeConfigFileName: {
|
||||
name: "admin",
|
||||
short: "Generates a kubeconfig file for the admin to use and for kubeadm itself",
|
||||
long: "Generates the kubeconfig file for the admin and for kubeadm itself, and saves it to %s file.",
|
||||
},
|
||||
kubeadmconstants.KubeletKubeConfigFileName: {
|
||||
name: "kubelet",
|
||||
short: "Generates a kubeconfig file for the kubelet to use *only* for cluster bootstrapping purposes",
|
||||
long: normalizer.LongDesc(`
|
||||
Generates the kubeconfig file for the kubelet to use and saves it to %s file.
|
||||
|
||||
Please note that this should *only* be used for cluster bootstrapping purposes. After your control plane is up,
|
||||
you should request all kubelet credentials from the CSR API.`),
|
||||
},
|
||||
kubeadmconstants.ControllerManagerKubeConfigFileName: {
|
||||
name: "controller-manager",
|
||||
short: "Generates a kubeconfig file for the controller manager to use",
|
||||
long: "Generates the kubeconfig file for the controller manager to use and saves it to %s file",
|
||||
},
|
||||
kubeadmconstants.SchedulerKubeConfigFileName: {
|
||||
name: "scheduler",
|
||||
short: "Generates a kubeconfig file for the scheduler to use",
|
||||
long: "Generates the kubeconfig file for the scheduler to use and saves it to %s file.",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// NewKubeConfigPhase creates a kubeadm workflow phase that creates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file.
|
||||
func NewKubeConfigPhase() workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: "kubeconfig",
|
||||
Short: "Generates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
Phases: []workflow.Phase{
|
||||
{
|
||||
Name: "all",
|
||||
Short: "Generates all kubeconfig files",
|
||||
InheritFlags: getKubeConfigPhaseFlags("all"),
|
||||
RunAllSiblings: true,
|
||||
},
|
||||
NewKubeConfigFilePhase(kubeadmconstants.AdminKubeConfigFileName),
|
||||
NewKubeConfigFilePhase(kubeadmconstants.KubeletKubeConfigFileName),
|
||||
NewKubeConfigFilePhase(kubeadmconstants.ControllerManagerKubeConfigFileName),
|
||||
NewKubeConfigFilePhase(kubeadmconstants.SchedulerKubeConfigFileName),
|
||||
},
|
||||
Run: runKubeConfig,
|
||||
}
|
||||
}
|
||||
|
||||
// NewKubeConfigFilePhase creates a kubeadm workflow phase that creates a kubeconfig file.
|
||||
func NewKubeConfigFilePhase(kubeConfigFileName string) workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: kubeconfigFilePhaseProperties[kubeConfigFileName].name,
|
||||
Short: kubeconfigFilePhaseProperties[kubeConfigFileName].short,
|
||||
Long: fmt.Sprintf(kubeconfigFilePhaseProperties[kubeConfigFileName].long, kubeConfigFileName),
|
||||
Run: runKubeConfigFile(kubeConfigFileName),
|
||||
InheritFlags: getKubeConfigPhaseFlags(kubeConfigFileName),
|
||||
}
|
||||
}
|
||||
|
||||
func getKubeConfigPhaseFlags(name string) []string {
|
||||
flags := []string{
|
||||
options.APIServerAdvertiseAddress,
|
||||
options.APIServerBindPort,
|
||||
options.CertificatesDir,
|
||||
options.CfgPath,
|
||||
options.KubeconfigDir,
|
||||
}
|
||||
if name == "all" || name == kubeadmconstants.KubeletKubeConfigFileName {
|
||||
flags = append(flags,
|
||||
options.NodeName,
|
||||
)
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
func runKubeConfig(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("kubeconfig phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
fmt.Printf("[kubeconfig] Using kubeconfig folder %q\n", data.KubeConfigDir())
|
||||
return nil
|
||||
}
|
||||
|
||||
// runKubeConfigFile executes kubeconfig creation logic.
|
||||
func runKubeConfigFile(kubeConfigFileName string) func(workflow.RunData) error {
|
||||
return func(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("kubeconfig phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
// if external CA mode, skip certificate authority generation
|
||||
if data.ExternalCA() {
|
||||
fmt.Printf("[kubeconfig] External CA mode: Using user provided %s\n", kubeConfigFileName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// if dryrunning, reads certificates from a temporary folder (and defer restore to the path originally specified by the user)
|
||||
cfg := data.Cfg()
|
||||
cfg.CertificatesDir = data.CertificateWriteDir()
|
||||
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
|
||||
|
||||
// creates the KubeConfig file (or use existing)
|
||||
return kubeconfigphase.CreateKubeConfigFile(kubeConfigFileName, data.KubeConfigDir(), data.Cfg())
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
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 phases
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
kubeletStartPhaseExample = normalizer.Examples(`
|
||||
# Writes a dynamic environment file with kubelet flags from a InitConfiguration file.
|
||||
kubeadm init phase kubelet-start --config config.yaml
|
||||
`)
|
||||
)
|
||||
|
||||
// NewKubeletStartPhase creates a kubeadm workflow phase that start kubelet on a node.
|
||||
func NewKubeletStartPhase() workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: "kubelet-start",
|
||||
Short: "Writes kubelet settings and (re)starts the kubelet",
|
||||
Long: "Writes a file with KubeletConfiguration and an environment file with node specific kubelet settings, and then (re)starts kubelet.",
|
||||
Example: kubeletStartPhaseExample,
|
||||
Run: runKubeletStart,
|
||||
InheritFlags: []string{
|
||||
options.CfgPath,
|
||||
options.NodeCRISocket,
|
||||
options.NodeName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// runKubeletStart executes kubelet start logic.
|
||||
func runKubeletStart(c workflow.RunData) error {
|
||||
data, ok := c.(InitData)
|
||||
if !ok {
|
||||
return errors.New("kubelet-start phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
// First off, configure the kubelet. In this short timeframe, kubeadm is trying to stop/restart the kubelet
|
||||
// Try to stop the kubelet service so no race conditions occur when configuring it
|
||||
if !data.DryRun() {
|
||||
klog.V(1).Infoln("Stopping the kubelet")
|
||||
kubeletphase.TryStopKubelet()
|
||||
}
|
||||
|
||||
// Write env file with flags for the kubelet to use. We do not need to write the --register-with-taints for the control-plane,
|
||||
// as we handle that ourselves in the mark-control-plane phase
|
||||
// TODO: Maybe we want to do that some time in the future, in order to remove some logic from the mark-control-plane phase?
|
||||
if err := kubeletphase.WriteKubeletDynamicEnvFile(&data.Cfg().ClusterConfiguration, &data.Cfg().NodeRegistration, false, data.KubeletDir()); err != nil {
|
||||
return errors.Wrap(err, "error writing a dynamic environment file for the kubelet")
|
||||
}
|
||||
|
||||
// Write the kubelet configuration file to disk.
|
||||
if err := kubeletphase.WriteConfigToDisk(data.Cfg().ComponentConfigs.Kubelet, data.KubeletDir()); err != nil {
|
||||
return errors.Wrap(err, "error writing kubelet configuration to disk")
|
||||
}
|
||||
|
||||
// Try to start the kubelet service in case it's inactive
|
||||
if !data.DryRun() {
|
||||
klog.V(1).Infoln("Starting the kubelet")
|
||||
kubeletphase.TryStartKubelet()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue