mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 11:21:47 +00:00
Merge pull request #52251 from sbezverk/kubeadm_lint_cleanup
Automatic merge from submit-queue (batch tested with PRs 52251, 52540). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.. kubeadm golint clean up Cleaning up golint discovered issue for kubeadm Fixes: https://github.com/kubernetes/kubeadm/issues/375
This commit is contained in:
commit
7fa13044bb
@ -14,6 +14,10 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package kubeadm is the package that contains the libraries that drive the kubeadm binary.
|
||||
// kubeadm is responsible for handling a Kubernetes cluster's lifecycle.
|
||||
|
||||
// +k8s:deepcopy-gen=package,register
|
||||
// +groupName=kubeadm.k8s.io
|
||||
|
||||
package kubeadm // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
|
@ -28,8 +28,10 @@ const GroupName = "kubeadm.k8s.io"
|
||||
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 = SchemeBuilder.AddToScheme
|
||||
// AddToScheme applies all the stored functions to the scheme.
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Kind takes an unqualified kind and returns a Group qualified GroupKind
|
||||
|
@ -22,6 +22,8 @@ import (
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MasterConfiguration contains a list of elements which make up master's
|
||||
// configuration object.
|
||||
type MasterConfiguration struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
@ -59,6 +61,7 @@ type MasterConfiguration struct {
|
||||
FeatureGates map[string]bool
|
||||
}
|
||||
|
||||
// API struct contains elements of API server address.
|
||||
type API struct {
|
||||
// AdvertiseAddress sets the address for the API server to advertise.
|
||||
AdvertiseAddress string
|
||||
@ -66,18 +69,21 @@ type API struct {
|
||||
BindPort int32
|
||||
}
|
||||
|
||||
// TokenDiscovery contains elements needed for token discovery
|
||||
type TokenDiscovery struct {
|
||||
ID string
|
||||
Secret string
|
||||
Addresses []string
|
||||
}
|
||||
|
||||
// Networking contains elements describing cluster's networking configuration
|
||||
type Networking struct {
|
||||
ServiceSubnet string
|
||||
PodSubnet string
|
||||
DNSDomain string
|
||||
}
|
||||
|
||||
// Etcd contains elements describing Etcd configuration
|
||||
type Etcd struct {
|
||||
Endpoints []string
|
||||
CAFile string
|
||||
@ -91,6 +97,7 @@ type Etcd struct {
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// NodeConfiguration contains elements describing a particular node
|
||||
type NodeConfiguration struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
|
@ -26,21 +26,31 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultServiceDNSDomain = "cluster.local"
|
||||
DefaultServicesSubnet = "10.96.0.0/12"
|
||||
DefaultKubernetesVersion = "stable-1.8"
|
||||
DefaultAPIBindPort = 6443
|
||||
// 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"
|
||||
// DefaultKubernetesVersion defines default kubernetes version
|
||||
DefaultKubernetesVersion = "stable-1.8"
|
||||
// DefaultAPIBindPort defines default API port
|
||||
DefaultAPIBindPort = 6443
|
||||
// DefaultAuthorizationModes defines default authorization modes
|
||||
DefaultAuthorizationModes = "Node,RBAC"
|
||||
DefaultCACertPath = "/etc/kubernetes/pki/ca.crt"
|
||||
DefaultCertificatesDir = "/etc/kubernetes/pki"
|
||||
DefaultEtcdDataDir = "/var/lib/etcd"
|
||||
DefaultImageRepository = "gcr.io/google_containers"
|
||||
// DefaultCACertPath defines default location of CA certificate
|
||||
DefaultCACertPath = "/etc/kubernetes/pki/ca.crt"
|
||||
// DefaultCertificatesDir defines default certificate directory
|
||||
DefaultCertificatesDir = "/etc/kubernetes/pki"
|
||||
// DefaultEtcdDataDir defines default location of etcd
|
||||
DefaultEtcdDataDir = "/var/lib/etcd"
|
||||
// DefaultImageRepository defines default image registry
|
||||
DefaultImageRepository = "gcr.io/google_containers"
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
return RegisterDefaults(scheme)
|
||||
}
|
||||
|
||||
// SetDefaults_MasterConfiguration assigns default values to Master node
|
||||
func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
|
||||
if obj.KubernetesVersion == "" {
|
||||
obj.KubernetesVersion = DefaultKubernetesVersion
|
||||
@ -81,6 +91,7 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_NodeConfiguration assigns default values to a regular node
|
||||
func SetDefaults_NodeConfiguration(obj *NodeConfiguration) {
|
||||
if obj.CACertPath == "" {
|
||||
obj.CACertPath = DefaultCACertPath
|
||||
|
@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package v1alpha1 is the package that contains the libraries that drive the kubeadm binary.
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=kubeadm.k8s.io
|
||||
// +k8s:deepcopy-gen=package
|
||||
|
@ -31,9 +31,12 @@ var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha
|
||||
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 = localSchemeBuilder.AddToScheme
|
||||
// AddToScheme applies all the stored functions to the scheme.
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -22,6 +22,8 @@ import (
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MasterConfiguration contains a list of elements which make up master's
|
||||
// configuration object.
|
||||
type MasterConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
@ -54,6 +56,7 @@ type MasterConfiguration struct {
|
||||
FeatureGates map[string]bool `json:"featureGates,omitempty"`
|
||||
}
|
||||
|
||||
// API struct contains elements of API server address.
|
||||
type API struct {
|
||||
// AdvertiseAddress sets the address for the API server to advertise.
|
||||
AdvertiseAddress string `json:"advertiseAddress"`
|
||||
@ -61,18 +64,21 @@ type API struct {
|
||||
BindPort int32 `json:"bindPort"`
|
||||
}
|
||||
|
||||
// TokenDiscovery contains elements needed for token discovery
|
||||
type TokenDiscovery struct {
|
||||
ID string `json:"id"`
|
||||
Secret string `json:"secret"`
|
||||
Addresses []string `json:"addresses"`
|
||||
}
|
||||
|
||||
// Networking contains elements describing cluster's networking configuration
|
||||
type Networking struct {
|
||||
ServiceSubnet string `json:"serviceSubnet"`
|
||||
PodSubnet string `json:"podSubnet"`
|
||||
DNSDomain string `json:"dnsDomain"`
|
||||
}
|
||||
|
||||
// Etcd contains elements describing Etcd configuration
|
||||
type Etcd struct {
|
||||
Endpoints []string `json:"endpoints"`
|
||||
CAFile string `json:"caFile"`
|
||||
@ -86,6 +92,7 @@ type Etcd struct {
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// NodeConfiguration contains elements describing a particular node
|
||||
type NodeConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
|
@ -58,6 +58,7 @@ var requiredAuthzModes = []string{
|
||||
authzmodes.ModeNode,
|
||||
}
|
||||
|
||||
// ValidateMasterConfiguration validates master configuration and collects all encountered errors
|
||||
func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateCloudProvider(c.CloudProvider, field.NewPath("cloudprovider"))...)
|
||||
@ -72,6 +73,7 @@ func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateNodeConfiguration validates node configuration and collects all encountered errors
|
||||
func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateDiscovery(c, field.NewPath("discovery"))...)
|
||||
@ -82,10 +84,10 @@ func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateAuthorizationModes validates authorization modes and collects all encountered errors
|
||||
func ValidateAuthorizationModes(authzModes []string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
found := map[string]bool{}
|
||||
|
||||
for _, authzMode := range authzModes {
|
||||
if !authzmodes.IsValidAuthorizationMode(authzMode) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, authzMode, "invalid authorization mode"))
|
||||
@ -105,6 +107,7 @@ func ValidateAuthorizationModes(authzModes []string, fldPath *field.Path) field.
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateDiscovery validates discovery related configuration and collects all encountered errors
|
||||
func ValidateDiscovery(c *kubeadm.NodeConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(c.DiscoveryToken) != 0 {
|
||||
@ -123,10 +126,10 @@ func ValidateDiscovery(c *kubeadm.NodeConfiguration, fldPath *field.Path) field.
|
||||
if len(c.DiscoveryFile) != 0 {
|
||||
allErrs = append(allErrs, ValidateDiscoveryFile(c.DiscoveryFile, fldPath)...)
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateArgSelection validates discovery related configuration and collects all encountered errors
|
||||
func ValidateArgSelection(cfg *kubeadm.NodeConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(cfg.DiscoveryToken) != 0 && len(cfg.DiscoveryFile) != 0 {
|
||||
@ -156,6 +159,7 @@ func ValidateArgSelection(cfg *kubeadm.NodeConfiguration, fldPath *field.Path) f
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateJoinDiscoveryTokenAPIServer validates discovery token for API server
|
||||
func ValidateJoinDiscoveryTokenAPIServer(c *kubeadm.NodeConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
for _, m := range c.DiscoveryTokenAPIServers {
|
||||
@ -167,6 +171,7 @@ func ValidateJoinDiscoveryTokenAPIServer(c *kubeadm.NodeConfiguration, fldPath *
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateDiscoveryFile validates location of a discovery file
|
||||
func ValidateDiscoveryFile(discoveryFile string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
u, err := url.Parse(discoveryFile)
|
||||
@ -189,6 +194,7 @@ func ValidateDiscoveryFile(discoveryFile string, fldPath *field.Path) field.Erro
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateToken validates token
|
||||
func ValidateToken(t string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
@ -203,6 +209,7 @@ func ValidateToken(t string, fldPath *field.Path) field.ErrorList {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateAPIServerCertSANs validates alternative names
|
||||
func ValidateAPIServerCertSANs(altnames []string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
for _, altname := range altnames {
|
||||
@ -213,6 +220,7 @@ func ValidateAPIServerCertSANs(altnames []string, fldPath *field.Path) field.Err
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIPFromString validates ip address
|
||||
func ValidateIPFromString(ipaddr string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if net.ParseIP(ipaddr) == nil {
|
||||
@ -221,6 +229,7 @@ func ValidateIPFromString(ipaddr string, fldPath *field.Path) field.ErrorList {
|
||||
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)
|
||||
@ -235,6 +244,7 @@ func ValidateIPNetFromString(subnet string, minAddrs int64, fldPath *field.Path)
|
||||
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("dns-domain"))...)
|
||||
@ -245,6 +255,7 @@ func ValidateNetworking(c *kubeadm.Networking, fldPath *field.Path) field.ErrorL
|
||||
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) {
|
||||
@ -253,6 +264,7 @@ func ValidateAbsolutePath(path string, fldPath *field.Path) field.ErrorList {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateNodeName validates the name of a node
|
||||
func ValidateNodeName(nodename string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if node.GetHostname(nodename) != nodename {
|
||||
@ -261,6 +273,7 @@ func ValidateNodeName(nodename string, fldPath *field.Path) field.ErrorList {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCloudProvider validates if cloud provider is supported
|
||||
func ValidateCloudProvider(provider string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(provider) == 0 {
|
||||
@ -275,6 +288,7 @@ func ValidateCloudProvider(provider string, fldPath *field.Path) field.ErrorList
|
||||
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") {
|
||||
@ -296,6 +310,7 @@ func ValidateMixedArguments(flag *pflag.FlagSet) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateFeatureGates validates provided feature gates
|
||||
func ValidateFeatureGates(featureGates map[string]bool, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
validFeatures := features.Keys(features.InitFeatureGates)
|
||||
@ -311,6 +326,7 @@ func ValidateFeatureGates(featureGates map[string]bool, fldPath *field.Path) fie
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateAPIEndpoint validates API server's endpoint
|
||||
func ValidateAPIEndpoint(c *kubeadm.MasterConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
|
@ -410,7 +410,6 @@ func TestValidateMixedArguments(t *testing.T) {
|
||||
}
|
||||
|
||||
var cfgPath string
|
||||
|
||||
for _, rt := range tests {
|
||||
f := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
if f.Parsed() {
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade"
|
||||
)
|
||||
|
||||
// NewKubeadmCommand return cobra.Command to run kubeadm command
|
||||
func NewKubeadmCommand(_ io.Reader, out, err io.Writer) *cobra.Command {
|
||||
cmds := &cobra.Command{
|
||||
Use: "kubeadm",
|
||||
|
@ -45,7 +45,7 @@ const defaultBoilerPlate = `
|
||||
`
|
||||
|
||||
var (
|
||||
completion_long = dedent.Dedent(`
|
||||
completionLong = dedent.Dedent(`
|
||||
Output shell completion code for the specified shell (bash or zsh).
|
||||
The shell code must be evalutated to provide interactive
|
||||
completion of kubeadm commands. This can be done by sourcing it from
|
||||
@ -63,7 +63,7 @@ var (
|
||||
|
||||
Note for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2`)
|
||||
|
||||
completion_example = dedent.Dedent(`
|
||||
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
|
||||
@ -82,23 +82,24 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
completion_shells = map[string]func(out io.Writer, cmd *cobra.Command) error{
|
||||
completionShells = map[string]func(out io.Writer, cmd *cobra.Command) error{
|
||||
"bash": runCompletionBash,
|
||||
"zsh": runCompletionZsh,
|
||||
}
|
||||
)
|
||||
|
||||
// NewCmdCompletion return command for executing "kubeadm completion" command
|
||||
func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command {
|
||||
shells := []string{}
|
||||
for s := range completion_shells {
|
||||
for s := range completionShells {
|
||||
shells = append(shells, s)
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "completion SHELL",
|
||||
Short: i18n.T("Output shell completion code for the specified shell (bash or zsh)"),
|
||||
Long: completion_long,
|
||||
Example: completion_example,
|
||||
Long: completionLong,
|
||||
Example: completionExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunCompletion(out, boilerPlate, cmd, args)
|
||||
kubeadmutil.CheckErr(err)
|
||||
@ -109,16 +110,17 @@ func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command {
|
||||
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 fmt.Errorf("shell not specified.")
|
||||
return fmt.Errorf("shell not specified")
|
||||
}
|
||||
if len(args) > 1 {
|
||||
return fmt.Errorf("too many arguments. expected only the shell type.")
|
||||
return fmt.Errorf("too many arguments. expected only the shell type")
|
||||
}
|
||||
run, found := completion_shells[args[0]]
|
||||
run, found := completionShells[args[0]]
|
||||
if !found {
|
||||
return fmt.Errorf("unsupported shell type %q.", args[0])
|
||||
return fmt.Errorf("unsupported shell type %q", args[0])
|
||||
}
|
||||
|
||||
if len(boilerPlate) == 0 {
|
||||
@ -135,7 +137,7 @@ func runCompletionBash(out io.Writer, kubeadm *cobra.Command) error {
|
||||
}
|
||||
|
||||
func runCompletionZsh(out io.Writer, kubeadm *cobra.Command) error {
|
||||
zsh_initialization := `
|
||||
zshInitialization := `
|
||||
__kubeadm_bash_source() {
|
||||
alias shopt=':'
|
||||
alias _expand=_bash_expand
|
||||
@ -276,18 +278,18 @@ __kubeadm_convert_bash_to_zsh() {
|
||||
-e "s/\\\$(type${RWORD}/\$(__kubeadm_type/g" \
|
||||
<<'BASH_COMPLETION_EOF'
|
||||
`
|
||||
out.Write([]byte(zsh_initialization))
|
||||
out.Write([]byte(zshInitialization))
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
kubeadm.GenBashCompletion(buf)
|
||||
out.Write(buf.Bytes())
|
||||
|
||||
zsh_tail := `
|
||||
zshTail := `
|
||||
BASH_COMPLETION_EOF
|
||||
}
|
||||
|
||||
__kubeadm_bash_source <(__kubeadm_convert_bash_to_zsh)
|
||||
`
|
||||
out.Write([]byte(zsh_tail))
|
||||
out.Write([]byte(zshTail))
|
||||
return nil
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// NewCmdConfig returns cobra.Command for "kubeadm config" command
|
||||
func NewCmdConfig(out io.Writer) *cobra.Command {
|
||||
|
||||
var kubeConfigFile string
|
||||
@ -64,6 +65,7 @@ func NewCmdConfig(out io.Writer) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigUpload returs cobra.Command for "kubeadm config upload" command
|
||||
func NewCmdConfigUpload(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "upload",
|
||||
@ -76,6 +78,7 @@ func NewCmdConfigUpload(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigView returs cobra.Command for "kubeadm config view" command
|
||||
func NewCmdConfigView(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "view",
|
||||
@ -95,6 +98,8 @@ func NewCmdConfigView(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmdConfigUploadFromFile verifies given kubernetes config file and returs cobra.Command for
|
||||
// "kubeadm config upload from-file" command
|
||||
func NewCmdConfigUploadFromFile(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
var cfgPath string
|
||||
cmd := &cobra.Command{
|
||||
@ -126,6 +131,7 @@ func NewCmdConfigUploadFromFile(out io.Writer, kubeConfigFile *string) *cobra.Co
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigUploadFromFlags returs cobra.Command for "kubeadm config upload from-flags" command
|
||||
func NewCmdConfigUploadFromFlags(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
cfg := &kubeadmapiext.MasterConfiguration{}
|
||||
api.Scheme.Default(cfg)
|
||||
|
@ -211,6 +211,7 @@ func AddInitOtherFlags(flagSet *flag.FlagSet, cfgPath *string, skipPreFlight, sk
|
||||
)
|
||||
}
|
||||
|
||||
// NewInit validates given arguments and instantiates Init struct with provided information.
|
||||
func NewInit(cfgPath string, cfg *kubeadmapi.MasterConfiguration, skipPreFlight, skipTokenPrint, dryRun bool) (*Init, error) {
|
||||
|
||||
fmt.Println("[kubeadm] WARNING: kubeadm is in beta, please do not use it for production clusters.")
|
||||
@ -256,6 +257,7 @@ func NewInit(cfgPath string, cfg *kubeadmapi.MasterConfiguration, skipPreFlight,
|
||||
return &Init{cfg: cfg, skipTokenPrint: skipTokenPrint, dryRun: dryRun}, nil
|
||||
}
|
||||
|
||||
// Init defines struct used by "kubeadm init" command
|
||||
type Init struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
skipTokenPrint bool
|
||||
|
@ -154,10 +154,12 @@ func NewCmdJoin(out io.Writer) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Join defines struct used by kubeadm join command
|
||||
type Join struct {
|
||||
cfg *kubeadmapi.NodeConfiguration
|
||||
}
|
||||
|
||||
// NewJoin instantiates Join struct with given arguments
|
||||
func NewJoin(cfgPath string, args []string, cfg *kubeadmapi.NodeConfiguration, skipPreFlight bool) (*Join, error) {
|
||||
fmt.Println("[kubeadm] WARNING: kubeadm is in beta, please do not use it for production clusters.")
|
||||
|
||||
@ -192,6 +194,7 @@ func NewJoin(cfgPath string, args []string, cfg *kubeadmapi.NodeConfiguration, s
|
||||
return &Join{cfg: cfg}, nil
|
||||
}
|
||||
|
||||
// Validate validates mixed arguments passed to cobra.Command
|
||||
func (j *Join) Validate(cmd *cobra.Command) error {
|
||||
if err := validation.ValidateMixedArguments(cmd.PersistentFlags()); err != nil {
|
||||
return err
|
||||
@ -206,7 +209,7 @@ func (j *Join) Run(out io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := kubeconfigutil.KubeConfigToClientSet(cfg)
|
||||
client, err := kubeconfigutil.ToClientSet(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ func NewSubCmdNodeBootstrapTokenPostCSRs(kubeConfigFile *string) *cobra.Command
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewSubCmdNodeBootstrapToken returns the Cobra command for running the allow-auto-approve sub-phase
|
||||
// NewSubCmdNodeBootstrapTokenAutoApprove returns the Cobra command for running the allow-auto-approve sub-phase
|
||||
func NewSubCmdNodeBootstrapTokenAutoApprove(kubeConfigFile *string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "allow-auto-approve",
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
)
|
||||
|
||||
// NewCmdPreFlight calls cobra.Command for preflight checks
|
||||
func NewCmdPreFlight() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "preflight",
|
||||
@ -36,6 +37,7 @@ func NewCmdPreFlight() *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdPreFlightMaster calls cobra.Command for master preflight checks
|
||||
func NewCmdPreFlightMaster() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "master",
|
||||
@ -49,6 +51,7 @@ func NewCmdPreFlightMaster() *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdPreFlightNode calls cobra.Command for node preflight checks
|
||||
func NewCmdPreFlightNode() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "node",
|
||||
|
@ -59,10 +59,12 @@ func NewCmdReset(out io.Writer) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Reset defines struct used for kubeadm reset command
|
||||
type Reset struct {
|
||||
certsDir string
|
||||
}
|
||||
|
||||
// NewReset instantiate Reset struct
|
||||
func NewReset(skipPreFlight bool, certsDir string) (*Reset, error) {
|
||||
if !skipPreFlight {
|
||||
fmt.Println("[preflight] Running pre-flight checks")
|
||||
|
@ -46,6 +46,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
)
|
||||
|
||||
// NewCmdToken returns cobra.Command for token management
|
||||
func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command {
|
||||
|
||||
var kubeConfigFile string
|
||||
@ -168,6 +169,7 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command {
|
||||
return tokenCmd
|
||||
}
|
||||
|
||||
// NewCmdTokenGenerate returns cobra.Command to generate new token
|
||||
func NewCmdTokenGenerate(out io.Writer) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "generate",
|
||||
@ -260,14 +262,14 @@ func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface) er
|
||||
w := tabwriter.NewWriter(out, 10, 4, 3, ' ', 0)
|
||||
fmt.Fprintln(w, "TOKEN\tTTL\tEXPIRES\tUSAGES\tDESCRIPTION\tEXTRA GROUPS")
|
||||
for _, secret := range secrets.Items {
|
||||
tokenId := getSecretString(&secret, bootstrapapi.BootstrapTokenIDKey)
|
||||
if len(tokenId) == 0 {
|
||||
tokenID := getSecretString(&secret, bootstrapapi.BootstrapTokenIDKey)
|
||||
if len(tokenID) == 0 {
|
||||
fmt.Fprintf(errW, "bootstrap token has no token-id data: %s\n", secret.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
// enforce the right naming convention
|
||||
if secret.Name != fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenId) {
|
||||
if secret.Name != fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenID) {
|
||||
fmt.Fprintf(errW, "bootstrap token name is not of the form '%s(token-id)': %s\n", bootstrapapi.BootstrapTokenSecretPrefix, secret.Name)
|
||||
continue
|
||||
}
|
||||
@ -277,7 +279,7 @@ func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface) er
|
||||
fmt.Fprintf(errW, "bootstrap token has no token-secret data: %s\n", secret.Name)
|
||||
continue
|
||||
}
|
||||
td := &kubeadmapi.TokenDiscovery{ID: tokenId, Secret: tokenSecret}
|
||||
td := &kubeadmapi.TokenDiscovery{ID: tokenID, Secret: tokenSecret}
|
||||
|
||||
// Expiration time is optional, if not specified this implies the token
|
||||
// never expires.
|
||||
@ -328,20 +330,20 @@ func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface) er
|
||||
}
|
||||
|
||||
// RunDeleteToken removes a bootstrap token from the server.
|
||||
func RunDeleteToken(out io.Writer, client clientset.Interface, tokenIdOrToken string) error {
|
||||
func RunDeleteToken(out io.Writer, client clientset.Interface, tokenIDOrToken string) error {
|
||||
// Assume the given first argument is a token id and try to parse it
|
||||
tokenId := tokenIdOrToken
|
||||
if err := tokenutil.ParseTokenID(tokenIdOrToken); err != nil {
|
||||
if tokenId, _, err = tokenutil.ParseToken(tokenIdOrToken); err != nil {
|
||||
return fmt.Errorf("given token or token id %q didn't match pattern [%q] or [%q]", tokenIdOrToken, tokenutil.TokenIDRegexpString, tokenutil.TokenRegexpString)
|
||||
tokenID := tokenIDOrToken
|
||||
if err := tokenutil.ParseTokenID(tokenIDOrToken); err != nil {
|
||||
if tokenID, _, err = tokenutil.ParseToken(tokenIDOrToken); err != nil {
|
||||
return fmt.Errorf("given token or token id %q didn't match pattern [%q] or [%q]", tokenIDOrToken, tokenutil.TokenIDRegexpString, tokenutil.TokenRegexpString)
|
||||
}
|
||||
}
|
||||
|
||||
tokenSecretName := fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenId)
|
||||
tokenSecretName := fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenID)
|
||||
if err := client.CoreV1().Secrets(metav1.NamespaceSystem).Delete(tokenSecretName, nil); err != nil {
|
||||
return fmt.Errorf("failed to delete bootstrap token [%v]", err)
|
||||
}
|
||||
fmt.Fprintf(out, "bootstrap token with id %q deleted\n", tokenId)
|
||||
fmt.Fprintf(out, "bootstrap token with id %q deleted\n", tokenID)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ type Version struct {
|
||||
ClientVersion *apimachineryversion.Info `json:"clientVersion"`
|
||||
}
|
||||
|
||||
// NewCmdVersion provides the version information of kubeadm.
|
||||
func NewCmdVersion(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
@ -49,6 +50,8 @@ func NewCmdVersion(out io.Writer) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// RunVersion provides the version information of kubeadm in format depending on an arguments
|
||||
// specified in cobra.Command.
|
||||
func RunVersion(out io.Writer, cmd *cobra.Command) error {
|
||||
clientVersion := version.Get()
|
||||
v := Version{
|
||||
|
@ -32,48 +32,87 @@ import (
|
||||
var KubernetesDir = "/etc/kubernetes"
|
||||
|
||||
const (
|
||||
// ManifestsSubDirName defines directory name to store manifests
|
||||
ManifestsSubDirName = "manifests"
|
||||
TempDirForKubeadm = "/etc/kubernetes/tmp"
|
||||
// TempDirForKubeadm defines temporary directory for kubeadm
|
||||
TempDirForKubeadm = "/etc/kubernetes/tmp"
|
||||
|
||||
// CACertAndKeyBaseName defines certificate authority base name
|
||||
CACertAndKeyBaseName = "ca"
|
||||
CACertName = "ca.crt"
|
||||
CAKeyName = "ca.key"
|
||||
// CACertName defines certificate name
|
||||
CACertName = "ca.crt"
|
||||
// CAKeyName defines certificate name
|
||||
CAKeyName = "ca.key"
|
||||
|
||||
// APIServerCertAndKeyBaseName defines API's server certificate and key base name
|
||||
APIServerCertAndKeyBaseName = "apiserver"
|
||||
APIServerCertName = "apiserver.crt"
|
||||
APIServerKeyName = "apiserver.key"
|
||||
APIServerCertCommonName = "kube-apiserver" //used as subject.commonname attribute (CN)
|
||||
// APIServerCertName defines API's server certificate name
|
||||
APIServerCertName = "apiserver.crt"
|
||||
// APIServerKeyName defines API's server key name
|
||||
APIServerKeyName = "apiserver.key"
|
||||
// APIServerCertCommonName defines API's server certificate common name (CN)
|
||||
APIServerCertCommonName = "kube-apiserver"
|
||||
|
||||
// APIServerKubeletClientCertAndKeyBaseName defines kubelet client certificate and key base name
|
||||
APIServerKubeletClientCertAndKeyBaseName = "apiserver-kubelet-client"
|
||||
APIServerKubeletClientCertName = "apiserver-kubelet-client.crt"
|
||||
APIServerKubeletClientKeyName = "apiserver-kubelet-client.key"
|
||||
APIServerKubeletClientCertCommonName = "kube-apiserver-kubelet-client" //used as subject.commonname attribute (CN)
|
||||
// APIServerKubeletClientCertName defines kubelet client certificate name
|
||||
APIServerKubeletClientCertName = "apiserver-kubelet-client.crt"
|
||||
// APIServerKubeletClientKeyName defines kubelet client key name
|
||||
APIServerKubeletClientKeyName = "apiserver-kubelet-client.key"
|
||||
// APIServerKubeletClientCertCommonName defines kubelet client certificate common name (CN)
|
||||
APIServerKubeletClientCertCommonName = "kube-apiserver-kubelet-client"
|
||||
|
||||
ServiceAccountKeyBaseName = "sa"
|
||||
ServiceAccountPublicKeyName = "sa.pub"
|
||||
// ServiceAccountKeyBaseName defines SA key base name
|
||||
ServiceAccountKeyBaseName = "sa"
|
||||
// ServiceAccountPublicKeyName defines SA public key base name
|
||||
ServiceAccountPublicKeyName = "sa.pub"
|
||||
// ServiceAccountPrivateKeyName defines SA private key base name
|
||||
ServiceAccountPrivateKeyName = "sa.key"
|
||||
|
||||
// FrontProxyCACertAndKeyBaseName defines front proxy CA certificate and key base name
|
||||
FrontProxyCACertAndKeyBaseName = "front-proxy-ca"
|
||||
FrontProxyCACertName = "front-proxy-ca.crt"
|
||||
FrontProxyCAKeyName = "front-proxy-ca.key"
|
||||
// FrontProxyCACertName defines front proxy CA certificate name
|
||||
FrontProxyCACertName = "front-proxy-ca.crt"
|
||||
// FrontProxyCAKeyName defaines front proxy CA key name
|
||||
FrontProxyCAKeyName = "front-proxy-ca.key"
|
||||
|
||||
// FrontProxyClientCertAndKeyBaseName defines front proxy certificate and key base name
|
||||
FrontProxyClientCertAndKeyBaseName = "front-proxy-client"
|
||||
FrontProxyClientCertName = "front-proxy-client.crt"
|
||||
FrontProxyClientKeyName = "front-proxy-client.key"
|
||||
FrontProxyClientCertCommonName = "front-proxy-client" //used as subject.commonname attribute (CN)
|
||||
// FrontProxyClientCertName defines front proxy certificate name
|
||||
FrontProxyClientCertName = "front-proxy-client.crt"
|
||||
// FrontProxyClientKeyName defines front proxy key name
|
||||
FrontProxyClientKeyName = "front-proxy-client.key"
|
||||
// FrontProxyClientCertCommonName defines front proxy certificate common name
|
||||
FrontProxyClientCertCommonName = "front-proxy-client" //used as subject.commonname attribute (CN)
|
||||
|
||||
AdminKubeConfigFileName = "admin.conf"
|
||||
KubeletBootstrapKubeConfigFileName = "bootstrap-kubelet.conf"
|
||||
KubeletKubeConfigFileName = "kubelet.conf"
|
||||
// AdminKubeConfigFileName defines name for the KubeConfig aimed to be used by the superuser/admin of the cluster
|
||||
AdminKubeConfigFileName = "admin.conf"
|
||||
// KubeletBootstrapKubeConfigFileName defines the file name for the KubeConfig that the kubelet will use to do
|
||||
// the TLS bootstrap to get itself an unique credential
|
||||
KubeletBootstrapKubeConfigFileName = "bootstrap-kubelet.conf"
|
||||
|
||||
// KubeletKubeConfigFileName defines the file name for the KubeConfig that the master kubelet will use for talking
|
||||
// to the API server
|
||||
KubeletKubeConfigFileName = "kubelet.conf"
|
||||
// ControllerManagerKubeConfigFileName defines the file name for the controller manager's KubeConfig file
|
||||
ControllerManagerKubeConfigFileName = "controller-manager.conf"
|
||||
SchedulerKubeConfigFileName = "scheduler.conf"
|
||||
// SchedulerKubeConfigFileName defines the file name for the scheduler's KubeConfig file
|
||||
SchedulerKubeConfigFileName = "scheduler.conf"
|
||||
|
||||
// Some well-known users and groups in the core Kubernetes authorization system
|
||||
|
||||
ControllerManagerUser = "system:kube-controller-manager"
|
||||
SchedulerUser = "system:kube-scheduler"
|
||||
MastersGroup = "system:masters"
|
||||
NodesGroup = "system:nodes"
|
||||
// ControllerManagerUser defines the well-known user the controller-manager should be authenticated as
|
||||
ControllerManagerUser = "system:kube-controller-manager"
|
||||
// SchedulerUser defines the well-known user the scheduler should be authenticated as
|
||||
SchedulerUser = "system:kube-scheduler"
|
||||
// MastersGroup defines the well-known group for the apiservers. This group is also superuser by default
|
||||
// (i.e. bound to the cluster-admin ClusterRole)
|
||||
MastersGroup = "system:masters"
|
||||
// NodesGroup defines the well-known group for all nodes.
|
||||
NodesGroup = "system:nodes"
|
||||
// NodesClusterRoleBinding defines the well-known ClusterRoleBinding which binds the too permissive system:node
|
||||
// ClusterRole to the system:nodes group. Since kubeadm is using the Node Authorizer, this ClusterRoleBinding's
|
||||
// system:nodes group subject is removed if present.
|
||||
NodesClusterRoleBinding = "system:node"
|
||||
|
||||
// APICallRetryInterval defines how long kubeadm should wait before retrying a failed API operation
|
||||
@ -83,7 +122,7 @@ const (
|
||||
// MarkMasterTimeout specifies how long kubeadm should wait for applying the label and taint on the master before timing out
|
||||
MarkMasterTimeout = 2 * time.Minute
|
||||
|
||||
// Minimum amount of nodes the Service subnet should allow.
|
||||
// MinimumAddressesInServiceSubnet defines minimum amount of nodes the Service subnet should allow.
|
||||
// We need at least ten, because the DNS service is always at the tenth cluster clusterIP
|
||||
MinimumAddressesInServiceSubnet = 10
|
||||
|
||||
@ -107,11 +146,16 @@ const (
|
||||
// DefaultEtcdVersion indicates the default etcd version that kubeadm uses
|
||||
DefaultEtcdVersion = "3.0.17"
|
||||
|
||||
Etcd = "etcd"
|
||||
KubeAPIServer = "kube-apiserver"
|
||||
// Etcd defines variable used internally when referring to etcd component
|
||||
Etcd = "etcd"
|
||||
// KubeAPIServer defines variable used internally when referring to kube-apiserver component
|
||||
KubeAPIServer = "kube-apiserver"
|
||||
// KubeControllerManager defines variable used internally when referring to kube-controller-manager component
|
||||
KubeControllerManager = "kube-controller-manager"
|
||||
KubeScheduler = "kube-scheduler"
|
||||
KubeProxy = "kube-proxy"
|
||||
// KubeScheduler defines variable used internally when referring to kube-scheduler component
|
||||
KubeScheduler = "kube-scheduler"
|
||||
// KubeProxy defines variable used internally when referring to kube-proxy component
|
||||
KubeProxy = "kube-proxy"
|
||||
|
||||
// SelfHostingPrefix describes the prefix workloads that are self-hosted by kubeadm has
|
||||
SelfHostingPrefix = "self-hosted-"
|
||||
@ -146,7 +190,9 @@ var (
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
}
|
||||
|
||||
AuthorizationPolicyPath = filepath.Join(KubernetesDir, "abac_policy.json")
|
||||
// AuthorizationPolicyPath defines the supported location of authorization policy file
|
||||
AuthorizationPolicyPath = filepath.Join(KubernetesDir, "abac_policy.json")
|
||||
// AuthorizationWebhookConfigPath defines the supported location of webhook config file
|
||||
AuthorizationWebhookConfigPath = filepath.Join(KubernetesDir, "webhook_authz.conf")
|
||||
|
||||
// DefaultTokenUsages specifies the default functions a token will get
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
)
|
||||
|
||||
// TokenUser defines token user
|
||||
const TokenUser = "tls-bootstrap-token-user"
|
||||
|
||||
// For returns a KubeConfig object that can be used for doing the TLS Bootstrap with the right credentials
|
||||
@ -60,7 +61,7 @@ func GetValidatedClusterInfoObject(cfg *kubeadmapi.NodeConfiguration) (*clientcm
|
||||
case len(cfg.DiscoveryToken) != 0:
|
||||
return token.RetrieveValidatedClusterInfo(cfg.DiscoveryToken, cfg.DiscoveryTokenAPIServers, cfg.DiscoveryTokenCACertHashes)
|
||||
default:
|
||||
return nil, fmt.Errorf("couldn't find a valid discovery configuration.")
|
||||
return nil, fmt.Errorf("couldn't find a valid discovery configuration")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ func ValidateClusterInfo(clusterinfo *clientcmdapi.Config) (*clientcmdapi.Cluste
|
||||
defaultCluster.CertificateAuthorityData,
|
||||
)
|
||||
|
||||
client, err := kubeconfigutil.KubeConfigToClientSet(configFromClusterInfo)
|
||||
client, err := kubeconfigutil.ToClientSet(configFromClusterInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -79,10 +79,9 @@ func ValidateClusterInfo(clusterinfo *clientcmdapi.Config) (*clientcmdapi.Cluste
|
||||
// In that case, trust the cluster admin and do not refresh the cluster-info credentials
|
||||
fmt.Printf("[discovery] Could not access the %s ConfigMap for refreshing the cluster-info information, but the TLS cert is valid so proceeding...\n", bootstrapapi.ConfigMapClusterInfo)
|
||||
return true, nil
|
||||
} else {
|
||||
fmt.Printf("[discovery] Failed to validate the API Server's identity, will try again: [%v]\n", err)
|
||||
return false, nil
|
||||
}
|
||||
fmt.Printf("[discovery] Failed to validate the API Server's identity, will try again: [%v]\n", err)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
@ -36,13 +36,14 @@ import (
|
||||
"k8s.io/kubernetes/pkg/controller/bootstrap"
|
||||
)
|
||||
|
||||
// BootstrapUser defines bootstrap user name
|
||||
const BootstrapUser = "token-bootstrap-client"
|
||||
|
||||
// RetrieveValidatedClusterInfo connects to the API Server and tries to fetch the cluster-info ConfigMap
|
||||
// It then makes sure it can trust the API Server by looking at the JWS-signed tokens and (if rootCAPubKeys is not empty)
|
||||
// validating the cluster CA against a set of pinned public keys
|
||||
func RetrieveValidatedClusterInfo(discoveryToken string, tokenAPIServers, rootCAPubKeys []string) (*clientcmdapi.Cluster, error) {
|
||||
tokenId, tokenSecret, err := tokenutil.ParseToken(discoveryToken)
|
||||
tokenID, tokenSecret, err := tokenutil.ParseToken(discoveryToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -61,7 +62,7 @@ func RetrieveValidatedClusterInfo(discoveryToken string, tokenAPIServers, rootCA
|
||||
insecureBootstrapConfig := buildInsecureBootstrapKubeConfig(endpoint)
|
||||
clusterName := insecureBootstrapConfig.Contexts[insecureBootstrapConfig.CurrentContext].Cluster
|
||||
|
||||
insecureClient, err := kubeconfigutil.KubeConfigToClientSet(insecureBootstrapConfig)
|
||||
insecureClient, err := kubeconfigutil.ToClientSet(insecureBootstrapConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -85,11 +86,11 @@ func RetrieveValidatedClusterInfo(discoveryToken string, tokenAPIServers, rootCA
|
||||
if !ok || len(insecureKubeconfigString) == 0 {
|
||||
return nil, fmt.Errorf("there is no %s key in the %s ConfigMap. This API Server isn't set up for token bootstrapping, can't connect", bootstrapapi.KubeConfigKey, bootstrapapi.ConfigMapClusterInfo)
|
||||
}
|
||||
detachedJWSToken, ok := insecureClusterInfo.Data[bootstrapapi.JWSSignatureKeyPrefix+tokenId]
|
||||
detachedJWSToken, ok := insecureClusterInfo.Data[bootstrapapi.JWSSignatureKeyPrefix+tokenID]
|
||||
if !ok || len(detachedJWSToken) == 0 {
|
||||
return nil, fmt.Errorf("there is no JWS signed token in the %s ConfigMap. This token id %q is invalid for this cluster, can't connect", bootstrapapi.ConfigMapClusterInfo, tokenId)
|
||||
return nil, fmt.Errorf("there is no JWS signed token in the %s ConfigMap. This token id %q is invalid for this cluster, can't connect", bootstrapapi.ConfigMapClusterInfo, tokenID)
|
||||
}
|
||||
if !bootstrap.DetachedTokenIsValid(detachedJWSToken, insecureKubeconfigString, tokenId, tokenSecret) {
|
||||
if !bootstrap.DetachedTokenIsValid(detachedJWSToken, insecureKubeconfigString, tokenID, tokenSecret) {
|
||||
return nil, fmt.Errorf("failed to verify JWS signature of received cluster info object, can't trust this API Server")
|
||||
}
|
||||
insecureKubeconfigBytes := []byte(insecureKubeconfigString)
|
||||
@ -126,7 +127,7 @@ func RetrieveValidatedClusterInfo(discoveryToken string, tokenAPIServers, rootCA
|
||||
|
||||
// Now that we know the proported cluster CA, connect back a second time validating with that CA
|
||||
secureBootstrapConfig := buildSecureBootstrapKubeConfig(endpoint, clusterCABytes)
|
||||
secureClient, err := kubeconfigutil.KubeConfigToClientSet(secureBootstrapConfig)
|
||||
secureClient, err := kubeconfigutil.ToClientSet(secureBootstrapConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
)
|
||||
|
||||
// GetCoreImage generates and returns the image for the core Kubernetes components or returns overrideImage if specified
|
||||
func GetCoreImage(image, repoPrefix, k8sVersion, overrideImage string) string {
|
||||
if overrideImage != "" {
|
||||
return overrideImage
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd"
|
||||
)
|
||||
|
||||
// Run creates and executes new kubeadm command
|
||||
func Run() error {
|
||||
// We do not want these flags to show up in --help
|
||||
pflag.CommandLine.MarkHidden("google-json-key")
|
||||
|
@ -31,7 +31,7 @@ const CSRContextAndUser = "kubelet-csr"
|
||||
|
||||
// PerformTLSBootstrap executes a node certificate signing request.
|
||||
func PerformTLSBootstrap(cfg *clientcmdapi.Config, hostName string) error {
|
||||
client, err := kubeconfigutil.KubeConfigToClientSet(cfg)
|
||||
client, err := kubeconfigutil.ToClientSet(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
)
|
||||
|
||||
// NewCertificateAuthority creates new certificate and private key for the certificate authority
|
||||
func NewCertificateAuthority() (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
key, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
@ -44,6 +45,7 @@ func NewCertificateAuthority() (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
return cert, key, nil
|
||||
}
|
||||
|
||||
// NewCertAndKey creates new certificate and key by passing the certificate authority certificate and key
|
||||
func NewCertAndKey(caCert *x509.Certificate, caKey *rsa.PrivateKey, config certutil.Config) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
key, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
@ -68,6 +70,7 @@ func HasServerAuth(cert *x509.Certificate) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// WriteCertAndKey stores certificate and key at the specified location
|
||||
func WriteCertAndKey(pkiPath string, name string, cert *x509.Certificate, key *rsa.PrivateKey) error {
|
||||
if err := WriteKey(pkiPath, name, key); err != nil {
|
||||
return err
|
||||
@ -80,6 +83,7 @@ func WriteCertAndKey(pkiPath string, name string, cert *x509.Certificate, key *r
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteCert stores the given certificate at the given location
|
||||
func WriteCert(pkiPath, name string, cert *x509.Certificate) error {
|
||||
if cert == nil {
|
||||
return fmt.Errorf("certificate cannot be nil when writing to file")
|
||||
@ -93,6 +97,7 @@ func WriteCert(pkiPath, name string, cert *x509.Certificate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteKey stores the given key at the given location
|
||||
func WriteKey(pkiPath, name string, key *rsa.PrivateKey) error {
|
||||
if key == nil {
|
||||
return fmt.Errorf("private key cannot be nil when writing to file")
|
||||
@ -106,6 +111,7 @@ func WriteKey(pkiPath, name string, key *rsa.PrivateKey) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WritePublicKey stores the given public key at the given location
|
||||
func WritePublicKey(pkiPath, name string, key *rsa.PublicKey) error {
|
||||
if key == nil {
|
||||
return fmt.Errorf("public key cannot be nil when writing to file")
|
||||
|
@ -64,6 +64,7 @@ var (
|
||||
minExternalEtcdVersion = semver.MustParse(kubeadmconstants.MinExternalEtcdVersion)
|
||||
)
|
||||
|
||||
// Error defines struct for communicating error messages generated by preflight checks
|
||||
type Error struct {
|
||||
Msg string
|
||||
}
|
||||
@ -86,6 +87,7 @@ type ServiceCheck struct {
|
||||
CheckIfActive bool
|
||||
}
|
||||
|
||||
// Check validates if the service is enabled and active.
|
||||
func (sc ServiceCheck) Check() (warnings, errors []error) {
|
||||
initSystem, err := initsystem.GetInitSystem()
|
||||
if err != nil {
|
||||
@ -114,11 +116,13 @@ func (sc ServiceCheck) Check() (warnings, errors []error) {
|
||||
return warnings, errors
|
||||
}
|
||||
|
||||
// FirewalldCheck checks if firewalld is enabled or active, and if so outputs a warning.
|
||||
// FirewalldCheck checks if firewalld is enabled or active. If it is, warn the user that there may be problems
|
||||
// if no actions are taken.
|
||||
type FirewalldCheck struct {
|
||||
ports []int
|
||||
}
|
||||
|
||||
// Check validates if the firewall is enabled and active.
|
||||
func (fc FirewalldCheck) Check() (warnings, errors []error) {
|
||||
initSystem, err := initsystem.GetInitSystem()
|
||||
if err != nil {
|
||||
@ -145,6 +149,7 @@ type PortOpenCheck struct {
|
||||
port int
|
||||
}
|
||||
|
||||
// Check validates if the particular port is available.
|
||||
func (poc PortOpenCheck) Check() (warnings, errors []error) {
|
||||
errors = []error{}
|
||||
ln, err := net.Listen("tcp", fmt.Sprintf(":%d", poc.port))
|
||||
@ -161,6 +166,7 @@ func (poc PortOpenCheck) Check() (warnings, errors []error) {
|
||||
// IsRootCheck verifies user is root
|
||||
type IsRootCheck struct{}
|
||||
|
||||
// Check validates if an user has root privileges.
|
||||
func (irc IsRootCheck) Check() (warnings, errors []error) {
|
||||
errors = []error{}
|
||||
if os.Getuid() != 0 {
|
||||
@ -175,6 +181,7 @@ type DirAvailableCheck struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Check validates if a directory does not exist or empty.
|
||||
func (dac DirAvailableCheck) Check() (warnings, errors []error) {
|
||||
errors = []error{}
|
||||
// If it doesn't exist we are good:
|
||||
@ -202,6 +209,7 @@ type FileAvailableCheck struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Check validates if the given file does not already exist.
|
||||
func (fac FileAvailableCheck) Check() (warnings, errors []error) {
|
||||
errors = []error{}
|
||||
if _, err := os.Stat(fac.Path); err == nil {
|
||||
@ -215,6 +223,7 @@ type FileExistingCheck struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Check validates if the given file already exists.
|
||||
func (fac FileExistingCheck) Check() (warnings, errors []error) {
|
||||
errors = []error{}
|
||||
if _, err := os.Stat(fac.Path); err != nil {
|
||||
@ -229,6 +238,7 @@ type FileContentCheck struct {
|
||||
Content []byte
|
||||
}
|
||||
|
||||
// Check validates if the given file contains the given content.
|
||||
func (fcc FileContentCheck) Check() (warnings, errors []error) {
|
||||
f, err := os.Open(fcc.Path)
|
||||
if err != nil {
|
||||
@ -251,12 +261,13 @@ func (fcc FileContentCheck) Check() (warnings, errors []error) {
|
||||
|
||||
}
|
||||
|
||||
// InPathCheck checks if the given executable is present in the path
|
||||
// InPathCheck checks if the given executable is present in $PATH
|
||||
type InPathCheck struct {
|
||||
executable string
|
||||
mandatory bool
|
||||
}
|
||||
|
||||
// Check validates if the given executable is present in the path.
|
||||
func (ipc InPathCheck) Check() (warnings, errors []error) {
|
||||
_, err := exec.LookPath(ipc.executable)
|
||||
if err != nil {
|
||||
@ -276,6 +287,7 @@ type HostnameCheck struct {
|
||||
nodeName string
|
||||
}
|
||||
|
||||
// Check validates if hostname match dns sub domain regex.
|
||||
func (hc HostnameCheck) Check() (warnings, errors []error) {
|
||||
errors = []error{}
|
||||
warnings = []error{}
|
||||
@ -300,6 +312,7 @@ type HTTPProxyCheck struct {
|
||||
Port int
|
||||
}
|
||||
|
||||
// Check validates http connectivity type, direct or via proxy.
|
||||
func (hst HTTPProxyCheck) Check() (warnings, errors []error) {
|
||||
|
||||
url := fmt.Sprintf("%s://%s:%d", hst.Proto, hst.Host, hst.Port)
|
||||
@ -326,6 +339,7 @@ type ExtraArgsCheck struct {
|
||||
SchedulerExtraArgs map[string]string
|
||||
}
|
||||
|
||||
// Check validates additional arguments of the control plane components.
|
||||
func (eac ExtraArgsCheck) Check() (warnings, errors []error) {
|
||||
argsCheck := func(name string, args map[string]string, f *pflag.FlagSet) []error {
|
||||
errs := []error{}
|
||||
@ -359,8 +373,10 @@ func (eac ExtraArgsCheck) Check() (warnings, errors []error) {
|
||||
return warnings, nil
|
||||
}
|
||||
|
||||
// SystemVerificationCheck defines struct used for for running the system verification node check in test/e2e_node/system
|
||||
type SystemVerificationCheck struct{}
|
||||
|
||||
// Check runs all individual checks
|
||||
func (sysver SystemVerificationCheck) Check() (warnings, errors []error) {
|
||||
// Create a buffered writer and choose a quite large value (1M) and suppose the output from the system verification test won't exceed the limit
|
||||
// Run the system verification check, but write to out buffered writer instead of stdout
|
||||
@ -397,11 +413,13 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) {
|
||||
return warns, nil
|
||||
}
|
||||
|
||||
// KubernetesVersionCheck validates kubernetes and kubeadm versions
|
||||
type KubernetesVersionCheck struct {
|
||||
KubeadmVersion string
|
||||
KubernetesVersion string
|
||||
}
|
||||
|
||||
// Check validates kubernetes and kubeadm versions
|
||||
func (kubever KubernetesVersionCheck) Check() (warnings, errors []error) {
|
||||
|
||||
// Skip this check for "super-custom builds", where apimachinery/the overall codebase version is not set.
|
||||
@ -434,6 +452,7 @@ func (kubever KubernetesVersionCheck) Check() (warnings, errors []error) {
|
||||
// SwapCheck warns if swap is enabled
|
||||
type SwapCheck struct{}
|
||||
|
||||
// Check validates whether swap is enabled or not
|
||||
func (swc SwapCheck) Check() (warnings, errors []error) {
|
||||
f, err := os.Open("/proc/swaps")
|
||||
if err != nil {
|
||||
@ -451,7 +470,7 @@ func (swc SwapCheck) Check() (warnings, errors []error) {
|
||||
}
|
||||
|
||||
if len(buf) > 1 {
|
||||
return []error{fmt.Errorf("Running with swap on is not supported. Please disable swap or set kubelet's --fail-swap-on flag to false.")}, nil
|
||||
return []error{fmt.Errorf("running with swap on is not supported. Please disable swap or set kubelet's --fail-swap-on flag to false")}, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
@ -467,6 +486,7 @@ type ExternalEtcdVersionCheck struct {
|
||||
Etcd kubeadmapi.Etcd
|
||||
}
|
||||
|
||||
// Check validates external etcd version
|
||||
func (evc ExternalEtcdVersionCheck) Check() (warnings, errors []error) {
|
||||
var config *tls.Config
|
||||
var err error
|
||||
@ -549,6 +569,7 @@ func (evc ExternalEtcdVersionCheck) configCertAndKey(config *tls.Config) (*tls.C
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (evc ExternalEtcdVersionCheck) getHTTPClient(config *tls.Config) *http.Client {
|
||||
if config != nil {
|
||||
transport := &http.Transport{
|
||||
@ -561,6 +582,7 @@ func (evc ExternalEtcdVersionCheck) getHTTPClient(config *tls.Config) *http.Clie
|
||||
}
|
||||
return &http.Client{Timeout: externalEtcdRequestTimeout}
|
||||
}
|
||||
|
||||
func getEtcdVersionResponse(client *http.Client, url string, target interface{}) error {
|
||||
loopCount := externalEtcdRequestRetries + 1
|
||||
var err error
|
||||
@ -590,6 +612,8 @@ func getEtcdVersionResponse(client *http.Client, url string, target interface{})
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// RunInitMasterChecks executes all individual, applicable to Master node checks.
|
||||
func RunInitMasterChecks(cfg *kubeadmapi.MasterConfiguration) error {
|
||||
// First, check if we're root separately from the other preflight checks and fail fast
|
||||
if err := RunRootCheckOnly(); err != nil {
|
||||
@ -655,6 +679,7 @@ func RunInitMasterChecks(cfg *kubeadmapi.MasterConfiguration) error {
|
||||
return RunChecks(checks, os.Stderr)
|
||||
}
|
||||
|
||||
// RunJoinNodeChecks executes all individual, applicable to node checks.
|
||||
func RunJoinNodeChecks(cfg *kubeadmapi.NodeConfiguration) error {
|
||||
// First, check if we're root separately from the other preflight checks and fail fast
|
||||
if err := RunRootCheckOnly(); err != nil {
|
||||
@ -688,6 +713,7 @@ func RunJoinNodeChecks(cfg *kubeadmapi.NodeConfiguration) error {
|
||||
return RunChecks(checks, os.Stderr)
|
||||
}
|
||||
|
||||
// RunRootCheckOnly initializes cheks slice of structs and call RunChecks
|
||||
func RunRootCheckOnly() error {
|
||||
checks := []Checker{
|
||||
IsRootCheck{},
|
||||
@ -717,6 +743,7 @@ func RunChecks(checks []Checker, ww io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TryStartKubelet attempts to bring up kubelet service
|
||||
func TryStartKubelet() {
|
||||
// If we notice that the kubelet service is inactive, try to start it
|
||||
initSystem, err := initsystem.GetInitSystem()
|
||||
|
@ -34,6 +34,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
// SetInitDynamicDefaults checks and sets conifugration values for Master node
|
||||
func SetInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error {
|
||||
|
||||
// Choose the right address for the API Server to advertise. If the advertise address is localhost or 0.0.0.0, the default interface's IP address is used
|
||||
@ -48,7 +49,6 @@ func SetInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error {
|
||||
if kubeadmutil.KubernetesIsCIVersion(cfg.KubernetesVersion) {
|
||||
cfg.CIImageRepository = kubeadmconstants.DefaultCIImageRepository
|
||||
}
|
||||
|
||||
// Validate version argument
|
||||
ver, err := kubeadmutil.KubernetesReleaseVersion(cfg.KubernetesVersion)
|
||||
if err != nil {
|
||||
@ -112,7 +112,6 @@ func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *
|
||||
// static default values to cfg only for values not provided with flags
|
||||
api.Scheme.Default(defaultversionedcfg)
|
||||
api.Scheme.Convert(defaultversionedcfg, internalcfg, nil)
|
||||
|
||||
// Applies dynamic defaults to settings not provided with flags
|
||||
if err := SetInitDynamicDefaults(internalcfg); err != nil {
|
||||
return nil, err
|
||||
|
@ -26,9 +26,12 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultErrorExitCode defines exit the code for failed action generally
|
||||
DefaultErrorExitCode = 1
|
||||
PreFlightExitCode = 2
|
||||
ValidationExitCode = 3
|
||||
// PreFlightExitCode defines exit the code for preflight checks
|
||||
PreFlightExitCode = 2
|
||||
// ValidationExitCode defines the exit code validation checks
|
||||
ValidationExitCode = 3
|
||||
)
|
||||
|
||||
type debugError interface {
|
||||
|
@ -72,11 +72,11 @@ func ClientSetFromFile(path string) (*clientset.Clientset, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load admin kubeconfig [%v]", err)
|
||||
}
|
||||
return KubeConfigToClientSet(config)
|
||||
return ToClientSet(config)
|
||||
}
|
||||
|
||||
// KubeConfigToClientSet converts a KubeConfig object to a client
|
||||
func KubeConfigToClientSet(config *clientcmdapi.Config) (*clientset.Clientset, error) {
|
||||
// ToClientSet converts a KubeConfig object to a client
|
||||
func ToClientSet(config *clientcmdapi.Config) (*clientset.Clientset, error) {
|
||||
clientConfig, err := clientcmd.NewDefaultClientConfig(*config, &clientcmd.ConfigOverrides{}).ClientConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create API client configuration from kubeconfig: %v", err)
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// ParseTemplate validates and parses passed as argument template
|
||||
func ParseTemplate(strtmpl string, obj interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
tmpl, err := template.New("template").Parse(strtmpl)
|
||||
|
@ -26,15 +26,21 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
TokenIDBytes = 3
|
||||
// TokenIDBytes defines a number of bytes used for a token id
|
||||
TokenIDBytes = 3
|
||||
// TokenSecretBytes defines a number of bytes used for a secret
|
||||
TokenSecretBytes = 8
|
||||
)
|
||||
|
||||
var (
|
||||
// TokenIDRegexpString defines token's id regular expression pattern
|
||||
TokenIDRegexpString = "^([a-z0-9]{6})$"
|
||||
TokenIDRegexp = regexp.MustCompile(TokenIDRegexpString)
|
||||
TokenRegexpString = "^([a-z0-9]{6})\\.([a-z0-9]{16})$"
|
||||
TokenRegexp = regexp.MustCompile(TokenRegexpString)
|
||||
// TokenIDRegexp is a compiled regular expression of TokenIDRegexpString
|
||||
TokenIDRegexp = regexp.MustCompile(TokenIDRegexpString)
|
||||
// TokenRegexpString defines id.secret regular expression pattern
|
||||
TokenRegexpString = "^([a-z0-9]{6})\\.([a-z0-9]{16})$"
|
||||
// TokenRegexp is a compiled regular expression of TokenRegexpString
|
||||
TokenRegexp = regexp.MustCompile(TokenRegexpString)
|
||||
)
|
||||
|
||||
func randBytes(length int) (string, error) {
|
||||
|
@ -187,7 +187,6 @@ func TestSplitVersion(t *testing.T) {
|
||||
// unknown area, not valid input.
|
||||
{"unknown/latest-1", "", "", false},
|
||||
}
|
||||
|
||||
// kubeReleaseBucketURL can be overriden during network tests, thus ensure
|
||||
// it will contain value corresponding to expected outcome for this unit test
|
||||
kubeReleaseBucketURL = "https://dl.k8s.io"
|
||||
|
@ -27,6 +27,8 @@ import (
|
||||
|
||||
// Forked from test/e2e/framework because the e2e framework is quite bloated
|
||||
// for our purposes here, and modified to remove undesired logging.
|
||||
|
||||
// RunCmd is a utility function for kubeadm testing that executes a specified command
|
||||
func RunCmd(command string, args ...string) (string, string, error) {
|
||||
var bout, berr bytes.Buffer
|
||||
cmd := exec.Command(command, args...)
|
||||
|
@ -9,21 +9,6 @@ cmd/kube-proxy/app
|
||||
cmd/kubeadm/app
|
||||
cmd/kubeadm/app/apis/kubeadm
|
||||
cmd/kubeadm/app/apis/kubeadm/v1alpha1
|
||||
cmd/kubeadm/app/apis/kubeadm/validation
|
||||
cmd/kubeadm/app/cmd
|
||||
cmd/kubeadm/app/cmd/phases
|
||||
cmd/kubeadm/app/constants
|
||||
cmd/kubeadm/app/discovery
|
||||
cmd/kubeadm/app/discovery/file
|
||||
cmd/kubeadm/app/discovery/token
|
||||
cmd/kubeadm/app/images
|
||||
cmd/kubeadm/app/phases/certs/pkiutil
|
||||
cmd/kubeadm/app/preflight
|
||||
cmd/kubeadm/app/util
|
||||
cmd/kubeadm/app/util/config
|
||||
cmd/kubeadm/app/util/kubeconfig
|
||||
cmd/kubeadm/app/util/token
|
||||
cmd/kubeadm/test/cmd
|
||||
cmd/kubectl/app
|
||||
cmd/kubelet/app
|
||||
cmd/kubelet/app/options
|
||||
|
Loading…
Reference in New Issue
Block a user