func (k *Kube) clearNodeDrain() error {
	if changed, err := k.node.SetSchedulableIfAnnotated(KubeDrainAnnotation); err != nil {
		return fmt.Errorf("Failed to clear node drain state: %v", err)
	} else if changed {
		log.Printf("Uncordoned drained kube node %v (with annotation %v)", k.node, KubeDrainAnnotation)
		return nil
	} else {
		log.Printf("Kube node %v is not marked as drained (with annotation %v)", k.node, KubeDrainAnnotation)
		return nil
	}
}
uncordon if drained before reboot
package main
import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"time"
	"github.com/kontena/pharos-host-upgrades/hosts"
	"github.com/kontena/pharos-host-upgrades/kube"
	"github.com/kontena/pharos-host-upgrades/kubectl"
)
const KubeLockAnnotation = "pharos-host-upgrades.kontena.io/lock"
const KubeDrainAnnotation = "pharos-host-upgrades.kontena.io/drain"
const KubeRebootAnnotation = "pharos-host-upgrades.kontena.io/reboot"
type KubeOptions struct {
	kube.Options
}
func (options KubeOptions) IsSet() bool {
	return !(options.Namespace == "" && options.DaemonSet == "" && options.Node == "")
}
type Kube struct {
	options  kube.Options
	hostInfo hosts.Info
	kube     *kube.Kube
	lock     *kube.Lock
	node     *kube.Node
}
func makeKube(options Options, hostInfo hosts.Info) (*Kube, error) {
	var k = Kube{
		options:  options.Kube.Options,
		hostInfo: hostInfo,
	}
	if !options.Kube.IsSet() {
		log.Printf("No --kube configuration")
		return nil, nil
	}
	log.Printf("Using --kube-namespace=%v --kube-daemonset=%v --kube-node=%v",
		options.Kube.Namespace,
		options.Kube.DaemonSet,
		options.Kube.Node,
	)
	if kube, err := kube.New(options.Kube.Options); err != nil {
		return nil, err
	} else {
		k.kube = kube
	}
	if err := k.initNode(); err != nil {
		return nil, err
	}
	if err := k.initLock(); err != nil {
		return nil, err
	}
	if err := k.clearNodeReboot(); err != nil {
		return nil, err
	}
	if err := k.clearNodeDrain(); err != nil {
		return nil, err
	}
	if err := k.clearLock(); err != nil {
		return nil, err
	}
	return &k, nil
}
func (k *Kube) initNode() error {
	if kubeNode, err := k.kube.Node(); err != nil {
		return err
	} else {
		k.node = kubeNode
	}
	return nil
}
func (k *Kube) initLock() error {
	if kubeLock, err := k.kube.Lock(KubeLockAnnotation); err != nil {
		return err
	} else {
		k.lock = kubeLock
	}
	return nil
}
func (k *Kube) checkReboot() (time.Time, bool, error) {
	var t time.Time
	if value, exists, err := k.node.GetAnnotation(KubeRebootAnnotation); err != nil {
		return t, false, fmt.Errorf("Faield to get node reboot annotation: %v", err)
	} else if !exists {
		return t, false, nil
	} else if err := json.Unmarshal([]byte(value), &t); err != nil {
		return t, true, fmt.Errorf("Failed to unmarshal reboot annotation: %v", err)
	} else {
		return t, true, nil
	}
}
func (k *Kube) clearNodeReboot() error {
	if rebootTime, rebooting, err := k.checkReboot(); err != nil {
		return err
	} else if !rebooting {
		log.Printf("Initialized kube node %v (not rebooting)", k.node)
		return nil
	} else if !k.hostInfo.BootTime.After(rebootTime) {
		return fmt.Errorf("Kube node %v is still rebooting (reboot=%v >= boot=%v)", k.node, rebootTime, k.hostInfo.BootTime)
	} else if err := k.node.SetCondition(MakeRebootConditionRebooted(k.hostInfo.BootTime)); err != nil {
		log.Printf("Failed to update node %v condition: %v", k.node, err)
		return nil
	} else if err := k.node.ClearAnnotation(KubeRebootAnnotation); err != nil {
		return fmt.Errorf("Failed to clear reboot annotation: %v", err)
	} else {
		log.Printf("Kube node %v was rebooted (reboot=%v < boot=%v)...", k.node, rebootTime, k.hostInfo.BootTime)
		return nil
	}
}