func GetKubernetesNamespaceFromMachines(ctx context.Context, c client.Client) (string, error) {
	mlist := &clusterv1.MachineList{}
	if err := c.List(ctx, mlist); err != nil {
		return "", err
	}
	for _, m := range mlist.Items {
		mNS := m.ObjectMeta.Namespace
		if mNS == "" {
			continue
		}
		return mNS, nil
	}
	return manifest.DefaultNamespace, nil
}
GetKubernetesNamespaceFromMachines reads the namespace of the Kubernetes control
plane from the applied machines. If no namespace is found, the
default Kubernetes namespace will be returned.
package machine
import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"github.com/blang/semver"
	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"
	existinginfrav1 "github.com/weaveworks/cluster-api-provider-existinginfra/apis/cluster.weave.works/v1alpha3"
	"github.com/weaveworks/cluster-api-provider-existinginfra/pkg/kubernetes"
	"github.com/weaveworks/cluster-api-provider-existinginfra/pkg/scheme"
	"github.com/weaveworks/cluster-api-provider-existinginfra/pkg/utilities/manifest"
	"github.com/weaveworks/libgitops/pkg/serializer"
	"k8s.io/apimachinery/pkg/util/validation/field"
	clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
	"sigs.k8s.io/controller-runtime/pkg/client"
)
func GetKubernetesVersion(machine *clusterv1.Machine) string {
	if machine == nil {
		return kubernetes.DefaultVersion
	}
	return getKubernetesVersion(machine)
}
func GetKubernetesVersionFromManifest(machinesManifestPath string) (string, string, error) {
	machines, bl, err := ParseManifest(machinesManifestPath)
	if err != nil {
		return "", "", err
	}
	return GetKubernetesVersionFromMasterIn(machines, bl)
}
func GetKubernetesVersionFromMasterIn(machines []*clusterv1.Machine, bl []*existinginfrav1.ExistingInfraMachine) (string, string, error) {
	errs := Validate(machines, bl)
	if len(errs) > 0 {
		return "", "", errs.ToAggregate()
	}
	machine, _ := FirstMaster(machines, bl)
	version := GetKubernetesVersion(machine)
	ns := machine.ObjectMeta.Namespace
	if ns == "" {
		ns = manifest.DefaultNamespace
	}
	log.WithField("machine", machine.Name).WithField("version", version).WithField("namespace", ns).Debug("Kubernetes version used")
	return version, ns, nil
}
func ParseManifest(file string) (ml []*clusterv1.Machine, bl []*existinginfrav1.ExistingInfraMachine, err error) {
	f, err := os.Open(file)
	if err != nil {
		return nil, nil, err
	}
	defer f.Close()
	ml, bl, err = Parse(f)
	if err != nil {
		err = errors.Wrapf(err, "parsing %q", file)
	}
	return
}
func Parse(rc io.ReadCloser) (ml []*clusterv1.Machine, bl []*existinginfrav1.ExistingInfraMachine, err error) {
	fr := serializer.NewYAMLFrameReader(rc)
	objs, err := scheme.Serializer.Decoder().DecodeAll(fr)
	if err != nil {
		return
	}
	for _, obj := range objs {
		switch typed := obj.(type) {
		case *clusterv1.Machine:
			ml = append(ml, typed)
		case *existinginfrav1.ExistingInfraMachine:
			bl = append(bl, typed)
		default:
			return nil, nil, fmt.Errorf("unexpected type %T", obj)
		}
	}
	return
}
func WriteManifest(machines []*clusterv1.Machine, eiMachines []*existinginfrav1.ExistingInfraMachine, path string) error {
	machineObjs := []interface{}{}
	for _, m := range machines {
		machineObjs = append(machineObjs, m)
	}
	for _, e := range eiMachines {
		machineObjs = append(machineObjs, e)
	}
	data, err := manifest.Marshal(machineObjs...)
	if err != nil {
		return errors.Wrap(err, "failed marshaling the machines file")
	}
	err = ioutil.WriteFile(path, data, 0644)
	if err != nil {
		return errors.Wrap(err, "failed writing the machines file")
	}
	return nil
}
func Validate(machines []*clusterv1.Machine, bl []*existinginfrav1.ExistingInfraMachine) field.ErrorList {
	if len(machines) == 0 {  
		return field.ErrorList{nonFieldError("no machines")}
	}
	var errors field.ErrorList
	for _, f := range []machineListValidationFunc{
		validateAtLeastOneMaster,
		validateVersions,
		validateKubernetesVersion,
	} {
		errors = append(errors, f(machines)...)
	}
	if len(machines) != len(bl) {
		errors = append(errors, nonFieldError("mismatch: %d Machines and %d ExistingInfraMachines", len(machines), len(bl)))
	} else {
		for i, m := range machines {
			ref := m.Spec.InfrastructureRef
			if ref.Name != bl[i].ObjectMeta.Name {
				errors = append(errors, nonFieldError("mismatch [%d]: reference %q != %q", i, ref.Name, bl[i].ObjectMeta.Name))
			}
		}
	}
	return errors
}
func nonFieldError(format string, args ...interface{}) *field.Error {
	return field.Invalid(field.NewPath("spec"), "[...]", fmt.Sprintf(format, args...))
}
func machinePath(i int, args ...string) *field.Path {
	return field.NewPath(fmt.Sprintf("machines[%d]", i), args...)
}
type machineListValidationFunc func([]*clusterv1.Machine) field.ErrorList
func validateAtLeastOneMaster(machines []*clusterv1.Machine) field.ErrorList {
	numMasters := 0
	for _, m := range machines {
		if IsMaster(m) {
			numMasters++
		}
	}
	if numMasters == 0 {
		return field.ErrorList{
			field.Invalid(
				field.NewPath("metadata", "labels", "set"),
				"",
				"no master node defined, need at least one master"),
		}
	}
	return field.ErrorList{}
}
func validateVersions(machines []*clusterv1.Machine) field.ErrorList {
	var errors field.ErrorList
	reference := machines[0].Spec.Version
	for i, m := range machines {
		if reference == nil {
			if m.Spec.Version != nil {
				errors = append(errors, field.Invalid(
					machinePath(i, "spec", "version"),
					m.Spec.Version,
					"inconsistent kubernetes version, expected nil"))
			}
		} else {
			if m.Spec.Version == nil {
				errors = append(errors, field.Invalid(
					machinePath(i, "spec", "version"),
					nil,
					fmt.Sprintf("inconsistent kubernetes version, expected %q", *reference)))
			} else if *reference != *m.Spec.Version {
				errors = append(errors, field.Invalid(
					machinePath(i, "spec", "version"),
					*m.Spec.Version,
					fmt.Sprintf("inconsistent kubernetes version, expected %q", *reference)))
			}
		}
	}
	return errors
}
func validateKubernetesVersion(machines []*clusterv1.Machine) field.ErrorList {
	s := machines[0].Spec.Version
	if s == nil {
		return field.ErrorList{}
	}
	version, err := semver.ParseTolerant(*s)
	if err != nil {
		return field.ErrorList{
			field.Invalid(
				machinePath(0, "spec", "version"),
				machines[0].Spec.Version,
				"version isn't a semver version"),
		}
	}
	ranges := []string{
		kubernetes.DefaultVersionsRange,
	}
	for i := range ranges {
		r := semver.MustParseRange(ranges[i])
		if !r(version) {
			return field.ErrorList{
				field.Invalid(
					machinePath(0, "spec", "version"),
					machines[0].Spec.Version,
					fmt.Sprintf("version doesn't match range: %s", ranges[i])),
			}
		}
	}
	return field.ErrorList{}
}
type machinePopulateFunc func(*clusterv1.Machine)
func populateVersions(m *clusterv1.Machine) {
	if m.Spec.Version != nil {
		return
	}
	versionCopy := kubernetes.DefaultVersion
	m.Spec.Version = &versionCopy
}
func fixupNodeRoleLabel(m *clusterv1.Machine) {
	if IsNode(m) {
		m.Labels["node-role.kubernetes.io/node"] = ""
	}
}
func Populate(machines []*clusterv1.Machine) {
	for _, f := range []machinePopulateFunc{
		populateVersions,
		fixupNodeRoleLabel,
	} {
		for _, machine := range machines {
			f(machine)
		}
	}
}
type InvalidMachinesHandler = func(machines []*clusterv1.Machine, bl []*existinginfrav1.ExistingInfraMachine, errors field.ErrorList) ([]*clusterv1.Machine, []*existinginfrav1.ExistingInfraMachine, error)
var NoOpInvalidMachinesHandler = func(machines []*clusterv1.Machine, errors field.ErrorList) ([]*clusterv1.Machine, error) {
	return nil, nil
}
func ParseAndDefaultAndValidate(machinesManifestPath string, errorsHandler InvalidMachinesHandler) ([]*clusterv1.Machine, []*existinginfrav1.ExistingInfraMachine, error) {
	machines, bl, err := ParseManifest(machinesManifestPath)
	if err != nil {
		return nil, nil, err
	}
	Populate(machines)
	errors := Validate(machines, bl)
	return errorsHandler(machines, bl, errors)
}