
- Move from the old github.com/golang/glog to k8s.io/klog - klog as explicit InitFlags() so we add them as necessary - we update the other repositories that we vendor that made a similar change from glog to klog * github.com/kubernetes/repo-infra * k8s.io/gengo/ * k8s.io/kube-openapi/ * github.com/google/cadvisor - Entirely remove all references to glog - Fix some tests by explicit InitFlags in their init() methods Change-Id: I92db545ff36fcec83afe98f550c9e630098b3135
180 lines
7.4 KiB
Go
180 lines
7.4 KiB
Go
/*
|
|
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 config
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
"k8s.io/klog"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
netutil "k8s.io/apimachinery/pkg/util/net"
|
|
"k8s.io/apimachinery/pkg/util/version"
|
|
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/constants"
|
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
|
)
|
|
|
|
// AnyConfigFileAndDefaultsToInternal reads either a InitConfiguration or JoinConfiguration and unmarshals it
|
|
func AnyConfigFileAndDefaultsToInternal(cfgPath string) (runtime.Object, error) {
|
|
b, err := ioutil.ReadFile(cfgPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
gvks, err := kubeadmutil.GroupVersionKindsFromBytes(b)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// First, check if the gvk list has InitConfiguration and in that case try to unmarshal it
|
|
if kubeadmutil.GroupVersionKindsHasInitConfiguration(gvks...) {
|
|
return ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1beta1.InitConfiguration{})
|
|
}
|
|
if kubeadmutil.GroupVersionKindsHasJoinConfiguration(gvks...) {
|
|
return JoinConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1beta1.JoinConfiguration{})
|
|
}
|
|
return nil, errors.Errorf("didn't recognize types with GroupVersionKind: %v", gvks)
|
|
}
|
|
|
|
// MarshalKubeadmConfigObject marshals an Object registered in the kubeadm scheme. If the object is a InitConfiguration or ClusterConfiguration, some extra logic is run
|
|
func MarshalKubeadmConfigObject(obj runtime.Object) ([]byte, error) {
|
|
switch internalcfg := obj.(type) {
|
|
case *kubeadmapi.InitConfiguration:
|
|
return MarshalInitConfigurationToBytes(internalcfg, kubeadmapiv1beta1.SchemeGroupVersion)
|
|
case *kubeadmapi.ClusterConfiguration:
|
|
return MarshalClusterConfigurationToBytes(internalcfg, kubeadmapiv1beta1.SchemeGroupVersion)
|
|
default:
|
|
return kubeadmutil.MarshalToYamlForCodecs(obj, kubeadmapiv1beta1.SchemeGroupVersion, kubeadmscheme.Codecs)
|
|
}
|
|
}
|
|
|
|
// DetectUnsupportedVersion reads YAML bytes, extracts the TypeMeta information and errors out with an user-friendly message if the API spec is too old for this kubeadm version
|
|
func DetectUnsupportedVersion(b []byte) error {
|
|
gvks, err := kubeadmutil.GroupVersionKindsFromBytes(b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// TODO: On our way to making the kubeadm API beta and higher, give good user output in case they use an old config file with a new kubeadm version, and
|
|
// tell them how to upgrade. The support matrix will look something like this now and in the future:
|
|
// v1.10 and earlier: v1alpha1
|
|
// v1.11: v1alpha1 read-only, writes only v1alpha2 config
|
|
// v1.12: v1alpha2 read-only, writes only v1alpha3 config. Warns if the user tries to use v1alpha1
|
|
// v1.13: v1alpha3 read-only, writes only v1beta1 config. Warns if the user tries to use v1alpha1 or v1alpha2
|
|
oldKnownAPIVersions := map[string]string{
|
|
"kubeadm.k8s.io/v1alpha1": "v1.11",
|
|
"kubeadm.k8s.io/v1alpha2": "v1.12",
|
|
}
|
|
// If we find an old API version in this gvk list, error out and tell the user why this doesn't work
|
|
knownKinds := map[string]bool{}
|
|
for _, gvk := range gvks {
|
|
if useKubeadmVersion := oldKnownAPIVersions[gvk.GroupVersion().String()]; len(useKubeadmVersion) != 0 {
|
|
return errors.Errorf("your configuration file uses an old API spec: %q. Please use kubeadm %s instead and run 'kubeadm config migrate --old-config old.yaml --new-config new.yaml', which will write the new, similar spec using a newer API version.", gvk.GroupVersion().String(), useKubeadmVersion)
|
|
}
|
|
knownKinds[gvk.Kind] = true
|
|
}
|
|
|
|
// InitConfiguration and JoinConfiguration may not apply together, warn if more than one is specified
|
|
mutuallyExclusive := []string{constants.InitConfigurationKind, constants.JoinConfigurationKind}
|
|
mutuallyExclusiveCount := 0
|
|
for _, kind := range mutuallyExclusive {
|
|
if knownKinds[kind] {
|
|
mutuallyExclusiveCount++
|
|
}
|
|
}
|
|
if mutuallyExclusiveCount > 1 {
|
|
klog.Warningf("WARNING: Detected resource kinds that may not apply: %v", mutuallyExclusive)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// NormalizeKubernetesVersion resolves version labels, sets alternative
|
|
// image registry if requested for CI builds, and validates minimal
|
|
// version that kubeadm SetInitDynamicDefaultssupports.
|
|
func NormalizeKubernetesVersion(cfg *kubeadmapi.ClusterConfiguration) error {
|
|
// Requested version is automatic CI build, thus use KubernetesCI Image Repository for core images
|
|
if kubeadmutil.KubernetesIsCIVersion(cfg.KubernetesVersion) {
|
|
cfg.CIImageRepository = constants.DefaultCIImageRepository
|
|
}
|
|
|
|
// Parse and validate the version argument and resolve possible CI version labels
|
|
ver, err := kubeadmutil.KubernetesReleaseVersion(cfg.KubernetesVersion)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cfg.KubernetesVersion = ver
|
|
|
|
// Parse the given kubernetes version and make sure it's higher than the lowest supported
|
|
k8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "couldn't parse Kubernetes version %q", cfg.KubernetesVersion)
|
|
}
|
|
if k8sVersion.LessThan(constants.MinimumControlPlaneVersion) {
|
|
return errors.Errorf("this version of kubeadm only supports deploying clusters with the control plane version >= %s. Current version: %s", constants.MinimumControlPlaneVersion.String(), cfg.KubernetesVersion)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// LowercaseSANs can be used to force all SANs to be lowercase so it passes IsDNS1123Subdomain
|
|
func LowercaseSANs(sans []string) {
|
|
for i, san := range sans {
|
|
lowercase := strings.ToLower(san)
|
|
if lowercase != san {
|
|
klog.V(1).Infof("lowercasing SAN %q to %q", san, lowercase)
|
|
sans[i] = lowercase
|
|
}
|
|
}
|
|
}
|
|
|
|
// VerifyAPIServerBindAddress can be used to verify if a bind address for the API Server is 0.0.0.0,
|
|
// in which case this address is not valid and should not be used.
|
|
func VerifyAPIServerBindAddress(address string) error {
|
|
ip := net.ParseIP(address)
|
|
if ip == nil {
|
|
return errors.Errorf("cannot parse IP address: %s", address)
|
|
}
|
|
if !ip.IsGlobalUnicast() {
|
|
return errors.Errorf("cannot use %q as the bind address for the API Server", address)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ChooseAPIServerBindAddress is a wrapper for netutil.ChooseBindAddress that also handles
|
|
// the case where no default routes were found and an IP for the API server could not be obatained.
|
|
func ChooseAPIServerBindAddress(bindAddress net.IP) (net.IP, error) {
|
|
ip, err := netutil.ChooseBindAddress(bindAddress)
|
|
if err != nil {
|
|
if netutil.IsNoRoutesError(err) {
|
|
klog.Warningf("WARNING: could not obtain a bind address for the API Server: %v; using: %s", err, constants.DefaultAPIServerBindAddress)
|
|
defaultIP := net.ParseIP(constants.DefaultAPIServerBindAddress)
|
|
if defaultIP == nil {
|
|
return nil, errors.Errorf("cannot parse default IP address: %s", constants.DefaultAPIServerBindAddress)
|
|
}
|
|
return defaultIP, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
return ip, nil
|
|
}
|