Merge remote-tracking branch 'upstream/master' into test-cmd-what

pull/564/head
Thomas Runyon 2019-01-28 20:49:31 -05:00
commit b308c53d6d
17 changed files with 112 additions and 101 deletions

View File

@ -136,16 +136,16 @@ func NewCmdInit(out io.Writer, initOptions *initOptions) *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()
c, err := initRunner.InitData(args)
kubeadmutil.CheckErr(err)
data := c.(initData)
data := c.(*initData)
fmt.Printf("[init] Using Kubernetes version: %s\n", data.cfg.KubernetesVersion)
err = initRunner.Run()
err = initRunner.Run(args)
kubeadmutil.CheckErr(err)
err = showJoinCommand(&data, out)
err = showJoinCommand(data, out)
kubeadmutil.CheckErr(err)
},
}
@ -181,8 +181,8 @@ func NewCmdInit(out io.Writer, initOptions *initOptions) *cobra.Command {
// 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) (workflow.RunData, error) {
return newInitData(cmd, initOptions, out)
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
@ -278,7 +278,7 @@ func newInitOptions() *initOptions {
// 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, options *initOptions, out io.Writer) (initData, error) {
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)
@ -286,27 +286,27 @@ func newInitData(cmd *cobra.Command, options *initOptions, out io.Writer) (initD
// 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 initData{}, err
return &initData{}, err
}
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(options.ignorePreflightErrors)
if err != nil {
return initData{}, err
return &initData{}, err
}
if err = validation.ValidateMixedArguments(cmd.Flags()); err != nil {
return initData{}, err
return &initData{}, err
}
if err = options.bto.ApplyTo(options.externalcfg); err != nil {
return initData{}, err
return &initData{}, err
}
// Either use the config file if specified, or convert public kubeadm API to the internal InitConfiguration
// and validates InitConfiguration
cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(options.cfgPath, options.externalcfg)
if err != nil {
return initData{}, err
return &initData{}, err
}
// override node name and CRI socket from the command line options
@ -318,17 +318,17 @@ func newInitData(cmd *cobra.Command, options *initOptions, out io.Writer) (initD
}
if err := configutil.VerifyAPIServerBindAddress(cfg.LocalAPIEndpoint.AdvertiseAddress); err != nil {
return initData{}, err
return &initData{}, err
}
if err := features.ValidateVersion(features.InitFeatureGates, cfg.FeatureGates, cfg.KubernetesVersion); err != nil {
return initData{}, err
return &initData{}, 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 initData{}, errors.Wrap(err, "couldn't create a temporary directory")
return &initData{}, errors.Wrap(err, "couldn't create a temporary directory")
}
}
@ -340,11 +340,11 @@ func newInitData(cmd *cobra.Command, options *initOptions, out io.Writer) (initD
kubeconfigDir = dryRunDir
}
if err := kubeconfigphase.ValidateKubeconfigsForExternalCA(kubeconfigDir, cfg); err != nil {
return initData{}, err
return &initData{}, err
}
}
return initData{
return &initData{
cfg: cfg,
certificatesDir: cfg.CertificatesDir,
skipTokenPrint: options.skipTokenPrint,
@ -359,27 +359,27 @@ func newInitData(cmd *cobra.Command, options *initOptions, out io.Writer) (initD
}
// Cfg returns initConfiguration.
func (d initData) Cfg() *kubeadmapi.InitConfiguration {
func (d *initData) Cfg() *kubeadmapi.InitConfiguration {
return d.cfg
}
// DryRun returns the DryRun flag.
func (d initData) DryRun() bool {
func (d *initData) DryRun() bool {
return d.dryRun
}
// SkipTokenPrint returns the SkipTokenPrint flag.
func (d initData) SkipTokenPrint() bool {
func (d *initData) SkipTokenPrint() bool {
return d.skipTokenPrint
}
// IgnorePreflightErrors returns the IgnorePreflightErrors flag.
func (d initData) IgnorePreflightErrors() sets.String {
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 {
func (d *initData) CertificateWriteDir() string {
if d.dryRun {
return d.dryRunDir
}
@ -387,12 +387,12 @@ func (d initData) CertificateWriteDir() string {
}
// CertificateDir returns the CertificateDir as originally specified by the user.
func (d initData) CertificateDir() string {
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 {
func (d *initData) KubeConfigDir() string {
if d.dryRun {
return d.dryRunDir
}
@ -400,7 +400,7 @@ func (d initData) KubeConfigDir() string {
}
// KubeConfigPath returns the path to the kubeconfig file to use for connecting to Kubernetes
func (d initData) KubeConfigPath() string {
func (d *initData) KubeConfigPath() string {
if d.dryRun {
d.kubeconfigPath = filepath.Join(d.dryRunDir, kubeadmconstants.AdminKubeConfigFileName)
}
@ -408,7 +408,7 @@ func (d initData) KubeConfigPath() string {
}
// ManifestDir returns the path where manifest should be stored or the temporary folder path in case of DryRun.
func (d initData) ManifestDir() string {
func (d *initData) ManifestDir() string {
if d.dryRun {
return d.dryRunDir
}
@ -416,7 +416,7 @@ func (d initData) ManifestDir() string {
}
// KubeletDir returns path of the kubelet configuration folder or the temporary folder in case of DryRun.
func (d initData) KubeletDir() string {
func (d *initData) KubeletDir() string {
if d.dryRun {
return d.dryRunDir
}
@ -424,19 +424,19 @@ func (d initData) KubeletDir() string {
}
// ExternalCA returns true if an external CA is provided by the user.
func (d initData) ExternalCA() bool {
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 {
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) {
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
@ -455,7 +455,7 @@ func (d initData) Client() (clientset.Interface, error) {
}
// Tokens returns an array of token strings.
func (d initData) Tokens() []string {
func (d *initData) Tokens() []string {
tokens := []string{}
for _, bt := range d.cfg.BootstrapTokens {
tokens = append(tokens, bt.Token.String())

View File

@ -142,7 +142,7 @@ func TestNewInitData(t *testing.T) {
}
// test newInitData method
data, err := newInitData(cmd, initOptions, nil)
data, err := newInitData(cmd, tc.args, initOptions, nil)
if err != nil && !tc.expectError {
t.Fatalf("newInitData returned unexpected error: %v", err)
}
@ -152,7 +152,7 @@ func TestNewInitData(t *testing.T) {
// exec additional validation on the returned value
if tc.validate != nil {
tc.validate(t, &data)
tc.validate(t, data)
}
})
}

View File

@ -159,7 +159,6 @@ var (
// 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 {
args *[]string
cfgPath string
token string
controlPlane bool
@ -191,17 +190,16 @@ func NewCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command {
Short: "Run this on any machine you wish to join an existing cluster",
Long: joinLongDescription,
Run: func(cmd *cobra.Command, args []string) {
joinOptions.args = &args
c, err := joinRunner.InitData()
c, err := joinRunner.InitData(args)
kubeadmutil.CheckErr(err)
err = joinRunner.Run()
err = joinRunner.Run(args)
kubeadmutil.CheckErr(err)
// TODO: remove this once we have all phases in place.
// the method joinData.Run() itself should be removed too.
data := c.(joinData)
data := c.(*joinData)
err = data.Run()
kubeadmutil.CheckErr(err)
},
@ -216,8 +214,8 @@ func NewCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command {
// 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) (workflow.RunData, error) {
return newJoinData(cmd, joinOptions, out)
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
@ -321,7 +319,7 @@ func newJoinOptions() *joinOptions {
// 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, options *joinOptions, out io.Writer) (joinData, error) {
func newJoinData(cmd *cobra.Command, args []string, options *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(options.externalcfg)
@ -344,13 +342,13 @@ func newJoinData(cmd *cobra.Command, options *joinOptions, out io.Writer) (joinD
}
// if an APIServerEndpoint from which to retrive cluster information was not provided, unset the Discovery.BootstrapToken object
if len(*options.args) == 0 {
if len(args) == 0 {
options.externalcfg.Discovery.BootstrapToken = nil
} else {
if len(options.cfgPath) == 0 && len(*options.args) > 1 {
klog.Warningf("[join] WARNING: More than one API server endpoint supplied on command line %v. Using the first one.", *options.args)
if len(options.cfgPath) == 0 && len(args) > 1 {
klog.Warningf("[join] WARNING: More than one API server endpoint supplied on command line %v. Using the first one.", args)
}
options.externalcfg.Discovery.BootstrapToken.APIServerEndpoint = (*options.args)[0]
options.externalcfg.Discovery.BootstrapToken.APIServerEndpoint = args[0]
}
// if not joining a control plane, unset the ControlPlane object
@ -360,11 +358,11 @@ func newJoinData(cmd *cobra.Command, options *joinOptions, out io.Writer) (joinD
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(options.ignorePreflightErrors)
if err != nil {
return joinData{}, err
return &joinData{}, err
}
if err = validation.ValidateMixedArguments(cmd.Flags()); err != nil {
return joinData{}, err
return &joinData{}, err
}
// Either use the config file if specified, or convert public kubeadm API to the internal JoinConfiguration
@ -379,7 +377,7 @@ func newJoinData(cmd *cobra.Command, options *joinOptions, out io.Writer) (joinD
cfg, err := configutil.JoinConfigFileAndDefaultsToInternalConfig(options.cfgPath, options.externalcfg)
if err != nil {
return joinData{}, err
return &joinData{}, err
}
// override node name and CRI socket from the command line options
@ -392,11 +390,11 @@ func newJoinData(cmd *cobra.Command, options *joinOptions, out io.Writer) (joinD
if cfg.ControlPlane != nil {
if err := configutil.VerifyAPIServerBindAddress(cfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress); err != nil {
return joinData{}, err
return &joinData{}, err
}
}
return joinData{
return &joinData{
cfg: cfg,
ignorePreflightErrors: ignorePreflightErrorsSet,
outputWriter: out,

View File

@ -220,7 +220,6 @@ func TestNewJoinData(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
// initialize an external join option and inject it to the join cmd
joinOptions := newJoinOptions()
joinOptions.args = &tc.args
cmd := NewCmdJoin(nil, joinOptions)
// sets cmd flags (that will be reflected on the join options)
@ -229,7 +228,7 @@ func TestNewJoinData(t *testing.T) {
}
// test newJoinData method
data, err := newJoinData(cmd, joinOptions, nil)
data, err := newJoinData(cmd, tc.args, joinOptions, nil)
if err != nil && !tc.expectError {
t.Fatalf("newJoinData returned unexpected error: %v", err)
}
@ -239,7 +238,7 @@ func TestNewJoinData(t *testing.T) {
// exec additional validation on the returned value
if tc.validate != nil {
tc.validate(t, &data)
tc.validate(t, data)
}
})
}

View File

@ -91,7 +91,7 @@ func TestCreateSparseCerts(t *testing.T) {
r := workflow.NewRunner()
r.AppendPhase(NewCertsPhase())
r.SetDataInitializer(func(*cobra.Command) (workflow.RunData, error) {
r.SetDataInitializer(func(*cobra.Command, []string) (workflow.RunData, error) {
certsData := &testCertsData{
cfg: testutil.GetDefaultInternalConfig(t),
}
@ -99,7 +99,7 @@ func TestCreateSparseCerts(t *testing.T) {
return certsData, nil
})
if err := r.Run(); (err != nil) != test.ExpectError {
if err := r.Run([]string{}); (err != nil) != test.ExpectError {
t.Fatalf("expected error to be %t, got %t (%v)", test.ExpectError, (err != nil), err)
}
})

View File

@ -102,10 +102,10 @@ func ExampleRunner_Run() {
// Defines the method that creates the runtime data shared
// among all the phases included in the workflow
myWorkflowRunner.SetDataInitializer(func(cmd *cobra.Command) (RunData, error) {
myWorkflowRunner.SetDataInitializer(func(cmd *cobra.Command, args []string) (RunData, error) {
return myWorkflowData{data: "some data"}, nil
})
// Runs the workflow
myWorkflowRunner.Run()
// Runs the workflow by passing a list of arguments
myWorkflowRunner.Run([]string{})
}

View File

@ -53,7 +53,7 @@ type Runner struct {
// runDataInitializer defines a function that creates the runtime data shared
// among all the phases included in the workflow
runDataInitializer func(*cobra.Command) (RunData, error)
runDataInitializer func(*cobra.Command, []string) (RunData, error)
// runData is part of the internal state of the runner and it is used for implementing
// a singleton in the InitData methods (thus avoiding to initialize data
@ -171,17 +171,17 @@ func (e *Runner) computePhaseRunFlags() (map[string]bool, error) {
// SetDataInitializer allows to setup a function that initialize the runtime data shared
// among all the phases included in the workflow.
// The method will receive in input the cmd that triggers the Runner (only if the runner is BindToCommand)
func (e *Runner) SetDataInitializer(builder func(cmd *cobra.Command) (RunData, error)) {
func (e *Runner) SetDataInitializer(builder func(cmd *cobra.Command, args []string) (RunData, error)) {
e.runDataInitializer = builder
}
// InitData triggers the creation of runtime data shared among all the phases included in the workflow.
// This action can be executed explicitly out, when it is necessary to get the RunData
// before actually executing Run, or implicitly when invoking Run.
func (e *Runner) InitData() (RunData, error) {
func (e *Runner) InitData(args []string) (RunData, error) {
if e.runData == nil && e.runDataInitializer != nil {
var err error
if e.runData, err = e.runDataInitializer(e.runCmd); err != nil {
if e.runData, err = e.runDataInitializer(e.runCmd, args); err != nil {
return nil, err
}
}
@ -190,7 +190,7 @@ func (e *Runner) InitData() (RunData, error) {
}
// Run the kubeadm composable kubeadm workflows.
func (e *Runner) Run() error {
func (e *Runner) Run(args []string) error {
e.prepareForExecution()
// determine which phase should be run according to RunnerOptions
@ -201,7 +201,7 @@ func (e *Runner) Run() error {
// builds the runner data
var data RunData
if data, err = e.InitData(); err != nil {
if data, err = e.InitData(args); err != nil {
return err
}
@ -309,7 +309,7 @@ func (e *Runner) BindToCommand(cmd *cobra.Command) {
phaseCommand := &cobra.Command{
Use: "phase",
Short: fmt.Sprintf("use this command to invoke single phase of the %s workflow", cmd.Name()),
Args: cobra.NoArgs, // this forces cobra to fail if a wrong phase name is passed
// TODO: this logic is currently lacking verification if a suphase name is valid!
}
cmd.AddCommand(phaseCommand)
@ -347,7 +347,7 @@ func (e *Runner) BindToCommand(cmd *cobra.Command) {
// overrides the command triggering the Runner using the phaseCmd
e.runCmd = cmd
e.Options.FilterPhases = []string{phaseSelector}
if err := e.Run(); err != nil {
if err := e.Run(args); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

View File

@ -172,7 +172,7 @@ func TestRunOrderAndConditions(t *testing.T) {
t.Run(u.name, func(t *testing.T) {
callstack = []string{}
w.Options = u.options
err := w.Run()
err := w.Run([]string{})
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -241,7 +241,7 @@ func TestRunHandleErrors(t *testing.T) {
for _, u := range usecases {
t.Run(u.name, func(t *testing.T) {
w.Options = u.options
err := w.Run()
err := w.Run([]string{})
if (err != nil) != u.expectedError {
t.Errorf("Unexpected error: %v", err)
}

View File

@ -38,4 +38,4 @@ if [[ ! -x "$importverifier" ]]; then
exit 1
fi
"${importverifier}" "k8s.io/" "${KUBE_ROOT}/hack/import-restrictions.yaml"
"${importverifier}" "k8s.io/" "${KUBE_ROOT}/staging/publishing/import-restrictions.yaml"

View File

@ -22,9 +22,7 @@ import (
"fmt"
"time"
"k8s.io/klog"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@ -37,6 +35,7 @@ import (
"k8s.io/client-go/tools/record"
clientretry "k8s.io/client-go/util/retry"
cloudprovider "k8s.io/cloud-provider"
"k8s.io/klog"
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
nodeutil "k8s.io/kubernetes/pkg/util/node"
@ -199,14 +198,22 @@ func (cnc *CloudNodeController) updateNodeAddress(node *v1.Node, instances cloud
}
func (cnc *CloudNodeController) UpdateCloudNode(_, newObj interface{}) {
if _, ok := newObj.(*v1.Node); !ok {
node, ok := newObj.(*v1.Node)
if !ok {
utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", newObj))
return
}
cnc.AddCloudNode(newObj)
cloudTaint := getCloudTaint(node.Spec.Taints)
if cloudTaint == nil {
// The node has already been initialized so nothing to do.
return
}
cnc.initializeNode(node)
}
// This processes nodes that were added into the cluster, and cloud initialize them if appropriate
// AddCloudNode handles initializing new nodes registered with the cloud taint.
func (cnc *CloudNodeController) AddCloudNode(obj interface{}) {
node := obj.(*v1.Node)
@ -216,6 +223,12 @@ func (cnc *CloudNodeController) AddCloudNode(obj interface{}) {
return
}
cnc.initializeNode(node)
}
// This processes nodes that were added into the cluster, and cloud initialize them if appropriate
func (cnc *CloudNodeController) initializeNode(node *v1.Node) {
instances, ok := cnc.cloud.Instances()
if !ok {
utilruntime.HandleError(fmt.Errorf("failed to get instances from cloud provider"))
@ -290,7 +303,7 @@ func (cnc *CloudNodeController) AddCloudNode(obj interface{}) {
}
}
curNode.Spec.Taints = excludeTaintFromList(curNode.Spec.Taints, *cloudTaint)
curNode.Spec.Taints = excludeCloudTaint(curNode.Spec.Taints)
_, err = cnc.kubeClient.CoreV1().Nodes().Update(curNode)
if err != nil {
@ -318,10 +331,10 @@ func getCloudTaint(taints []v1.Taint) *v1.Taint {
return nil
}
func excludeTaintFromList(taints []v1.Taint, toExclude v1.Taint) []v1.Taint {
func excludeCloudTaint(taints []v1.Taint) []v1.Taint {
newTaints := []v1.Taint{}
for _, taint := range taints {
if toExclude.MatchTaint(&taint) {
if taint.Key == schedulerapi.TaintExternalCloudProvider {
continue
}
newTaints = append(newTaints, taint)

View File

@ -950,7 +950,7 @@ func (n *NodeLabelChecker) CheckNodeLabelPresence(pod *v1.Pod, meta PredicateMet
return true, nil, nil
}
// ServiceAffinity defines a struct used for create service affinity predicates.
// ServiceAffinity defines a struct used for creating service affinity predicates.
type ServiceAffinity struct {
podLister algorithm.PodLister
serviceLister algorithm.ServiceLister
@ -1012,7 +1012,7 @@ func NewServiceAffinityPredicate(podLister algorithm.PodLister, serviceLister al
//
// To do this, we "reverse engineer" a selector by introspecting existing pods running under the same service+namespace.
// These backfilled labels in the selector "L" are defined like so:
// - L is a label that the ServiceAffinity object needs as a matching constraints.
// - L is a label that the ServiceAffinity object needs as a matching constraint.
// - L is not defined in the pod itself already.
// - and SOME pod, from a service, in the same namespace, ALREADY scheduled onto a node, has a matching value.
//

View File

@ -27,7 +27,7 @@ import (
)
// CalculateNodeAffinityPriorityMap prioritizes nodes according to node affinity scheduling preferences
// indicated in PreferredDuringSchedulingIgnoredDuringExecution. Each time a node match a preferredSchedulingTerm,
// indicated in PreferredDuringSchedulingIgnoredDuringExecution. Each time a node matchs a preferredSchedulingTerm,
// it will a get an add of preferredSchedulingTerm.Weight. Thus, the more preferredSchedulingTerms
// the node satisfies and the more the preferredSchedulingTerm that is satisfied weights, the higher
// score the node gets.

View File

@ -25,7 +25,7 @@ import (
schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"
)
// EmptyPriorityMetadataProducer should returns a no-op PriorityMetadataProducer type.
// EmptyPriorityMetadataProducer should return a no-op PriorityMetadataProducer type.
func TestEmptyPriorityMetadataProducer(t *testing.T) {
fakePod := new(v1.Pod)
fakeLabelSelector := labels.SelectorFromSet(labels.Set{"foo": "bar"})

View File

@ -25,7 +25,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/code-generator
name: release-1.12
go: 1.10.4
go: 1.10.8
- source:
branch: release-1.13
dir: staging/src/k8s.io/code-generator
@ -52,7 +52,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/apimachinery
name: release-1.12
go: 1.10.4
go: 1.10.8
- source:
branch: release-1.13
dir: staging/src/k8s.io/apimachinery
@ -88,7 +88,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/api
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12
@ -214,7 +214,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/apiserver
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12
@ -283,7 +283,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/kube-aggregator
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12
@ -368,7 +368,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/sample-apiserver
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12
@ -463,7 +463,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/sample-controller
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12
@ -561,7 +561,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/apiextensions-apiserver
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12
@ -635,7 +635,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/metrics
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12
@ -675,7 +675,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/csi-api
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12
@ -717,7 +717,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/cli-runtime
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: api
branch: release-1.12
@ -759,7 +759,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/sample-cli-plugin
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: api
branch: release-1.12
@ -799,7 +799,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/kube-proxy
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12
@ -829,7 +829,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/kubelet
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12
@ -863,7 +863,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/kube-scheduler
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12
@ -897,7 +897,7 @@ rules:
branch: release-1.12
dir: staging/src/k8s.io/kube-controller-manager
name: release-1.12
go: 1.10.4
go: 1.10.8
dependencies:
- repository: apimachinery
branch: release-1.12

View File

@ -374,8 +374,9 @@ var _ = SIGDescribe("Daemon set [Serial]", func() {
rollback of updates to a DaemonSet.
*/
framework.ConformanceIt("should rollback without unnecessary restarts", func() {
// Skip clusters with only one node, where we cannot have half-done DaemonSet rollout for this test
framework.SkipUnlessNodeCountIsAtLeast(2)
if framework.TestContext.CloudConfig.NumNodes < 2 {
framework.Logf("Conformance test suite needs a cluster with at least 2 nodes.")
}
framework.Logf("Create a RollingUpdate DaemonSet")
label := map[string]string{daemonsetNameLabel: dsName}

View File

@ -4916,7 +4916,7 @@ func GetNodeInternalIP(node *v1.Node) (string, error) {
}
}
if host == "" {
return "", fmt.Errorf("Couldn't get the external IP of host %s with addresses %v", node.Name, node.Status.Addresses)
return "", fmt.Errorf("Couldn't get the internal IP of host %s with addresses %v", node.Name, node.Status.Addresses)
}
return host, nil
}