kops/pkg/validation/validate_cluster.go

155 lines
4.9 KiB
Go

/*
Copyright 2016 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 validation
import (
"fmt"
"time"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
)
// A cluster to validate
type ValidationCluster struct {
MastersReady bool `json:"mastersReady,omitempty"`
MastersReadyArray []*ValidationNode `json:"mastersReadyArray,omitempty"`
MastersNotReadyArray []*ValidationNode `json:"mastersNotReadyArray,omitempty"`
MastersCount int `json:"mastersCount,omitempty"`
NodesReady bool `json:"nodesReady,omitempty"`
NodesReadyArray []*ValidationNode `json:"nodesReadyArray,omitempty"`
NodesNotReadyArray []*ValidationNode `json:"nodesNotReadyArray,omitempty"`
NodesCount int `json:"nodesCount,omitempty"`
NodeList *v1.NodeList `json:"nodeList,omitempty"`
}
// A K8s node to be validated
type ValidationNode struct {
Zone string `json:"zone,omitempty"`
Role string `json:"role,omitempty"`
Hostname string `json:"hostname,omitempty"`
Status v1.ConditionStatus `json:"status,omitempty"`
}
// ValidateCluster validate a k8s cluster with a provided instance group list
func ValidateCluster(clusterName string, instanceGroupList *kops.InstanceGroupList, clusterKubernetesClient release_1_5.Interface) (*ValidationCluster, error) {
var instanceGroups []*kops.InstanceGroup
validationCluster := &ValidationCluster{}
for i := range instanceGroupList.Items {
ig := &instanceGroupList.Items[i]
instanceGroups = append(instanceGroups, ig)
if ig.Spec.Role == kops.InstanceGroupRoleMaster {
validationCluster.MastersCount += *ig.Spec.MinSize
} else if ig.Spec.Role == kops.InstanceGroupRoleNode {
validationCluster.NodesCount += *ig.Spec.MinSize
}
}
if len(instanceGroups) == 0 {
return validationCluster, fmt.Errorf("No InstanceGroup objects found")
}
timeout, err := time.ParseDuration("30s")
if err != nil {
return nil, fmt.Errorf("Cannot set timeout %q: %v", clusterName, err)
}
nodeAA, err := NewNodeAPIAdapter(clusterKubernetesClient, timeout)
if err != nil {
return nil, fmt.Errorf("error building node adapter for %q: %v", clusterName, err)
}
validationCluster.NodeList, err = nodeAA.GetAllNodes()
if err != nil {
return nil, fmt.Errorf("Cannot get nodes for %q: %v", clusterName, err)
}
return validateTheNodes(clusterName, validationCluster)
}
func getRoleNode(node *v1.Node) string {
role := kops.RoleNodeLabelValue
if val, ok := node.ObjectMeta.Labels[kops.RoleLabelName]; ok {
role = val
}
return role
}
func validateTheNodes(clusterName string, validationCluster *ValidationCluster) (*ValidationCluster, error) {
nodes := validationCluster.NodeList
if nodes == nil || len(nodes.Items) == 0 {
return validationCluster, fmt.Errorf("No nodes found in validationCluster")
}
for i := range nodes.Items {
node := &nodes.Items[i]
role := getRoleNode(node)
n := &ValidationNode{
Zone: node.ObjectMeta.Labels["failure-domain.beta.kubernetes.io/zone"],
Hostname: node.ObjectMeta.Labels["kubernetes.io/hostname"],
Role: role,
Status: GetNodeConditionStatus(node),
}
ready := IsNodeOrMasterReady(node)
// TODO: Use instance group role instead...
if n.Role == kops.RoleMasterLabelValue {
if ready {
validationCluster.MastersReadyArray = append(validationCluster.MastersReadyArray, n)
} else {
validationCluster.MastersNotReadyArray = append(validationCluster.MastersNotReadyArray, n)
}
} else if n.Role == kops.RoleNodeLabelValue {
if ready {
validationCluster.NodesReadyArray = append(validationCluster.NodesReadyArray, n)
} else {
validationCluster.NodesNotReadyArray = append(validationCluster.NodesNotReadyArray, n)
}
}
}
validationCluster.MastersReady = true
if len(validationCluster.MastersNotReadyArray) != 0 || validationCluster.MastersCount !=
len(validationCluster.MastersReadyArray) {
validationCluster.MastersReady = false
}
validationCluster.NodesReady = true
if len(validationCluster.NodesNotReadyArray) != 0 || validationCluster.NodesCount !=
len(validationCluster.NodesReadyArray) {
validationCluster.NodesReady = false
}
if validationCluster.MastersReady && validationCluster.NodesReady {
return validationCluster, nil
} else {
// TODO: This isn't an error...
return validationCluster, fmt.Errorf("Your cluster is NOT ready %s", clusterName)
}
}